hrx 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,304 @@
1
+ # Copyright 2018 Google Inc
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'hrx'
16
+
17
+ RSpec.describe HRX::Archive, "as a child" do
18
+ let(:parent) {HRX::Archive.parse(<<END)}
19
+ <===> before
20
+ file before dir
21
+
22
+ <===> dir/top
23
+ top-level child
24
+
25
+ <===> dir/sub/mid
26
+ mid-level child
27
+
28
+ <===> dir/sub/dir/
29
+ <===> interrupt
30
+ interruption not in dir
31
+
32
+ <===> dir/sub/lower/bottom
33
+ bottom-level child
34
+
35
+ <===> after
36
+ file after dir
37
+ END
38
+
39
+ let(:child) {parent.child_archive("dir")}
40
+
41
+ context "#entries" do
42
+ it "is frozen" do
43
+ expect do
44
+ child.entries << HRX::Directory.new("dir")
45
+ end.to raise_error(RuntimeError)
46
+ end
47
+
48
+ it "should only contain entries in the directory" do
49
+ expect(child.entries.length).to be == 4
50
+ expect(child.entries[0].path).to be == "top"
51
+ expect(child.entries[1].path).to be == "sub/mid"
52
+ expect(child.entries[2].path).to be == "sub/dir/"
53
+ expect(child.entries[3].path).to be == "sub/lower/bottom"
54
+ end
55
+
56
+ it "should reflect changes to the child archive" do
57
+ child << HRX::File.new("another", "")
58
+ expect(child.entries.length).to be == 5
59
+ expect(child.entries.last.path).to be == "another"
60
+ end
61
+
62
+ it "should reflect changes to the parent archive" do
63
+ parent << HRX::File.new("dir/another", "")
64
+ expect(child.entries.length).to be == 5
65
+ expect(child.entries.last.path).to be == "another"
66
+ end
67
+ end
68
+
69
+ context "#[]" do
70
+ it "should return a top-level entry" do
71
+ expect(child["top"].path).to be == "top"
72
+ expect(child["top"].content).to be == "top-level child\n"
73
+ end
74
+
75
+ it "should return a nested entry" do
76
+ expect(child["sub/lower/bottom"].path).to be == "sub/lower/bottom"
77
+ expect(child["sub/lower/bottom"].content).to be == "bottom-level child\n"
78
+ end
79
+
80
+ it "should return an explicit directory" do
81
+ expect(child["sub/dir"].path).to be == "sub/dir/"
82
+ expect(child["sub/dir"]).not_to respond_to(:content)
83
+ end
84
+
85
+ it "shouldn't return a file that isn't in the directory" do
86
+ expect(child["interrupt"]).to be_nil
87
+ end
88
+
89
+ it "should reflect changes to the child archive" do
90
+ child << HRX::File.new("another", "another contents\n")
91
+ expect(child["another"].path).to be == "another"
92
+ expect(child["another"].content).to be == "another contents\n"
93
+ end
94
+
95
+ it "should reflect changes to the parent archive" do
96
+ parent << HRX::File.new("dir/another", "another contents\n")
97
+ expect(child["another"].path).to be == "another"
98
+ expect(child["another"].content).to be == "another contents\n"
99
+ end
100
+ end
101
+
102
+ context "#read" do
103
+ it "should read a top-level file" do
104
+ expect(child.read("top")).to be == "top-level child\n"
105
+ end
106
+
107
+ it "should read a nested file" do
108
+ expect(child.read("sub/lower/bottom")).to be == "bottom-level child\n"
109
+ end
110
+
111
+ it "shouldn't read a file that isn't in the directory" do
112
+ expect {child.read("interrupt")}.to(
113
+ raise_error(HRX::Error, 'There is no file at "interrupt"'))
114
+ end
115
+
116
+ it "should reflect changes to the child archive" do
117
+ child << HRX::File.new("another", "another contents\n")
118
+ expect(child.read("another")).to be == "another contents\n"
119
+ end
120
+
121
+ it "should reflect changes to the parent archive" do
122
+ parent << HRX::File.new("dir/another", "another contents\n")
123
+ expect(child.read("another")).to be == "another contents\n"
124
+ end
125
+ end
126
+
127
+ context "#child_archive" do
128
+ let(:grandchild) {child.child_archive("sub")}
129
+
130
+ it "should access an even more nested entry" do
131
+ expect(grandchild.read("mid")).to be == "mid-level child\n"
132
+ end
133
+
134
+ it "should reflect changes in the parent archive" do
135
+ parent << HRX::File.new("dir/sub/another", "another contents\n")
136
+ expect(grandchild.entries.length).to be == 4
137
+ expect(grandchild.entries.last.path).to be == "another"
138
+ expect(grandchild.read("another")).to be == "another contents\n"
139
+ end
140
+
141
+ it "should propagate changes to the parent archive" do
142
+ grandchild << HRX::File.new("another", "another contents\n")
143
+ expect(parent.entries.length).to be == 8
144
+ expect(parent.entries.last.path).to be == "dir/sub/another"
145
+ expect(parent.read("dir/sub/another")).to be == "another contents\n"
146
+ end
147
+ end
148
+
149
+ context "#write" do
150
+ before(:each) {child.write("another", "another contents\n")}
151
+
152
+ it "should be visible in the child archive" do
153
+ expect(child.entries.length).to be == 5
154
+ expect(child.entries.last.path).to be == "another"
155
+ expect(child.read("another")).to be == "another contents\n"
156
+ end
157
+
158
+ it "should be visible in the parent archive" do
159
+ expect(parent.entries.length).to be == 8
160
+ previous_path = "dir/" + child.entries[-2].path
161
+ new_index = parent.entries.find_index {|e| e.path == previous_path} + 1
162
+ expect(parent.entries[new_index].path).to be == "dir/another"
163
+ expect(parent.read("dir/another")).to be == "another contents\n"
164
+ end
165
+ end
166
+
167
+ context "#delete" do
168
+ context "for a single file" do
169
+ before(:each) {child.delete("top")}
170
+
171
+ it "should be visible in the child archive" do
172
+ expect(child.entries.length).to be == 3
173
+ expect(child["top"]).to be_nil
174
+ end
175
+
176
+ it "should be visible in the parent archive" do
177
+ expect(parent.entries.length).to be == 6
178
+ expect(parent["dir/top"]).to be_nil
179
+ end
180
+ end
181
+
182
+ context "recursively" do
183
+ before(:each) {child.delete("sub", recursive: true)}
184
+
185
+ it "should be visible in the child archive" do
186
+ expect(child.entries.length).to be == 1
187
+ expect(child["sub/mid"]).to be_nil
188
+ expect(child["sub/dir"]).to be_nil
189
+ expect(child["sub/lower/bottom"]).to be_nil
190
+ end
191
+
192
+ it "should be visible in the parent archive" do
193
+ expect(parent.entries.length).to be == 4
194
+ expect(child["dir/sub/mid"]).to be_nil
195
+ expect(child["dir/sub/dir"]).to be_nil
196
+ expect(child["dir/sub/lower/bottom"]).to be_nil
197
+ end
198
+ end
199
+ end
200
+
201
+ context "#last_comment=" do
202
+ before(:each) {child.last_comment = "comment\n"}
203
+
204
+ it "sets the #last_comment field" do
205
+ expect(child.last_comment).to be == "comment\n"
206
+ end
207
+
208
+ it "affects the child's #to_hrx" do
209
+ expect(child.to_hrx).to end_with("<===>\ncomment\n")
210
+ end
211
+
212
+ it "doesn't affect the parent's #to_hrx" do
213
+ expect(parent.to_hrx).not_to include("\ncomment\n")
214
+ end
215
+ end
216
+
217
+ context "#add" do
218
+ context "with no position" do
219
+ before(:each) {child.add(HRX::File.new("another", "another contents\n"))}
220
+
221
+ it "should be visible in the child archive" do
222
+ expect(child.entries.length).to be == 5
223
+ expect(child.entries.last.path).to be == "another"
224
+ expect(child.read("another")).to be == "another contents\n"
225
+ end
226
+
227
+ it "should be visible in the parent archive" do
228
+ expect(parent.entries.length).to be == 8
229
+ expect(parent.entries.last.path).to be == "dir/another"
230
+ expect(parent.read("dir/another")).to be == "another contents\n"
231
+ end
232
+ end
233
+
234
+ context "with a position" do
235
+ before(:each) do
236
+ child.add(HRX::File.new("another", "another contents\n"), after: "sub/mid")
237
+ end
238
+
239
+ it "should be visible in the child archive" do
240
+ expect(child.entries.length).to be == 5
241
+ new_index = child.entries.find_index {|e| e.path == "sub/mid"} + 1
242
+ expect(child.entries[new_index].path).to be == "another"
243
+ expect(child.read("another")).to be == "another contents\n"
244
+ end
245
+
246
+ it "should be visible in the parent archive" do
247
+ expect(parent.entries.length).to be == 8
248
+ new_index = parent.entries.find_index {|e| e.path == "dir/sub/mid"} + 1
249
+ expect(parent.entries[new_index].path).to be == "dir/another"
250
+ expect(parent.read("dir/another")).to be == "another contents\n"
251
+ end
252
+ end
253
+ end
254
+
255
+ context "#to_hrx" do
256
+ it "should only serialize entries in the directory" do
257
+ expect(child.to_hrx).to be == <<END
258
+ <===> top
259
+ top-level child
260
+
261
+ <===> sub/mid
262
+ mid-level child
263
+
264
+ <===> sub/dir/
265
+ <===> sub/lower/bottom
266
+ bottom-level child
267
+ END
268
+ end
269
+
270
+ it "should reflect changes to the child archive" do
271
+ child << HRX::File.new("another", "")
272
+ expect(child.to_hrx).to be == <<END
273
+ <===> top
274
+ top-level child
275
+
276
+ <===> sub/mid
277
+ mid-level child
278
+
279
+ <===> sub/dir/
280
+ <===> sub/lower/bottom
281
+ bottom-level child
282
+
283
+ <===> another
284
+ END
285
+ end
286
+
287
+ it "should reflect changes to the parent archive" do
288
+ parent << HRX::File.new("dir/another", "")
289
+ expect(child.to_hrx).to be == <<END
290
+ <===> top
291
+ top-level child
292
+
293
+ <===> sub/mid
294
+ mid-level child
295
+
296
+ <===> sub/dir/
297
+ <===> sub/lower/bottom
298
+ bottom-level child
299
+
300
+ <===> another
301
+ END
302
+ end
303
+ end
304
+ end
@@ -0,0 +1,57 @@
1
+ # coding: utf-8
2
+ # Copyright 2018 Google Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'hrx'
17
+
18
+ require_relative 'validates_path'
19
+
20
+ RSpec.describe HRX::Directory, "#initialize" do
21
+ let(:constructor) {lambda {|path| HRX::Directory.new(path)}}
22
+ include_examples "validates paths"
23
+
24
+ it "requires the path to be convertible to UTF-8" do
25
+ expect do
26
+ HRX::Directory.new("\xc3\x28".b)
27
+ end.to raise_error(EncodingError)
28
+ end
29
+
30
+ it "requires the comment to be convertible to UTF-8" do
31
+ expect do
32
+ HRX::Directory.new("dir", comment: "\xc3\x28".b)
33
+ end.to raise_error(EncodingError)
34
+ end
35
+
36
+ context "with arguments that are convertible to UTF-8" do
37
+ subject do
38
+ ika = "いか".encode("SJIS")
39
+ HRX::Directory.new(ika, comment: ika)
40
+ end
41
+
42
+ it("converts #path") {expect(subject.path).to be == "いか/"}
43
+ it("converts #comment") {expect(subject.comment).to be == "いか"}
44
+ end
45
+
46
+ it "forbids a path with a newline" do
47
+ expect {HRX::Directory.new("di\nr")}.to raise_error(HRX::ParseError)
48
+ end
49
+
50
+ it "doesn't add a slash to a path that has one" do
51
+ expect(HRX::Directory.new("dir/").path).to be == "dir/"
52
+ end
53
+
54
+ it "adds a slash to a path without one" do
55
+ expect(HRX::Directory.new("dir").path).to be == "dir/"
56
+ end
57
+ end
@@ -0,0 +1,60 @@
1
+ # coding: utf-8
2
+ # Copyright 2018 Google Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'hrx'
17
+
18
+ require_relative 'validates_path'
19
+
20
+ RSpec.describe HRX::File, "#initialize" do
21
+ let(:constructor) {lambda {|path| HRX::File.new(path, "")}}
22
+ include_examples "validates paths"
23
+
24
+ it "requires the path to be convertible to UTF-8" do
25
+ expect do
26
+ HRX::File.new("\xc3\x28".b, "")
27
+ end.to raise_error(EncodingError)
28
+ end
29
+
30
+ it "requires the content to be convertible to UTF-8" do
31
+ expect do
32
+ HRX::File.new("file", "\xc3\x28".b)
33
+ end.to raise_error(EncodingError)
34
+ end
35
+
36
+ it "requires the comment to be convertible to UTF-8" do
37
+ expect do
38
+ HRX::File.new("file", "", comment: "\xc3\x28".b)
39
+ end.to raise_error(EncodingError)
40
+ end
41
+
42
+ it "forbids a path with a trailing slash" do
43
+ expect {HRX::File.new("file/", "")}.to raise_error(HRX::ParseError)
44
+ end
45
+
46
+ it "forbids a path with a newline" do
47
+ expect {HRX::File.new("fi\nle", "")}.to raise_error(HRX::ParseError)
48
+ end
49
+
50
+ context "with arguments that are convertible to UTF-8" do
51
+ subject do
52
+ ika = "いか".encode("SJIS")
53
+ HRX::File.new(ika, ika, comment: ika)
54
+ end
55
+
56
+ it("converts #path") {expect(subject.path).to be == "いか"}
57
+ it("converts #content") {expect(subject.content).to be == "いか"}
58
+ it("converts #comment") {expect(subject.comment).to be == "いか"}
59
+ end
60
+ end
@@ -0,0 +1,60 @@
1
+ # Copyright 2018 Google Inc
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'linked-list'
16
+
17
+ require 'hrx'
18
+
19
+ RSpec.describe HRX::OrderedNode do
20
+ context "a list of ordered nodes" do
21
+ subject do
22
+ LinkedList::List.new <<
23
+ HRX::OrderedNode.new("do") <<
24
+ HRX::OrderedNode.new("re") <<
25
+ HRX::OrderedNode.new("me") <<
26
+ HRX::OrderedNode.new("fa") <<
27
+ HRX::OrderedNode.new("so")
28
+ end
29
+
30
+ def it_should_be_ordered
31
+ subject.each_node.each_cons(2) do |n1, n2|
32
+ expect(n1.order).to be < n2.order
33
+ end
34
+ end
35
+
36
+ it "should begin ordered" do
37
+ it_should_be_ordered
38
+ end
39
+
40
+ it "should remain ordered when a node is deleted" do
41
+ subject.delete "me"
42
+ it_should_be_ordered
43
+ end
44
+
45
+ it "should remain ordered when a node is added at the beginning" do
46
+ subject.unshift HRX::OrderedNode.new("ti")
47
+ it_should_be_ordered
48
+ end
49
+
50
+ it "should remain ordered when a node is added in the middle" do
51
+ subject.insert HRX::OrderedNode.new("re#"), after: "re"
52
+ it_should_be_ordered
53
+ end
54
+
55
+ it "should remain ordered when a node is added at the end" do
56
+ subject << HRX::OrderedNode.new("la")
57
+ it_should_be_ordered
58
+ end
59
+ end
60
+ end