rambling-trie 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -0
- data/LICENSE +1 -1
- data/README.md +68 -29
- data/lib/rambling/trie/comparable.rb +2 -3
- data/lib/rambling/trie/compressible.rb +3 -5
- data/lib/rambling/trie/compressor.rb +2 -12
- data/lib/rambling/trie/configuration/properties.rb +8 -14
- data/lib/rambling/trie/configuration/provider_collection.rb +19 -27
- data/lib/rambling/trie/container.rb +28 -42
- data/lib/rambling/trie/enumerable.rb +4 -2
- data/lib/rambling/trie/nodes/compressed.rb +4 -5
- data/lib/rambling/trie/nodes/missing.rb +1 -2
- data/lib/rambling/trie/nodes/node.rb +21 -34
- data/lib/rambling/trie/nodes/raw.rb +2 -2
- data/lib/rambling/trie/readers/plain_text.rb +10 -6
- data/lib/rambling/trie/readers/reader.rb +19 -0
- data/lib/rambling/trie/readers.rb +1 -1
- data/lib/rambling/trie/serializers/file.rb +1 -1
- data/lib/rambling/trie/serializers/marshal.rb +12 -20
- data/lib/rambling/trie/serializers/serializer.rb +27 -0
- data/lib/rambling/trie/serializers/yaml.rb +10 -16
- data/lib/rambling/trie/serializers/zip.rb +9 -5
- data/lib/rambling/trie/serializers.rb +1 -1
- data/lib/rambling/trie/stringifyable.rb +1 -1
- data/lib/rambling/trie/version.rb +1 -1
- data/lib/rambling/trie.rb +19 -22
- data/rambling-trie.gemspec +9 -5
- data/spec/integration/rambling/trie_spec.rb +49 -20
- data/spec/lib/rambling/trie/comparable_spec.rb +29 -39
- data/spec/lib/rambling/trie/compressor_spec.rb +17 -14
- data/spec/lib/rambling/trie/configuration/properties_spec.rb +25 -7
- data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +44 -16
- data/spec/lib/rambling/trie/container_spec.rb +202 -327
- data/spec/lib/rambling/trie/enumerable_spec.rb +18 -10
- data/spec/lib/rambling/trie/inspectable_spec.rb +9 -3
- data/spec/lib/rambling/trie/nodes/compressed_spec.rb +6 -0
- data/spec/lib/rambling/trie/nodes/node_spec.rb +1 -1
- data/spec/lib/rambling/trie/nodes/raw_spec.rb +32 -27
- data/spec/lib/rambling/trie/readers/plain_text_spec.rb +11 -1
- data/spec/lib/rambling/trie/readers/reader_spec.rb +14 -0
- data/spec/lib/rambling/trie/serializers/file_spec.rb +2 -4
- data/spec/lib/rambling/trie/serializers/marshal_spec.rb +2 -4
- data/spec/lib/rambling/trie/serializers/serializer_spec.rb +21 -0
- data/spec/lib/rambling/trie/serializers/yaml_spec.rb +2 -4
- data/spec/lib/rambling/trie/serializers/zip_spec.rb +24 -16
- data/spec/lib/rambling/trie/stringifyable_spec.rb +17 -13
- data/spec/lib/rambling/trie_spec.rb +107 -45
- data/spec/spec_helper.rb +16 -9
- data/spec/support/shared_examples/a_compressible_trie.rb +9 -3
- data/spec/support/shared_examples/a_container_partial_word.rb +17 -0
- data/spec/support/shared_examples/a_container_scan.rb +14 -0
- data/spec/support/shared_examples/a_container_word.rb +43 -0
- data/spec/support/shared_examples/a_container_words_within.rb +44 -0
- data/spec/support/shared_examples/a_serializable_trie.rb +5 -9
- data/spec/support/shared_examples/a_serializer.rb +37 -14
- data/spec/support/shared_examples/a_trie_data_structure.rb +24 -10
- data/spec/support/shared_examples/a_trie_node.rb +22 -14
- data/spec/support/shared_examples/a_trie_node_implementation.rb +40 -43
- metadata +25 -9
@@ -15,25 +15,27 @@ describe Rambling::Trie do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'returns a new instance of the trie container' do
|
18
|
-
expect(
|
18
|
+
expect(described_class.create).to eq container
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'with a block' do
|
22
22
|
it 'yields the new container' do
|
23
23
|
yielded = nil
|
24
|
-
|
24
|
+
described_class.create { |trie| yielded = trie }
|
25
25
|
expect(yielded).to eq container
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'with a filepath' do
|
30
30
|
let(:filepath) { 'a test filepath' }
|
31
|
-
let
|
31
|
+
let :reader do
|
32
|
+
instance_double 'Rambling::Trie::Readers::PlainText', :reader
|
33
|
+
end
|
32
34
|
let(:words) { %w(a couple of test words over here) }
|
33
35
|
|
34
36
|
before do
|
35
37
|
receive_and_yield = receive(:each_word)
|
36
|
-
words.inject
|
38
|
+
words.inject receive_and_yield do |yielder, word|
|
37
39
|
yielder.and_yield word
|
38
40
|
end
|
39
41
|
|
@@ -42,7 +44,7 @@ describe Rambling::Trie do
|
|
42
44
|
end
|
43
45
|
|
44
46
|
it 'loads every word' do
|
45
|
-
|
47
|
+
described_class.create filepath, reader
|
46
48
|
|
47
49
|
words.each do |word|
|
48
50
|
expect(container).to have_received(:<<).with word
|
@@ -52,17 +54,23 @@ describe Rambling::Trie do
|
|
52
54
|
|
53
55
|
context 'without any reader' do
|
54
56
|
let(:filepath) { 'a test filepath' }
|
55
|
-
let
|
57
|
+
let :reader do
|
58
|
+
instance_double(
|
59
|
+
'Rambling::Trie::Readers::PlainText',
|
60
|
+
:reader,
|
61
|
+
each_word: nil,
|
62
|
+
)
|
63
|
+
end
|
56
64
|
|
57
65
|
before do
|
58
|
-
|
66
|
+
described_class.config do |c|
|
59
67
|
c.readers.add :default, reader
|
60
68
|
c.readers.default = reader
|
61
69
|
end
|
62
70
|
end
|
63
71
|
|
64
72
|
it 'defaults to a plain text reader' do
|
65
|
-
|
73
|
+
described_class.create filepath, nil
|
66
74
|
|
67
75
|
expect(reader).to have_received(:each_word).with filepath
|
68
76
|
end
|
@@ -70,29 +78,53 @@ describe Rambling::Trie do
|
|
70
78
|
end
|
71
79
|
|
72
80
|
describe '.load' do
|
81
|
+
let(:filepath) { 'a path to a file' }
|
73
82
|
let(:root) { Rambling::Trie::Nodes::Raw.new }
|
74
83
|
let(:compressor) { Rambling::Trie::Compressor.new }
|
75
84
|
let(:container) { Rambling::Trie::Container.new root, compressor }
|
76
|
-
let
|
77
|
-
|
85
|
+
let :serializer do
|
86
|
+
instance_double(
|
87
|
+
'Rambling::True::Serializers::File',
|
88
|
+
:serializer,
|
89
|
+
load: root,
|
90
|
+
)
|
91
|
+
end
|
78
92
|
|
79
93
|
it 'returns a new container with the loaded root node' do
|
80
|
-
trie =
|
94
|
+
trie = described_class.load filepath, serializer
|
81
95
|
expect(trie).to eq container
|
82
96
|
end
|
83
97
|
|
84
98
|
it 'uses the serializer to load the root node from the given filepath' do
|
85
|
-
|
99
|
+
described_class.load filepath, serializer
|
86
100
|
expect(serializer).to have_received(:load).with filepath
|
87
101
|
end
|
88
102
|
|
89
103
|
context 'without a serializer' do
|
90
|
-
let
|
91
|
-
|
92
|
-
|
104
|
+
let :marshal_serializer do
|
105
|
+
instance_double(
|
106
|
+
'Rambling::Trie::Serializers::Marshal',
|
107
|
+
:marshal_serializer,
|
108
|
+
load: nil,
|
109
|
+
)
|
110
|
+
end
|
111
|
+
let :default_serializer do
|
112
|
+
instance_double(
|
113
|
+
'Rambling::Trie::Serializers::File',
|
114
|
+
:default_serializer,
|
115
|
+
load: nil,
|
116
|
+
)
|
117
|
+
end
|
118
|
+
let :yaml_serializer do
|
119
|
+
instance_double(
|
120
|
+
'Rambling::Trie::Serializers::Yaml',
|
121
|
+
:yaml_serializer,
|
122
|
+
load: nil,
|
123
|
+
)
|
124
|
+
end
|
93
125
|
|
94
126
|
before do
|
95
|
-
|
127
|
+
described_class.config do |c|
|
96
128
|
c.serializers.add :default, default_serializer
|
97
129
|
c.serializers.add :marshal, marshal_serializer
|
98
130
|
c.serializers.add :yml, yaml_serializer
|
@@ -102,18 +134,21 @@ describe Rambling::Trie do
|
|
102
134
|
end
|
103
135
|
end
|
104
136
|
|
105
|
-
|
106
|
-
|
107
|
-
|
137
|
+
[
|
138
|
+
['.marshal', :marshal_serializer],
|
139
|
+
['.yml', :yaml_serializer],
|
140
|
+
['.yaml', :yaml_serializer],
|
141
|
+
['', :default_serializer],
|
142
|
+
].each do |test_params|
|
143
|
+
extension, serializer = test_params
|
144
|
+
filepath = "test#{extension}"
|
108
145
|
|
109
|
-
|
110
|
-
|
146
|
+
it "uses extension-based serializer (#{filepath} -> #{serializer})" do
|
147
|
+
serializer_instance = public_send serializer
|
111
148
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
Rambling::Trie.load 'test'
|
116
|
-
expect(default_serializer).to have_received(:load).with 'test'
|
149
|
+
described_class.load filepath
|
150
|
+
expect(serializer_instance).to have_received(:load).with filepath
|
151
|
+
end
|
117
152
|
end
|
118
153
|
end
|
119
154
|
|
@@ -121,7 +156,7 @@ describe Rambling::Trie do
|
|
121
156
|
it 'yields the new container' do
|
122
157
|
yielded = nil
|
123
158
|
|
124
|
-
|
159
|
+
described_class.load filepath, serializer do |trie|
|
125
160
|
yielded = trie
|
126
161
|
end
|
127
162
|
|
@@ -132,16 +167,36 @@ describe Rambling::Trie do
|
|
132
167
|
|
133
168
|
describe '.dump' do
|
134
169
|
let(:filename) { 'a trie' }
|
135
|
-
let(:root) {
|
136
|
-
let
|
170
|
+
let(:root) { instance_double 'Rambling::Trie::Serializers::Marshal', :root }
|
171
|
+
let :compressor do
|
172
|
+
instance_double 'Rambling::Trie::Serializers::Marshal', :compressor
|
173
|
+
end
|
137
174
|
let(:trie) { Rambling::Trie::Container.new root, compressor }
|
138
175
|
|
139
|
-
let
|
140
|
-
|
141
|
-
|
176
|
+
let :marshal_serializer do
|
177
|
+
instance_double(
|
178
|
+
'Rambling::Trie::Serializers::Marshal',
|
179
|
+
:marshal_serializer,
|
180
|
+
dump: nil,
|
181
|
+
)
|
182
|
+
end
|
183
|
+
let :yaml_serializer do
|
184
|
+
instance_double(
|
185
|
+
'Rambling::Trie::Serializers::Yaml',
|
186
|
+
:yaml_serializer,
|
187
|
+
dump: nil,
|
188
|
+
)
|
189
|
+
end
|
190
|
+
let :default_serializer do
|
191
|
+
instance_double(
|
192
|
+
'Rambling::Trie::Serializers::File',
|
193
|
+
:default_serializer,
|
194
|
+
dump: nil,
|
195
|
+
)
|
196
|
+
end
|
142
197
|
|
143
198
|
before do
|
144
|
-
|
199
|
+
described_class.config do |c|
|
145
200
|
c.serializers.add :default, default_serializer
|
146
201
|
c.serializers.add :marshal, marshal_serializer
|
147
202
|
c.serializers.add :yml, yaml_serializer
|
@@ -151,32 +206,39 @@ describe Rambling::Trie do
|
|
151
206
|
end
|
152
207
|
|
153
208
|
it 'uses the configured default serializer by default' do
|
154
|
-
|
209
|
+
described_class.dump trie, filename
|
155
210
|
expect(default_serializer).to have_received(:dump).with root, filename
|
156
211
|
end
|
157
212
|
|
158
213
|
context 'when provided with a format' do
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
214
|
+
[
|
215
|
+
['.marshal', :marshal_serializer],
|
216
|
+
['.yml', :yaml_serializer],
|
217
|
+
['', :default_serializer],
|
218
|
+
].each do |test_params|
|
219
|
+
extension, serializer = test_params
|
220
|
+
|
221
|
+
it 'uses the corresponding serializer' do
|
222
|
+
filepath = "#{filename}#{extension}"
|
223
|
+
serializer_instance = public_send serializer
|
224
|
+
|
225
|
+
described_class.dump trie, filepath
|
226
|
+
expect(serializer_instance).to have_received(:dump)
|
227
|
+
.with root, filepath
|
228
|
+
end
|
167
229
|
end
|
168
230
|
end
|
169
231
|
end
|
170
232
|
|
171
233
|
describe '.config' do
|
172
234
|
it 'returns the properties' do
|
173
|
-
expect(
|
235
|
+
expect(described_class.config).to eq described_class.send :properties
|
174
236
|
end
|
175
237
|
|
176
238
|
it 'yields the properties' do
|
177
239
|
yielded = nil
|
178
|
-
|
179
|
-
expect(yielded).to eq
|
240
|
+
described_class.config { |c| yielded = c }
|
241
|
+
expect(yielded).to eq described_class.send :properties
|
180
242
|
end
|
181
243
|
end
|
182
244
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'yaml'
|
3
4
|
require 'simplecov'
|
4
|
-
require 'coveralls'
|
5
5
|
|
6
|
-
|
7
|
-
SimpleCov::Formatter::HTMLFormatter,
|
8
|
-
Coveralls::SimpleCov::Formatter,
|
9
|
-
]
|
6
|
+
COVERAGE_FILTER = %r{/spec/}.freeze
|
10
7
|
|
11
|
-
|
12
|
-
|
8
|
+
if ENV.key? 'COVERALLS_REPO_TOKEN'
|
9
|
+
require 'coveralls'
|
10
|
+
|
11
|
+
SimpleCov.formatters = [
|
12
|
+
SimpleCov::Formatter::HTMLFormatter,
|
13
|
+
Coveralls::SimpleCov::Formatter,
|
14
|
+
]
|
15
|
+
|
16
|
+
Coveralls.wear! { add_filter COVERAGE_FILTER }
|
17
|
+
else
|
18
|
+
SimpleCov.start { add_filter COVERAGE_FILTER }
|
13
19
|
end
|
14
20
|
|
15
21
|
require 'rspec'
|
@@ -21,7 +27,7 @@ RSpec.configure do |config|
|
|
21
27
|
config.tty = true
|
22
28
|
config.formatter = :documentation
|
23
29
|
config.order = :random
|
24
|
-
config.
|
30
|
+
config.filter_run_when_matching :focus
|
25
31
|
config.raise_errors_for_deprecations!
|
26
32
|
end
|
27
33
|
|
@@ -29,7 +35,8 @@ require 'support/config'
|
|
29
35
|
|
30
36
|
%w(
|
31
37
|
a_compressible_trie a_serializable_trie a_serializer a_trie_data_structure
|
32
|
-
a_trie_node a_trie_node_implementation
|
38
|
+
a_trie_node a_trie_node_implementation a_container_scan a_container_word
|
39
|
+
a_container_partial_word a_container_words_within
|
33
40
|
).each do |name|
|
34
41
|
require File.join('support', 'shared_examples', name)
|
35
42
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
shared_examples_for 'a compressible trie' do
|
4
|
-
context '
|
4
|
+
context 'with an uncompressed trie' do
|
5
5
|
it_behaves_like 'a trie data structure'
|
6
6
|
|
7
7
|
it 'does not alter the input' do
|
@@ -16,7 +16,7 @@ shared_examples_for 'a compressible trie' do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
context '
|
19
|
+
context 'with an compressed trie' do
|
20
20
|
let!(:original_root) { trie.root }
|
21
21
|
let!(:original_keys) { original_root.children_tree.keys }
|
22
22
|
let!(:original_values) { original_root.children_tree.values }
|
@@ -31,9 +31,15 @@ shared_examples_for 'a compressible trie' do
|
|
31
31
|
expect(trie).to be_compressed
|
32
32
|
end
|
33
33
|
|
34
|
-
it 'leaves the original root intact' do
|
34
|
+
it 'leaves the original root keys intact' do
|
35
35
|
expect(original_root.children_tree.keys).to eq original_keys
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'leaves the original trie keys intact' do
|
36
39
|
expect(trie.children_tree.keys).to eq original_keys
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'leaves the original trie values intact' do
|
37
43
|
expect(trie.children_tree.values).not_to eq original_values
|
38
44
|
end
|
39
45
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples_for 'a matching container#partial_word' do
|
4
|
+
%w(h he hell hello hi hig high).each do |prefix|
|
5
|
+
it 'matches part of the word' do
|
6
|
+
expect(container.partial_word? prefix).to be true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
shared_examples_for 'a non-matching container#partial_word' do
|
12
|
+
it 'does not match any part of the word' do
|
13
|
+
%w(ha hal al).each do |word|
|
14
|
+
expect(container.partial_word? word).to be false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples_for 'a matching container#scan' do
|
4
|
+
[
|
5
|
+
['hi', %w(hi high highlight histerical)],
|
6
|
+
['hig', %w(high highlight)],
|
7
|
+
].each do |test_params|
|
8
|
+
prefix, expected = test_params
|
9
|
+
|
10
|
+
it "returns an array with the words that match '#{prefix}'" do
|
11
|
+
expect(container.scan prefix).to eq expected
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples_for 'a matching container#word' do
|
4
|
+
%w(hello high).each do |word|
|
5
|
+
it 'matches the whole word' do
|
6
|
+
expect(container.word? word).to be true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
shared_examples_for 'a non-matching container#word' do
|
12
|
+
%w(halt al).each do |word|
|
13
|
+
it 'does not match the whole word' do
|
14
|
+
expect(container.word? word).to be false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
shared_examples_for 'a propagating node' do
|
20
|
+
[
|
21
|
+
[true, 'Rambling::Trie::Nodes::Compressed'],
|
22
|
+
[false, 'Rambling::Trie::Nodes::Raw'],
|
23
|
+
].each do |test_params|
|
24
|
+
compressed_value, instance_double_class = test_params
|
25
|
+
|
26
|
+
context "when root has compressed=#{compressed_value}" do
|
27
|
+
let :root do
|
28
|
+
instance_double(
|
29
|
+
instance_double_class,
|
30
|
+
:root,
|
31
|
+
compressed?: compressed_value,
|
32
|
+
word?: nil,
|
33
|
+
partial_word?: nil,
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'calls the root with the word characters' do
|
38
|
+
container.public_send method_name, 'words'
|
39
|
+
expect(root).to have_received(method_name).with %w(w o r d s)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples_for 'a matching container#words_within' do
|
4
|
+
[
|
5
|
+
['word', %w(word)],
|
6
|
+
['wordxyz', %w(word)],
|
7
|
+
].each do |test_params|
|
8
|
+
phrase, expected = test_params
|
9
|
+
|
10
|
+
it "returns an array with the word found in the phrase '#{phrase}'" do
|
11
|
+
expect(container.words_within phrase).to match_array expected
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples_for 'a non-matching container#words_within' do
|
17
|
+
it 'returns an array with all words found in the phrase' do
|
18
|
+
expect(container.words_within 'xyzword otherzxyone')
|
19
|
+
.to match_array %w(word other one)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
shared_examples_for 'a matching container#words_within?' do
|
24
|
+
context 'when phrase does not contain any words' do
|
25
|
+
it 'returns false' do
|
26
|
+
expect(container.words_within? 'xyz').to be false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when phrase contains any word' do
|
31
|
+
['xyz words', 'xyzone word'].each do |phrase|
|
32
|
+
it "returns true for '#{phrase}'" do
|
33
|
+
expect(container.words_within? phrase).to be true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
shared_examples_for 'a non-matching container#words_within?' do
|
40
|
+
it 'returns an array with all words found in the phrase' do
|
41
|
+
expect(container.words_within 'xyzword otherzxyone')
|
42
|
+
.to match_array %w(word other one)
|
43
|
+
end
|
44
|
+
end
|
@@ -2,24 +2,20 @@
|
|
2
2
|
|
3
3
|
shared_examples_for 'a serializable trie' do
|
4
4
|
let(:tmp_path) { File.join ::SPEC_ROOT, 'tmp' }
|
5
|
-
let(:filepath) { File.join tmp_path, "trie-root.#{
|
5
|
+
let(:filepath) { File.join tmp_path, "trie-root.#{file_format}" }
|
6
6
|
|
7
|
-
context '
|
8
|
-
before
|
9
|
-
Rambling::Trie.dump trie_to_serialize, filepath
|
10
|
-
end
|
7
|
+
context 'with an uncompressed trie' do
|
8
|
+
before { Rambling::Trie.dump trie_to_serialize, filepath }
|
11
9
|
|
12
10
|
it_behaves_like 'a compressible trie' do
|
13
11
|
let(:trie) { Rambling::Trie.load filepath }
|
14
12
|
end
|
15
13
|
end
|
16
14
|
|
17
|
-
context '
|
15
|
+
context 'with an compressed trie' do
|
18
16
|
let(:trie) { Rambling::Trie.load filepath }
|
19
17
|
|
20
|
-
before
|
21
|
-
Rambling::Trie.dump trie_to_serialize.compress!, filepath
|
22
|
-
end
|
18
|
+
before { Rambling::Trie.dump trie_to_serialize.compress!, filepath }
|
23
19
|
|
24
20
|
it_behaves_like 'a trie data structure'
|
25
21
|
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
shared_examples_for 'a serializer' do
|
4
|
+
subject(:serializer) { described_class.new }
|
5
|
+
|
4
6
|
let(:trie) { Rambling::Trie.create }
|
5
7
|
let(:tmp_path) { File.join ::SPEC_ROOT, 'tmp' }
|
6
|
-
let(:filepath) { File.join tmp_path, "trie-root.#{
|
8
|
+
let(:filepath) { File.join tmp_path, "trie-root.#{file_format}" }
|
7
9
|
let(:content) { trie.root }
|
8
10
|
|
9
11
|
before do
|
@@ -12,26 +14,47 @@ shared_examples_for 'a serializer' do
|
|
12
14
|
end
|
13
15
|
|
14
16
|
describe '#dump' do
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
[true, false].each do |compress_value|
|
18
|
+
context "with compressed=#{compress_value} trie" do
|
19
|
+
let(:formatted_content) { format_content.call content }
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
before { trie.compress! if compress_value }
|
22
|
+
|
23
|
+
it 'returns the size in bytes of the file dumped' do
|
24
|
+
total_bytes = serializer.dump content, filepath
|
25
|
+
expect(total_bytes).to be_within(20).of formatted_content.size
|
26
|
+
end
|
22
27
|
|
23
|
-
|
24
|
-
|
28
|
+
it 'creates the file with the provided path' do
|
29
|
+
serializer.dump content, filepath
|
30
|
+
expect(File.exist? filepath).to be true
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'converts the contents to the appropriate format' do
|
34
|
+
serializer.dump content, filepath
|
35
|
+
expect(File.size filepath).to be_within(20).of formatted_content.size
|
36
|
+
end
|
37
|
+
end
|
25
38
|
end
|
26
39
|
end
|
27
40
|
|
28
41
|
describe '#load' do
|
29
|
-
|
30
|
-
|
31
|
-
|
42
|
+
[true, false].each do |compress_value|
|
43
|
+
context "with compressed=#{compress_value} trie" do
|
44
|
+
before do
|
45
|
+
trie.compress! if compress_value
|
46
|
+
serializer.dump content, filepath
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'loads the dumped object back into memory' do
|
50
|
+
expect(serializer.load filepath).to eq content
|
51
|
+
end
|
32
52
|
|
33
|
-
|
34
|
-
|
53
|
+
it "loads a compressed=#{compress_value} object" do
|
54
|
+
loaded = serializer.load filepath
|
55
|
+
expect(loaded.compressed?).to be compress_value unless :file == file_format
|
56
|
+
end
|
57
|
+
end
|
35
58
|
end
|
36
59
|
end
|
37
60
|
end
|
@@ -2,25 +2,39 @@
|
|
2
2
|
|
3
3
|
shared_examples_for 'a trie data structure' do
|
4
4
|
it 'contains all the words previously provided' do
|
5
|
-
words.each
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
words.each { |word| expect(trie).to include word }
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'returns true for #word? for all words previously provided' do
|
9
|
+
words.each { |word| expect(trie.word? word).to be true }
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'matches the full word for all words in file' do
|
13
|
+
words.each { |word| expect(trie.match? word).to be true }
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'matches the start of all the words in file' do
|
17
|
+
words.each { |word| expect(trie.match? word[0..-2]).to be true }
|
9
18
|
end
|
10
19
|
|
11
|
-
it '
|
20
|
+
it 'returns true for #partial_word? with full word for all words in file' do
|
21
|
+
words.each { |word| expect(trie.partial_word? word).to be true }
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'returns true for #partial_word? with the start of all words in file' do
|
25
|
+
words.each { |word| expect(trie.partial_word? word[0..-2]).to be true }
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'extracts words within larger strings' do
|
12
29
|
words.each do |word|
|
13
|
-
|
14
|
-
expect(trie.
|
15
|
-
expect(trie.partial_word? word).to be true
|
16
|
-
expect(trie.partial_word? word[0..-2]).to be true
|
30
|
+
phrase = "x#{word}y"
|
31
|
+
expect(trie.words_within phrase).to include word
|
17
32
|
end
|
18
33
|
end
|
19
34
|
|
20
35
|
it 'identifies words within larger strings' do
|
21
36
|
words.each do |word|
|
22
37
|
phrase = "x#{word}y"
|
23
|
-
expect(trie.words_within phrase).to include word
|
24
38
|
expect(trie.words_within? phrase).to be true
|
25
39
|
end
|
26
40
|
end
|