rox-rollout 4.7.1 → 5.0.2

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.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +34 -13
  3. data/.editorconfig +12 -0
  4. data/.github/workflows/ruby.yml +20 -0
  5. data/.rubocop.yml +17 -0
  6. data/Gemfile +2 -2
  7. data/README.md +32 -0
  8. data/Rakefile +12 -9
  9. data/bin/console +3 -4
  10. data/e2e/container.rb +11 -14
  11. data/e2e/custom_props.rb +9 -9
  12. data/e2e/rox_e2e_test.rb +17 -19
  13. data/e2e/test_vars.rb +3 -6
  14. data/e2e-server/run_server.sh +12 -0
  15. data/e2e-server/server.rb +158 -0
  16. data/example/local.rb +40 -0
  17. data/lib/rox/core/analytics.rb +18 -0
  18. data/lib/rox/core/client/buid.rb +8 -8
  19. data/lib/rox/core/client/device_properties.rb +7 -1
  20. data/lib/rox/core/client/dynamic_api.rb +53 -15
  21. data/lib/rox/core/client/internal_flags.rb +14 -2
  22. data/lib/rox/core/client/sdk_settings.rb +1 -1
  23. data/lib/rox/core/configuration/configuration.rb +1 -1
  24. data/lib/rox/core/configuration/configuration_fetched_args.rb +2 -2
  25. data/lib/rox/core/configuration/configuration_fetched_invoker.rb +8 -3
  26. data/lib/rox/core/configuration/configuration_parser.rb +38 -37
  27. data/lib/rox/core/configuration/fetcher_error.rb +1 -1
  28. data/lib/rox/core/configuration/fetcher_status.rb +1 -1
  29. data/lib/rox/core/configuration/models/experiment_model.rb +1 -1
  30. data/lib/rox/core/configuration/models/target_group_model.rb +1 -1
  31. data/lib/rox/core/consts/build.rb +2 -2
  32. data/lib/rox/core/consts/environment.rb +10 -8
  33. data/lib/rox/core/consts/property_type.rb +16 -17
  34. data/lib/rox/core/context/merged_context.rb +2 -1
  35. data/lib/rox/core/core.rb +89 -38
  36. data/lib/rox/core/entities/default_flag_values.rb +10 -0
  37. data/lib/rox/core/entities/flag.rb +22 -7
  38. data/lib/rox/core/entities/flag_setter.rb +6 -6
  39. data/lib/rox/core/entities/rox_double.rb +11 -0
  40. data/lib/rox/core/entities/rox_int.rb +11 -0
  41. data/lib/rox/core/entities/{variant.rb → rox_string.rb} +20 -13
  42. data/lib/rox/core/error_handling/exception_trigger.rb +10 -0
  43. data/lib/rox/core/error_handling/userspace_handler_exception.rb +12 -0
  44. data/lib/rox/core/error_handling/userspace_unhandled_error_invoker.rb +41 -0
  45. data/lib/rox/core/impression/impression_args.rb +2 -2
  46. data/lib/rox/core/impression/impression_invoker.rb +41 -7
  47. data/lib/rox/core/impression/models/experiment.rb +1 -1
  48. data/lib/rox/core/impression/models/reporting_value.rb +10 -2
  49. data/lib/rox/core/logging/logging.rb +3 -3
  50. data/lib/rox/core/logging/no_op_logger.rb +1 -1
  51. data/lib/rox/core/network/configuration_fetcher.rb +2 -2
  52. data/lib/rox/core/network/configuration_fetcher_roxy.rb +2 -2
  53. data/lib/rox/core/network/configuration_fetcher_self_managed.rb +30 -0
  54. data/lib/rox/core/network/configuration_source.rb +1 -1
  55. data/lib/rox/core/network/request.rb +1 -1
  56. data/lib/rox/core/network/request_configuration_builder.rb +5 -5
  57. data/lib/rox/core/network/request_data.rb +1 -1
  58. data/lib/rox/core/network/response.rb +6 -8
  59. data/lib/rox/core/network/state_sender.rb +63 -19
  60. data/lib/rox/core/notifications/notification_listener.rb +4 -4
  61. data/lib/rox/core/properties/custom_property.rb +1 -1
  62. data/lib/rox/core/properties/custom_property_type.rb +1 -1
  63. data/lib/rox/core/properties/device_property.rb +2 -2
  64. data/lib/rox/core/properties/property_factory.rb +132 -0
  65. data/lib/rox/core/register/registerer.rb +13 -12
  66. data/lib/rox/core/reporting/error_reporter.rb +14 -13
  67. data/lib/rox/core/repositories/experiment_repository.rb +2 -4
  68. data/lib/rox/core/repositories/flag_repository.rb +7 -7
  69. data/lib/rox/core/repositories/roxx/experiments_extensions.rb +8 -8
  70. data/lib/rox/core/repositories/roxx/properties_extensions.rb +32 -7
  71. data/lib/rox/core/repositories/target_group_repository.rb +2 -4
  72. data/lib/rox/core/roxx/evaluation_result.rb +2 -0
  73. data/lib/rox/core/roxx/node.rb +1 -1
  74. data/lib/rox/core/roxx/parser.rb +35 -21
  75. data/lib/rox/core/roxx/regular_expression_extensions.rb +6 -3
  76. data/lib/rox/core/roxx/string_tokenizer.rb +3 -1
  77. data/lib/rox/core/roxx/symbols.rb +1 -1
  78. data/lib/rox/core/roxx/token_type.rb +1 -1
  79. data/lib/rox/core/roxx/tokenized_expression.rb +16 -12
  80. data/lib/rox/core/roxx/value_compare_extensions.rb +49 -29
  81. data/lib/rox/core/security/signature_verifier.rb +3 -3
  82. data/lib/rox/core/security/signature_verifier_mock.rb +12 -0
  83. data/lib/rox/core/utils/type_utils.rb +1 -1
  84. data/lib/rox/server/client/server_properties.rb +1 -1
  85. data/lib/rox/server/flags/normalize_flag_type.rb +25 -0
  86. data/lib/rox/server/flags/rox_double.rb +8 -0
  87. data/lib/rox/server/flags/rox_flag.rb +1 -1
  88. data/lib/rox/server/flags/rox_int.rb +8 -0
  89. data/lib/rox/server/flags/rox_string.rb +8 -0
  90. data/lib/rox/server/flags/server_entities_provider.rb +14 -4
  91. data/lib/rox/server/logging/server_logger.rb +2 -2
  92. data/lib/rox/server/rox_options.rb +39 -8
  93. data/lib/rox/server/rox_server.rb +84 -59
  94. data/lib/rox/version.rb +1 -1
  95. data/rox.gemspec +11 -9
  96. metadata +62 -33
  97. data/CODEOWNERS +0 -1
  98. data/README_DEVELOP.md +0 -25
  99. data/_archive/.document +0 -5
  100. data/_archive/.rspec +0 -1
  101. data/_archive/Gemfile +0 -15
  102. data/_archive/Gemfile.lock +0 -87
  103. data/_archive/README.md +0 -32
  104. data/_archive/README.rdoc +0 -19
  105. data/_archive/Rakefile +0 -50
  106. data/_archive/lib/expr_function_definition.rb +0 -52
  107. data/_archive/lib/function_definition.rb +0 -48
  108. data/_archive/lib/function_token.rb +0 -12
  109. data/_archive/lib/object_extends.rb +0 -12
  110. data/_archive/lib/ruby_interpreter.rb +0 -292
  111. data/_archive/lib/stack.rb +0 -48
  112. data/_archive/lib/string_extends.rb +0 -14
  113. data/_archive/spec/ruby_interpreter_spec.rb +0 -203
  114. data/_archive/spec/spec_helper.rb +0 -30
  115. data/_archive/spec/stack_spec.rb +0 -77
  116. data/lib/rox/server/flags/rox_variant.rb +0 -8
@@ -1,26 +1,51 @@
1
1
  require 'rox/core/roxx/token_type'
2
+ require 'rox/core/error_handling/exception_trigger'
3
+ require 'rox/core/error_handling/userspace_handler_exception'
2
4
 
3
5
  module Rox
4
6
  module Core
5
7
  class PropertiesExtensions
6
- def initialize(parser, properties_repository)
8
+ def initialize(parser, properties_repository, dynamic_property_rule_handler = nil)
7
9
  @parser = parser
8
10
  @properties_repository = properties_repository
11
+ @dynamic_property_rule_handler = dynamic_property_rule_handler
9
12
  end
10
13
 
11
14
  def extend
12
- @parser.add_operator('property') do |parser, stack, context|
15
+ @parser.add_operator('property') do |_parser, stack, context|
13
16
  prop_name = stack.pop.to_s
14
17
  property = @properties_repository.custom_property(prop_name)
18
+ value = get_value(prop_name, property, context)
15
19
 
16
- if property.nil?
17
- stack.push(TokenType::UNDEFINED)
20
+ stack.push(value.nil? ? TokenType::UNDEFINED : value)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def get_value(prop_name, property, context)
27
+ if property.nil?
28
+ if @dynamic_property_rule_handler.nil?
29
+ TokenType::UNDEFINED
18
30
  else
19
- value = property.value(context)
20
- stack.push(value.nil? ? TokenType::UNDEFINED : value)
31
+ get_value_from_dynamic_property_rule_handler(prop_name, context)
21
32
  end
33
+ else
34
+ get_value_from_property(property, context)
22
35
  end
23
36
  end
37
+
38
+ def get_value_from_dynamic_property_rule_handler(prop_name, context)
39
+ @dynamic_property_rule_handler.call(prop_name, context)
40
+ rescue StandardError => e
41
+ raise Rox::Core::UserspaceHandlerException, handler, ExceptionTrigger::DYNAMIC_PROPERTIES_RULE, e
42
+ end
43
+
44
+ def get_value_from_property(property, context)
45
+ property.value(context)
46
+ rescue StandardError => e
47
+ raise Rox::Core::UserspaceHandlerException, handler, ExceptionTrigger::CUSTOM_PROPERTY_GENERATOR, e
48
+ end
24
49
  end
25
50
  end
26
- end
51
+ end
@@ -5,13 +5,11 @@ module Rox
5
5
  @target_groups = []
6
6
  end
7
7
 
8
- def target_groups=(target_groups)
9
- @target_groups = target_groups
10
- end
8
+ attr_writer :target_groups
11
9
 
12
10
  def target_group(id)
13
11
  @target_groups.detect { |g| g.id == id }
14
12
  end
15
13
  end
16
14
  end
17
- end
15
+ end
@@ -13,6 +13,7 @@ module Rox
13
13
  def bool_value
14
14
  return false if value.nil?
15
15
  return value if Utils.boolean?(value)
16
+
16
17
  nil
17
18
  end
18
19
 
@@ -21,6 +22,7 @@ module Rox
21
22
  return nil if value.nil?
22
23
  return Flag::FLAG_TRUE_VALUE if value
23
24
  return Flag::FLAG_FALSE_VALUE unless value
25
+
24
26
  nil
25
27
  end
26
28
  end
@@ -8,4 +8,4 @@ module Rox
8
8
  UNKNOWN = 'Unknown'.freeze
9
9
  end
10
10
  end
11
- end
11
+ end
@@ -7,19 +7,24 @@ require 'rox/core/roxx/regular_expression_extensions'
7
7
  require 'rox/core/roxx/tokenized_expression'
8
8
  require 'rox/core/utils/type_utils'
9
9
  require 'rox/core/logging/logging'
10
+ require 'rox/core/error_handling/userspace_handler_exception'
10
11
 
11
12
  module Rox
12
13
  module Core
13
14
  class Parser
14
- def initialize
15
+ attr_accessor :global_context
16
+
17
+ def initialize(user_unhandled_error_invoker)
15
18
  @operators_map = {}
19
+ @global_context = nil
16
20
  set_basic_operators
21
+ @user_unhandled_error_invoker = user_unhandled_error_invoker
17
22
  ValueCompareExtensions.new(self).extend
18
23
  RegularExpressionExtensions.new(self).extend
19
24
  end
20
25
 
21
- def add_operator(oper, &block)
22
- @operators_map[oper] = block
26
+ def add_operator(operator, &block)
27
+ @operators_map[operator] = block
23
28
  end
24
29
 
25
30
  def evaluate_expression(expression, context = nil)
@@ -29,11 +34,12 @@ module Rox
29
34
  begin
30
35
  reverse_tokens.each do |token|
31
36
  node = token
32
- if node.type == NodeTypes::RAND
37
+ case node.type
38
+ when NodeTypes::RAND
33
39
  stack.push(node.value)
34
- elsif node.type == NodeTypes::RATOR
40
+ when NodeTypes::RATOR
35
41
  handler = @operators_map[node.value]
36
- handler.call(self, stack, context) unless handler.nil?
42
+ handler&.call(self, stack, context)
37
43
  else
38
44
  return EvaluationResult.new(nil)
39
45
  end
@@ -43,14 +49,18 @@ module Rox
43
49
  result = nil if result == TokenType::UNDEFINED
44
50
 
45
51
  EvaluationResult.new(result)
46
- rescue StandardError => ex
47
- Logging.logger.warn("Roxx Exception: Failed evaluate expression: #{ex}")
52
+ rescue Rox::Core::UserspaceHandlerException => e
53
+ @user_unhandled_error_invoker.invoke(e.exception_source, e.exception_trigger, e.exception)
54
+ Logging.logger.warn("Roxx Exception: Failed evaluate expression, user unhandled expression: #{e}")
55
+ EvaluationResult.new(nil)
56
+ rescue StandardError => e
57
+ Logging.logger.warn("Roxx Exception: Failed evaluate expression: #{e}")
48
58
  EvaluationResult.new(nil)
49
59
  end
50
60
  end
51
61
 
52
62
  def set_basic_operators
53
- add_operator('isUndefined') do |parser, stack, context|
63
+ add_operator('isUndefined') do |_parser, stack, _context|
54
64
  op1 = stack.pop
55
65
  if op1.is_a?(TokenType)
56
66
  stack.push(op1 == TokenType::UNDEFINED)
@@ -59,29 +69,31 @@ module Rox
59
69
  end
60
70
  end
61
71
 
62
- add_operator('now') do |parser, stack, context|
72
+ add_operator('now') do |_parser, stack, _context|
63
73
  stack.push((Time.now.to_f * 1000).to_i)
64
74
  end
65
75
 
66
- add_operator('and') do |parser, stack, context|
76
+ add_operator('and') do |_parser, stack, _context|
67
77
  op1 = stack.pop
68
78
  op2 = stack.pop
69
79
  op1 = false if op1 == TokenType::UNDEFINED
70
80
  op2 = false if op2 == TokenType::UNDEFINED
71
81
  raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) && Utils.boolean?(op2)
82
+
72
83
  stack.push(op1 && op2)
73
84
  end
74
85
 
75
- add_operator('or') do |parser, stack, context|
86
+ add_operator('or') do |_parser, stack, _context|
76
87
  op1 = stack.pop
77
88
  op2 = stack.pop
78
89
  op1 = false if op1 == TokenType::UNDEFINED
79
90
  op2 = false if op2 == TokenType::UNDEFINED
80
91
  raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) && Utils.boolean?(op2)
92
+
81
93
  stack.push(op1 || op2)
82
94
  end
83
95
 
84
- add_operator('ne') do |parser, stack, context|
96
+ add_operator('ne') do |_parser, stack, _context|
85
97
  op1 = stack.pop
86
98
  op2 = stack.pop
87
99
  op1 = false if op1 == TokenType::UNDEFINED
@@ -89,7 +101,7 @@ module Rox
89
101
  stack.push(op1 != op2)
90
102
  end
91
103
 
92
- add_operator('eq') do |parser, stack, context|
104
+ add_operator('eq') do |_parser, stack, _context|
93
105
  op1 = stack.pop
94
106
  op2 = stack.pop
95
107
  op1 = false if op1 == TokenType::UNDEFINED
@@ -97,18 +109,20 @@ module Rox
97
109
  stack.push(op1 == op2)
98
110
  end
99
111
 
100
- add_operator('not') do |parser, stack, context|
112
+ add_operator('not') do |_parser, stack, _context|
101
113
  op1 = stack.pop
102
114
  op1 = false if op1 == TokenType::UNDEFINED
103
115
  raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1)
116
+
104
117
  stack.push(!op1)
105
118
  end
106
119
 
107
- add_operator('ifThen') do |parser, stack, context|
120
+ add_operator('ifThen') do |_parser, stack, _context|
108
121
  condition_expression = stack.pop
109
122
  true_expression = stack.pop
110
123
  false_expression = stack.pop
111
124
  raise ArgumentError, 'should be boolean' unless Utils.boolean?(condition_expression)
125
+
112
126
  if condition_expression
113
127
  stack.push(true_expression)
114
128
  else
@@ -116,7 +130,7 @@ module Rox
116
130
  end
117
131
  end
118
132
 
119
- add_operator('inArray') do |parser, stack, context|
133
+ add_operator('inArray') do |_parser, stack, _context|
120
134
  op1 = stack.pop
121
135
  op2 = stack.pop
122
136
  if op2.is_a?(Array)
@@ -126,7 +140,7 @@ module Rox
126
140
  end
127
141
  end
128
142
 
129
- add_operator('md5') do |parser, stack, context|
143
+ add_operator('md5') do |_parser, stack, _context|
130
144
  op1 = stack.pop
131
145
  if op1.is_a?(String)
132
146
  stack.push(Digest::MD5.hexdigest(op1))
@@ -135,7 +149,7 @@ module Rox
135
149
  end
136
150
  end
137
151
 
138
- add_operator('concat') do |parser, stack, context|
152
+ add_operator('concat') do |_parser, stack, _context|
139
153
  op1 = stack.pop
140
154
  op2 = stack.pop
141
155
  if op1.is_a?(String) && op2.is_a?(String)
@@ -145,7 +159,7 @@ module Rox
145
159
  end
146
160
  end
147
161
 
148
- add_operator('b64d') do |parser, stack, context|
162
+ add_operator('b64d') do |_parser, stack, _context|
149
163
  op1 = stack.pop
150
164
  if op1.is_a?(String)
151
165
  decoded = Base64.decode64(op1)
@@ -158,4 +172,4 @@ module Rox
158
172
  end
159
173
  end
160
174
  end
161
- end
175
+ end
@@ -6,11 +6,14 @@ module Rox
6
6
  end
7
7
 
8
8
  def extend
9
- @parser.add_operator('match') do |parser, stack, context|
9
+ @parser.add_operator('match') do |_parser, stack, _context|
10
10
  text = stack.pop
11
11
  pattern = stack.pop
12
12
  flags = stack.pop
13
- raise ArgumentError, 'should be string' unless text.is_a?(String) && pattern.is_a?(String) && flags.is_a?(String)
13
+ unless text.is_a?(String) && pattern.is_a?(String) && flags.is_a?(String)
14
+ raise ArgumentError,
15
+ 'should be string'
16
+ end
14
17
 
15
18
  options = 0
16
19
  flags.each_char do |flag|
@@ -30,4 +33,4 @@ module Rox
30
33
  end
31
34
  end
32
35
  end
33
- end
36
+ end
@@ -17,6 +17,7 @@ module Rox
17
17
  while !@ret_delims && position < @max_position
18
18
  c = @text[position]
19
19
  break unless delimiter?(c)
20
+
20
21
  position += 1
21
22
  end
22
23
  position
@@ -27,6 +28,7 @@ module Rox
27
28
  while position < @max_position
28
29
  c = @text[position]
29
30
  break if delimiter?(c)
31
+
30
32
  position += 1
31
33
  end
32
34
 
@@ -65,4 +67,4 @@ module Rox
65
67
  end
66
68
  end
67
69
  end
68
- end
70
+ end
@@ -11,4 +11,4 @@ module Rox
11
11
  ROXX_UNDEFINED_TYPE = 'UndefinedType'.freeze
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -27,4 +27,4 @@ module Rox
27
27
  UNDEFINED = TokenType.new(Symbols::ROXX_UNDEFINED_TYPE, Symbols::ROXX_UNDEFINED)
28
28
  end
29
29
  end
30
- end
30
+ end
@@ -49,7 +49,8 @@ module Rox
49
49
  @dict_key = nil
50
50
 
51
51
  delimiters_to_use = TokenizedExpression::TOKEN_DELIMITERS
52
- normalized_expression = expression.gsub(TokenizedExpression::ESCAPED_QUOTE, TokenizedExpression::ESCAPED_QUOTE_PLACEHOLDER)
52
+ normalized_expression = expression.gsub(TokenizedExpression::ESCAPED_QUOTE,
53
+ TokenizedExpression::ESCAPED_QUOTE_PLACEHOLDER)
53
54
  tokenizer = StringTokenizer.new(normalized_expression, delimiters_to_use, true)
54
55
 
55
56
  token = nil
@@ -71,14 +72,16 @@ module Rox
71
72
  @array_accumulator = nil
72
73
  push_node(node_from_array(array_result))
73
74
  elsif token == TokenizedExpression::STRING_DELIMITER
74
- push_node(node_from_token(Symbols::ROXX_EMPTY_STRING)) if prev_token == TokenizedExpression::STRING_DELIMITER
75
- delimiters_to_use = in_string ? TokenizedExpression::TOKEN_DELIMITERS : TokenizedExpression::STRING_DELIMITER
76
- else
77
- if delimiters_to_use == TokenizedExpression::STRING_DELIMITER
78
- push_node(Node.new(NodeTypes::RAND, token.gsub(TokenizedExpression::ESCAPED_QUOTE_PLACEHOLDER, TokenizedExpression::ESCAPED_QUOTE)))
79
- elsif !TokenizedExpression::TOKEN_DELIMITERS.include?(token) && token != TokenizedExpression::PRE_POST_STRING_CHAR
80
- push_node(node_from_token(token))
75
+ if prev_token == TokenizedExpression::STRING_DELIMITER
76
+ push_node(node_from_token(Symbols::ROXX_EMPTY_STRING))
81
77
  end
78
+ delimiters_to_use = in_string ? TokenizedExpression::TOKEN_DELIMITERS : TokenizedExpression::STRING_DELIMITER
79
+ elsif delimiters_to_use == TokenizedExpression::STRING_DELIMITER
80
+ push_node(Node.new(NodeTypes::RAND,
81
+ token.gsub(TokenizedExpression::ESCAPED_QUOTE_PLACEHOLDER,
82
+ TokenizedExpression::ESCAPED_QUOTE)))
83
+ elsif !TokenizedExpression::TOKEN_DELIMITERS.include?(token) && token != TokenizedExpression::PRE_POST_STRING_CHAR
84
+ push_node(node_from_token(token))
82
85
  end
83
86
  end
84
87
 
@@ -100,15 +103,16 @@ module Rox
100
103
  return Node.new(NodeTypes::RAND, TokenType::UNDEFINED) if token == Symbols::ROXX_UNDEFINED
101
104
 
102
105
  token_type = TokenType.from_token(token)
103
- return Node.new(NodeTypes::RAND, token[1...-1]) if token_type == TokenType::STRING
106
+ return Node.new(NodeTypes::RAND, token[1...-2]) if token_type == TokenType::STRING
107
+
104
108
  if token_type == TokenType::NUMBER
105
109
  begin
106
110
  return Node.new(NodeTypes::RAND, Integer(token))
107
111
  rescue ArgumentError
108
112
  begin
109
113
  return Node.new(NodeTypes::RAND, Float(token))
110
- rescue ArgumentError => ex
111
- raise ArgumentError, "Excepted Number, got '#{token}' (#{token_type}): #{ex}"
114
+ rescue ArgumentError => e
115
+ raise ArgumentError, "Excepted Number, got '#{token}' (#{token_type}): #{e}"
112
116
  end
113
117
  end
114
118
  end
@@ -116,4 +120,4 @@ module Rox
116
120
  end
117
121
  end
118
122
  end
119
- end
123
+ end
@@ -6,47 +6,67 @@ module Rox
6
6
  end
7
7
 
8
8
  def extend
9
- @parser.add_operator('lt') do |parser, stack, context|
10
- op1 = stack.pop
11
- op2 = stack.pop
12
- if op1.is_a?(Numeric) && op2.is_a?(Numeric)
9
+ @parser.add_operator('lt') do |_parser, stack, _context|
10
+ begin
11
+ op1 = stack.pop.to_f
12
+ op2 = stack.pop.to_f
13
13
  stack.push(op1 < op2)
14
- else
14
+ rescue StandardError
15
15
  stack.push(false)
16
16
  end
17
17
  end
18
18
 
19
- @parser.add_operator('lte') do |parser, stack, context|
20
- op1 = stack.pop
21
- op2 = stack.pop
22
- if op1.is_a?(Numeric) && op2.is_a?(Numeric)
19
+ @parser.add_operator('lte') do |_parser, stack, _context|
20
+ begin
21
+ op1 = stack.pop.to_f
22
+ op2 = stack.pop.to_f
23
23
  stack.push(op1 <= op2)
24
- else
24
+ rescue StandardError
25
25
  stack.push(false)
26
26
  end
27
27
  end
28
28
 
29
- @parser.add_operator('gt') do |parser, stack, context|
30
- op1 = stack.pop
31
- op2 = stack.pop
32
- if op1.is_a?(Numeric) && op2.is_a?(Numeric)
29
+ @parser.add_operator('gt') do |_parser, stack, _context|
30
+ begin
31
+ op1 = stack.pop.to_f
32
+ op2 = stack.pop.to_f
33
33
  stack.push(op1 > op2)
34
- else
34
+ rescue StandardError
35
35
  stack.push(false)
36
36
  end
37
37
  end
38
38
 
39
- @parser.add_operator('gte') do |parser, stack, context|
40
- op1 = stack.pop
41
- op2 = stack.pop
42
- if op1.is_a?(Numeric) && op2.is_a?(Numeric)
39
+ @parser.add_operator('gte') do |_parser, stack, _context|
40
+ begin
41
+ op1 = stack.pop.to_f
42
+ op2 = stack.pop.to_f
43
43
  stack.push(op1 >= op2)
44
- else
44
+ rescue StandardError
45
+ stack.push(false)
46
+ end
47
+ end
48
+
49
+ @parser.add_operator('numne') do |_parser, stack, _context|
50
+ begin
51
+ op1 = stack.pop.to_f
52
+ op2 = stack.pop.to_f
53
+ stack.push(op1 != op2)
54
+ rescue StandardError
55
+ stack.push(false)
56
+ end
57
+ end
58
+
59
+ @parser.add_operator('numeq') do |_parser, stack, _context|
60
+ begin
61
+ op1 = stack.pop.to_f
62
+ op2 = stack.pop.to_f
63
+ stack.push(op1 == op2)
64
+ rescue StandardError
45
65
  stack.push(false)
46
66
  end
47
67
  end
48
68
 
49
- @parser.add_operator('semverNe') do |parser, stack, context|
69
+ @parser.add_operator('semverNe') do |_parser, stack, _context|
50
70
  op1 = stack.pop
51
71
  op2 = stack.pop
52
72
  if op1.is_a?(String) && op2.is_a?(String)
@@ -57,7 +77,7 @@ module Rox
57
77
  end
58
78
  end
59
79
 
60
- @parser.add_operator('semverEq') do |parser, stack, context|
80
+ @parser.add_operator('semverEq') do |_parser, stack, _context|
61
81
  op1 = stack.pop
62
82
  op2 = stack.pop
63
83
  if op1.is_a?(String) && op2.is_a?(String)
@@ -68,7 +88,7 @@ module Rox
68
88
  end
69
89
  end
70
90
 
71
- @parser.add_operator('semverLt') do |parser, stack, context|
91
+ @parser.add_operator('semverLt') do |_parser, stack, _context|
72
92
  op1 = stack.pop
73
93
  op2 = stack.pop
74
94
  if op1.is_a?(String) && op2.is_a?(String)
@@ -79,7 +99,7 @@ module Rox
79
99
  end
80
100
  end
81
101
 
82
- @parser.add_operator('semverLte') do |parser, stack, context|
102
+ @parser.add_operator('semverLte') do |_parser, stack, _context|
83
103
  op1 = stack.pop
84
104
  op2 = stack.pop
85
105
  if op1.is_a?(String) && op2.is_a?(String)
@@ -90,7 +110,7 @@ module Rox
90
110
  end
91
111
  end
92
112
 
93
- @parser.add_operator('semverGt') do |parser, stack, context|
113
+ @parser.add_operator('semverGt') do |_parser, stack, _context|
94
114
  op1 = stack.pop
95
115
  op2 = stack.pop
96
116
  if op1.is_a?(String) && op2.is_a?(String)
@@ -101,7 +121,7 @@ module Rox
101
121
  end
102
122
  end
103
123
 
104
- @parser.add_operator('semverGte') do |parser, stack, context|
124
+ @parser.add_operator('semverGte') do |_parser, stack, _context|
105
125
  op1 = stack.pop
106
126
  op2 = stack.pop
107
127
  if op1.is_a?(String) && op2.is_a?(String)
@@ -123,15 +143,15 @@ module Rox
123
143
  return [version1, version2] if segment_count1 == segment_count2
124
144
 
125
145
  if segment_count1 < segment_count2
126
- version1 += '.0' * (segment_count2 - segment_count1) + '.0'
146
+ version1 += "#{'.0' * (segment_count2 - segment_count1)}.0"
127
147
  version2 += '.1'
128
148
  else
129
149
  version1 += '.1'
130
- version2 += '.0' * (segment_count1 - segment_count2) + '.0'
150
+ version2 += "#{'.0' * (segment_count1 - segment_count2)}.0"
131
151
  end
132
152
 
133
153
  [version1, version2]
134
154
  end
135
155
  end
136
156
  end
137
- end
157
+ end
@@ -4,15 +4,15 @@ require 'openssl'
4
4
  module Rox
5
5
  module Core
6
6
  class SignatureVerifier
7
- ROX_CERTIFICATE_BASE64 = 'MIIDWDCCAkACCQDR039HDUMyzTANBgkqhkiG9w0BAQUFADBuMQswCQYDVQQHEwJjYTETMBEGA1UEChMKcm9sbG91dC5pbzERMA8GA1UECxMIc2VjdXJpdHkxFzAVBgNVBAMTDnd3dy5yb2xsb3V0LmlvMR4wHAYJKoZIhvcNAQkBFg9leWFsQHJvbGxvdXQuaW8wHhcNMTQwODE4MDkzNjAyWhcNMjQwODE1MDkzNjAyWjBuMQswCQYDVQQHEwJjYTETMBEGA1UEChMKcm9sbG91dC5pbzERMA8GA1UECxMIc2VjdXJpdHkxFzAVBgNVBAMTDnd3dy5yb2xsb3V0LmlvMR4wHAYJKoZIhvcNAQkBFg9leWFsQHJvbGxvdXQuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDq8GMRFLyaQVDEdcHlYm7NnGrAqhLP2E/27W21yTQein7r8FOT/7jJ0PLpcGLw/3zDT5wzIJ3OtFy4HWre2hn7wmt+bI+bbS/9kKrmqkpjAj1+PwnB4lhEad27lolMCuz5purqi209k7q51IMdfq0/Ot7P/Bmp+LBNs2F4jMsPYxZUUYkVTAmPqgnwxuWoJZan/OGNjtj9OGg8eOcOfcyxC4GDR/Yail+kht4I/HHesSXVukqXntsbdgnXKFkX682TuFPc3pd8ly+6N6OSWpbNV8UmEVZygnxWT3vxBT2TWvFexbW52KOFY91wIkjt+IPEMPJBPPDiN9J2nuttvfMpAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAIXrD6YsIhZa6fYDAR8huP0V3BRwMKjeLGLCXLzvuPaoQGDhn4RJNgz3leNcomIkV/AwneeS9BXgBAcEKjNeLD+nW58RSRnAfxDT5cUtQgIeR6dFmEK05u+8j/cK3VO410xr0taNMbmJfEn07WjfCdcJS3hsGJuVmEUC85KYznbIcafQMGklLYArXYVnR3XKqzxcLohSPX99weujH5wt78Zy3pXxuYCDETwhgcCYCQaZz7mpvtSOub3JQT+Ir5cBSdyI1oPI2dIamUL5+ntTyll/1rbYj83qREw8PKA9Q0KIIgfpggy19TS9zknwOLz44wRdLyT2tFoaiRqHvm6JKaA='
7
+ ROX_CERTIFICATE_BASE64 = 'MIIDWDCCAkACCQDR039HDUMyzTANBgkqhkiG9w0BAQUFADBuMQswCQYDVQQHEwJjYTETMBEGA1UEChMKcm9sbG91dC5pbzERMA8GA1UECxMIc2VjdXJpdHkxFzAVBgNVBAMTDnd3dy5yb2xsb3V0LmlvMR4wHAYJKoZIhvcNAQkBFg9leWFsQHJvbGxvdXQuaW8wHhcNMTQwODE4MDkzNjAyWhcNMjQwODE1MDkzNjAyWjBuMQswCQYDVQQHEwJjYTETMBEGA1UEChMKcm9sbG91dC5pbzERMA8GA1UECxMIc2VjdXJpdHkxFzAVBgNVBAMTDnd3dy5yb2xsb3V0LmlvMR4wHAYJKoZIhvcNAQkBFg9leWFsQHJvbGxvdXQuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDq8GMRFLyaQVDEdcHlYm7NnGrAqhLP2E/27W21yTQein7r8FOT/7jJ0PLpcGLw/3zDT5wzIJ3OtFy4HWre2hn7wmt+bI+bbS/9kKrmqkpjAj1+PwnB4lhEad27lolMCuz5purqi209k7q51IMdfq0/Ot7P/Bmp+LBNs2F4jMsPYxZUUYkVTAmPqgnwxuWoJZan/OGNjtj9OGg8eOcOfcyxC4GDR/Yail+kht4I/HHesSXVukqXntsbdgnXKFkX682TuFPc3pd8ly+6N6OSWpbNV8UmEVZygnxWT3vxBT2TWvFexbW52KOFY91wIkjt+IPEMPJBPPDiN9J2nuttvfMpAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAIXrD6YsIhZa6fYDAR8huP0V3BRwMKjeLGLCXLzvuPaoQGDhn4RJNgz3leNcomIkV/AwneeS9BXgBAcEKjNeLD+nW58RSRnAfxDT5cUtQgIeR6dFmEK05u+8j/cK3VO410xr0taNMbmJfEn07WjfCdcJS3hsGJuVmEUC85KYznbIcafQMGklLYArXYVnR3XKqzxcLohSPX99weujH5wt78Zy3pXxuYCDETwhgcCYCQaZz7mpvtSOub3JQT+Ir5cBSdyI1oPI2dIamUL5+ntTyll/1rbYj83qREw8PKA9Q0KIIgfpggy19TS9zknwOLz44wRdLyT2tFoaiRqHvm6JKaA='.freeze
8
8
 
9
9
  def verify(data, signature_base64)
10
10
  certificate_bytes = Base64.decode64(SignatureVerifier::ROX_CERTIFICATE_BASE64)
11
11
  cert = OpenSSL::X509::Certificate.new certificate_bytes
12
12
  rsa = cert.public_key
13
13
  signature_bytes = Base64.decode64(signature_base64)
14
- rsa.verify(OpenSSL::Digest::SHA256.new, signature_bytes, data)
14
+ rsa.verify(OpenSSL::Digest.new('SHA256'), signature_bytes, data)
15
15
  end
16
16
  end
17
17
  end
18
- end
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+
4
+ module Rox
5
+ module Core
6
+ class SignatureVerifierMock
7
+ def verify(_data, _signature_base64)
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
@@ -6,4 +6,4 @@ module Rox
6
6
  end
7
7
  end
8
8
  end
9
- end
9
+ end
@@ -17,4 +17,4 @@ module Rox
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -0,0 +1,25 @@
1
+ module Rox
2
+ module Server
3
+ class NormalizeFlagType
4
+ def self.normalize_string(string_value)
5
+ string_value
6
+ end
7
+
8
+ def self.normalize_int(string_value)
9
+ Integer(string_value)
10
+ end
11
+
12
+ def self.normalize_float(string_value)
13
+ Float(string_value)
14
+ end
15
+
16
+ def self.normalize_boolean(string_value)
17
+ if string_value.is_a?(Boolean)
18
+ string_value
19
+ else
20
+ string_value == 'True'
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ require 'rox/core/entities/rox_double'
2
+
3
+ module Rox
4
+ module Server
5
+ class RoxDouble < Rox::Core::RoxDouble
6
+ end
7
+ end
8
+ end
@@ -16,4 +16,4 @@ module Rox
16
16
  end
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -0,0 +1,8 @@
1
+ require 'rox/core/entities/rox_int'
2
+
3
+ module Rox
4
+ module Server
5
+ class RoxInt < Rox::Core::RoxInt
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'rox/core/entities/rox_string'
2
+
3
+ module Rox
4
+ module Server
5
+ class RoxString < Rox::Core::RoxString
6
+ end
7
+ end
8
+ end