liquid 4.0.2 → 5.1.0

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +59 -0
  3. data/README.md +6 -0
  4. data/lib/liquid/block.rb +31 -14
  5. data/lib/liquid/block_body.rb +166 -53
  6. data/lib/liquid/condition.rb +41 -20
  7. data/lib/liquid/context.rb +107 -52
  8. data/lib/liquid/document.rb +47 -9
  9. data/lib/liquid/drop.rb +4 -2
  10. data/lib/liquid/errors.rb +20 -18
  11. data/lib/liquid/expression.rb +29 -34
  12. data/lib/liquid/extensions.rb +2 -0
  13. data/lib/liquid/file_system.rb +6 -4
  14. data/lib/liquid/forloop_drop.rb +11 -4
  15. data/lib/liquid/i18n.rb +5 -3
  16. data/lib/liquid/interrupts.rb +3 -1
  17. data/lib/liquid/lexer.rb +30 -23
  18. data/lib/liquid/locales/en.yml +3 -1
  19. data/lib/liquid/parse_context.rb +20 -4
  20. data/lib/liquid/parse_tree_visitor.rb +2 -2
  21. data/lib/liquid/parser.rb +30 -18
  22. data/lib/liquid/parser_switching.rb +17 -3
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +26 -14
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/range_lookup.rb +13 -3
  27. data/lib/liquid/register.rb +6 -0
  28. data/lib/liquid/resource_limits.rb +47 -8
  29. data/lib/liquid/standardfilters.rb +95 -46
  30. data/lib/liquid/static_registers.rb +44 -0
  31. data/lib/liquid/strainer_factory.rb +36 -0
  32. data/lib/liquid/strainer_template.rb +53 -0
  33. data/lib/liquid/tablerowloop_drop.rb +6 -4
  34. data/lib/liquid/tag/disableable.rb +22 -0
  35. data/lib/liquid/tag/disabler.rb +21 -0
  36. data/lib/liquid/tag.rb +28 -6
  37. data/lib/liquid/tags/assign.rb +24 -10
  38. data/lib/liquid/tags/break.rb +8 -3
  39. data/lib/liquid/tags/capture.rb +11 -8
  40. data/lib/liquid/tags/case.rb +40 -27
  41. data/lib/liquid/tags/comment.rb +5 -3
  42. data/lib/liquid/tags/continue.rb +8 -3
  43. data/lib/liquid/tags/cycle.rb +25 -14
  44. data/lib/liquid/tags/decrement.rb +6 -3
  45. data/lib/liquid/tags/echo.rb +34 -0
  46. data/lib/liquid/tags/for.rb +68 -44
  47. data/lib/liquid/tags/if.rb +39 -23
  48. data/lib/liquid/tags/ifchanged.rb +11 -10
  49. data/lib/liquid/tags/include.rb +34 -47
  50. data/lib/liquid/tags/increment.rb +7 -3
  51. data/lib/liquid/tags/raw.rb +14 -11
  52. data/lib/liquid/tags/render.rb +84 -0
  53. data/lib/liquid/tags/table_row.rb +23 -19
  54. data/lib/liquid/tags/unless.rb +23 -15
  55. data/lib/liquid/template.rb +53 -72
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +18 -10
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +13 -3
  60. data/lib/liquid/variable.rb +46 -41
  61. data/lib/liquid/variable_lookup.rb +11 -6
  62. data/lib/liquid/version.rb +2 -1
  63. data/lib/liquid.rb +17 -5
  64. data/test/integration/assign_test.rb +74 -5
  65. data/test/integration/blank_test.rb +11 -8
  66. data/test/integration/block_test.rb +47 -1
  67. data/test/integration/capture_test.rb +18 -10
  68. data/test/integration/context_test.rb +609 -5
  69. data/test/integration/document_test.rb +4 -2
  70. data/test/integration/drop_test.rb +67 -83
  71. data/test/integration/error_handling_test.rb +73 -61
  72. data/test/integration/expression_test.rb +46 -0
  73. data/test/integration/filter_test.rb +53 -42
  74. data/test/integration/hash_ordering_test.rb +5 -3
  75. data/test/integration/output_test.rb +26 -24
  76. data/test/integration/parsing_quirks_test.rb +19 -7
  77. data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
  78. data/test/integration/security_test.rb +30 -21
  79. data/test/integration/standard_filter_test.rb +385 -281
  80. data/test/integration/tag/disableable_test.rb +59 -0
  81. data/test/integration/tag_test.rb +45 -0
  82. data/test/integration/tags/break_tag_test.rb +4 -2
  83. data/test/integration/tags/continue_tag_test.rb +4 -2
  84. data/test/integration/tags/echo_test.rb +13 -0
  85. data/test/integration/tags/for_tag_test.rb +107 -51
  86. data/test/integration/tags/if_else_tag_test.rb +5 -3
  87. data/test/integration/tags/include_tag_test.rb +76 -52
  88. data/test/integration/tags/increment_tag_test.rb +4 -2
  89. data/test/integration/tags/liquid_tag_test.rb +116 -0
  90. data/test/integration/tags/raw_tag_test.rb +14 -11
  91. data/test/integration/tags/render_tag_test.rb +213 -0
  92. data/test/integration/tags/standard_tag_test.rb +38 -31
  93. data/test/integration/tags/statements_test.rb +23 -21
  94. data/test/integration/tags/table_row_test.rb +2 -0
  95. data/test/integration/tags/unless_else_tag_test.rb +4 -2
  96. data/test/integration/template_test.rb +132 -124
  97. data/test/integration/trim_mode_test.rb +78 -44
  98. data/test/integration/variable_test.rb +74 -32
  99. data/test/test_helper.rb +113 -22
  100. data/test/unit/block_unit_test.rb +19 -24
  101. data/test/unit/condition_unit_test.rb +79 -77
  102. data/test/unit/file_system_unit_test.rb +6 -4
  103. data/test/unit/i18n_unit_test.rb +7 -5
  104. data/test/unit/lexer_unit_test.rb +11 -9
  105. data/test/{integration → unit}/parse_tree_visitor_test.rb +16 -2
  106. data/test/unit/parser_unit_test.rb +37 -35
  107. data/test/unit/partial_cache_unit_test.rb +128 -0
  108. data/test/unit/regexp_unit_test.rb +17 -15
  109. data/test/unit/static_registers_unit_test.rb +156 -0
  110. data/test/unit/strainer_factory_unit_test.rb +100 -0
  111. data/test/unit/strainer_template_unit_test.rb +82 -0
  112. data/test/unit/tag_unit_test.rb +5 -3
  113. data/test/unit/tags/case_tag_unit_test.rb +3 -1
  114. data/test/unit/tags/for_tag_unit_test.rb +4 -2
  115. data/test/unit/tags/if_tag_unit_test.rb +3 -1
  116. data/test/unit/template_factory_unit_test.rb +12 -0
  117. data/test/unit/template_unit_test.rb +19 -10
  118. data/test/unit/tokenizer_unit_test.rb +26 -19
  119. data/test/unit/variable_unit_test.rb +51 -49
  120. metadata +76 -50
  121. data/lib/liquid/strainer.rb +0 -66
  122. data/lib/liquid/truffle.rb +0 -5
  123. data/test/truffle/truffle_test.rb +0 -9
  124. data/test/unit/context_unit_test.rb +0 -489
  125. data/test/unit/strainer_unit_test.rb +0 -164
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class ParserUnitTest < Minitest::Test
@@ -5,72 +7,72 @@ class ParserUnitTest < Minitest::Test
5
7
 
6
8
  def test_consume
7
9
  p = Parser.new("wat: 7")
8
- assert_equal 'wat', p.consume(:id)
9
- assert_equal ':', p.consume(:colon)
10
- assert_equal '7', p.consume(:number)
10
+ assert_equal('wat', p.consume(:id))
11
+ assert_equal(':', p.consume(:colon))
12
+ assert_equal('7', p.consume(:number))
11
13
  end
12
14
 
13
15
  def test_jump
14
16
  p = Parser.new("wat: 7")
15
17
  p.jump(2)
16
- assert_equal '7', p.consume(:number)
18
+ assert_equal('7', p.consume(:number))
17
19
  end
18
20
 
19
21
  def test_consume?
20
22
  p = Parser.new("wat: 7")
21
- assert_equal 'wat', p.consume?(:id)
22
- assert_equal false, p.consume?(:dot)
23
- assert_equal ':', p.consume(:colon)
24
- assert_equal '7', p.consume?(:number)
23
+ assert_equal('wat', p.consume?(:id))
24
+ assert_equal(false, p.consume?(:dot))
25
+ assert_equal(':', p.consume(:colon))
26
+ assert_equal('7', p.consume?(:number))
25
27
  end
26
28
 
27
29
  def test_id?
28
30
  p = Parser.new("wat 6 Peter Hegemon")
29
- assert_equal 'wat', p.id?('wat')
30
- assert_equal false, p.id?('endgame')
31
- assert_equal '6', p.consume(:number)
32
- assert_equal 'Peter', p.id?('Peter')
33
- assert_equal false, p.id?('Achilles')
31
+ assert_equal('wat', p.id?('wat'))
32
+ assert_equal(false, p.id?('endgame'))
33
+ assert_equal('6', p.consume(:number))
34
+ assert_equal('Peter', p.id?('Peter'))
35
+ assert_equal(false, p.id?('Achilles'))
34
36
  end
35
37
 
36
38
  def test_look
37
39
  p = Parser.new("wat 6 Peter Hegemon")
38
- assert_equal true, p.look(:id)
39
- assert_equal 'wat', p.consume(:id)
40
- assert_equal false, p.look(:comparison)
41
- assert_equal true, p.look(:number)
42
- assert_equal true, p.look(:id, 1)
43
- assert_equal false, p.look(:number, 1)
40
+ assert_equal(true, p.look(:id))
41
+ assert_equal('wat', p.consume(:id))
42
+ assert_equal(false, p.look(:comparison))
43
+ assert_equal(true, p.look(:number))
44
+ assert_equal(true, p.look(:id, 1))
45
+ assert_equal(false, p.look(:number, 1))
44
46
  end
45
47
 
46
48
  def test_expressions
47
49
  p = Parser.new("hi.there hi?[5].there? hi.there.bob")
48
- assert_equal 'hi.there', p.expression
49
- assert_equal 'hi?[5].there?', p.expression
50
- assert_equal 'hi.there.bob', p.expression
50
+ assert_equal('hi.there', p.expression)
51
+ assert_equal('hi?[5].there?', p.expression)
52
+ assert_equal('hi.there.bob', p.expression)
51
53
 
52
54
  p = Parser.new("567 6.0 'lol' \"wut\"")
53
- assert_equal '567', p.expression
54
- assert_equal '6.0', p.expression
55
- assert_equal "'lol'", p.expression
56
- assert_equal '"wut"', p.expression
55
+ assert_equal('567', p.expression)
56
+ assert_equal('6.0', p.expression)
57
+ assert_equal("'lol'", p.expression)
58
+ assert_equal('"wut"', p.expression)
57
59
  end
58
60
 
59
61
  def test_ranges
60
62
  p = Parser.new("(5..7) (1.5..9.6) (young..old) (hi[5].wat..old)")
61
- assert_equal '(5..7)', p.expression
62
- assert_equal '(1.5..9.6)', p.expression
63
- assert_equal '(young..old)', p.expression
64
- assert_equal '(hi[5].wat..old)', p.expression
63
+ assert_equal('(5..7)', p.expression)
64
+ assert_equal('(1.5..9.6)', p.expression)
65
+ assert_equal('(young..old)', p.expression)
66
+ assert_equal('(hi[5].wat..old)', p.expression)
65
67
  end
66
68
 
67
69
  def test_arguments
68
70
  p = Parser.new("filter: hi.there[5], keyarg: 7")
69
- assert_equal 'filter', p.consume(:id)
70
- assert_equal ':', p.consume(:colon)
71
- assert_equal 'hi.there[5]', p.argument
72
- assert_equal ',', p.consume(:comma)
73
- assert_equal 'keyarg: 7', p.argument
71
+ assert_equal('filter', p.consume(:id))
72
+ assert_equal(':', p.consume(:colon))
73
+ assert_equal('hi.there[5]', p.argument)
74
+ assert_equal(',', p.consume(:comma))
75
+ assert_equal('keyarg: 7', p.argument)
74
76
  end
75
77
 
76
78
  def test_invalid_expression
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class PartialCacheUnitTest < Minitest::Test
6
+ def test_uses_the_file_system_register_if_present
7
+ context = Liquid::Context.build(
8
+ registers: {
9
+ file_system: StubFileSystem.new('my_partial' => 'my partial body'),
10
+ }
11
+ )
12
+
13
+ partial = Liquid::PartialCache.load(
14
+ 'my_partial',
15
+ context: context,
16
+ parse_context: Liquid::ParseContext.new
17
+ )
18
+
19
+ assert_equal('my partial body', partial.render)
20
+ end
21
+
22
+ def test_reads_from_the_file_system_only_once_per_file
23
+ file_system = StubFileSystem.new('my_partial' => 'some partial body')
24
+ context = Liquid::Context.build(
25
+ registers: { file_system: file_system }
26
+ )
27
+
28
+ 2.times do
29
+ Liquid::PartialCache.load(
30
+ 'my_partial',
31
+ context: context,
32
+ parse_context: Liquid::ParseContext.new
33
+ )
34
+ end
35
+
36
+ assert_equal(1, file_system.file_read_count)
37
+ end
38
+
39
+ def test_cache_state_is_stored_per_context
40
+ parse_context = Liquid::ParseContext.new
41
+ shared_file_system = StubFileSystem.new(
42
+ 'my_partial' => 'my shared value'
43
+ )
44
+ context_one = Liquid::Context.build(
45
+ registers: {
46
+ file_system: shared_file_system,
47
+ }
48
+ )
49
+ context_two = Liquid::Context.build(
50
+ registers: {
51
+ file_system: shared_file_system,
52
+ }
53
+ )
54
+
55
+ 2.times do
56
+ Liquid::PartialCache.load(
57
+ 'my_partial',
58
+ context: context_one,
59
+ parse_context: parse_context
60
+ )
61
+ end
62
+
63
+ Liquid::PartialCache.load(
64
+ 'my_partial',
65
+ context: context_two,
66
+ parse_context: parse_context
67
+ )
68
+
69
+ assert_equal(2, shared_file_system.file_read_count)
70
+ end
71
+
72
+ def test_cache_is_not_broken_when_a_different_parse_context_is_used
73
+ file_system = StubFileSystem.new('my_partial' => 'some partial body')
74
+ context = Liquid::Context.build(
75
+ registers: { file_system: file_system }
76
+ )
77
+
78
+ Liquid::PartialCache.load(
79
+ 'my_partial',
80
+ context: context,
81
+ parse_context: Liquid::ParseContext.new(my_key: 'value one')
82
+ )
83
+ Liquid::PartialCache.load(
84
+ 'my_partial',
85
+ context: context,
86
+ parse_context: Liquid::ParseContext.new(my_key: 'value two')
87
+ )
88
+
89
+ # Technically what we care about is that the file was parsed twice,
90
+ # but measuring file reads is an OK proxy for this.
91
+ assert_equal(1, file_system.file_read_count)
92
+ end
93
+
94
+ def test_uses_default_template_factory_when_no_template_factory_found_in_register
95
+ context = Liquid::Context.build(
96
+ registers: {
97
+ file_system: StubFileSystem.new('my_partial' => 'my partial body'),
98
+ }
99
+ )
100
+
101
+ partial = Liquid::PartialCache.load(
102
+ 'my_partial',
103
+ context: context,
104
+ parse_context: Liquid::ParseContext.new
105
+ )
106
+
107
+ assert_equal('my partial body', partial.render)
108
+ end
109
+
110
+ def test_uses_template_factory_register_if_present
111
+ template_factory = StubTemplateFactory.new
112
+ context = Liquid::Context.build(
113
+ registers: {
114
+ file_system: StubFileSystem.new('my_partial' => 'my partial body'),
115
+ template_factory: template_factory,
116
+ }
117
+ )
118
+
119
+ partial = Liquid::PartialCache.load(
120
+ 'my_partial',
121
+ context: context,
122
+ parse_context: Liquid::ParseContext.new
123
+ )
124
+
125
+ assert_equal('my partial body', partial.render)
126
+ assert_equal(1, template_factory.count)
127
+ end
128
+ end
@@ -1,44 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class RegexpUnitTest < Minitest::Test
4
6
  include Liquid
5
7
 
6
8
  def test_empty
7
- assert_equal [], ''.scan(QuotedFragment)
9
+ assert_equal([], ''.scan(QuotedFragment))
8
10
  end
9
11
 
10
12
  def test_quote
11
- assert_equal ['"arg 1"'], '"arg 1"'.scan(QuotedFragment)
13
+ assert_equal(['"arg 1"'], '"arg 1"'.scan(QuotedFragment))
12
14
  end
13
15
 
14
16
  def test_words
15
- assert_equal ['arg1', 'arg2'], 'arg1 arg2'.scan(QuotedFragment)
17
+ assert_equal(['arg1', 'arg2'], 'arg1 arg2'.scan(QuotedFragment))
16
18
  end
17
19
 
18
20
  def test_tags
19
- assert_equal ['<tr>', '</tr>'], '<tr> </tr>'.scan(QuotedFragment)
20
- assert_equal ['<tr></tr>'], '<tr></tr>'.scan(QuotedFragment)
21
- assert_equal ['<style', 'class="hello">', '</style>'], %(<style class="hello">' </style>).scan(QuotedFragment)
21
+ assert_equal(['<tr>', '</tr>'], '<tr> </tr>'.scan(QuotedFragment))
22
+ assert_equal(['<tr></tr>'], '<tr></tr>'.scan(QuotedFragment))
23
+ assert_equal(['<style', 'class="hello">', '</style>'], %(<style class="hello">' </style>).scan(QuotedFragment))
22
24
  end
23
25
 
24
26
  def test_double_quoted_words
25
- assert_equal ['arg1', 'arg2', '"arg 3"'], 'arg1 arg2 "arg 3"'.scan(QuotedFragment)
27
+ assert_equal(['arg1', 'arg2', '"arg 3"'], 'arg1 arg2 "arg 3"'.scan(QuotedFragment))
26
28
  end
27
29
 
28
30
  def test_single_quoted_words
29
- assert_equal ['arg1', 'arg2', "'arg 3'"], 'arg1 arg2 \'arg 3\''.scan(QuotedFragment)
31
+ assert_equal(['arg1', 'arg2', "'arg 3'"], 'arg1 arg2 \'arg 3\''.scan(QuotedFragment))
30
32
  end
31
33
 
32
34
  def test_quoted_words_in_the_middle
33
- assert_equal ['arg1', 'arg2', '"arg 3"', 'arg4'], 'arg1 arg2 "arg 3" arg4 '.scan(QuotedFragment)
35
+ assert_equal(['arg1', 'arg2', '"arg 3"', 'arg4'], 'arg1 arg2 "arg 3" arg4 '.scan(QuotedFragment))
34
36
  end
35
37
 
36
38
  def test_variable_parser
37
- assert_equal ['var'], 'var'.scan(VariableParser)
38
- assert_equal ['var', 'method'], 'var.method'.scan(VariableParser)
39
- assert_equal ['var', '[method]'], 'var[method]'.scan(VariableParser)
40
- assert_equal ['var', '[method]', '[0]'], 'var[method][0]'.scan(VariableParser)
41
- assert_equal ['var', '["method"]', '[0]'], 'var["method"][0]'.scan(VariableParser)
42
- assert_equal ['var', '[method]', '[0]', 'method'], 'var[method][0].method'.scan(VariableParser)
39
+ assert_equal(['var'], 'var'.scan(VariableParser))
40
+ assert_equal(['var', 'method'], 'var.method'.scan(VariableParser))
41
+ assert_equal(['var', '[method]'], 'var[method]'.scan(VariableParser))
42
+ assert_equal(['var', '[method]', '[0]'], 'var[method][0]'.scan(VariableParser))
43
+ assert_equal(['var', '["method"]', '[0]'], 'var["method"][0]'.scan(VariableParser))
44
+ assert_equal(['var', '[method]', '[0]', 'method'], 'var[method][0].method'.scan(VariableParser))
43
45
  end
44
46
  end # RegexpTest
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class StaticRegistersUnitTest < Minitest::Test
6
+ include Liquid
7
+
8
+ def test_set
9
+ static_register = StaticRegisters.new(a: 1, b: 2)
10
+ static_register[:b] = 22
11
+ static_register[:c] = 33
12
+
13
+ assert_equal(1, static_register[:a])
14
+ assert_equal(22, static_register[:b])
15
+ assert_equal(33, static_register[:c])
16
+ end
17
+
18
+ def test_get_missing_key
19
+ static_register = StaticRegisters.new
20
+
21
+ assert_nil(static_register[:missing])
22
+ end
23
+
24
+ def test_delete
25
+ static_register = StaticRegisters.new(a: 1, b: 2)
26
+ static_register[:b] = 22
27
+ static_register[:c] = 33
28
+
29
+ assert_nil(static_register.delete(:a))
30
+
31
+ assert_equal(22, static_register.delete(:b))
32
+
33
+ assert_equal(33, static_register.delete(:c))
34
+ assert_nil(static_register[:c])
35
+
36
+ assert_nil(static_register.delete(:d))
37
+ end
38
+
39
+ def test_fetch
40
+ static_register = StaticRegisters.new(a: 1, b: 2)
41
+ static_register[:b] = 22
42
+ static_register[:c] = 33
43
+
44
+ assert_equal(1, static_register.fetch(:a))
45
+ assert_equal(1, static_register.fetch(:a, "default"))
46
+ assert_equal(22, static_register.fetch(:b))
47
+ assert_equal(22, static_register.fetch(:b, "default"))
48
+ assert_equal(33, static_register.fetch(:c))
49
+ assert_equal(33, static_register.fetch(:c, "default"))
50
+
51
+ assert_raises(KeyError) do
52
+ static_register.fetch(:d)
53
+ end
54
+ assert_equal("default", static_register.fetch(:d, "default"))
55
+
56
+ result = static_register.fetch(:d) { "default" }
57
+ assert_equal("default", result)
58
+
59
+ result = static_register.fetch(:d, "default 1") { "default 2" }
60
+ assert_equal("default 2", result)
61
+ end
62
+
63
+ def test_key
64
+ static_register = StaticRegisters.new(a: 1, b: 2)
65
+ static_register[:b] = 22
66
+ static_register[:c] = 33
67
+
68
+ assert_equal(true, static_register.key?(:a))
69
+ assert_equal(true, static_register.key?(:b))
70
+ assert_equal(true, static_register.key?(:c))
71
+ assert_equal(false, static_register.key?(:d))
72
+ end
73
+
74
+ def test_static_register_can_be_frozen
75
+ static_register = StaticRegisters.new(a: 1)
76
+
77
+ static_register.static.freeze
78
+
79
+ assert_raises(RuntimeError) do
80
+ static_register.static[:a] = "foo"
81
+ end
82
+
83
+ assert_raises(RuntimeError) do
84
+ static_register.static[:b] = "foo"
85
+ end
86
+
87
+ assert_raises(RuntimeError) do
88
+ static_register.static.delete(:a)
89
+ end
90
+
91
+ assert_raises(RuntimeError) do
92
+ static_register.static.delete(:c)
93
+ end
94
+ end
95
+
96
+ def test_new_static_retains_static
97
+ static_register = StaticRegisters.new(a: 1, b: 2)
98
+ static_register[:b] = 22
99
+ static_register[:c] = 33
100
+
101
+ new_static_register = StaticRegisters.new(static_register)
102
+ new_static_register[:b] = 222
103
+
104
+ newest_static_register = StaticRegisters.new(new_static_register)
105
+ newest_static_register[:c] = 333
106
+
107
+ assert_equal(1, static_register[:a])
108
+ assert_equal(22, static_register[:b])
109
+ assert_equal(33, static_register[:c])
110
+
111
+ assert_equal(1, new_static_register[:a])
112
+ assert_equal(222, new_static_register[:b])
113
+ assert_nil(new_static_register[:c])
114
+
115
+ assert_equal(1, newest_static_register[:a])
116
+ assert_equal(2, newest_static_register[:b])
117
+ assert_equal(333, newest_static_register[:c])
118
+ end
119
+
120
+ def test_multiple_instances_are_unique
121
+ static_register_1 = StaticRegisters.new(a: 1, b: 2)
122
+ static_register_1[:b] = 22
123
+ static_register_1[:c] = 33
124
+
125
+ static_register_2 = StaticRegisters.new(a: 10, b: 20)
126
+ static_register_2[:b] = 220
127
+ static_register_2[:c] = 330
128
+
129
+ assert_equal({ a: 1, b: 2 }, static_register_1.static)
130
+ assert_equal(1, static_register_1[:a])
131
+ assert_equal(22, static_register_1[:b])
132
+ assert_equal(33, static_register_1[:c])
133
+
134
+ assert_equal({ a: 10, b: 20 }, static_register_2.static)
135
+ assert_equal(10, static_register_2[:a])
136
+ assert_equal(220, static_register_2[:b])
137
+ assert_equal(330, static_register_2[:c])
138
+ end
139
+
140
+ def test_initialization_reused_static_same_memory_object
141
+ static_register_1 = StaticRegisters.new(a: 1, b: 2)
142
+ static_register_1[:b] = 22
143
+ static_register_1[:c] = 33
144
+
145
+ static_register_2 = StaticRegisters.new(static_register_1)
146
+
147
+ assert_equal(1, static_register_2[:a])
148
+ assert_equal(2, static_register_2[:b])
149
+ assert_nil(static_register_2[:c])
150
+
151
+ static_register_1.static[:b] = 222
152
+ static_register_1.static[:c] = 333
153
+
154
+ assert_same(static_register_1.static, static_register_2.static)
155
+ end
156
+ end