hrx 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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