gold_mine 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.
@@ -0,0 +1,3 @@
1
+ module GoldMine
2
+ VERSION="1.0.0" unless defined? GoldMine::VERSION
3
+ end
@@ -0,0 +1,72 @@
1
+ require "spec_helper"
2
+
3
+ describe GoldMine::DB do
4
+ add_temp_file
5
+ subject { GoldMine::DB.new(path: temp_file.path) }
6
+
7
+ describe "#initialize" do
8
+ subject { GoldMine::DB.new }
9
+ let(:path) { subject.instance_variable_get("@path") }
10
+ let(:options) { subject.instance_variable_get("@options") }
11
+
12
+ context "without a :path option" do
13
+ it "assigns built-in database path to the @path" do
14
+ default_path = File.expand_path("../../../fortunes/fortunes", __FILE__)
15
+ expect(path).to eq(default_path)
16
+ end
17
+ end
18
+
19
+ context "without a :delim option" do
20
+ it "assigns default delimiter to the :delim option" do
21
+ expect(options[:delim]).to eq("%")
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "#random" do
27
+ temp_file <<-EOF.gsub(/^ {6}/, "")
28
+ "His mind is like a steel trap ― full of mice."
29
+ ― Foghorn Leghorn
30
+ %
31
+ "Humor is a drug which it's the fashion to abuse."
32
+ ― William Gilbert
33
+ EOF
34
+
35
+ it "returns the instance of fortune class" do
36
+ expect(subject.random).to be_a(GoldMine::Fortune)
37
+ end
38
+
39
+ it "returns the random fortune" do
40
+ results = []
41
+ 1000.times { results << subject.random }
42
+ expect(results.uniq.size).to be > 1
43
+ end
44
+ end
45
+
46
+ describe "#fortunes" do
47
+ temp_file <<-EOF.gsub(/^ {6}/, "")
48
+ "Deliver yesterday, code today, think tomorrow."
49
+ %
50
+ "Die? I should say not, dear fellow. No Barrymore would allow such a
51
+ conventional thing to happen to him."
52
+ ― John Barrymore's dying words
53
+ %
54
+ "Do not stop to ask what is it;
55
+ Let us go and make our visit."
56
+ ― T. S. Eliot, "The Love Song of J. Alfred Prufrock"
57
+ EOF
58
+
59
+ it "returns the array with fortune instances" do
60
+ array = subject.fortunes.map { |f| f.is_a?(GoldMine::Fortune) }
61
+ expect(array).to_not include(false)
62
+ end
63
+
64
+ it "returns properly formated fortunes" do
65
+ expect(subject.fortunes.first.content).to eq("\"Deliver yesterday, code today, think tomorrow.\"")
66
+ end
67
+
68
+ it "returns all fortunes from a database" do
69
+ expect(subject.fortunes.size).to eq(3)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,68 @@
1
+ require "spec_helper"
2
+
3
+ describe GoldMine::Fortune do
4
+ describe "#initialize" do
5
+ context "with content" do
6
+ subject do
7
+ GoldMine::Fortune.new <<-EOF.gsub(/^ {10}/, "")
8
+ I hate quotations.
9
+ ― Ralph Waldo Emerson
10
+ EOF
11
+ end
12
+
13
+ it "assigns a text without attribution to the @content" do
14
+ expect(subject.instance_variable_get("@content")).to eq("I hate quotations.\n")
15
+ end
16
+
17
+ it "assigns an attribution to the @attribution" do
18
+ expect(subject.instance_variable_get("@attribution")).to eq("Ralph Waldo Emerson")
19
+ end
20
+ end
21
+ end
22
+
23
+ describe "#to_s" do
24
+ shared_examples "a formatting" do |format|
25
+ it "returns the string in the correct format" do
26
+ expect(subject.to_s).to eq(format)
27
+ end
28
+ end
29
+
30
+ context "when a content is empty and an attribution is empty" do
31
+ it "returns the empty string" do
32
+ expect(subject.to_s).to eq("")
33
+ end
34
+ end
35
+
36
+ context "when a content is empty and an attribution is not empty" do
37
+ before { subject.instance_variable_set("@attribution", "Yogi Berra") }
38
+
39
+ it "returns the empty string" do
40
+ expect(subject.to_s).to eq("")
41
+ end
42
+ end
43
+
44
+ context "when a content is not empty and an attribution is empty" do
45
+ before { subject.instance_variable_set("@content", "You can observe a lot just by watching.") }
46
+
47
+ include_examples "a formatting", <<-EOS.gsub(/^ {8}/, "")
48
+
49
+ You can observe a lot just by watching.
50
+
51
+ EOS
52
+ end
53
+
54
+ context "when an content is not empty and an attribution is not empty" do
55
+ before do
56
+ subject.instance_variable_set("@attribution", "Yogi Berra")
57
+ subject.instance_variable_set("@content", "You can observe a lot just by watching.")
58
+ end
59
+
60
+ include_examples "a formatting", <<-EOS.gsub(/^ {8}/, "")
61
+
62
+ You can observe a lot just by watching.
63
+ ― Yogi Berra
64
+
65
+ EOS
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+
3
+ describe GoldMine::IndexReader do
4
+ add_temp_file
5
+ subject { described_class.new(temp_file.path) }
6
+
7
+ INDEX_HEADER = {
8
+ version: 2,
9
+ numstr: 3,
10
+ longlen: 612,
11
+ shortlen: 28,
12
+ flags: 0,
13
+ delim: 37
14
+ }
15
+
16
+ temp_file (INDEX_HEADER.values + [0, 12, 154]).pack("N*")
17
+
18
+ describe "#initialize" do
19
+ it "assigns a path to the @path" do
20
+ expect(subject.instance_variable_get("@path")).to eq(temp_file.path)
21
+ end
22
+ end
23
+
24
+ describe "#header_fields" do
25
+ it "returns an array of each value extracted" do
26
+ expect(subject.header_fields).to be_instance_of(Array)
27
+ end
28
+
29
+ it "returns an array including six elements" do
30
+ expect(subject.header_fields.size).to eq(6)
31
+ end
32
+
33
+ INDEX_HEADER.each_with_index do |(element, value), index|
34
+ it "returns an array where element at #{index+1} position is a #{element}" do
35
+ expect(subject.header_fields[index]).to eq(value)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "#get_pointers" do
41
+ it "returns an array instance" do
42
+ expect(subject.get_pointers).to be_instance_of(Array)
43
+ end
44
+
45
+ it "extracts pointers from index file" do
46
+ expect(subject.get_pointers).to eq([0, 12, 154])
47
+ end
48
+ end
49
+
50
+ describe "#get_pointer_at" do
51
+ it "returns pointer by index" do
52
+ expect(subject.get_pointer_at(1)).to eq(12)
53
+ end
54
+ end
55
+
56
+ describe "#random_pointer" do
57
+ it "returns random pointer" do
58
+ results = []
59
+ 1000.times { results << subject.random_pointer }
60
+ expect(results.uniq.size).to be > 1
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,202 @@
1
+ require "spec_helper"
2
+ require "tmpdir"
3
+
4
+ describe GoldMine::IndexWriter do
5
+ add_temp_file
6
+ subject { described_class.new(temp_file.path) }
7
+
8
+ describe "#initialize" do
9
+ let(:options) { subject.instance_variable_get("@options") }
10
+
11
+ context "without an options" do
12
+ it "assigns default options to @options" do
13
+ default_options = {
14
+ version: 2,
15
+ delim: "%",
16
+ randomized: false,
17
+ ordered: false,
18
+ rotated: false,
19
+ comments: false
20
+ }
21
+ expect(options).to eq(default_options)
22
+ end
23
+ end
24
+
25
+ context "with an options" do
26
+ subject { described_class.new(temp_file.path, version: 12) }
27
+
28
+ it "merged them with the default options" do
29
+ expect(options[:version]).to eq(12)
30
+ end
31
+ end
32
+
33
+ it "assings to @shortlen very high number" do
34
+ shortlen = subject.instance_variable_get("@shortlen")
35
+ expect(shortlen).to be >= 99999
36
+ end
37
+
38
+ context "with an :ordered option and a :randomized option" do
39
+ subject { described_class.new(temp_file.path, randomized: true, ordered: true) }
40
+
41
+ it "excludes :randomized" do
42
+ flags = subject.instance_variable_get("@flags")
43
+ expect(flags[:randomized]).to be_false
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#load_pointers" do
49
+ temp_file <<-EOF.gsub(/^ {6}/, "")
50
+ %
51
+ I Like Facebook
52
+ %
53
+ "I see fire"
54
+ -- Ed Sheeran
55
+ %
56
+ CTSG
57
+ EOF
58
+
59
+ let(:load_pointers) { subject.load_pointers }
60
+
61
+ context "when :comments option is true" do
62
+ subject { described_class.new(temp_file.path, comments: true) }
63
+
64
+ temp_file <<-EOF.gsub(/^ {8}/, "")
65
+ %% It's new!
66
+ "Be or not to be"
67
+ %% What?!
68
+ -- Shakespeare
69
+ %
70
+ %% Todo: Change it!
71
+ EOF
72
+
73
+ describe "omits lines starting with double delimeter" do
74
+ it { expect(load_pointers.size).to eq(1) }
75
+ it { expect(load_pointers[0][0]).to eq(13) }
76
+ end
77
+ end
78
+
79
+ it "returns the array with correct size" do
80
+ expect(load_pointers.size).to eq(3)
81
+ end
82
+
83
+ it "assings end of file position to @eof" do
84
+ expect(subject.instance_variable_get("@eof")).to eq(62)
85
+ end
86
+
87
+ it "assings length of shortest fortune to @shortlen" do
88
+ expect(subject.instance_variable_get("@shortlen")).to eq(5)
89
+ end
90
+
91
+ it "assings length of longest fortune to @longlen" do
92
+ expect(subject.instance_variable_get("@longlen")).to eq(35)
93
+ end
94
+
95
+ describe "loads a fortune as an array" do
96
+ it { expect(load_pointers.sample).to be_a(Array) }
97
+
98
+ it "where first element is a correct pointer" do
99
+ expect(load_pointers[1][0]).to eq(20)
100
+ end
101
+
102
+ it "where second element is a first character" do
103
+ expect(load_pointers[0][1]).to eq("I")
104
+ end
105
+
106
+ it "even when is first and preceded by a delimeter" do
107
+ expect(load_pointers[0][0]).to eq(2)
108
+ end
109
+
110
+ it "even when is located at the bottom of the file" do
111
+ expect(load_pointers[2][0]).to eq(57)
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "#order_pointers!" do
117
+ it "organizes @pointers alphabetically" do
118
+ subject.instance_variable_set("@pointers", [[23, "S"], [43, "A"], [61, "Z"]])
119
+ subject.order_pointers!
120
+ expect(subject.instance_variable_get("@pointers")).to eq([[43, "A"], [23, "S"], [61, "Z"]])
121
+ end
122
+ end
123
+
124
+ describe "#shuffle_pointers!" do
125
+ it "shuffles @pointers" do
126
+ input = [[0, "A"], [1, "B"], [2, "C"]]
127
+ subject.instance_variable_set("@pointers", input)
128
+ subject.shuffle_pointers!
129
+ expect(subject.instance_variable_get("@pointers")).to_not eq(input)
130
+ end
131
+ end
132
+
133
+ describe "#write" do
134
+ context "when @index_path is presence" do
135
+ before do
136
+ subject.instance_variable_set("@index_path", Dir.tmpdir + "/custom.dat")
137
+ end
138
+
139
+ it "saves a file at @index_path" do
140
+ subject.write
141
+ expect(File.exists?(subject.instance_variable_get("@index_path"))).to be_true
142
+ end
143
+ end
144
+
145
+ context "when @index_path is not presence" do
146
+ it "savas a file at @path.dat" do
147
+ subject.write
148
+ expect(File.exists?(subject.instance_variable_get('@path') + ".dat")).to be_true
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "#offsets" do
154
+ it "returns offsets from @pointers" do
155
+ subject.instance_variable_set("@pointers", [[0, "A"], [1, "B"]])
156
+ expect(subject.offsets).to eq([0, 1])
157
+ end
158
+ end
159
+
160
+ describe "#packed_pointers" do
161
+ describe "packs offsets into binary sequence" do
162
+ it "32-bit unsigned and big-endian" do
163
+ subject.instance_variable_set("@pointers", [[0, "A"], [22, "B"], [30, "C"]])
164
+ expect(subject.packed_pointers).to eq("\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x1E")
165
+ end
166
+ end
167
+ end
168
+
169
+ describe "#packed_eof" do
170
+ describe "packs @eof into binary sequence" do
171
+ it "as 32-bit unsigned big-endian" do
172
+ subject.instance_variable_set("@eof", 100)
173
+ expect(subject.packed_eof).to eq("\x00\x00\x00d")
174
+ end
175
+ end
176
+ end
177
+
178
+ describe "#packed_header" do
179
+ before do
180
+ subject.instance_variable_set("@version", 2)
181
+ subject.instance_variable_set("@numstr", 23)
182
+ subject.instance_variable_set("@longlen", 31)
183
+ subject.instance_variable_set("@shortlen", 7)
184
+ subject.instance_variable_set("@flags", 0)
185
+ subject.instance_variable_set("@delim", "%")
186
+ end
187
+
188
+ describe "packs header into binary sequence with big-endian convention where" do
189
+ let(:unpacked_header) { subject.packed_header.unpack("N*") }
190
+
191
+ ["version", "numstr", "longlen", "shortlen", "flags"].each_with_index do |e, i|
192
+ it "#{i+1} element is a 32-bit unsigned integer representing #{e}" do
193
+ expect(unpacked_header[i]).to eq(subject.instance_variable_get("@#{e}"))
194
+ end
195
+ end
196
+
197
+ it "6 element is a 32-bit integer representing delim" do
198
+ expect(unpacked_header[5]).to eq(subject.instance_variable_get("@delim").ord << 24)
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,11 @@
1
+ require "bundler/setup"
2
+ Bundler.setup
3
+
4
+ %w{gold_mine}.each { |x| require x }
5
+
6
+ Dir[GoldMine.base_dir.join("spec", "support", "**", "*.rb")].each { |f| require f }
7
+
8
+ RSpec.configure do |c|
9
+ c.include TempFile
10
+ c.mock_with :rspec
11
+ end
@@ -0,0 +1,25 @@
1
+ require "tempfile"
2
+
3
+ module TempFile
4
+ def self.included(example_group)
5
+ example_group.extend(self)
6
+ end
7
+
8
+ def add_temp_file
9
+ let(:temp_file) do
10
+ Tempfile.new("gold_mine")
11
+ end
12
+ end
13
+
14
+ def temp_file(content = "")
15
+ before do
16
+ temp_file.open
17
+ temp_file.write(content)
18
+ temp_file.close
19
+ end
20
+
21
+ after do
22
+ temp_file.unlink
23
+ end
24
+ end
25
+ end