rox-rollout 0.1.3
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 +7 -0
- data/.circleci/config.yml +45 -0
- data/.gitignore +8 -0
- data/Gemfile +6 -0
- data/LICENSE +50 -0
- data/README_DEVELOP.md +19 -0
- data/Rakefile +16 -0
- data/_archive/.document +5 -0
- data/_archive/.rspec +1 -0
- data/_archive/Gemfile +15 -0
- data/_archive/Gemfile.lock +87 -0
- data/_archive/README.md +32 -0
- data/_archive/README.rdoc +19 -0
- data/_archive/Rakefile +50 -0
- data/_archive/lib/expr_function_definition.rb +52 -0
- data/_archive/lib/function_definition.rb +48 -0
- data/_archive/lib/function_token.rb +12 -0
- data/_archive/lib/object_extends.rb +12 -0
- data/_archive/lib/ruby_interpreter.rb +292 -0
- data/_archive/lib/stack.rb +48 -0
- data/_archive/lib/string_extends.rb +14 -0
- data/_archive/spec/ruby_interpreter_spec.rb +203 -0
- data/_archive/spec/spec_helper.rb +30 -0
- data/_archive/spec/stack_spec.rb +77 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/e2e/container.rb +38 -0
- data/e2e/custom_props.rb +55 -0
- data/e2e/rox_e2e_test.rb +159 -0
- data/e2e/test_vars.rb +24 -0
- data/lib/rox.rb +5 -0
- data/lib/rox/core/client/buid.rb +82 -0
- data/lib/rox/core/client/device_properties.rb +45 -0
- data/lib/rox/core/client/internal_flags.rb +20 -0
- data/lib/rox/core/client/sdk_settings.rb +5 -0
- data/lib/rox/core/configuration/configuration.rb +5 -0
- data/lib/rox/core/configuration/configuration_fetched_args.rb +23 -0
- data/lib/rox/core/configuration/configuration_fetched_invoker.rb +37 -0
- data/lib/rox/core/configuration/configuration_parser.rb +85 -0
- data/lib/rox/core/configuration/fetcher_error.rb +13 -0
- data/lib/rox/core/configuration/fetcher_status.rb +10 -0
- data/lib/rox/core/configuration/models/experiment_model.rb +5 -0
- data/lib/rox/core/configuration/models/target_group_model.rb +5 -0
- data/lib/rox/core/consts/build.rb +8 -0
- data/lib/rox/core/consts/environment.rb +42 -0
- data/lib/rox/core/consts/property_type.rb +29 -0
- data/lib/rox/core/context/merged_context.rb +16 -0
- data/lib/rox/core/core.rb +131 -0
- data/lib/rox/core/entities/flag.rb +26 -0
- data/lib/rox/core/entities/flag_setter.rb +39 -0
- data/lib/rox/core/entities/variant.rb +56 -0
- data/lib/rox/core/impression/impression_args.rb +5 -0
- data/lib/rox/core/impression/impression_invoker.rb +41 -0
- data/lib/rox/core/impression/models/experiment.rb +14 -0
- data/lib/rox/core/impression/models/reporting_value.rb +5 -0
- data/lib/rox/core/logging/logging.rb +17 -0
- data/lib/rox/core/logging/no_op_logger.rb +11 -0
- data/lib/rox/core/network/configuration_fetch_result.rb +5 -0
- data/lib/rox/core/network/configuration_fetcher.rb +38 -0
- data/lib/rox/core/network/configuration_fetcher_base.rb +25 -0
- data/lib/rox/core/network/configuration_fetcher_roxy.rb +29 -0
- data/lib/rox/core/network/configuration_source.rb +9 -0
- data/lib/rox/core/network/request.rb +46 -0
- data/lib/rox/core/network/request_configuration_builder.rb +48 -0
- data/lib/rox/core/network/request_data.rb +5 -0
- data/lib/rox/core/network/response.rb +16 -0
- data/lib/rox/core/properties/custom_property.rb +18 -0
- data/lib/rox/core/properties/custom_property_type.rb +18 -0
- data/lib/rox/core/properties/device_property.rb +11 -0
- data/lib/rox/core/register/registerer.rb +35 -0
- data/lib/rox/core/reporting/error_reporter.rb +152 -0
- data/lib/rox/core/repositories/custom_property_repository.rb +61 -0
- data/lib/rox/core/repositories/experiment_repository.rb +21 -0
- data/lib/rox/core/repositories/flag_repository.rb +49 -0
- data/lib/rox/core/repositories/roxx/experiments_extensions.rb +82 -0
- data/lib/rox/core/repositories/roxx/properties_extensions.rb +26 -0
- data/lib/rox/core/repositories/target_group_repository.rb +17 -0
- data/lib/rox/core/roxx/core_stack.rb +22 -0
- data/lib/rox/core/roxx/evaluation_result.rb +28 -0
- data/lib/rox/core/roxx/node.rb +11 -0
- data/lib/rox/core/roxx/parser.rb +143 -0
- data/lib/rox/core/roxx/regular_expression_extensions.rb +33 -0
- data/lib/rox/core/roxx/string_tokenizer.rb +68 -0
- data/lib/rox/core/roxx/symbols.rb +14 -0
- data/lib/rox/core/roxx/token_type.rb +30 -0
- data/lib/rox/core/roxx/tokenized_expression.rb +119 -0
- data/lib/rox/core/roxx/value_compare_extensions.rb +137 -0
- data/lib/rox/core/security/signature_verifier.rb +18 -0
- data/lib/rox/core/utils/periodic_task.rb +12 -0
- data/lib/rox/core/utils/type_utils.rb +9 -0
- data/lib/rox/server/client/sdk_settings.rb +5 -0
- data/lib/rox/server/client/server_properties.rb +20 -0
- data/lib/rox/server/flags/rox_flag.rb +19 -0
- data/lib/rox/server/flags/rox_variant.rb +8 -0
- data/lib/rox/server/logging/server_logger.rb +35 -0
- data/lib/rox/server/rox_options.rb +27 -0
- data/lib/rox/server/rox_server.rb +83 -0
- data/lib/rox/version.rb +3 -0
- data/rox.gemspec +29 -0
- metadata +184 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
require 'pry'
|
|
2
|
+
require_relative 'object_extends'
|
|
3
|
+
require_relative 'string_extends'
|
|
4
|
+
require_relative 'function_token'
|
|
5
|
+
require_relative 'function_definition'
|
|
6
|
+
require_relative 'expr_function_definition'
|
|
7
|
+
|
|
8
|
+
class Expression
|
|
9
|
+
attr :expr, :stack
|
|
10
|
+
|
|
11
|
+
def initialize(expr_val, stack)
|
|
12
|
+
@expr = expr_val
|
|
13
|
+
@stack = stack
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def evaluate
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
@expr
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class ValueExpression < Expression
|
|
25
|
+
def evaluate
|
|
26
|
+
@expr
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class UndefinedValue < ValueExpression
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class StringValue < ValueExpression
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class BooleanValue < ValueExpression
|
|
37
|
+
def evaluate
|
|
38
|
+
@expr.to_boolean
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class FloatValue < ValueExpression
|
|
43
|
+
def evaluate
|
|
44
|
+
@expr
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class FunctionExpression < Expression
|
|
49
|
+
extend ExprFunctionDefinition
|
|
50
|
+
|
|
51
|
+
attr :evaluators
|
|
52
|
+
|
|
53
|
+
unary_bool_func :not, '!'
|
|
54
|
+
|
|
55
|
+
bool_func :and, '&'
|
|
56
|
+
bool_func :or, '|'
|
|
57
|
+
|
|
58
|
+
comp_func :eq, '=='
|
|
59
|
+
comp_func :ne, '!='
|
|
60
|
+
comp_func :lt, '<'
|
|
61
|
+
comp_func :lte, '<='
|
|
62
|
+
comp_func :gt, '>'
|
|
63
|
+
comp_func :gte, '>='
|
|
64
|
+
|
|
65
|
+
def initialize(expr_val, stack)
|
|
66
|
+
super(expr_val, stack)
|
|
67
|
+
|
|
68
|
+
@functions = ['isUndefined', 'now']
|
|
69
|
+
@functions << self.class.instance_variable_get('@func_list')
|
|
70
|
+
@functions.flatten!
|
|
71
|
+
|
|
72
|
+
prepare_evaluators()
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def evaluate
|
|
76
|
+
ev = @evaluators[@expr]
|
|
77
|
+
return ev.call unless ev.nil?
|
|
78
|
+
|
|
79
|
+
#todo log invalid function
|
|
80
|
+
@stack.push BooleanValue.new(false, @stack) if ev.nil?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def prepare_evaluators()
|
|
86
|
+
@evaluators = @functions.map{|f| [f, ->{ self.send("evaluate_#{f}")}]}.to_h
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def evaluate_isUndefined
|
|
90
|
+
a = @stack.pop
|
|
91
|
+
@stack.push BooleanValue.new(a.evaluate == :undefined, @stack)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def evaluate_now
|
|
95
|
+
Time.now.to_f.round(3)*1000
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
## RubyInterpreter ##
|
|
101
|
+
#
|
|
102
|
+
# goal: Interpret expression in forward polish notation with some functions
|
|
103
|
+
#
|
|
104
|
+
class RubyInterpreter
|
|
105
|
+
extend FunctionDefinition
|
|
106
|
+
|
|
107
|
+
attr_reader :func_stack, :operands_stack
|
|
108
|
+
attr_reader :expr_stack
|
|
109
|
+
|
|
110
|
+
#operators
|
|
111
|
+
unary_bool_func :not, '!'
|
|
112
|
+
|
|
113
|
+
bool_func :and, '&'
|
|
114
|
+
bool_func :or, '|'
|
|
115
|
+
|
|
116
|
+
comp_func :eq, '=='
|
|
117
|
+
comp_func :ne, '!='
|
|
118
|
+
|
|
119
|
+
comp_func :lt, '<'
|
|
120
|
+
comp_func :lte, '<='
|
|
121
|
+
comp_func :gt, '>'
|
|
122
|
+
comp_func :gte, '>='
|
|
123
|
+
|
|
124
|
+
def initialize
|
|
125
|
+
@func_stack = Stack.new
|
|
126
|
+
@operands_stack = Stack.new
|
|
127
|
+
@expr_stack = Stack.new
|
|
128
|
+
|
|
129
|
+
@func_list ||= []
|
|
130
|
+
@func_list << self.class.instance_variable_get('@func_list')
|
|
131
|
+
@func_list << ['isUndefined', 'now']
|
|
132
|
+
@func_list.flatten!
|
|
133
|
+
|
|
134
|
+
@funcs_re ||= Regexp.new(@func_list.join('|') )
|
|
135
|
+
end
|
|
136
|
+
#todo make unary/2ry functions by define_method (dry code)
|
|
137
|
+
|
|
138
|
+
def prepare_expr_stack(tokens)
|
|
139
|
+
is_string_token = false
|
|
140
|
+
string_token = ''
|
|
141
|
+
|
|
142
|
+
tokens.each do |tkn, i|
|
|
143
|
+
|
|
144
|
+
if is_string_token && tkn != '"'
|
|
145
|
+
string_token += tkn
|
|
146
|
+
next
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
case tkn
|
|
150
|
+
when 'undefined'
|
|
151
|
+
@expr_stack.push( UndefinedValue.new(tkn.to_sym, @expr_stack) )
|
|
152
|
+
when '"'
|
|
153
|
+
if( is_string_token ) #todo check pair "
|
|
154
|
+
is_string_token = false
|
|
155
|
+
@expr_stack.push StringValue.new(string_token, @expr_stack)
|
|
156
|
+
string_token = ''
|
|
157
|
+
else
|
|
158
|
+
is_string_token = true
|
|
159
|
+
end
|
|
160
|
+
when ',' , '(', ')', ' '
|
|
161
|
+
#do nothing
|
|
162
|
+
when @funcs_re
|
|
163
|
+
@expr_stack.push( FunctionExpression.new( tkn , @expr_stack) )
|
|
164
|
+
when 'true', 'false'
|
|
165
|
+
@expr_stack.push BooleanValue.new(tkn, @expr_stack)
|
|
166
|
+
else
|
|
167
|
+
fval, is_float = tkn.to_float
|
|
168
|
+
if(is_float)
|
|
169
|
+
@expr_stack.push FloatValue.new(fval, @expr_stack)
|
|
170
|
+
else
|
|
171
|
+
#todo show error message 'unknown token'
|
|
172
|
+
return 'false'
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def evaluate_expr_stack()
|
|
179
|
+
@func_evaluators = @func_list.map{|f| [f, ->(){ self.send("evaluate_func_#{f}")}]}.to_h
|
|
180
|
+
|
|
181
|
+
value = false
|
|
182
|
+
|
|
183
|
+
while !@expr_stack.empty? do
|
|
184
|
+
expr = @expr_stack.pop
|
|
185
|
+
value = expr.evaluate unless expr.nil?
|
|
186
|
+
|
|
187
|
+
return false if expr.nil? #todo show error message
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
value
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def evaluateExpression2(expr)
|
|
195
|
+
@expr_stack.clear
|
|
196
|
+
|
|
197
|
+
tokens = expr.scan(/\d+\.?\d*|\s+|,|\(|"|\)|\w+|\W+/)
|
|
198
|
+
|
|
199
|
+
prepare_expr_stack(tokens)
|
|
200
|
+
expr_stack.invert()
|
|
201
|
+
evaluate_expr_stack()
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Evaluate expression
|
|
205
|
+
#
|
|
206
|
+
# info:
|
|
207
|
+
# 1. Language is polish forward notation with custom functions
|
|
208
|
+
# 2. Function list:
|
|
209
|
+
# a. and(a,b)
|
|
210
|
+
#
|
|
211
|
+
def evaluateExpression(expr)
|
|
212
|
+
@func_stack.clear
|
|
213
|
+
@operands_stack.clear
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
tokens = expr.scan(/\d+\.?\d*|\s+|,|\(|"|\)|\w+|\W+/)
|
|
217
|
+
|
|
218
|
+
is_string_token = false
|
|
219
|
+
string_token = ''
|
|
220
|
+
|
|
221
|
+
@funcs_re ||= Regexp.new(@func_list.join('|') )
|
|
222
|
+
|
|
223
|
+
#prepare stack
|
|
224
|
+
tokens.each do |tkn, i|
|
|
225
|
+
if is_string_token && tkn != '"'
|
|
226
|
+
string_token += tkn
|
|
227
|
+
next
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
case tkn
|
|
231
|
+
when 'undefined'
|
|
232
|
+
@operands_stack.push( tkn.to_sym )
|
|
233
|
+
when '"'
|
|
234
|
+
if( is_string_token ) #todo check pair "
|
|
235
|
+
is_string_token = false
|
|
236
|
+
@operands_stack.push string_token
|
|
237
|
+
string_token = ''
|
|
238
|
+
else
|
|
239
|
+
is_string_token = true
|
|
240
|
+
end
|
|
241
|
+
when ',' , '(', ')', ' '
|
|
242
|
+
#do nothing
|
|
243
|
+
when @funcs_re
|
|
244
|
+
@func_stack.push( FunctionToken.new( tkn, @operands_stack.size ) )
|
|
245
|
+
when 'true', 'false'
|
|
246
|
+
@operands_stack.push tkn
|
|
247
|
+
else
|
|
248
|
+
fval, is_float = tkn.to_float
|
|
249
|
+
if(is_float)
|
|
250
|
+
@operands_stack.push(fval)
|
|
251
|
+
else
|
|
252
|
+
#todo show error message 'unknown token'
|
|
253
|
+
return 'false'
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
#evaluate stack
|
|
259
|
+
@func_evals ||= prepare_func_evaluators()
|
|
260
|
+
|
|
261
|
+
while !@func_stack.empty? do
|
|
262
|
+
|
|
263
|
+
token = @func_stack.pop
|
|
264
|
+
|
|
265
|
+
feval = @func_evals[token.name]
|
|
266
|
+
|
|
267
|
+
feval.call(token.stack_index) unless feval.nil?
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
@operands_stack.pop
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
private
|
|
274
|
+
|
|
275
|
+
def prepare_func_evaluators()
|
|
276
|
+
# make hash with functors: 'or' => ->(stack_index){ self.send('evaluateOr', stack_index) }
|
|
277
|
+
return @func_list.map{|f| [f, ->(stack_index){ self.send("evaluate#{f[0].upcase}#{f[1..-1]}", stack_index) }]}.to_h
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
#evaluators
|
|
281
|
+
|
|
282
|
+
def evaluateIsUndefined(stack_index)
|
|
283
|
+
a = @operands_stack.pop
|
|
284
|
+
@operands_stack.push (a == :undefined).to_s
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def evaluateNow(stack_index)
|
|
288
|
+
@operands_stack.insert Time.now().tv_sec.to_f, stack_index
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class Stack
|
|
2
|
+
|
|
3
|
+
class EmptyError < StandardError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@elements = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def push(value)
|
|
11
|
+
@elements.push value
|
|
12
|
+
value
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pop
|
|
16
|
+
raise EmptyError.new('Stack is empty') if empty?
|
|
17
|
+
|
|
18
|
+
@elements.pop
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def poke(value, index)
|
|
22
|
+
@elements[index] = value
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def insert(value, index)
|
|
26
|
+
@elements.insert(index, value)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def clear
|
|
30
|
+
@elements.clear
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def empty?
|
|
34
|
+
@elements.size == 0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_s
|
|
38
|
+
@elements.join(',')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def size
|
|
42
|
+
@elements.size
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def invert
|
|
46
|
+
@elements.reverse!
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe 'RubyInterpreter' do
|
|
4
|
+
let(:parser){ RubyInterpreter.new }
|
|
5
|
+
|
|
6
|
+
def check_parser_clean
|
|
7
|
+
expect(parser.operands_stack.empty?).to eq(true)
|
|
8
|
+
expect(parser.func_stack.empty?).to eq(true)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def check_parsing(expr, result)
|
|
12
|
+
expect(parser.evaluateExpression(expr)).to eq(result)
|
|
13
|
+
check_parser_clean
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def check_parser_clean2
|
|
17
|
+
expect(parser.expr_stack.empty?).to eq(true)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def check_parsing2(expr, result)
|
|
21
|
+
expect(parser.evaluateExpression2(expr)).to eq(result)
|
|
22
|
+
check_parser_clean2
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'and function' do
|
|
26
|
+
it 'checks and(true,true) == true' do
|
|
27
|
+
check_parsing2('and(true, true)', true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'checks and(true,false) == false' do
|
|
31
|
+
check_parsing2('and(true, false)', false)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'checks and(false,true) == false' do
|
|
35
|
+
check_parsing2('and(false, true)', false)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'checks and(false,false) == false' do
|
|
39
|
+
check_parsing2('and(false, false)', false)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'or function' do
|
|
44
|
+
it 'checks or(true, true) == true' do
|
|
45
|
+
check_parsing2('or(true, true)', true)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'checks or(true, false) == true' do
|
|
49
|
+
check_parsing2('or(true, false)', true)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'checks or(false, true) == true' do
|
|
53
|
+
check_parsing2('or(false, true)', true)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'checks or(false, false) == false' do
|
|
57
|
+
check_parsing2('or(false, false)', false)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context 'not function' do
|
|
62
|
+
it 'checks not(false) == true' do
|
|
63
|
+
check_parsing2('not(false)', true)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'checks not(true) == false' do
|
|
67
|
+
check_parsing2('not(true)', false)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'checks not(undefined) == false' do
|
|
71
|
+
check_parsing2('not(undefined)', true)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context 'eq function' do
|
|
76
|
+
it 'checks eq("la la", "la la")) == true' do
|
|
77
|
+
check_parsing2('eq("la la", "la la")', true);
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'checks eq("la la", "la,la")) == false' do
|
|
81
|
+
check_parsing2('eq("la la", "la,la")', false);
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'checks eq("lala", "lala") == true' do
|
|
85
|
+
check_parsing2('eq("lala", "lala")', true)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'checks eq(undefined, undefined) == true' do
|
|
89
|
+
check_parsing2('eq(undefined, undefined)', true)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'lt function' do
|
|
94
|
+
it 'checks lt(500,100) == false' do
|
|
95
|
+
check_parsing2('lt(500, 100)', false)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'checks lt(500,500) == false' do
|
|
99
|
+
check_parsing2('lt(500, 500)', false)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'checks lt(500,500.54) == true' do
|
|
103
|
+
check_parsing2('lt(500, 500.54)', true)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'lte function' do
|
|
108
|
+
it 'checks lte(500, 500) == true' do
|
|
109
|
+
check_parsing2('lte(500, 500)', true)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'gt function' do
|
|
114
|
+
it 'checks gt(500, 100) == true' do
|
|
115
|
+
check_parsing2('gt(500,100)',true)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'checks gt(500, 500) == false' do
|
|
119
|
+
check_parsing2('gt(500,500)',false)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'checks gt(500.54, 500) == true' do
|
|
123
|
+
check_parsing2('gt(500.54,500)',true)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context 'gte function' do
|
|
128
|
+
it 'checks gte(500, 500) == true' do
|
|
129
|
+
check_parsing2('gte(500,500)',true)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'checks gte("500", 500) == false' do
|
|
133
|
+
check_parsing2('gte("500",500)',false)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context 'isUndefined function' do
|
|
138
|
+
it 'checks isUndefined(undefined) == true' do
|
|
139
|
+
check_parsing2('isUndefined(undefined)', true)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'checks isUndefined("undefined") == false' do
|
|
143
|
+
check_parsing2('isUndefined("undefined")', false)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'checks isUndefined(123123) == false' do
|
|
147
|
+
check_parsing2('isUndefined(123123)', false)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
context 'now() function' do
|
|
152
|
+
it 'checks gte(now(), now()) == true' do
|
|
153
|
+
check_parsing2('gte(now(), now())', true)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'checks gte(now(), 2458.123) == true' do
|
|
157
|
+
check_parsing2('gte(now(), 2458.123)', true)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
context 'complex checks' do
|
|
162
|
+
it 'checks and(true, or(true, true)) == true' do
|
|
163
|
+
check_parsing2('and(true, or(true, true))', true);
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'checks and(true, or(false, true)) == true' do
|
|
167
|
+
check_parsing2('and(true, or(false, true))', true);
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'checks and(true, or(false, false)) == false' do
|
|
171
|
+
check_parsing2('and(true, or(false, false))', false);
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'checks not(and(false, or(false, true))) == true' do
|
|
175
|
+
check_parsing2('not(and(false, or(false, true)))', true);
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'checks ne(100.123, 100.321) == true' do
|
|
179
|
+
check_parsing2('ne(100.123, 100.321)', true)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'checks not(eq(undefined, undefined)) == false' do
|
|
183
|
+
check_parsing('not(eq(undefined, undefined))', 'false')
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'checks not(eq(not(undefined), not(undefined))) == true' do
|
|
187
|
+
check_parsing2('not(eq(not(undefined), not(undefined)))', true )
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
context 'error checking' do
|
|
193
|
+
it 'checks NOT_AN_OPERATOR(500, 500) == false' do
|
|
194
|
+
check_parsing('NOT_AN_OPERATOR(500,500)', 'false')
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it 'checks JUSTAWORD(500, 500) == false' do
|
|
198
|
+
check_parsing('JUSTAWORD(500,500)', 'false')
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
#todo check non-matched pairs
|
|
203
|
+
end
|