rambling-trie 1.0.2 → 2.2.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.
- checksums.yaml +5 -5
- data/Gemfile +6 -3
- data/Guardfile +3 -1
- data/README.md +30 -12
- data/Rakefile +8 -0
- data/lib/rambling-trie.rb +2 -0
- data/lib/rambling/trie.rb +48 -26
- data/lib/rambling/trie/comparable.rb +6 -3
- data/lib/rambling/trie/compressible.rb +16 -0
- data/lib/rambling/trie/compressor.rb +39 -24
- data/lib/rambling/trie/configuration.rb +3 -1
- data/lib/rambling/trie/configuration/properties.rb +18 -9
- data/lib/rambling/trie/configuration/provider_collection.rb +38 -17
- data/lib/rambling/trie/container.rb +123 -36
- data/lib/rambling/trie/enumerable.rb +6 -4
- data/lib/rambling/trie/inspectable.rb +2 -0
- data/lib/rambling/trie/invalid_operation.rb +3 -1
- data/lib/rambling/trie/nodes.rb +13 -0
- data/lib/rambling/trie/nodes/compressed.rb +98 -0
- data/lib/rambling/trie/nodes/missing.rb +12 -0
- data/lib/rambling/trie/nodes/node.rb +183 -0
- data/lib/rambling/trie/nodes/raw.rb +82 -0
- data/lib/rambling/trie/readers.rb +3 -1
- data/lib/rambling/trie/readers/plain_text.rb +3 -11
- data/lib/rambling/trie/serializers.rb +3 -1
- data/lib/rambling/trie/serializers/file.rb +2 -0
- data/lib/rambling/trie/serializers/marshal.rb +15 -5
- data/lib/rambling/trie/serializers/yaml.rb +21 -5
- data/lib/rambling/trie/serializers/zip.rb +15 -8
- data/lib/rambling/trie/stringifyable.rb +8 -2
- data/lib/rambling/trie/version.rb +3 -1
- data/rambling-trie.gemspec +21 -10
- data/spec/assets/test_words.es_DO.txt +1 -0
- data/spec/integration/rambling/trie_spec.rb +44 -35
- data/spec/lib/rambling/trie/comparable_spec.rb +8 -15
- data/spec/lib/rambling/trie/compressor_spec.rb +90 -13
- data/spec/lib/rambling/trie/configuration/properties_spec.rb +21 -13
- data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +18 -34
- data/spec/lib/rambling/trie/container_spec.rb +183 -217
- data/spec/lib/rambling/trie/enumerable_spec.rb +14 -9
- data/spec/lib/rambling/trie/inspectable_spec.rb +36 -11
- data/spec/lib/rambling/trie/nodes/compressed_spec.rb +37 -0
- data/spec/lib/rambling/trie/nodes/node_spec.rb +9 -0
- data/spec/lib/rambling/trie/nodes/raw_spec.rb +179 -0
- data/spec/lib/rambling/trie/readers/plain_text_spec.rb +3 -1
- data/spec/lib/rambling/trie/serializers/file_spec.rb +6 -4
- data/spec/lib/rambling/trie/serializers/marshal_spec.rb +5 -7
- data/spec/lib/rambling/trie/serializers/yaml_spec.rb +5 -7
- data/spec/lib/rambling/trie/serializers/zip_spec.rb +18 -20
- data/spec/lib/rambling/trie/stringifyable_spec.rb +14 -11
- data/spec/lib/rambling/trie_spec.rb +18 -11
- data/spec/spec_helper.rb +10 -5
- data/spec/support/config.rb +10 -0
- data/spec/support/helpers/add_word.rb +20 -0
- data/spec/support/helpers/one_line_heredoc.rb +11 -0
- data/spec/support/shared_examples/a_compressible_trie.rb +40 -0
- data/spec/support/shared_examples/a_serializable_trie.rb +10 -6
- data/spec/support/shared_examples/a_serializer.rb +9 -1
- data/spec/support/shared_examples/a_trie_data_structure.rb +2 -0
- data/spec/support/shared_examples/a_trie_node.rb +127 -0
- data/spec/{lib/rambling/trie/compressed_node_spec.rb → support/shared_examples/a_trie_node_implementation.rb} +25 -72
- metadata +42 -31
- data/lib/rambling/trie/compressable.rb +0 -14
- data/lib/rambling/trie/compressed_node.rb +0 -120
- data/lib/rambling/trie/missing_node.rb +0 -8
- data/lib/rambling/trie/node.rb +0 -97
- data/lib/rambling/trie/raw_node.rb +0 -96
- data/spec/lib/rambling/trie/node_spec.rb +0 -86
- data/spec/lib/rambling/trie/raw_node_spec.rb +0 -389
- data/spec/support/shared_examples/a_compressable_trie.rb +0 -26
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Rambling::Trie::Configuration::ProviderCollection do
|
@@ -11,15 +13,15 @@ describe Rambling::Trie::Configuration::ProviderCollection do
|
|
11
13
|
|
12
14
|
let(:provider_collection) do
|
13
15
|
Rambling::Trie::Configuration::ProviderCollection.new(
|
14
|
-
|
16
|
+
:provider,
|
15
17
|
configured_providers,
|
16
|
-
configured_default
|
18
|
+
configured_default,
|
17
19
|
)
|
18
20
|
end
|
19
21
|
|
20
22
|
describe '.new' do
|
21
23
|
it 'has a name' do
|
22
|
-
expect(provider_collection.name).to eq
|
24
|
+
expect(provider_collection.name).to eq :provider
|
23
25
|
end
|
24
26
|
|
25
27
|
it 'has the given providers' do
|
@@ -45,32 +47,20 @@ describe Rambling::Trie::Configuration::ProviderCollection do
|
|
45
47
|
|
46
48
|
before do
|
47
49
|
allow(providers) .to receive_messages(
|
48
|
-
:[] =>
|
49
|
-
:
|
50
|
-
keys: nil,
|
51
|
-
values: nil,
|
50
|
+
:[] => 'value',
|
51
|
+
keys: %i(a b),
|
52
52
|
)
|
53
53
|
end
|
54
54
|
|
55
|
-
it 'delegates
|
56
|
-
provider_collection[:key]
|
55
|
+
it 'delegates `#[]` to providers' do
|
56
|
+
expect(provider_collection[:key]).to eq 'value'
|
57
57
|
expect(providers).to have_received(:[]).with :key
|
58
58
|
end
|
59
59
|
|
60
|
-
it '
|
61
|
-
provider_collection
|
62
|
-
expect(providers).to have_received(:[]=).with :key, 'hello'
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'delegates #keys to providers' do
|
66
|
-
provider_collection.keys
|
60
|
+
it 'aliases `#formats` to `providers#keys`' do
|
61
|
+
expect(provider_collection.formats).to eq %i(a b)
|
67
62
|
expect(providers).to have_received :keys
|
68
63
|
end
|
69
|
-
|
70
|
-
it 'delegates #values to providers' do
|
71
|
-
provider_collection.values
|
72
|
-
expect(providers).to have_received :values
|
73
|
-
end
|
74
64
|
end
|
75
65
|
|
76
66
|
describe '#add' do
|
@@ -96,26 +86,20 @@ describe Rambling::Trie::Configuration::ProviderCollection do
|
|
96
86
|
end
|
97
87
|
|
98
88
|
context 'when the given value is not in the providers list' do
|
99
|
-
it '
|
100
|
-
expect
|
101
|
-
|
102
|
-
|
103
|
-
rescue
|
104
|
-
end
|
105
|
-
end.not_to change { provider_collection.default }
|
89
|
+
it 'raises an error and keeps the default provider' do
|
90
|
+
expect { provider_collection.default = other_provider }
|
91
|
+
.to raise_error(ArgumentError)
|
92
|
+
.and(not_change { provider_collection.default })
|
106
93
|
end
|
107
94
|
|
108
95
|
it 'raises an ArgumentError' do
|
109
|
-
expect
|
110
|
-
|
111
|
-
end.to raise_error ArgumentError
|
96
|
+
expect { provider_collection.default = other_provider }
|
97
|
+
.to raise_error ArgumentError
|
112
98
|
end
|
113
99
|
end
|
114
100
|
|
115
101
|
context 'when the providers list is empty' do
|
116
|
-
let(:configured_providers)
|
117
|
-
{}
|
118
|
-
end
|
102
|
+
let(:configured_providers) { {} }
|
119
103
|
|
120
104
|
it 'accepts nil' do
|
121
105
|
provider_collection.default = nil
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Rambling::Trie::Container do
|
4
6
|
let(:container) { Rambling::Trie::Container.new root, compressor }
|
5
7
|
let(:compressor) { Rambling::Trie::Compressor.new }
|
6
|
-
let(:root) { Rambling::Trie::
|
8
|
+
let(:root) { Rambling::Trie::Nodes::Raw.new }
|
7
9
|
|
8
10
|
describe '.new' do
|
9
11
|
it 'uses the provided node as root' do
|
@@ -14,8 +16,8 @@ describe Rambling::Trie::Container do
|
|
14
16
|
it 'yields the container' do
|
15
17
|
yielded = nil
|
16
18
|
|
17
|
-
container = Rambling::Trie::Container.new root, compressor do |
|
18
|
-
yielded =
|
19
|
+
container = Rambling::Trie::Container.new root, compressor do |c|
|
20
|
+
yielded = c
|
19
21
|
end
|
20
22
|
|
21
23
|
expect(yielded).to be container
|
@@ -24,40 +26,51 @@ describe Rambling::Trie::Container do
|
|
24
26
|
end
|
25
27
|
|
26
28
|
describe '#add' do
|
27
|
-
|
28
|
-
|
29
|
+
it 'adds the word to the root node' do
|
30
|
+
add_word container, 'hello'
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
+
expect(root.children.size).to eq 1
|
33
|
+
expect(root.to_a).to eq %w(hello)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#concat' do
|
38
|
+
it 'adds all the words to the root node' do
|
39
|
+
container.concat %w(other words)
|
40
|
+
|
41
|
+
expect(root.children.size).to eq 2
|
42
|
+
expect(root.to_a).to eq %w(other words)
|
32
43
|
end
|
33
44
|
|
34
|
-
it '
|
35
|
-
container.
|
36
|
-
|
45
|
+
it 'returns all the corresponding nodes' do
|
46
|
+
nodes = container.concat %w(other words)
|
47
|
+
|
48
|
+
expect(nodes.first.letter).to eq :o
|
49
|
+
expect(nodes.last.letter).to eq :w
|
37
50
|
end
|
38
51
|
end
|
39
52
|
|
40
53
|
describe '#compress!' do
|
41
|
-
let(:node) {
|
54
|
+
let(:node) { Rambling::Trie::Nodes::Compressed.new }
|
42
55
|
|
43
56
|
before do
|
44
57
|
allow(compressor).to receive(:compress).and_return node
|
45
|
-
|
58
|
+
|
59
|
+
add_word root, 'yes'
|
60
|
+
node[:yes] = Rambling::Trie::Nodes::Compressed.new
|
46
61
|
end
|
47
62
|
|
48
63
|
it 'compresses the trie using the compressor' do
|
49
64
|
container.compress!
|
50
65
|
|
51
|
-
expect(compressor).to have_received(:compress)
|
52
|
-
.with root
|
66
|
+
expect(compressor).to have_received(:compress).with root
|
53
67
|
end
|
54
68
|
|
55
69
|
it 'changes to the root returned by the compressor' do
|
56
70
|
container.compress!
|
57
|
-
container.add 'word'
|
58
71
|
|
59
|
-
expect(root).not_to
|
60
|
-
expect(
|
72
|
+
expect(container.root).not_to eq root
|
73
|
+
expect(container.root).to eq node
|
61
74
|
end
|
62
75
|
|
63
76
|
it 'returns itself' do
|
@@ -73,13 +86,57 @@ describe Rambling::Trie::Container do
|
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
89
|
+
describe '#compress' do
|
90
|
+
let(:node) { Rambling::Trie::Nodes::Compressed.new }
|
91
|
+
|
92
|
+
before do
|
93
|
+
allow(compressor).to receive(:compress).and_return node
|
94
|
+
|
95
|
+
add_word root, 'yes'
|
96
|
+
node[:yes] = Rambling::Trie::Nodes::Compressed.new
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'compresses the trie using the compressor' do
|
100
|
+
container.compress
|
101
|
+
|
102
|
+
expect(compressor).to have_received(:compress).with root
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns a container with the new root' do
|
106
|
+
new_container = container.compress
|
107
|
+
|
108
|
+
expect(new_container.root).not_to eq root
|
109
|
+
expect(new_container.root).to eq node
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'returns a new container' do
|
113
|
+
expect(container.compress).not_to eq container
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'can compress multiple times' do
|
117
|
+
container.compress
|
118
|
+
container.compress
|
119
|
+
|
120
|
+
expect(compressor).to have_received(:compress).twice
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'cannot compress the result' do
|
124
|
+
new_container = container.compress
|
125
|
+
new_container.compress
|
126
|
+
|
127
|
+
expect(compressor).to have_received(:compress).once
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
76
131
|
describe '#word?' do
|
132
|
+
let(:root) do
|
133
|
+
double :root,
|
134
|
+
compressed?: compressed,
|
135
|
+
word?: nil
|
136
|
+
end
|
137
|
+
|
77
138
|
context 'for an uncompressed root' do
|
78
|
-
let(:
|
79
|
-
double :root,
|
80
|
-
compressed?: false,
|
81
|
-
word?: nil
|
82
|
-
end
|
139
|
+
let(:compressed) { true }
|
83
140
|
|
84
141
|
it 'calls the root with the word characters' do
|
85
142
|
container.word? 'words'
|
@@ -88,11 +145,7 @@ describe Rambling::Trie::Container do
|
|
88
145
|
end
|
89
146
|
|
90
147
|
context 'for a compressed root' do
|
91
|
-
let(:
|
92
|
-
double :root,
|
93
|
-
compressed?: true,
|
94
|
-
word?: nil
|
95
|
-
end
|
148
|
+
let(:compressed) { false }
|
96
149
|
|
97
150
|
it 'calls the root with the full word' do
|
98
151
|
container.word? 'words'
|
@@ -102,12 +155,14 @@ describe Rambling::Trie::Container do
|
|
102
155
|
end
|
103
156
|
|
104
157
|
describe '#partial_word?' do
|
158
|
+
let(:root) do
|
159
|
+
double :root,
|
160
|
+
compressed?: compressed,
|
161
|
+
partial_word?: nil
|
162
|
+
end
|
163
|
+
|
105
164
|
context 'for an uncompressed root' do
|
106
|
-
let(:
|
107
|
-
double :root,
|
108
|
-
compressed?: false,
|
109
|
-
partial_word?: nil
|
110
|
-
end
|
165
|
+
let(:compressed) { true }
|
111
166
|
|
112
167
|
it 'calls the root with the word characters' do
|
113
168
|
container.partial_word? 'words'
|
@@ -116,11 +171,7 @@ describe Rambling::Trie::Container do
|
|
116
171
|
end
|
117
172
|
|
118
173
|
context 'for a compressed root' do
|
119
|
-
let(:
|
120
|
-
double :root,
|
121
|
-
compressed?: true,
|
122
|
-
partial_word?: nil
|
123
|
-
end
|
174
|
+
let(:compressed) { false }
|
124
175
|
|
125
176
|
it 'calls the root with the word characters' do
|
126
177
|
container.partial_word? 'words'
|
@@ -139,7 +190,7 @@ describe Rambling::Trie::Container do
|
|
139
190
|
children_tree: nil,
|
140
191
|
compressed?: nil,
|
141
192
|
each: nil,
|
142
|
-
|
193
|
+
key?: nil,
|
143
194
|
inspect: nil,
|
144
195
|
letter: nil,
|
145
196
|
parent: nil,
|
@@ -168,17 +219,12 @@ describe Rambling::Trie::Container do
|
|
168
219
|
|
169
220
|
it 'aliases `#<<` to `#add`' do
|
170
221
|
container << 'words'
|
171
|
-
expect(root).to have_received(:add).with
|
222
|
+
expect(root).to have_received(:add).with %i(s d r o w)
|
172
223
|
end
|
173
224
|
|
174
225
|
it 'delegates `#[]` to the root node' do
|
175
|
-
container
|
176
|
-
expect(root).to have_received
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'delegates `#as_word` to the root node' do
|
180
|
-
container.as_word
|
181
|
-
expect(root).to have_received :as_word
|
226
|
+
container[:yep]
|
227
|
+
expect(root).to have_received(:[]).with :yep
|
182
228
|
end
|
183
229
|
|
184
230
|
it 'delegates `#children` to the root node' do
|
@@ -196,14 +242,19 @@ describe Rambling::Trie::Container do
|
|
196
242
|
expect(root).to have_received :compressed?
|
197
243
|
end
|
198
244
|
|
199
|
-
it 'delegates `#
|
200
|
-
container.
|
201
|
-
expect(root).to have_received :
|
245
|
+
it 'delegates `#key?` to the root node' do
|
246
|
+
container.key? :yup
|
247
|
+
expect(root).to have_received(:key?).with :yup
|
202
248
|
end
|
203
249
|
|
204
|
-
it '
|
205
|
-
container.has_key?
|
206
|
-
expect(root).to have_received :
|
250
|
+
it 'aliases `#has_key?` to `#key?`' do
|
251
|
+
container.has_key? :yup
|
252
|
+
expect(root).to have_received(:key?).with :yup
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'aliases `#has_letter?` to `#has_key?`' do
|
256
|
+
container.has_letter? :yup
|
257
|
+
expect(root).to have_received(:key?).with :yup
|
207
258
|
end
|
208
259
|
|
209
260
|
it 'delegates `#inspect` to the root node' do
|
@@ -211,140 +262,48 @@ describe Rambling::Trie::Container do
|
|
211
262
|
expect(root).to have_received :inspect
|
212
263
|
end
|
213
264
|
|
214
|
-
it 'delegates `#letter` to the root node' do
|
215
|
-
container.letter
|
216
|
-
expect(root).to have_received :letter
|
217
|
-
end
|
218
|
-
|
219
|
-
it 'delegates `#parent` to the root node' do
|
220
|
-
container.parent
|
221
|
-
expect(root).to have_received :parent
|
222
|
-
end
|
223
|
-
|
224
265
|
it 'delegates `#size` to the root node' do
|
225
266
|
container.size
|
226
267
|
expect(root).to have_received :size
|
227
268
|
end
|
228
|
-
|
229
|
-
it 'delegates `#to_s` to the root node' do
|
230
|
-
container.to_s
|
231
|
-
expect(root).to have_received :to_s
|
232
|
-
end
|
233
269
|
end
|
234
270
|
|
235
271
|
describe '#compress!' do
|
236
|
-
|
237
|
-
let(:root) { Rambling::Trie::RawNode.new }
|
238
|
-
|
239
|
-
context 'with at least one word' do
|
240
|
-
it 'keeps the root letter nil' do
|
241
|
-
container.add 'all'
|
242
|
-
container.compress!
|
243
|
-
|
244
|
-
expect(container.letter).to be_nil
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
context 'with a single word' do
|
249
|
-
before do
|
250
|
-
container.add 'all'
|
251
|
-
container.compress!
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'compresses into a single node without children' do
|
255
|
-
expect(container[:all].letter).to eq :all
|
256
|
-
expect(container[:all].children.size).to eq 0
|
257
|
-
expect(container[:all]).to be_terminal
|
258
|
-
expect(container[:all]).to be_compressed
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
context 'with two words' do
|
263
|
-
before do
|
264
|
-
container.add 'all'
|
265
|
-
container.add 'ask'
|
266
|
-
container.compress!
|
267
|
-
end
|
268
|
-
|
269
|
-
it 'compresses into corresponding three nodes' do
|
270
|
-
expect(container[:a].letter).to eq :a
|
271
|
-
expect(container[:a].children.size).to eq 2
|
272
|
-
|
273
|
-
expect(container[:a][:ll].letter).to eq :ll
|
274
|
-
expect(container[:a][:sk].letter).to eq :sk
|
275
|
-
|
276
|
-
expect(container[:a][:ll].children.size).to eq 0
|
277
|
-
expect(container[:a][:sk].children.size).to eq 0
|
278
|
-
|
279
|
-
expect(container[:a][:ll]).to be_terminal
|
280
|
-
expect(container[:a][:sk]).to be_terminal
|
281
|
-
|
282
|
-
expect(container[:a][:ll]).to be_compressed
|
283
|
-
expect(container[:a][:sk]).to be_compressed
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
it 'reassigns the parent nodes correctly' do
|
288
|
-
container.add 'repay'
|
289
|
-
container.add 'rest'
|
290
|
-
container.add 'repaint'
|
272
|
+
it 'gets a new root from the compressor' do
|
291
273
|
container.compress!
|
292
274
|
|
293
|
-
expect(container
|
294
|
-
expect(container
|
295
|
-
|
296
|
-
expect(container[:re][:pa].letter).to eq :pa
|
297
|
-
expect(container[:re][:st].letter).to eq :st
|
298
|
-
|
299
|
-
expect(container[:re][:pa].children.size).to eq 2
|
300
|
-
expect(container[:re][:st].children.size).to eq 0
|
301
|
-
|
302
|
-
expect(container[:re][:pa][:y].letter).to eq :y
|
303
|
-
expect(container[:re][:pa][:int].letter).to eq :int
|
304
|
-
|
305
|
-
expect(container[:re][:pa][:y].children.size).to eq 0
|
306
|
-
expect(container[:re][:pa][:int].children.size).to eq 0
|
307
|
-
|
308
|
-
expect(container[:re][:pa][:y].parent).to eq container[:re][:pa]
|
309
|
-
expect(container[:re][:pa][:int].parent).to eq container[:re][:pa]
|
275
|
+
expect(container.root).not_to be root
|
276
|
+
expect(container.root).to be_compressed
|
277
|
+
expect(root).not_to be_compressed
|
310
278
|
end
|
311
279
|
|
312
|
-
it '
|
313
|
-
|
314
|
-
container.add 'your'
|
315
|
-
container.add 'yours'
|
280
|
+
it 'generates a new root with the words from the passed root' do
|
281
|
+
words = %w(a few words hello hell)
|
316
282
|
|
283
|
+
add_words container, words
|
317
284
|
container.compress!
|
318
285
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
expect(container[:you][:r]).to be_compressed
|
323
|
-
|
324
|
-
expect(container[:you][:r][:s].letter).to eq :s
|
325
|
-
expect(container[:you][:r][:s]).to be_compressed
|
286
|
+
words.each do |word|
|
287
|
+
expect(container).to include word
|
288
|
+
end
|
326
289
|
end
|
327
290
|
|
328
291
|
describe 'and trying to add a word' do
|
329
292
|
it 'raises an error' do
|
330
|
-
container
|
331
|
-
container.add 'rest'
|
332
|
-
container.add 'repaint'
|
293
|
+
add_words container, %w(repay rest repaint)
|
333
294
|
container.compress!
|
334
295
|
|
335
|
-
expect
|
296
|
+
expect do
|
297
|
+
add_word container, 'restaurant'
|
298
|
+
end.to raise_error Rambling::Trie::InvalidOperation
|
336
299
|
end
|
337
300
|
end
|
338
301
|
end
|
339
302
|
|
340
303
|
describe '#word?' do
|
341
|
-
let(:compressor) { Rambling::Trie::Compressor.new }
|
342
|
-
let(:root) { Rambling::Trie::RawNode.new }
|
343
|
-
|
344
304
|
context 'word is contained' do
|
345
305
|
before do
|
346
|
-
container
|
347
|
-
container.add 'high'
|
306
|
+
add_words container, %w(hello high)
|
348
307
|
end
|
349
308
|
|
350
309
|
it 'matches the whole word' do
|
@@ -366,7 +325,7 @@ describe Rambling::Trie::Container do
|
|
366
325
|
|
367
326
|
context 'word is not contained' do
|
368
327
|
before do
|
369
|
-
container
|
328
|
+
add_word container, 'hello'
|
370
329
|
end
|
371
330
|
|
372
331
|
it 'does not match the whole word' do
|
@@ -390,8 +349,7 @@ describe Rambling::Trie::Container do
|
|
390
349
|
describe '#partial_word?' do
|
391
350
|
context 'word is contained' do
|
392
351
|
before do
|
393
|
-
container
|
394
|
-
container.add 'high'
|
352
|
+
add_words container, %w(hello high)
|
395
353
|
end
|
396
354
|
|
397
355
|
it 'matches part of the word' do
|
@@ -416,27 +374,25 @@ describe Rambling::Trie::Container do
|
|
416
374
|
end
|
417
375
|
end
|
418
376
|
|
377
|
+
shared_examples_for 'a non matching tree' do
|
378
|
+
it 'does not match any part of the word' do
|
379
|
+
%w(ha hal al).each do |word|
|
380
|
+
expect(container.partial_word? word).to be false
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
419
385
|
context 'word is not contained' do
|
420
386
|
before do
|
421
|
-
container
|
387
|
+
add_word container, 'hello'
|
422
388
|
end
|
423
389
|
|
424
|
-
|
425
|
-
|
426
|
-
expect(container.partial_word? 'hal').to be false
|
427
|
-
expect(container.partial_word? 'al').to be false
|
390
|
+
context 'and the root is uncompressed' do
|
391
|
+
it_behaves_like 'a non matching tree'
|
428
392
|
end
|
429
393
|
|
430
394
|
context 'and the root has been compressed' do
|
431
|
-
|
432
|
-
container.compress!
|
433
|
-
end
|
434
|
-
|
435
|
-
it 'does not match any part of the word' do
|
436
|
-
expect(container.partial_word? 'ha').to be false
|
437
|
-
expect(container.partial_word? 'hal').to be false
|
438
|
-
expect(container.partial_word? 'al').to be false
|
439
|
-
end
|
395
|
+
it_behaves_like 'a non matching tree'
|
440
396
|
end
|
441
397
|
end
|
442
398
|
end
|
@@ -444,23 +400,12 @@ describe Rambling::Trie::Container do
|
|
444
400
|
describe '#scan' do
|
445
401
|
context 'words that match are not contained' do
|
446
402
|
before do
|
447
|
-
%w(hi hello high hell highlight histerical)
|
448
|
-
container.add word
|
449
|
-
end
|
403
|
+
add_words container, %w(hi hello high hell highlight histerical)
|
450
404
|
end
|
451
405
|
|
452
406
|
it 'returns an array with the words that match' do
|
453
|
-
expect(container.scan 'hi').to eq
|
454
|
-
|
455
|
-
'high',
|
456
|
-
'highlight',
|
457
|
-
'histerical'
|
458
|
-
]
|
459
|
-
|
460
|
-
expect(container.scan 'hig').to eq [
|
461
|
-
'high',
|
462
|
-
'highlight'
|
463
|
-
]
|
407
|
+
expect(container.scan 'hi').to eq %w(hi high highlight histerical)
|
408
|
+
expect(container.scan 'hig').to eq %w(high highlight)
|
464
409
|
end
|
465
410
|
|
466
411
|
context 'and the root has been compressed' do
|
@@ -469,28 +414,19 @@ describe Rambling::Trie::Container do
|
|
469
414
|
end
|
470
415
|
|
471
416
|
it 'returns an array with the words that match' do
|
472
|
-
expect(container.scan 'hi').to eq
|
473
|
-
|
474
|
-
'high',
|
475
|
-
'highlight',
|
476
|
-
'histerical'
|
477
|
-
]
|
478
|
-
|
479
|
-
expect(container.scan 'hig').to eq [
|
480
|
-
'high',
|
481
|
-
'highlight'
|
482
|
-
]
|
417
|
+
expect(container.scan 'hi').to eq %w(hi high highlight histerical)
|
418
|
+
expect(container.scan 'hig').to eq %w(high highlight)
|
483
419
|
end
|
484
420
|
end
|
485
421
|
end
|
486
422
|
|
487
423
|
context 'words that match are not contained' do
|
488
424
|
before do
|
489
|
-
container
|
425
|
+
add_word container, 'hello'
|
490
426
|
end
|
491
427
|
|
492
428
|
it 'returns an empty array' do
|
493
|
-
expect(container.scan 'hi').to eq
|
429
|
+
expect(container.scan 'hi').to eq %w()
|
494
430
|
end
|
495
431
|
|
496
432
|
context 'and the root has been compressed' do
|
@@ -499,7 +435,7 @@ describe Rambling::Trie::Container do
|
|
499
435
|
end
|
500
436
|
|
501
437
|
it 'returns an empty array' do
|
502
|
-
expect(container.scan 'hi').to eq
|
438
|
+
expect(container.scan 'hi').to eq %w()
|
503
439
|
end
|
504
440
|
end
|
505
441
|
end
|
@@ -507,9 +443,7 @@ describe Rambling::Trie::Container do
|
|
507
443
|
|
508
444
|
describe '#words_within' do
|
509
445
|
before do
|
510
|
-
%w(one word and other words)
|
511
|
-
container.add word
|
512
|
-
end
|
446
|
+
add_words container, %w(one word and other words)
|
513
447
|
end
|
514
448
|
|
515
449
|
context 'phrase does not contain any words' do
|
@@ -564,7 +498,8 @@ describe Rambling::Trie::Container do
|
|
564
498
|
|
565
499
|
context 'phrase contains a few words' do
|
566
500
|
it 'returns an array with all words found in the phrase' do
|
567
|
-
expect(container.words_within 'xyzword otherzxyone')
|
501
|
+
expect(container.words_within 'xyzword otherzxyone')
|
502
|
+
.to match_array %w(word other one)
|
568
503
|
end
|
569
504
|
|
570
505
|
context 'and the node is compressed' do
|
@@ -573,7 +508,8 @@ describe Rambling::Trie::Container do
|
|
573
508
|
end
|
574
509
|
|
575
510
|
it 'returns an array with all words found in the phrase' do
|
576
|
-
expect(container.words_within 'xyzword otherzxyone')
|
511
|
+
expect(container.words_within 'xyzword otherzxyone')
|
512
|
+
.to match_array %w(word other one)
|
577
513
|
end
|
578
514
|
end
|
579
515
|
end
|
@@ -581,9 +517,7 @@ describe Rambling::Trie::Container do
|
|
581
517
|
|
582
518
|
describe '#words_within?' do
|
583
519
|
before do
|
584
|
-
%w(one word and other words)
|
585
|
-
container.add word
|
586
|
-
end
|
520
|
+
add_words container, %w(one word and other words)
|
587
521
|
end
|
588
522
|
|
589
523
|
context 'phrase does not contain any words' do
|
@@ -602,7 +536,9 @@ describe Rambling::Trie::Container do
|
|
602
536
|
|
603
537
|
describe '#==' do
|
604
538
|
context 'when the root nodes are the same' do
|
605
|
-
let(:other_container)
|
539
|
+
let(:other_container) do
|
540
|
+
Rambling::Trie::Container.new container.root, compressor
|
541
|
+
end
|
606
542
|
|
607
543
|
it 'returns true' do
|
608
544
|
expect(container).to eq other_container
|
@@ -610,11 +546,13 @@ describe Rambling::Trie::Container do
|
|
610
546
|
end
|
611
547
|
|
612
548
|
context 'when the root nodes are not the same' do
|
613
|
-
let(:other_root) { Rambling::Trie::
|
549
|
+
let(:other_root) { Rambling::Trie::Nodes::Raw.new }
|
614
550
|
let(:other_container) do
|
615
|
-
Rambling::Trie::Container.new other_root, compressor
|
616
|
-
|
617
|
-
|
551
|
+
Rambling::Trie::Container.new other_root, compressor
|
552
|
+
end
|
553
|
+
|
554
|
+
before do
|
555
|
+
add_word other_container, 'hola'
|
618
556
|
end
|
619
557
|
|
620
558
|
it 'returns false' do
|
@@ -622,4 +560,32 @@ describe Rambling::Trie::Container do
|
|
622
560
|
end
|
623
561
|
end
|
624
562
|
end
|
563
|
+
|
564
|
+
describe '#each' do
|
565
|
+
before do
|
566
|
+
add_words container, %w(yes no why)
|
567
|
+
end
|
568
|
+
|
569
|
+
it 'returns an enumerator when no block is given' do
|
570
|
+
expect(container.each).to be_instance_of Enumerator
|
571
|
+
end
|
572
|
+
|
573
|
+
it 'iterates through all words contained' do
|
574
|
+
expect(container.each.to_a).to eq %w(yes no why)
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
describe '#inspect' do
|
579
|
+
before do
|
580
|
+
add_words container, %w(a few words hello hell)
|
581
|
+
end
|
582
|
+
|
583
|
+
it 'returns the container class name plus the root inspection' do
|
584
|
+
expect(container.inspect).to eq one_line <<~CONTAINER
|
585
|
+
#<Rambling::Trie::Container root: #<Rambling::Trie::Nodes::Raw letter: nil,
|
586
|
+
terminal: nil,
|
587
|
+
children: [:a, :f, :w, :h]>>
|
588
|
+
CONTAINER
|
589
|
+
end
|
590
|
+
end
|
625
591
|
end
|