rambling-trie 0.9.3 → 1.0.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 +4 -4
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.md +133 -26
- data/Rakefile +1 -2
- data/lib/rambling/trie.rb +53 -9
- data/lib/rambling/trie/comparable.rb +16 -0
- data/lib/rambling/trie/compressable.rb +14 -0
- data/lib/rambling/trie/compressed_node.rb +38 -14
- data/lib/rambling/trie/compressor.rb +14 -10
- data/lib/rambling/trie/configuration.rb +11 -0
- data/lib/rambling/trie/configuration/properties.rb +66 -0
- data/lib/rambling/trie/configuration/provider_collection.rb +101 -0
- data/lib/rambling/trie/container.rb +57 -17
- data/lib/rambling/trie/enumerable.rb +1 -1
- data/lib/rambling/trie/forwardable.rb +9 -4
- data/lib/rambling/trie/inspectable.rb +37 -0
- data/lib/rambling/trie/invalid_operation.rb +3 -2
- data/lib/rambling/trie/missing_node.rb +2 -1
- data/lib/rambling/trie/node.rb +40 -30
- data/lib/rambling/trie/raw_node.rb +29 -13
- data/lib/rambling/trie/readers.rb +11 -0
- data/lib/rambling/trie/readers/plain_text.rb +26 -0
- data/lib/rambling/trie/serializers.rb +11 -0
- data/lib/rambling/trie/serializers/file.rb +25 -0
- data/lib/rambling/trie/serializers/marshal.rb +38 -0
- data/lib/rambling/trie/serializers/yaml.rb +39 -0
- data/lib/rambling/trie/serializers/zip.rb +67 -0
- data/lib/rambling/trie/stringifyable.rb +20 -0
- data/lib/rambling/trie/version.rb +1 -1
- data/rambling-trie.gemspec +2 -2
- data/spec/integration/rambling/trie_spec.rb +45 -49
- data/spec/lib/rambling/trie/comparable_spec.rb +104 -0
- data/spec/lib/rambling/trie/compressed_node_spec.rb +44 -0
- data/spec/lib/rambling/trie/configuration/properties_spec.rb +49 -0
- data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +165 -0
- data/spec/lib/rambling/trie/container_spec.rb +127 -38
- data/spec/lib/rambling/trie/{inspector_spec.rb → inspectable_spec.rb} +7 -5
- data/spec/lib/rambling/trie/raw_node_spec.rb +22 -41
- data/spec/lib/rambling/trie/readers/plain_text_spec.rb +14 -0
- data/spec/lib/rambling/trie/serializers/file_spec.rb +11 -0
- data/spec/lib/rambling/trie/serializers/marshal_spec.rb +14 -0
- data/spec/lib/rambling/trie/serializers/yaml_spec.rb +14 -0
- data/spec/lib/rambling/trie/serializers/zip_spec.rb +30 -0
- data/spec/lib/rambling/trie/stringifyable_spec.rb +82 -0
- data/spec/lib/rambling/trie_spec.rb +120 -7
- data/spec/spec_helper.rb +7 -1
- data/spec/support/config.rb +5 -0
- data/spec/support/shared_examples/a_compressable_trie.rb +26 -0
- data/spec/support/shared_examples/a_serializable_trie.rb +26 -0
- data/spec/support/shared_examples/a_serializer.rb +29 -0
- data/spec/support/shared_examples/a_trie_data_structure.rb +29 -0
- data/spec/tmp/.gitkeep +0 -0
- metadata +51 -24
- data/lib/rambling/trie/compression.rb +0 -13
- data/lib/rambling/trie/inspector.rb +0 -11
- data/lib/rambling/trie/plain_text_reader.rb +0 -23
- data/lib/rambling/trie/tasks/gem.rb +0 -17
- data/lib/rambling/trie/tasks/helpers/path.rb +0 -17
- data/lib/rambling/trie/tasks/helpers/performance_report.rb +0 -17
- data/lib/rambling/trie/tasks/helpers/time.rb +0 -7
- data/lib/rambling/trie/tasks/performance.rb +0 -15
- data/lib/rambling/trie/tasks/performance/all.rb +0 -17
- data/lib/rambling/trie/tasks/performance/benchmark.rb +0 -201
- data/lib/rambling/trie/tasks/performance/directory.rb +0 -11
- data/lib/rambling/trie/tasks/performance/flamegraph.rb +0 -119
- data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +0 -147
- data/lib/rambling/trie/tasks/performance/profile/memory.rb +0 -143
- data/spec/lib/rambling/trie/plain_text_reader_spec.rb +0 -18
@@ -6,49 +6,23 @@ describe Rambling::Trie::Container do
|
|
6
6
|
let(:root) { Rambling::Trie::RawNode.new }
|
7
7
|
|
8
8
|
describe '.new' do
|
9
|
-
|
10
|
-
|
11
|
-
allow(Rambling::Trie::RawNode).to receive(:new)
|
12
|
-
.and_return root
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'initializes an empty trie root node' do
|
16
|
-
Rambling::Trie::Container.new
|
17
|
-
expect(Rambling::Trie::RawNode).to have_received :new
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'without a specified compressor' do
|
22
|
-
before do
|
23
|
-
allow(Rambling::Trie::Compressor).to receive(:new)
|
24
|
-
.and_return compressor
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'initializes a compressor' do
|
28
|
-
Rambling::Trie::Container.new
|
29
|
-
expect(Rambling::Trie::Compressor).to have_received :new
|
30
|
-
end
|
9
|
+
it 'uses the provided node as root' do
|
10
|
+
expect(container.root).to be root
|
31
11
|
end
|
32
12
|
|
33
13
|
context 'with a block' do
|
34
14
|
it 'yields the container' do
|
35
|
-
|
15
|
+
yielded = nil
|
36
16
|
|
37
|
-
container = Rambling::Trie::Container.new root do |container|
|
38
|
-
|
17
|
+
container = Rambling::Trie::Container.new root, compressor do |container|
|
18
|
+
yielded = container
|
39
19
|
end
|
40
20
|
|
41
|
-
expect(
|
21
|
+
expect(yielded).to be container
|
42
22
|
end
|
43
23
|
end
|
44
24
|
end
|
45
25
|
|
46
|
-
describe '#root' do
|
47
|
-
it 'returns the trie root node' do
|
48
|
-
expect(container.root).to eq root
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
26
|
describe '#add' do
|
53
27
|
let(:clone) { double :clone }
|
54
28
|
let(:word) { double :word, clone: clone }
|
@@ -470,12 +444,9 @@ describe Rambling::Trie::Container do
|
|
470
444
|
describe '#scan' do
|
471
445
|
context 'words that match are not contained' do
|
472
446
|
before do
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
container.add 'hell'
|
477
|
-
container.add 'highlight'
|
478
|
-
container.add 'histerical'
|
447
|
+
%w(hi hello high hell highlight histerical).each do |word|
|
448
|
+
container.add word
|
449
|
+
end
|
479
450
|
end
|
480
451
|
|
481
452
|
it 'returns an array with the words that match' do
|
@@ -533,4 +504,122 @@ describe Rambling::Trie::Container do
|
|
533
504
|
end
|
534
505
|
end
|
535
506
|
end
|
507
|
+
|
508
|
+
describe '#words_within' do
|
509
|
+
before do
|
510
|
+
%w(one word and other words).each do |word|
|
511
|
+
container.add word
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
context 'phrase does not contain any words' do
|
516
|
+
it 'returns an empty array' do
|
517
|
+
expect(container.words_within 'xyz').to match_array []
|
518
|
+
end
|
519
|
+
|
520
|
+
context 'and the node is compressed' do
|
521
|
+
before do
|
522
|
+
container.compress!
|
523
|
+
end
|
524
|
+
|
525
|
+
it 'returns an empty array' do
|
526
|
+
expect(container.words_within 'xyz').to match_array []
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
context 'phrase contains one word at the start of the phrase' do
|
532
|
+
it 'returns an array with the word found in the phrase' do
|
533
|
+
expect(container.words_within 'word').to match_array %w(word)
|
534
|
+
expect(container.words_within 'wordxyz').to match_array %w(word)
|
535
|
+
end
|
536
|
+
|
537
|
+
context 'and the node is compressed' do
|
538
|
+
before do
|
539
|
+
container.compress!
|
540
|
+
end
|
541
|
+
|
542
|
+
it 'returns an array with the word found in the phrase' do
|
543
|
+
expect(container.words_within 'word').to match_array %w(word)
|
544
|
+
expect(container.words_within 'wordxyz').to match_array %w(word)
|
545
|
+
end
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
context 'phrase contains one word at the end of the phrase' do
|
550
|
+
it 'returns an array with the word found in the phrase' do
|
551
|
+
expect(container.words_within 'xyz word').to match_array %w(word)
|
552
|
+
end
|
553
|
+
|
554
|
+
context 'and the node is compressed' do
|
555
|
+
before do
|
556
|
+
container.compress!
|
557
|
+
end
|
558
|
+
|
559
|
+
it 'returns an array with the word found in the phrase' do
|
560
|
+
expect(container.words_within 'xyz word').to match_array %w(word)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
context 'phrase contains a few words' do
|
566
|
+
it 'returns an array with all words found in the phrase' do
|
567
|
+
expect(container.words_within 'xyzword otherzxyone').to match_array %w(word other one)
|
568
|
+
end
|
569
|
+
|
570
|
+
context 'and the node is compressed' do
|
571
|
+
before do
|
572
|
+
container.compress!
|
573
|
+
end
|
574
|
+
|
575
|
+
it 'returns an array with all words found in the phrase' do
|
576
|
+
expect(container.words_within 'xyzword otherzxyone').to match_array %w(word other one)
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
describe '#words_within?' do
|
583
|
+
before do
|
584
|
+
%w(one word and other words).each do |word|
|
585
|
+
container.add word
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
context 'phrase does not contain any words' do
|
590
|
+
it 'returns false' do
|
591
|
+
expect(container.words_within? 'xyz').to be false
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
context 'phrase contains any word' do
|
596
|
+
it 'returns true' do
|
597
|
+
expect(container.words_within? 'xyz words').to be true
|
598
|
+
expect(container.words_within? 'xyzone word').to be true
|
599
|
+
end
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
describe '#==' do
|
604
|
+
context 'when the root nodes are the same' do
|
605
|
+
let(:other_container) { Rambling::Trie::Container.new container.root, compressor }
|
606
|
+
|
607
|
+
it 'returns true' do
|
608
|
+
expect(container).to eq other_container
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
context 'when the root nodes are not the same' do
|
613
|
+
let(:other_root) { Rambling::Trie::RawNode.new }
|
614
|
+
let(:other_container) do
|
615
|
+
Rambling::Trie::Container.new other_root, compressor do |c|
|
616
|
+
c << 'hola'
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
it 'returns false' do
|
621
|
+
expect(container).not_to eq other_container
|
622
|
+
end
|
623
|
+
end
|
624
|
+
end
|
536
625
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Rambling::Trie::
|
3
|
+
describe Rambling::Trie::Inspectable do
|
4
4
|
let(:root) { Rambling::Trie::RawNode.new }
|
5
5
|
|
6
6
|
before do
|
@@ -9,10 +9,12 @@ describe Rambling::Trie::Inspector do
|
|
9
9
|
|
10
10
|
describe '#inspect' do
|
11
11
|
let(:node) { root[:o] }
|
12
|
+
let(:terminal_node) { root[:o][:n][:l][:y] }
|
12
13
|
|
13
14
|
it 'returns a pretty printed version of the node' do
|
14
|
-
expect(root.inspect).to eq "#<Rambling::Trie::RawNode letter: nil, children: [:o, :t, :w]>"
|
15
|
-
expect(node.inspect).to eq "#<Rambling::Trie::RawNode letter: :o, children: [:n]>"
|
15
|
+
expect(root.inspect).to eq "#<Rambling::Trie::RawNode letter: nil, terminal: nil, children: [:o, :t, :w]>"
|
16
|
+
expect(node.inspect).to eq "#<Rambling::Trie::RawNode letter: :o, terminal: nil, children: [:n]>"
|
17
|
+
expect(terminal_node.inspect).to eq "#<Rambling::Trie::RawNode letter: :y, terminal: true, children: []>"
|
16
18
|
end
|
17
19
|
|
18
20
|
context 'for a compressed node' do
|
@@ -21,8 +23,8 @@ describe Rambling::Trie::Inspector do
|
|
21
23
|
let(:compressed_node) { compressed_root[:only] }
|
22
24
|
|
23
25
|
it 'returns a pretty printed version of the compressed node' do
|
24
|
-
expect(compressed_root.inspect).to eq "#<Rambling::Trie::CompressedNode letter: nil, children: [:only, :three, :words]>"
|
25
|
-
expect(compressed_node.inspect).to eq "#<Rambling::Trie::CompressedNode letter: :only, children: []>"
|
26
|
+
expect(compressed_root.inspect).to eq "#<Rambling::Trie::CompressedNode letter: nil, terminal: nil, children: [:only, :three, :words]>"
|
27
|
+
expect(compressed_node.inspect).to eq "#<Rambling::Trie::CompressedNode letter: :only, terminal: true, children: []>"
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -347,61 +347,42 @@ describe Rambling::Trie::RawNode do
|
|
347
347
|
end
|
348
348
|
end
|
349
349
|
|
350
|
-
describe '#
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
it 'returns nil' do
|
359
|
-
expect(node.as_word).to be_empty
|
360
|
-
end
|
350
|
+
describe '#match_prefix' do
|
351
|
+
before do
|
352
|
+
node.letter = :i
|
353
|
+
node.add 'gnite'
|
354
|
+
node.add 'mport'
|
355
|
+
node.add 'mportant'
|
356
|
+
node.add 'mportantly'
|
361
357
|
end
|
362
358
|
|
363
|
-
context '
|
359
|
+
context 'when the node is terminal' do
|
364
360
|
before do
|
365
|
-
node.
|
366
|
-
node.add ''
|
361
|
+
node.terminal!
|
367
362
|
end
|
368
363
|
|
369
|
-
it '
|
370
|
-
expect(node.
|
364
|
+
it 'adds itself to the words' do
|
365
|
+
expect(node.match_prefix %w(g n i t e)).to include 'i'
|
371
366
|
end
|
372
367
|
end
|
373
368
|
|
374
|
-
context '
|
375
|
-
|
376
|
-
node.
|
377
|
-
node.add 'll'
|
378
|
-
end
|
379
|
-
|
380
|
-
it 'returns the expected small word' do
|
381
|
-
expect(node[:l][:l].as_word).to eq 'all'
|
382
|
-
end
|
383
|
-
|
384
|
-
it 'raises an error for a non terminal node' do
|
385
|
-
expect { node[:l].as_word }.to raise_error Rambling::Trie::InvalidOperation
|
369
|
+
context 'when the node is not terminal' do
|
370
|
+
it 'does not add itself to the words' do
|
371
|
+
expect(node.match_prefix %w(g n i t e)).not_to include 'i'
|
386
372
|
end
|
387
373
|
end
|
388
374
|
|
389
|
-
context '
|
390
|
-
|
391
|
-
node.
|
392
|
-
|
393
|
-
end
|
394
|
-
|
395
|
-
it 'returns the expected long word' do
|
396
|
-
expect(node[:e][:a][:u][:t][:i][:f][:u][:l].as_word).to eq 'beautiful'
|
375
|
+
context 'when the first few chars match a terminal node' do
|
376
|
+
it 'adds those terminal nodes to the words' do
|
377
|
+
words = node.match_prefix(%w(m p o r t a n t l y)).to_a
|
378
|
+
expect(words).to include 'import', 'important', 'importantly'
|
397
379
|
end
|
398
380
|
end
|
399
381
|
|
400
|
-
context '
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
expect(node.as_word).to be_empty
|
382
|
+
context 'when the first few chars do not match a terminal node' do
|
383
|
+
it 'does not add any other words found' do
|
384
|
+
words = node.match_prefix(%w(m p m p o r t a n t l y)).to_a
|
385
|
+
expect(words).not_to include 'import', 'important', 'importantly'
|
405
386
|
end
|
406
387
|
end
|
407
388
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rambling::Trie::Readers::PlainText do
|
4
|
+
describe '#each_word' do
|
5
|
+
let(:filepath) { File.join(::SPEC_ROOT, 'assets', 'test_words.en_US.txt') }
|
6
|
+
let(:words) { File.readlines(filepath).map &:chomp }
|
7
|
+
|
8
|
+
it 'yields every word yielded by the file' do
|
9
|
+
yielded = []
|
10
|
+
subject.each_word(filepath) { |word| yielded << word }
|
11
|
+
expect(yielded).to eq words
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rambling::Trie::Serializers::File do
|
4
|
+
let(:serializer) { Rambling::Trie::Serializers::File.new }
|
5
|
+
|
6
|
+
it_behaves_like 'a serializer' do
|
7
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'tmp', 'trie-root.file' }
|
8
|
+
let(:content) { 'a few words to validate that load and dump are working' }
|
9
|
+
let(:formatted_content) { content }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rambling::Trie::Serializers::Marshal do
|
4
|
+
let(:serializer) { Rambling::Trie::Serializers::Marshal.new }
|
5
|
+
|
6
|
+
let(:words) { %w(a few words to validate that load and dump are working) }
|
7
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
8
|
+
|
9
|
+
it_behaves_like 'a serializer' do
|
10
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'tmp', 'trie-root.marshal' }
|
11
|
+
let(:content) { trie.root }
|
12
|
+
let(:formatted_content) { Marshal.dump content }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rambling::Trie::Serializers::Yaml do
|
4
|
+
let(:serializer) { Rambling::Trie::Serializers::Yaml.new }
|
5
|
+
|
6
|
+
let(:words) { %w(a few words to validate that load and dump are working) }
|
7
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
8
|
+
|
9
|
+
it_behaves_like 'a serializer' do
|
10
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'tmp', 'trie-root.yml' }
|
11
|
+
let(:content) { trie.root }
|
12
|
+
let(:formatted_content) { YAML.dump content }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rambling::Trie::Serializers::Zip do
|
4
|
+
let(:properties) { Rambling::Trie::Configuration::Properties.new }
|
5
|
+
let(:serializer) { Rambling::Trie::Serializers::Zip.new properties }
|
6
|
+
|
7
|
+
let(:words) { %w(a few words to validate that load and dump are working) }
|
8
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
9
|
+
let(:tmp_path) { File.join ::SPEC_ROOT, 'tmp' }
|
10
|
+
|
11
|
+
before do
|
12
|
+
properties.tmp_path = tmp_path
|
13
|
+
end
|
14
|
+
|
15
|
+
it_behaves_like 'a serializer' do
|
16
|
+
let(:filename) { 'trie-root.marshal' }
|
17
|
+
let(:filepath) { File.join tmp_path, "#{filename}.zip" }
|
18
|
+
let(:content) { trie.root }
|
19
|
+
let(:formatted_content) { zip Marshal.dump content }
|
20
|
+
end
|
21
|
+
|
22
|
+
def zip content
|
23
|
+
io = Zip::OutputStream.write_buffer do |io|
|
24
|
+
io.put_next_entry filename
|
25
|
+
io.write content
|
26
|
+
end
|
27
|
+
io.rewind
|
28
|
+
io.read
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rambling::Trie::Stringifyable do
|
4
|
+
describe '#as_word' do
|
5
|
+
let(:node) { Rambling::Trie::RawNode.new }
|
6
|
+
|
7
|
+
context 'for an empty node' do
|
8
|
+
before do
|
9
|
+
node.add ''
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns nil' do
|
13
|
+
expect(node.as_word).to be_empty
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'for one letter' do
|
18
|
+
before do
|
19
|
+
node.letter = :a
|
20
|
+
node.add ''
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns the expected one letter word' do
|
24
|
+
expect(node.as_word).to eq 'a'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'for a small word' do
|
29
|
+
before do
|
30
|
+
node.letter = :a
|
31
|
+
node.add 'll'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns the expected small word' do
|
35
|
+
expect(node[:l][:l].as_word).to eq 'all'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises an error for a non terminal node' do
|
39
|
+
expect { node[:l].as_word }.to raise_error Rambling::Trie::InvalidOperation
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'for a long word' do
|
44
|
+
before do
|
45
|
+
node.letter = :b
|
46
|
+
node.add 'eautiful'
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns the expected long word' do
|
50
|
+
expect(node[:e][:a][:u][:t][:i][:f][:u][:l].as_word).to eq 'beautiful'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'for a node with nil letter' do
|
55
|
+
let(:node) { Rambling::Trie::RawNode.new nil }
|
56
|
+
|
57
|
+
it 'returns nil' do
|
58
|
+
expect(node.as_word).to be_empty
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'for a compressed node' do
|
63
|
+
let(:compressor) { Rambling::Trie::Compressor.new }
|
64
|
+
let(:compressed_node) { compressor.compress node }
|
65
|
+
|
66
|
+
before do
|
67
|
+
node.letter = :a
|
68
|
+
node.add 'm'
|
69
|
+
node.add 'dd'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'returns the words for the terminal nodes' do
|
73
|
+
expect(compressed_node[:m].as_word).to eq 'am'
|
74
|
+
expect(compressed_node[:dd].as_word).to eq 'add'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'raise an error for non terminal nodes' do
|
78
|
+
expect { compressed_node.as_word }.to raise_error Rambling::Trie::InvalidOperation
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|