gloo 6.7.2 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CLAUDE.md +1 -0
- data/docs/application.md +3 -1
- data/docs/iterators.md +39 -3
- data/docs/language_syntax.md +53 -5
- data/docs/objects.md +59 -2
- data/docs/operators.md +16 -0
- data/docs/plugins.md +9 -1
- data/docs/verbs.md +4 -2
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +24 -0
- data/lib/gloo/app/engine.rb +64 -8
- data/lib/gloo/app/log.rb +47 -6
- data/lib/gloo/convert/converter.rb +63 -2
- data/lib/gloo/convert/string_to_date.rb +14 -0
- data/lib/gloo/convert/string_to_datetime.rb +16 -0
- data/lib/gloo/convert/string_to_decimal.rb +13 -0
- data/lib/gloo/convert/string_to_integer.rb +9 -2
- data/lib/gloo/convert/string_to_time.rb +28 -0
- data/lib/gloo/core/error.rb +11 -2
- data/lib/gloo/core/event_manager.rb +7 -4
- data/lib/gloo/core/factory.rb +16 -11
- data/lib/gloo/core/gloo_system.rb +3 -2
- data/lib/gloo/core/here.rb +6 -1
- data/lib/gloo/core/invoker.rb +2 -3
- data/lib/gloo/core/not_found.rb +42 -0
- data/lib/gloo/core/obj.rb +30 -3
- data/lib/gloo/core/op.rb +2 -0
- data/lib/gloo/core/parser.rb +1 -1
- data/lib/gloo/core/pn.rb +33 -12
- data/lib/gloo/core/tokens.rb +38 -0
- data/lib/gloo/core/verb.rb +54 -0
- data/lib/gloo/exec/dispatch.rb +5 -6
- data/lib/gloo/exec/exec_env.rb +13 -0
- data/lib/gloo/exec/runner.rb +10 -2
- data/lib/gloo/exec/script.rb +13 -1
- data/lib/gloo/expr/expression.rb +39 -1
- data/lib/gloo/expr/op_plus.rb +3 -0
- data/lib/gloo/objs/basic/boolean.rb +16 -0
- data/lib/gloo/objs/basic/container.rb +154 -6
- data/lib/gloo/objs/basic/decimal.rb +1 -0
- data/lib/gloo/objs/basic/integer.rb +1 -0
- data/lib/gloo/objs/basic/string.rb +0 -1
- data/lib/gloo/objs/basic/string_msgs.rb +68 -32
- data/lib/gloo/objs/ctrl/each.rb +22 -3
- data/lib/gloo/objs/ctrl/each_dir.rb +20 -7
- data/lib/gloo/objs/ctrl/each_file.rb +78 -9
- data/lib/gloo/objs/ctrl/function.rb +6 -5
- data/lib/gloo/objs/dt/date.rb +28 -11
- data/lib/gloo/objs/dt/datetime.rb +72 -21
- data/lib/gloo/objs/dt/dt_tools.rb +46 -2
- data/lib/gloo/objs/dt/time.rb +28 -11
- data/lib/gloo/objs/str_utils/cipher.rb +17 -4
- data/lib/gloo/objs/str_utils/password.rb +6 -2
- data/lib/gloo/objs/system/erb.rb +9 -3
- data/lib/gloo/objs/system/file_handle.rb +57 -21
- data/lib/gloo/objs/system/system.rb +6 -2
- data/lib/gloo/objs/web/http_get.rb +12 -2
- data/lib/gloo/objs/web/http_post.rb +6 -2
- data/lib/gloo/objs/web/json.rb +38 -18
- data/lib/gloo/objs/web/uri.rb +36 -16
- data/lib/gloo/persist/file_loader.rb +72 -11
- data/lib/gloo/persist/file_saver.rb +2 -1
- data/lib/gloo/persist/indent_stack.rb +49 -33
- data/lib/gloo/persist/line_splitter.rb +40 -3
- data/lib/gloo/persist/persist_man.rb +2 -4
- data/lib/gloo/plugin/ext_manager.rb +6 -9
- data/lib/gloo/plugin/lib_manager.rb +2 -2
- data/lib/gloo/verbs/break.rb +1 -0
- data/lib/gloo/verbs/check.rb +1 -1
- data/lib/gloo/verbs/cls.rb +1 -0
- data/lib/gloo/verbs/create.rb +32 -4
- data/lib/gloo/verbs/execute.rb +1 -1
- data/lib/gloo/verbs/exists.rb +27 -15
- data/lib/gloo/verbs/files.rb +2 -1
- data/lib/gloo/verbs/help.rb +1 -0
- data/lib/gloo/verbs/if.rb +1 -1
- data/lib/gloo/verbs/invoke.rb +1 -1
- data/lib/gloo/verbs/list.rb +4 -3
- data/lib/gloo/verbs/load.rb +3 -3
- data/lib/gloo/verbs/move.rb +10 -8
- data/lib/gloo/verbs/put.rb +20 -8
- data/lib/gloo/verbs/quit.rb +1 -0
- data/lib/gloo/verbs/redirect.rb +8 -2
- data/lib/gloo/verbs/reload.rb +9 -1
- data/lib/gloo/verbs/run.rb +2 -2
- data/lib/gloo/verbs/save.rb +4 -2
- data/lib/gloo/verbs/tell.rb +1 -1
- data/lib/gloo/verbs/unless.rb +1 -1
- data/lib/gloo/verbs/unload.rb +8 -0
- data/test.gloo/ctrl/each.test.gloo +88 -0
- data/test.gloo/dt/datetime.test.gloo +5 -3
- data/test.gloo/lang/convert.test.gloo +1 -0
- data/test.gloo/lang/declaration.test.gloo +38 -0
- data/test.gloo/lang/exceptions.test.gloo +68 -0
- data/test.gloo/lang/failures.test.gloo +143 -0
- data/test.gloo/lang/gloo_sys.test.gloo +14 -9
- data/test.gloo/lang/it.test.gloo +139 -0
- data/test.gloo/lang/naming.test.gloo +21 -0
- data/test.gloo/lang/ops.test.gloo +30 -0
- data/test.gloo/math/div.test.gloo +2 -2
- data/test.gloo/math/mult.test.gloo +4 -4
- data/test.gloo/objs/can.test.gloo +104 -0
- data/test.gloo/objs/function.test.gloo +1 -0
- data/test.gloo/objs/string.test.gloo +24 -0
- data/test.gloo/string/str.test.gloo +28 -0
- data/test.gloo/verbs/check.test.gloo +10 -1
- data/test.gloo/verbs/create.test.gloo +37 -0
- data/test.gloo/verbs/exists.test.gloo +34 -1
- data/test.gloo/verbs/invoke.test.gloo +1 -0
- data/test.gloo/verbs/list.test.gloo +1 -0
- data/test.gloo/verbs/load.test.gloo +2 -0
- data/test.gloo/verbs/reload.test.gloo +1 -0
- data/test.gloo/verbs/save.test.gloo +2 -0
- data/test.gloo/verbs/throw.test.gloo +2 -0
- data/test.gloo/verbs/unload.test.gloo +35 -0
- metadata +4 -1
data/lib/gloo/verbs/unload.rb
CHANGED
|
@@ -16,6 +16,7 @@ module Gloo
|
|
|
16
16
|
# This will unload all loaded objects and reset the engine state.
|
|
17
17
|
#
|
|
18
18
|
def run
|
|
19
|
+
return if extra_words_err?( 'nothing was unloaded; to unload one object, use tell x to unload' )
|
|
19
20
|
return unless @engine.persist_man.maps
|
|
20
21
|
|
|
21
22
|
@engine.persist_man.unload_all
|
|
@@ -58,6 +59,13 @@ module Gloo
|
|
|
58
59
|
'save state prior to executing.',
|
|
59
60
|
:syntax => [ 'unload' ],
|
|
60
61
|
:result => 'All objects will be unloaded from the heap.',
|
|
62
|
+
:errors => [
|
|
63
|
+
'unload takes no object, so nothing was unloaded — anything ' \
|
|
64
|
+
'written after unload is an error, and nothing is unloaded. ' \
|
|
65
|
+
'To unload one object, use tell x to unload.'
|
|
66
|
+
],
|
|
67
|
+
:notes => 'unload takes no object; to unload just one object, ' \
|
|
68
|
+
'send it the unload message (tell x to unload).',
|
|
61
69
|
:examples => <<~EXAMPLES.strip
|
|
62
70
|
> unload
|
|
63
71
|
EXAMPLES
|
|
@@ -35,3 +35,91 @@ tests.ctrl.each [can] :
|
|
|
35
35
|
tell ^^.rpt to run
|
|
36
36
|
eval ^^.count = 3
|
|
37
37
|
assert "expected repeat to run 3 times"
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Each file / each dir over a nested folder tree.
|
|
41
|
+
# The tree is built under /tmp and removed at the end.
|
|
42
|
+
#
|
|
43
|
+
|
|
44
|
+
tests.ctrl.each_folder [can] :
|
|
45
|
+
|
|
46
|
+
count [int] : 0
|
|
47
|
+
|
|
48
|
+
make_tree [system] :
|
|
49
|
+
command [string] : rm -rf /tmp/gloo_each_walk && mkdir -p /tmp/gloo_each_walk/a/deep /tmp/gloo_each_walk/.obs && touch /tmp/gloo_each_walk/top.md /tmp/gloo_each_walk/notes.txt /tmp/gloo_each_walk/a/x.md /tmp/gloo_each_walk/a/deep/Y.MD /tmp/gloo_each_walk/.obs/o.md
|
|
50
|
+
get_output [bool] : false
|
|
51
|
+
remove_tree [system] :
|
|
52
|
+
command [string] : rm -rf /tmp/gloo_each_walk
|
|
53
|
+
get_output [bool] : false
|
|
54
|
+
|
|
55
|
+
files [each] :
|
|
56
|
+
file [file] :
|
|
57
|
+
in [file] : /tmp/gloo_each_walk
|
|
58
|
+
ext [string] : md
|
|
59
|
+
recursive [bool] : true
|
|
60
|
+
do [script] :
|
|
61
|
+
eval ^^.count + 1
|
|
62
|
+
put it into ^^.count
|
|
63
|
+
|
|
64
|
+
wild [each] :
|
|
65
|
+
file [file] :
|
|
66
|
+
in [file] : /tmp/gloo_each_walk/**/
|
|
67
|
+
ext [string] : md
|
|
68
|
+
do [script] :
|
|
69
|
+
eval ^^.count + 1
|
|
70
|
+
put it into ^^.count
|
|
71
|
+
|
|
72
|
+
top [each] :
|
|
73
|
+
file [file] :
|
|
74
|
+
in [file] : /tmp/gloo_each_walk
|
|
75
|
+
do [script] :
|
|
76
|
+
eval ^^.count + 1
|
|
77
|
+
put it into ^^.count
|
|
78
|
+
|
|
79
|
+
dirs [each] :
|
|
80
|
+
dir [file] :
|
|
81
|
+
in [file] : /tmp/gloo_each_walk
|
|
82
|
+
recursive [bool] : true
|
|
83
|
+
do [script] :
|
|
84
|
+
eval ^^.count + 1
|
|
85
|
+
put it into ^^.count
|
|
86
|
+
|
|
87
|
+
recursive_each_file [test] :
|
|
88
|
+
description [string] : Recursive each file finds nested files, ignoring ext case and hidden folders.
|
|
89
|
+
on_test [script] :
|
|
90
|
+
tell ^^.make_tree to run
|
|
91
|
+
put 0 into ^^.count
|
|
92
|
+
tell ^^.files to run
|
|
93
|
+
eval ^^.count = 3
|
|
94
|
+
assert "expected top.md, a/x.md and a/deep/Y.MD"
|
|
95
|
+
tell ^^.remove_tree to run
|
|
96
|
+
|
|
97
|
+
wildcard_in_folder [test] :
|
|
98
|
+
description [string] : A ** wildcard in the folder walks the tree too.
|
|
99
|
+
on_test [script] :
|
|
100
|
+
tell ^^.make_tree to run
|
|
101
|
+
put 0 into ^^.count
|
|
102
|
+
tell ^^.wild to run
|
|
103
|
+
eval ^^.count = 3
|
|
104
|
+
assert "expected the same 3 files as recursive"
|
|
105
|
+
tell ^^.remove_tree to run
|
|
106
|
+
|
|
107
|
+
files_only_by_default [test] :
|
|
108
|
+
description [string] : Each file without ext lists files, not folders.
|
|
109
|
+
on_test [script] :
|
|
110
|
+
tell ^^.make_tree to run
|
|
111
|
+
put 0 into ^^.count
|
|
112
|
+
tell ^^.top to run
|
|
113
|
+
eval ^^.count = 2
|
|
114
|
+
assert "expected top.md and notes.txt, but not the folder a"
|
|
115
|
+
tell ^^.remove_tree to run
|
|
116
|
+
|
|
117
|
+
recursive_each_dir [test] :
|
|
118
|
+
description [string] : Recursive each dir lists every folder in the tree, skipping hidden ones.
|
|
119
|
+
on_test [script] :
|
|
120
|
+
tell ^^.make_tree to run
|
|
121
|
+
put 0 into ^^.count
|
|
122
|
+
tell ^^.dirs to run
|
|
123
|
+
eval ^^.count = 2
|
|
124
|
+
assert "expected a and a/deep"
|
|
125
|
+
tell ^^.remove_tree to run
|
|
@@ -5,15 +5,17 @@
|
|
|
5
5
|
tests.dt.datetime [can] :
|
|
6
6
|
|
|
7
7
|
d [dt] :
|
|
8
|
+
# Only the now test uses this; the others set d, and tests run in random order.
|
|
9
|
+
fresh [dt] :
|
|
8
10
|
|
|
9
11
|
now [test] :
|
|
10
12
|
description [string] : Get the current datetime
|
|
11
13
|
on_test [script] :
|
|
12
|
-
check ^^.
|
|
14
|
+
check ^^.fresh for blank?
|
|
13
15
|
assert "expected new datetime to be blank"
|
|
14
16
|
|
|
15
|
-
tell ^^.
|
|
16
|
-
check ^^.
|
|
17
|
+
tell ^^.fresh to now
|
|
18
|
+
check ^^.fresh for blank?
|
|
17
19
|
refute "expected datetime to not be blank after now"
|
|
18
20
|
|
|
19
21
|
is_today [test] :
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Declaration syntax tests
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
tests.lang.declaration [can] :
|
|
6
|
+
|
|
7
|
+
# A fixture deliberately missing the ']' after its type, loaded inside
|
|
8
|
+
# its test so the syntax error it reports belongs to that test.
|
|
9
|
+
# Loading reads the type as 'int' anyway.
|
|
10
|
+
unclosed_file [file] : /tmp/gloo_declaration_test.gloo
|
|
11
|
+
unclosed_src [text] : BEGIN
|
|
12
|
+
declaration_fixture [container] :
|
|
13
|
+
unclosed [int : 7
|
|
14
|
+
END
|
|
15
|
+
|
|
16
|
+
closed_then_colon [int]: 8
|
|
17
|
+
|
|
18
|
+
type_missing_its_closing_bracket [test] :
|
|
19
|
+
description [string] : a type missing its ']' is still read as that type, with its value.
|
|
20
|
+
expect_errors [bool] : true
|
|
21
|
+
on_test [script] :
|
|
22
|
+
tell ^^.unclosed_file to write ( ^^.unclosed_src )
|
|
23
|
+
load /tmp/gloo_declaration_test.gloo
|
|
24
|
+
eval declaration_fixture.unclosed = 7
|
|
25
|
+
assert "expected the value 7"
|
|
26
|
+
|
|
27
|
+
put '12' into declaration_fixture.unclosed
|
|
28
|
+
eval declaration_fixture.unclosed = 12
|
|
29
|
+
assert "expected it to still be an integer"
|
|
30
|
+
|
|
31
|
+
tell declaration_fixture to unload
|
|
32
|
+
tell ^^.unclosed_file to delete
|
|
33
|
+
|
|
34
|
+
closed_type_followed_by_the_colon [test] :
|
|
35
|
+
description [string] : a ']' followed directly by ':' is a normal declaration.
|
|
36
|
+
on_test [script] :
|
|
37
|
+
eval ^^.closed_then_colon = 8
|
|
38
|
+
assert "expected the value 8"
|
|
@@ -20,9 +20,12 @@ tests.lang.exceptions [can] :
|
|
|
20
20
|
error_data [can] :
|
|
21
21
|
message [string] :
|
|
22
22
|
backtrace [string] :
|
|
23
|
+
kind [string] :
|
|
24
|
+
location [string] :
|
|
23
25
|
|
|
24
26
|
confirm_throw_fires_on_exception [test] :
|
|
25
27
|
description [string] : Confirm throw fires on_exception and populates exception_data, but does not fire on_error.
|
|
28
|
+
expect_errors [bool] : true
|
|
26
29
|
on_test [script] :
|
|
27
30
|
put false into ^^.exc_fired
|
|
28
31
|
put false into ^^.err_fired
|
|
@@ -40,6 +43,7 @@ tests.lang.exceptions [can] :
|
|
|
40
43
|
|
|
41
44
|
confirm_execution_continues_after_throw [test] :
|
|
42
45
|
description [string] : Confirm execution continues with the next line after a throw.
|
|
46
|
+
expect_errors [bool] : true
|
|
43
47
|
on_test [script] :
|
|
44
48
|
throw "boom"
|
|
45
49
|
eval 2 + 2
|
|
@@ -48,6 +52,7 @@ tests.lang.exceptions [can] :
|
|
|
48
52
|
|
|
49
53
|
confirm_on_error_still_works [test] :
|
|
50
54
|
description [string] : Confirm on_error still fires for a genuine gloo-level error, independent of on_exception.
|
|
55
|
+
expect_errors [bool] : true
|
|
51
56
|
on_test [script] :
|
|
52
57
|
put false into ^^.exc_fired
|
|
53
58
|
put false into ^^.err_fired
|
|
@@ -59,3 +64,66 @@ tests.lang.exceptions [can] :
|
|
|
59
64
|
|
|
60
65
|
eval ^^.exc_fired = false
|
|
61
66
|
assert "expected on_exception to NOT have fired for a gloo-level error"
|
|
67
|
+
|
|
68
|
+
confirm_missing_value_fires_on_error [test] :
|
|
69
|
+
description [string] : Using a missing object as a value is a runtime error, but asking whether it exists is not.
|
|
70
|
+
expect_errors [bool] : true
|
|
71
|
+
on_test [script] :
|
|
72
|
+
put false into ^^.err_fired
|
|
73
|
+
exists? instance ^^.no_such_value
|
|
74
|
+
eval ^^.err_fired = false
|
|
75
|
+
assert "expected exists? on a missing object to not fire on_error"
|
|
76
|
+
|
|
77
|
+
show ^^.no_such_value
|
|
78
|
+
eval ^^.err_fired = true
|
|
79
|
+
assert "expected using a missing object as a value to fire on_error"
|
|
80
|
+
|
|
81
|
+
eval ^^.error_data.message = "Object '^^.no_such_value' was not found."
|
|
82
|
+
assert "expected error_data.message to name the missing object"
|
|
83
|
+
|
|
84
|
+
kept [string] : keep me
|
|
85
|
+
|
|
86
|
+
confirm_put_of_missing_value_keeps_target [test] :
|
|
87
|
+
description [string] : A put whose value uses a missing object leaves the target unchanged.
|
|
88
|
+
expect_errors [bool] : true
|
|
89
|
+
on_test [script] :
|
|
90
|
+
put 'keep me' into ^^.kept
|
|
91
|
+
put ^^.no_such_value into ^^.kept
|
|
92
|
+
eval ^^.kept = 'keep me'
|
|
93
|
+
assert "expected the target to keep its value"
|
|
94
|
+
|
|
95
|
+
confirm_error_kind [test] :
|
|
96
|
+
description [string] : error_data.kind says whether the command couldn't be understood (syntax) or couldn't be done (runtime).
|
|
97
|
+
expect_errors [bool] : true
|
|
98
|
+
on_test [script] :
|
|
99
|
+
nosuchverb
|
|
100
|
+
eval ^^.error_data.kind = 'syntax'
|
|
101
|
+
assert "expected an unknown verb to be a syntax error"
|
|
102
|
+
|
|
103
|
+
show ^^.no_such_value
|
|
104
|
+
eval ^^.error_data.kind = 'runtime'
|
|
105
|
+
assert "expected a missing object to be a runtime error"
|
|
106
|
+
|
|
107
|
+
confirm_error_location [test] :
|
|
108
|
+
description [string] : error_data.location names the script and line that failed.
|
|
109
|
+
expect_errors [bool] : true
|
|
110
|
+
on_test [script] :
|
|
111
|
+
show 1
|
|
112
|
+
show ^^.no_such_value
|
|
113
|
+
eval ^^.error_data.location = 'tests.lang.exceptions.confirm_error_location.on_test, line 2'
|
|
114
|
+
assert "expected the location of the failed line"
|
|
115
|
+
|
|
116
|
+
num [int] : 5
|
|
117
|
+
|
|
118
|
+
confirm_bad_value_is_a_warning [test] :
|
|
119
|
+
description [string] : A value that isn't really of its type is a warning, not an error; the best guess is used.
|
|
120
|
+
expect_errors [bool] : true
|
|
121
|
+
on_test [script] :
|
|
122
|
+
put false into ^^.err_fired
|
|
123
|
+
put 'x' into ^^.num
|
|
124
|
+
eval ^^.err_fired = false
|
|
125
|
+
assert "expected a bad value to not fire on_error"
|
|
126
|
+
|
|
127
|
+
eval ^^.num = 0
|
|
128
|
+
assert "expected the best guess, 0"
|
|
129
|
+
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Predictable failures tests
|
|
3
|
+
#
|
|
4
|
+
# A failure a script can cause with ordinary bad input or the outside
|
|
5
|
+
# world (invalid JSON, a template with a mistake, a value that isn't a
|
|
6
|
+
# date) is a gloo runtime error: it fires on_error (not on_exception),
|
|
7
|
+
# reads "Could not ...", and a command that would set it sets it false.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
tests.lang.failures [can] :
|
|
11
|
+
|
|
12
|
+
err_fired [bool] : false
|
|
13
|
+
exc_fired [bool] : false
|
|
14
|
+
|
|
15
|
+
on_error [script] :
|
|
16
|
+
put true into ^.err_fired
|
|
17
|
+
|
|
18
|
+
on_exception [script] :
|
|
19
|
+
put true into ^.exc_fired
|
|
20
|
+
|
|
21
|
+
error_data [can] :
|
|
22
|
+
message [string] :
|
|
23
|
+
backtrace [string] :
|
|
24
|
+
kind [string] :
|
|
25
|
+
location [string] :
|
|
26
|
+
|
|
27
|
+
j [json] : {bad
|
|
28
|
+
e [erb] :
|
|
29
|
+
template [text] : <%= 1 + %>
|
|
30
|
+
params [can] :
|
|
31
|
+
result [text] :
|
|
32
|
+
d [date] :
|
|
33
|
+
msg [string] :
|
|
34
|
+
|
|
35
|
+
invalid_json_is_an_error [test] :
|
|
36
|
+
description [string] : Pretty-printing invalid JSON fires on_error, not on_exception, and it is false.
|
|
37
|
+
expect_errors [bool] : true
|
|
38
|
+
on_test [script] :
|
|
39
|
+
put false into ^^.err_fired
|
|
40
|
+
put false into ^^.exc_fired
|
|
41
|
+
tell ^^.j to pretty
|
|
42
|
+
eval it = false
|
|
43
|
+
assert "expected it to be false"
|
|
44
|
+
|
|
45
|
+
eval ^^.err_fired = true
|
|
46
|
+
assert "expected on_error to fire"
|
|
47
|
+
eval ^^.exc_fired = false
|
|
48
|
+
assert "expected on_exception not to fire"
|
|
49
|
+
|
|
50
|
+
put ^^.error_data.message into ^^.msg
|
|
51
|
+
check ^^.msg for starts_with? ( 'Could not parse the JSON in tests.lang.failures.j:' )
|
|
52
|
+
assert "expected the error to say what couldn't be done"
|
|
53
|
+
|
|
54
|
+
template_syntax_error_is_an_error [test] :
|
|
55
|
+
description [string] : An erb template with a syntax error is a gloo error, and gloo keeps running.
|
|
56
|
+
expect_errors [bool] : true
|
|
57
|
+
on_test [script] :
|
|
58
|
+
put false into ^^.err_fired
|
|
59
|
+
put false into ^^.exc_fired
|
|
60
|
+
run ^^.e
|
|
61
|
+
eval it = false
|
|
62
|
+
assert "expected it to be false"
|
|
63
|
+
|
|
64
|
+
eval ^^.err_fired = true
|
|
65
|
+
assert "expected on_error to fire"
|
|
66
|
+
eval ^^.exc_fired = false
|
|
67
|
+
assert "expected on_exception not to fire"
|
|
68
|
+
|
|
69
|
+
not_a_date_is_an_error [test] :
|
|
70
|
+
description [string] : A date message on a value that isn't a date fires on_error, and it is false.
|
|
71
|
+
expect_errors [bool] : true
|
|
72
|
+
on_test [script] :
|
|
73
|
+
put '' into ^^.d
|
|
74
|
+
put false into ^^.err_fired
|
|
75
|
+
put false into ^^.exc_fired
|
|
76
|
+
tell ^^.d to mm
|
|
77
|
+
eval it = false
|
|
78
|
+
assert "expected it to be false"
|
|
79
|
+
|
|
80
|
+
eval ^^.err_fired = true
|
|
81
|
+
assert "expected on_error to fire"
|
|
82
|
+
eval ^^.exc_fired = false
|
|
83
|
+
assert "expected on_exception not to fire"
|
|
84
|
+
|
|
85
|
+
unknown_unit_is_an_error [test] :
|
|
86
|
+
description [string] : Adding an amount with an unknown unit fires on_error, and it is false.
|
|
87
|
+
expect_errors [bool] : true
|
|
88
|
+
on_test [script] :
|
|
89
|
+
put '2026-01-01' into ^^.d
|
|
90
|
+
put false into ^^.err_fired
|
|
91
|
+
tell ^^.d to add ( '3 dayz' )
|
|
92
|
+
eval it = false
|
|
93
|
+
assert "expected it to be false"
|
|
94
|
+
|
|
95
|
+
eval ^^.err_fired = true
|
|
96
|
+
assert "expected on_error to fire"
|
|
97
|
+
|
|
98
|
+
eval ^^.error_data.message = "'3 dayz' is not an amount like '1 day' or '3 months'."
|
|
99
|
+
assert "expected the error to show what an amount looks like"
|
|
100
|
+
|
|
101
|
+
#
|
|
102
|
+
# Chronic phrases are still dates: the checks above only catch a value
|
|
103
|
+
# that couldn't be read as one.
|
|
104
|
+
#
|
|
105
|
+
|
|
106
|
+
tests.lang.chronic_phrases [can] :
|
|
107
|
+
|
|
108
|
+
d [date] :
|
|
109
|
+
now [date] :
|
|
110
|
+
dt [datetime] :
|
|
111
|
+
a [string] :
|
|
112
|
+
b [string] :
|
|
113
|
+
|
|
114
|
+
today_is_a_date [test] :
|
|
115
|
+
description [string] : put 'today' into a date gives today's date.
|
|
116
|
+
on_test [script] :
|
|
117
|
+
put 'today' into ^^.d
|
|
118
|
+
tell ^^.now to now
|
|
119
|
+
tell ^^.d to format ( '%Y-%m-%d' )
|
|
120
|
+
put it into ^^.a
|
|
121
|
+
tell ^^.now to format ( '%Y-%m-%d' )
|
|
122
|
+
put it into ^^.b
|
|
123
|
+
eval ^^.a = ^^.b
|
|
124
|
+
assert "expected 'today' to be today's date"
|
|
125
|
+
|
|
126
|
+
add_to_a_phrase [test] :
|
|
127
|
+
description [string] : A date set from a phrase can be added to.
|
|
128
|
+
on_test [script] :
|
|
129
|
+
put '2026-01-01' into ^^.d
|
|
130
|
+
tell ^^.d to add ( '1 week' )
|
|
131
|
+
eval it = '2026.01.08'
|
|
132
|
+
assert "expected a week later"
|
|
133
|
+
|
|
134
|
+
tomorrow_is_in_the_future [test] :
|
|
135
|
+
description [string] : 'tomorrow at 3pm' in a datetime is tomorrow, and in the future.
|
|
136
|
+
on_test [script] :
|
|
137
|
+
put 'tomorrow at 3pm' into ^^.dt
|
|
138
|
+
tell ^^.dt to is_tomorrow
|
|
139
|
+
assert "expected it to be tomorrow"
|
|
140
|
+
tell ^^.dt to is_future
|
|
141
|
+
assert "expected it to be in the future"
|
|
142
|
+
tell ^^.dt to is_past
|
|
143
|
+
refute "expected it not to be in the past"
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
tests.lang.gloo_sys [can] :
|
|
6
6
|
|
|
7
|
+
# How many of the platform_*? checks are true.
|
|
8
|
+
platforms [int] : 0
|
|
9
|
+
|
|
7
10
|
get_platform_info [test] :
|
|
8
11
|
description [string] : Get the platform info.
|
|
9
12
|
on_test [script] :
|
|
@@ -89,16 +92,18 @@ tests.lang.gloo_sys [can] :
|
|
|
89
92
|
assert "expected screen_cols to be greater than 0"
|
|
90
93
|
|
|
91
94
|
get_platform_os [test] :
|
|
92
|
-
description [string] :
|
|
95
|
+
description [string] : Exactly one of mac, windows and linux is true, on any platform.
|
|
93
96
|
on_test [script] :
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
put 0 into ^^.platforms
|
|
98
|
+
|
|
99
|
+
eval $.platform_mac?
|
|
100
|
+
if it then tell ^^.platforms to inc
|
|
96
101
|
|
|
97
|
-
eval $.platform_windows?
|
|
98
|
-
|
|
102
|
+
eval $.platform_windows?
|
|
103
|
+
if it then tell ^^.platforms to inc
|
|
99
104
|
|
|
100
|
-
eval $.platform_linux?
|
|
101
|
-
|
|
105
|
+
eval $.platform_linux?
|
|
106
|
+
if it then tell ^^.platforms to inc
|
|
102
107
|
|
|
103
|
-
eval
|
|
104
|
-
assert "expected
|
|
108
|
+
eval ^^.platforms = 1
|
|
109
|
+
assert "expected exactly one of platform_mac, platform_windows and platform_linux to be true"
|
data/test.gloo/lang/it.test.gloo
CHANGED
|
@@ -37,3 +37,142 @@ tests.lang.it [can] :
|
|
|
37
37
|
list ^^.n
|
|
38
38
|
eval it = 42
|
|
39
39
|
assert "expected it to survive statements that don't produce a result"
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# it is a read-only result value, not an object: it can be read, but
|
|
43
|
+
# nothing can target it.
|
|
44
|
+
#
|
|
45
|
+
|
|
46
|
+
tests.lang.it_read_only [can] :
|
|
47
|
+
|
|
48
|
+
err_fired [bool] : false
|
|
49
|
+
s [string] :
|
|
50
|
+
|
|
51
|
+
on_error [script] :
|
|
52
|
+
put true into ^.err_fired
|
|
53
|
+
|
|
54
|
+
error_data [can] :
|
|
55
|
+
message [string] :
|
|
56
|
+
backtrace [string] :
|
|
57
|
+
kind [string] :
|
|
58
|
+
location [string] :
|
|
59
|
+
|
|
60
|
+
message_to_it_is_an_error [test] :
|
|
61
|
+
description [string] : Sending it a message reports an error that says what to do instead.
|
|
62
|
+
expect_errors [bool] : true
|
|
63
|
+
on_test [script] :
|
|
64
|
+
put false into ^^.err_fired
|
|
65
|
+
eval 'abc'
|
|
66
|
+
check it for starts_with? ( 'a' )
|
|
67
|
+
eval ^^.err_fired = true
|
|
68
|
+
assert "expected check it for ... to be an error"
|
|
69
|
+
|
|
70
|
+
eval ^^.error_data.message = "it isn't an object and can't be sent messages; put it into an object first (put it into x)."
|
|
71
|
+
assert "expected the error to say to put it into an object first"
|
|
72
|
+
|
|
73
|
+
put_into_it_is_an_error [test] :
|
|
74
|
+
description [string] : Putting a value into it is an error.
|
|
75
|
+
expect_errors [bool] : true
|
|
76
|
+
on_test [script] :
|
|
77
|
+
put false into ^^.err_fired
|
|
78
|
+
put 'x' into it
|
|
79
|
+
eval ^^.err_fired = true
|
|
80
|
+
assert "expected put into it to be an error"
|
|
81
|
+
|
|
82
|
+
put_it_into_an_object_works [test] :
|
|
83
|
+
description [string] : The workaround: put it into an object, then send that object the message.
|
|
84
|
+
on_test [script] :
|
|
85
|
+
put false into ^^.err_fired
|
|
86
|
+
eval 'abc'
|
|
87
|
+
put it into ^^.s
|
|
88
|
+
check ^^.s for starts_with? ( 'a' )
|
|
89
|
+
assert "expected the message to work on the object"
|
|
90
|
+
|
|
91
|
+
eval ^^.err_fired = false
|
|
92
|
+
assert "expected no error"
|
|
93
|
+
|
|
94
|
+
#
|
|
95
|
+
# The it rule: a command that works out a value puts it in it; when
|
|
96
|
+
# something goes wrong, it is false.
|
|
97
|
+
#
|
|
98
|
+
|
|
99
|
+
tests.lang.it_rule [can] :
|
|
100
|
+
|
|
101
|
+
err_fired [bool] : false
|
|
102
|
+
s [string] :
|
|
103
|
+
kept [string] : keep me
|
|
104
|
+
|
|
105
|
+
on_error [script] :
|
|
106
|
+
put true into ^.err_fired
|
|
107
|
+
|
|
108
|
+
failed_put_sets_it_false [test] :
|
|
109
|
+
description [string] : A put whose value can't be worked out sets it to false and keeps the target.
|
|
110
|
+
expect_errors [bool] : true
|
|
111
|
+
on_test [script] :
|
|
112
|
+
put false into ^^.err_fired
|
|
113
|
+
eval 'before'
|
|
114
|
+
put ^^.no_such_value into ^^.kept
|
|
115
|
+
eval it = false
|
|
116
|
+
assert "expected it to be false after a failed put"
|
|
117
|
+
|
|
118
|
+
eval ^^.kept = 'keep me'
|
|
119
|
+
assert "expected the target to keep its value"
|
|
120
|
+
|
|
121
|
+
eval ^^.err_fired = true
|
|
122
|
+
assert "expected the failed put to be an error"
|
|
123
|
+
|
|
124
|
+
put_into_missing_object_sets_it_false [test] :
|
|
125
|
+
description [string] : A put into an object that doesn't exist sets it to false.
|
|
126
|
+
expect_errors [bool] : true
|
|
127
|
+
on_test [script] :
|
|
128
|
+
eval 'before'
|
|
129
|
+
put 'x' into ^^.no_such_target
|
|
130
|
+
eval it = false
|
|
131
|
+
assert "expected it to be false"
|
|
132
|
+
|
|
133
|
+
value_messages_set_it [test] :
|
|
134
|
+
description [string] : A message that changes its own value also puts the new value in it.
|
|
135
|
+
on_test [script] :
|
|
136
|
+
put ' padded ' into ^^.s
|
|
137
|
+
tell ^^.s to trim
|
|
138
|
+
eval it = 'padded'
|
|
139
|
+
assert "expected trim to put the trimmed string in it"
|
|
140
|
+
|
|
141
|
+
put 'a b' into ^^.s
|
|
142
|
+
tell ^^.s to format_for_html
|
|
143
|
+
eval it = 'a b'
|
|
144
|
+
assert "expected format_for_html to put the result in it"
|
|
145
|
+
|
|
146
|
+
failed_function_sets_it_false [test] :
|
|
147
|
+
description [string] : A function whose on_invoke fails sets it to false.
|
|
148
|
+
expect_errors [bool] : true
|
|
149
|
+
on_test [script] :
|
|
150
|
+
eval 'before'
|
|
151
|
+
invoke ^^.failing
|
|
152
|
+
eval it = false
|
|
153
|
+
assert "expected it to be false after a failed invoke"
|
|
154
|
+
|
|
155
|
+
failing [ƒ] :
|
|
156
|
+
params [can] :
|
|
157
|
+
on_invoke [script] :
|
|
158
|
+
put 1 into no.such.object
|
|
159
|
+
result [int] :
|
|
160
|
+
|
|
161
|
+
message_to_missing_object_sets_it_false [test] :
|
|
162
|
+
description [string] : A message that can't be delivered leaves no stale value in it.
|
|
163
|
+
expect_errors [bool] : true
|
|
164
|
+
on_test [script] :
|
|
165
|
+
eval 'stale'
|
|
166
|
+
tell ^^.no_such_obj to get_parent
|
|
167
|
+
eval it = false
|
|
168
|
+
assert "expected it to be false after a message to a missing object"
|
|
169
|
+
|
|
170
|
+
eval 'stale'
|
|
171
|
+
tell ^^.s to no_such_msg
|
|
172
|
+
eval it = false
|
|
173
|
+
assert "expected it to be false after a message the object doesn't take"
|
|
174
|
+
|
|
175
|
+
eval 'stale'
|
|
176
|
+
run ^^.no_such_obj
|
|
177
|
+
eval it = false
|
|
178
|
+
assert "expected it to be false after running a missing object"
|
|
@@ -14,6 +14,14 @@ tests.lang.naming [can] :
|
|
|
14
14
|
string [string] : a type keyword as a name
|
|
15
15
|
put [string] : a verb keyword as a name
|
|
16
16
|
|
|
17
|
+
# A fixture with a deliberately nameless object, loaded inside its
|
|
18
|
+
# test so the syntax error it reports belongs to that test.
|
|
19
|
+
nameless_file [file] : /tmp/gloo_naming_test.gloo
|
|
20
|
+
nameless_src [text] : BEGIN
|
|
21
|
+
naming_fixture [container] :
|
|
22
|
+
[string] : no name given
|
|
23
|
+
END
|
|
24
|
+
|
|
17
25
|
first_of_a_duplicate_name_wins [test] :
|
|
18
26
|
description [string] : when two siblings share a name, the path always reaches the first.
|
|
19
27
|
on_test [script] :
|
|
@@ -40,3 +48,16 @@ tests.lang.naming [can] :
|
|
|
40
48
|
|
|
41
49
|
eval ^^.put = 'a verb keyword as a name'
|
|
42
50
|
assert "expected a verb keyword to be usable as a name"
|
|
51
|
+
|
|
52
|
+
declaration_with_no_name_gets_a_placeholder [test] :
|
|
53
|
+
description [string] : a declaration with no name loads under the placeholder name unnamed_1.
|
|
54
|
+
expect_errors [bool] : true
|
|
55
|
+
on_test [script] :
|
|
56
|
+
tell ^^.nameless_file to write ( ^^.nameless_src )
|
|
57
|
+
load /tmp/gloo_naming_test.gloo
|
|
58
|
+
eval naming_fixture.unnamed_1 = 'no name given'
|
|
59
|
+
assert "expected the nameless object to be reached as unnamed_1"
|
|
60
|
+
|
|
61
|
+
tell naming_fixture to unload
|
|
62
|
+
tell ^^.nameless_file to delete
|
|
63
|
+
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
tests.lang.ops [can] :
|
|
6
6
|
|
|
7
|
+
first [string] : Ada
|
|
8
|
+
last [string] : Lovelace
|
|
9
|
+
full [string] :
|
|
10
|
+
|
|
7
11
|
confirm_eq_ops [test] :
|
|
8
12
|
description [string] : Confirm equality operations.
|
|
9
13
|
on_test [script] :
|
|
@@ -75,3 +79,29 @@ tests.lang.ops [can] :
|
|
|
75
79
|
|
|
76
80
|
eval 1 <= 1
|
|
77
81
|
assert "expected 1 <= 1"
|
|
82
|
+
|
|
83
|
+
confirm_and_joins [test] :
|
|
84
|
+
description [string] : and joins values, the same as +.
|
|
85
|
+
on_test [script] :
|
|
86
|
+
put ^^.first and ' ' and ^^.last into ^^.full
|
|
87
|
+
eval ^^.full = 'Ada Lovelace'
|
|
88
|
+
assert "expected first and ' ' and last to be 'Ada Lovelace'"
|
|
89
|
+
|
|
90
|
+
eval 2 and 3 = 5
|
|
91
|
+
assert "expected 2 and 3 to be 5"
|
|
92
|
+
|
|
93
|
+
confirm_join_without_operator [test] :
|
|
94
|
+
description [string] : Values side by side with no operator between them are joined.
|
|
95
|
+
on_test [script] :
|
|
96
|
+
put 'hello ' 'world' into ^^.full
|
|
97
|
+
eval ^^.full = 'hello world'
|
|
98
|
+
assert "expected 'hello ' 'world' to be 'hello world'"
|
|
99
|
+
|
|
100
|
+
put ^^.first ' ' ^^.last into ^^.full
|
|
101
|
+
eval ^^.full = 'Ada Lovelace'
|
|
102
|
+
assert "expected first ' ' last to be 'Ada Lovelace'"
|
|
103
|
+
|
|
104
|
+
put 'a' 'b' + 'c' and 'd' into ^^.full
|
|
105
|
+
eval ^^.full = 'abcd'
|
|
106
|
+
assert "expected no operator, + and and to mix"
|
|
107
|
+
|
|
@@ -28,8 +28,8 @@ tests.math.div [can] :
|
|
|
28
28
|
eval 10.5 / 5 = 2.1
|
|
29
29
|
assert 'expected 10.5 / 5 = 2.1'
|
|
30
30
|
|
|
31
|
-
eval 100.5 /
|
|
32
|
-
assert 'expected 100.5 /
|
|
31
|
+
eval 100.5 / 201 = 0.5
|
|
32
|
+
assert 'expected 100.5 / 201 = 0.5'
|
|
33
33
|
|
|
34
34
|
eval 1.5 / 10.5 = 0.1
|
|
35
35
|
refute 'expected 1.5 / 10.5 != 0.1'
|