1 // NodeTest.cpp
2
3 #include <cppunit/TestCase.h>
4 #include <cppunit/TestCaller.h>
5 #include <cppunit/TestSuite.h>
6 #include <TestUtils.h>
7
8 #include <errno.h>
9 #include <fs_attr.h> // For struct attr_info
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <sys/stat.h> // For struct stat
13
14 #include <Directory.h>
15 #include <Entry.h>
16 #include <Node.h>
17 #include <StorageDefs.h>
18 #include <String.h>
19 #include <TypeConstants.h>
20
21 #include "NodeTest.h"
22
23
24 // == for attr_info
25 static
26 inline
27 bool
operator ==(const attr_info & info1,const attr_info & info2)28 operator==(const attr_info &info1, const attr_info &info2)
29 {
30 return (info1.type == info2.type && info1.size == info2.size);
31 }
32
33 // Suite
34 CppUnit::Test*
Suite()35 NodeTest::Suite() {
36 CppUnit::TestSuite *suite = new CppUnit::TestSuite();
37
38 StatableTest::AddBaseClassTests<NodeTest>("BNode::", suite);
39
40 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Init Test1", &NodeTest::InitTest1) );
41 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Init Test2", &NodeTest::InitTest2) );
42 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Attribute Directory Test", &NodeTest::AttrDirTest) );
43 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Attribute Read/Write/Remove Test", &NodeTest::AttrTest) );
44 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Attribute Rename Test"
45 #if TEST_R5
46 " (NOTE: test not actually performed with R5 libraries)"
47 #endif
48 , &NodeTest::AttrRenameTest) );
49 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Attribute Info Test", &NodeTest::AttrInfoTest) );
50 // TODO: AttrBString deadlocks entire OS (UnitTester at 100% CPU,
51 // windows don't respond to actions, won't open, OS won't even shut down)
52 //suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Attribute BString Test", &NodeTest::AttrBStringTest) );
53 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Sync Test", &NodeTest::SyncTest) );
54 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Dup Test", &NodeTest::DupTest) );
55 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Equality Test", &NodeTest::EqualityTest) );
56 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Assignment Test", &NodeTest::AssignmentTest) );
57 suite->addTest( new CppUnit::TestCaller<NodeTest>("BNode::Lock Test"
58 , &NodeTest::LockTest) );
59
60 return suite;
61 }
62
63 // ConvertTestNodesToStatables
64 static
65 void
ConvertTestStatablesToNodes(TestNodes & testNodes,TestStatables & testStatables)66 ConvertTestStatablesToNodes(TestNodes& testNodes, TestStatables& testStatables)
67 {
68 BNode *node;
69 string entryName;
70 for (testNodes.rewind(); testNodes.getNext(node, entryName); )
71 testStatables.add(node, entryName);
72 testNodes.clear(); // avoid deletion
73 }
74
75 // CreateROStatables
76 void
CreateROStatables(TestStatables & testEntries)77 NodeTest::CreateROStatables(TestStatables& testEntries)
78 {
79 TestNodes testNodes;
80 CreateRONodes(testNodes);
81 ConvertTestStatablesToNodes(testNodes, testEntries);
82 }
83
84 // CreateRWStatables
85 void
CreateRWStatables(TestStatables & testEntries)86 NodeTest::CreateRWStatables(TestStatables& testEntries)
87 {
88 TestNodes testNodes;
89 CreateRWNodes(testNodes);
90 ConvertTestStatablesToNodes(testNodes, testEntries);
91 }
92
93 // CreateUninitializedStatables
94 void
CreateUninitializedStatables(TestStatables & testEntries)95 NodeTest::CreateUninitializedStatables(TestStatables& testEntries)
96 {
97 TestNodes testNodes;
98 CreateUninitializedNodes(testNodes);
99 ConvertTestStatablesToNodes(testNodes, testEntries);
100 }
101
102 // CreateRONodes
103 void
CreateRONodes(TestNodes & testEntries)104 NodeTest::CreateRONodes(TestNodes& testEntries)
105 {
106 const char *filename;
107 filename = "/tmp";
108 testEntries.add(new BNode(filename), filename);
109 filename = "/";
110 testEntries.add(new BNode(filename), filename);
111 filename = "/boot";
112 testEntries.add(new BNode(filename), filename);
113 filename = "/boot/home";
114 testEntries.add(new BNode(filename), filename);
115 filename = "/boot/home/Desktop";
116 testEntries.add(new BNode(filename), filename);
117 filename = existingFilename;
118 testEntries.add(new BNode(filename), filename);
119 filename = dirLinkname;
120 testEntries.add(new BNode(filename), filename);
121 filename = fileLinkname;
122 testEntries.add(new BNode(filename), filename);
123 }
124
125 // CreateRWNodes
126 void
CreateRWNodes(TestNodes & testEntries)127 NodeTest::CreateRWNodes(TestNodes& testEntries)
128 {
129 const char *filename;
130 filename = existingFilename;
131 testEntries.add(new BNode(filename), filename);
132 filename = existingDirname;
133 testEntries.add(new BNode(filename), filename);
134 filename = existingSubDirname;
135 testEntries.add(new BNode(filename), filename);
136 filename = dirLinkname;
137 testEntries.add(new BNode(filename), filename);
138 filename = fileLinkname;
139 testEntries.add(new BNode(filename), filename);
140 filename = relDirLinkname;
141 testEntries.add(new BNode(filename), filename);
142 filename = relFileLinkname;
143 testEntries.add(new BNode(filename), filename);
144 filename = cyclicLinkname1;
145 testEntries.add(new BNode(filename), filename);
146 }
147
148 // CreateUninitializedNodes
149 void
CreateUninitializedNodes(TestNodes & testEntries)150 NodeTest::CreateUninitializedNodes(TestNodes& testEntries)
151 {
152 testEntries.add(new BNode, "");
153 }
154
155 // setUp
156 void
setUp()157 NodeTest::setUp()
158 {
159 StatableTest::setUp();
160 execCommand(
161 string("touch ") + existingFilename
162 + "; mkdir " + existingDirname
163 + "; mkdir " + existingSubDirname
164 + "; ln -s " + existingDirname + " " + dirLinkname
165 + "; ln -s " + existingFilename + " " + fileLinkname
166 + "; ln -s " + existingRelDirname + " " + relDirLinkname
167 + "; ln -s " + existingRelFilename + " " + relFileLinkname
168 + "; ln -s " + nonExistingDirname + " " + badLinkname
169 + "; ln -s " + cyclicLinkname1 + " " + cyclicLinkname2
170 + "; ln -s " + cyclicLinkname2 + " " + cyclicLinkname1
171 );
172 }
173
174 // tearDown
175 void
tearDown()176 NodeTest::tearDown()
177 {
178 StatableTest::tearDown();
179 // cleanup
180 string cmdLine("rm -rf ");
181 for (int32 i = 0; i < allFilenameCount; i++)
182 cmdLine += string(" ") + allFilenames[i];
183 if (allFilenameCount > 0)
184 execCommand(cmdLine);
185 }
186
187 // InitTest1
188 void
InitTest1()189 NodeTest::InitTest1()
190 {
191 const char *dirLink = dirLinkname;
192 const char *dirSuperLink = dirSuperLinkname;
193 const char *dirRelLink = dirRelLinkname;
194 const char *fileLink = fileLinkname;
195 const char *existingDir = existingDirname;
196 const char *existingSuperDir = existingSuperDirname;
197 const char *existingRelDir = existingRelDirname;
198 const char *existingFile = existingFilename;
199 const char *existingSuperFile = existingSuperFilename;
200 const char *existingRelFile = existingRelFilename;
201 const char *nonExisting = nonExistingDirname;
202 const char *nonExistingSuper = nonExistingSuperDirname;
203 const char *nonExistingRel = nonExistingRelDirname;
204 // 1. default constructor
205 NextSubTest();
206 {
207 BNode node;
208 CPPUNIT_ASSERT( node.InitCheck() == B_NO_INIT );
209 }
210
211 // 2. BNode(const char*)
212 NextSubTest();
213 {
214 BNode node(fileLink);
215 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
216 }
217 NextSubTest();
218 {
219 BNode node(nonExisting);
220 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
221 }
222 NextSubTest();
223 {
224 BNode node((const char *)NULL);
225 CPPUNIT_ASSERT( equals(node.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
226 }
227 NextSubTest();
228 {
229 BNode node("");
230 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
231 }
232 NextSubTest();
233 {
234 BNode node(existingFile);
235 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
236 }
237 NextSubTest();
238 {
239 BNode node(existingDir);
240 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
241 }
242 NextSubTest();
243 {
244 BNode node(tooLongEntryname);
245 CPPUNIT_ASSERT( node.InitCheck() == B_NAME_TOO_LONG );
246 }
247
248 // 3. BNode(const BEntry*)
249 NextSubTest();
250 {
251 BEntry entry(dirLink);
252 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
253 BNode node(&entry);
254 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
255 }
256 NextSubTest();
257 {
258 BEntry entry(nonExisting);
259 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
260 BNode node(&entry);
261 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
262 }
263 NextSubTest();
264 {
265 BNode node((BEntry *)NULL);
266 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
267 }
268 NextSubTest();
269 {
270 BEntry entry;
271 BNode node(&entry);
272 CPPUNIT_ASSERT( equals(node.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
273 }
274 NextSubTest();
275 {
276 BEntry entry(existingFile);
277 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
278 BNode node(&entry);
279 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
280
281 }
282 NextSubTest();
283 {
284 BEntry entry(existingDir);
285 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
286 BNode node(&entry);
287 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
288
289 }
290 NextSubTest();
291 {
292 BEntry entry(tooLongEntryname);
293 // R5 returns E2BIG instead of B_NAME_TOO_LONG
294 CPPUNIT_ASSERT( equals(entry.InitCheck(), E2BIG, B_NAME_TOO_LONG) );
295 BNode node(&entry);
296 CPPUNIT_ASSERT( equals(node.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
297 }
298
299 // 4. BNode(const entry_ref*)
300 NextSubTest();
301 {
302 BEntry entry(dirLink);
303 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
304 entry_ref ref;
305 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
306 BNode node(&ref);
307 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
308 }
309 NextSubTest();
310 {
311 BEntry entry(nonExisting);
312 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
313 entry_ref ref;
314 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
315 BNode node(&ref);
316 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
317 }
318 NextSubTest();
319 {
320 BNode node((entry_ref *)NULL);
321 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
322 }
323 NextSubTest();
324 {
325 BEntry entry(existingFile);
326 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
327 entry_ref ref;
328 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
329 BNode node(&ref);
330 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
331 }
332 NextSubTest();
333 {
334 BEntry entry(existingDir);
335 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
336 entry_ref ref;
337 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
338 BNode node(&ref);
339 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
340 }
341
342 // 5. BNode(const BDirectory*, const char*)
343 NextSubTest();
344 {
345 BDirectory pathDir(dirSuperLink);
346 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
347 BNode node(&pathDir, dirRelLink);
348 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
349 }
350 NextSubTest();
351 {
352 BDirectory pathDir(dirSuperLink);
353 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
354 BNode node(&pathDir, dirLink);
355 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
356 }
357 NextSubTest();
358 {
359 BDirectory pathDir(nonExistingSuper);
360 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
361 BNode node(&pathDir, nonExistingRel);
362 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
363 }
364 NextSubTest();
365 {
366 BNode node((BDirectory *)NULL, (const char *)NULL);
367 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
368 }
369 NextSubTest();
370 {
371 BNode node((BDirectory *)NULL, dirLink);
372 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
373 }
374 NextSubTest();
375 {
376 BDirectory pathDir(dirSuperLink);
377 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
378 BNode node(&pathDir, (const char *)NULL);
379 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
380 }
381 NextSubTest();
382 {
383 BDirectory pathDir(dirSuperLink);
384 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
385 BNode node(&pathDir, "");
386 CPPUNIT_ASSERT(node.InitCheck() == B_ENTRY_NOT_FOUND);
387 }
388 NextSubTest();
389 {
390 BDirectory pathDir(existingSuperFile);
391 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
392 BNode node(&pathDir, existingRelFile);
393 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
394 }
395 NextSubTest();
396 {
397 BDirectory pathDir(existingSuperDir);
398 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
399 BNode node(&pathDir, existingRelDir);
400 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
401 }
402 NextSubTest();
403 {
404 BDirectory pathDir(tooLongSuperEntryname);
405 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
406 BNode node(&pathDir, tooLongRelEntryname);
407 CPPUNIT_ASSERT( node.InitCheck() == B_NAME_TOO_LONG );
408 }
409 NextSubTest();
410 {
411 BDirectory pathDir(fileSuperDirname);
412 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
413 BNode node(&pathDir, fileRelDirname);
414 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
415 }
416 }
417
418 // InitTest2
419 void
InitTest2()420 NodeTest::InitTest2()
421 {
422 const char *dirLink = dirLinkname;
423 const char *dirSuperLink = dirSuperLinkname;
424 const char *dirRelLink = dirRelLinkname;
425 const char *fileLink = fileLinkname;
426 const char *existingDir = existingDirname;
427 const char *existingSuperDir = existingSuperDirname;
428 const char *existingRelDir = existingRelDirname;
429 const char *existingFile = existingFilename;
430 const char *existingSuperFile = existingSuperFilename;
431 const char *existingRelFile = existingRelFilename;
432 const char *nonExisting = nonExistingDirname;
433 const char *nonExistingSuper = nonExistingSuperDirname;
434 const char *nonExistingRel = nonExistingRelDirname;
435 BNode node;
436 // 2. BNode(const char*)
437 NextSubTest();
438 CPPUNIT_ASSERT( node.SetTo(fileLink) == B_OK );
439 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
440 //
441 NextSubTest();
442 CPPUNIT_ASSERT( node.SetTo(nonExisting) == B_ENTRY_NOT_FOUND );
443 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
444 //
445 NextSubTest();
446 CPPUNIT_ASSERT( equals(node.SetTo((const char *)NULL), B_BAD_VALUE,
447 B_NO_INIT) );
448 CPPUNIT_ASSERT( equals(node.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
449 //
450 NextSubTest();
451 CPPUNIT_ASSERT( node.SetTo("") == B_ENTRY_NOT_FOUND );
452 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
453 //
454 NextSubTest();
455 CPPUNIT_ASSERT( node.SetTo(existingFile) == B_OK );
456 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
457 //
458 NextSubTest();
459 CPPUNIT_ASSERT( node.SetTo(existingDir) == B_OK );
460 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
461 //
462 NextSubTest();
463 CPPUNIT_ASSERT( node.SetTo(tooLongEntryname) == B_NAME_TOO_LONG );
464 CPPUNIT_ASSERT( node.InitCheck() == B_NAME_TOO_LONG );
465
466 // 3. BNode(const BEntry*)
467 NextSubTest();
468 BEntry entry(dirLink);
469 CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
470 CPPUNIT_ASSERT( node.SetTo(&entry) == B_OK );
471 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
472 //
473 NextSubTest();
474 CPPUNIT_ASSERT( entry.SetTo(nonExisting) == B_OK );
475 CPPUNIT_ASSERT( node.SetTo(&entry) == B_ENTRY_NOT_FOUND );
476 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
477 //
478 NextSubTest();
479 CPPUNIT_ASSERT( node.SetTo((BEntry *)NULL) == B_BAD_VALUE );
480 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
481 //
482 NextSubTest();
483 entry.Unset();
484 CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
485 CPPUNIT_ASSERT( equals(node.SetTo(&entry), B_BAD_ADDRESS, B_BAD_VALUE) );
486 CPPUNIT_ASSERT( equals(node.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
487 //
488 NextSubTest();
489 CPPUNIT_ASSERT( entry.SetTo(existingFile) == B_OK );
490 CPPUNIT_ASSERT( node.SetTo(&entry) == B_OK );
491 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
492 //
493 NextSubTest();
494 CPPUNIT_ASSERT( entry.SetTo(existingDir) == B_OK );
495 CPPUNIT_ASSERT( node.SetTo(&entry) == B_OK );
496 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
497 //
498 NextSubTest();
499 // R5 returns E2BIG instead of B_NAME_TOO_LONG
500 CPPUNIT_ASSERT( equals(entry.SetTo(tooLongEntryname), E2BIG, B_NAME_TOO_LONG) );
501 CPPUNIT_ASSERT( equals(node.SetTo(&entry), B_BAD_ADDRESS, B_BAD_VALUE) );
502 CPPUNIT_ASSERT( equals(node.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
503
504 // 4. BNode(const entry_ref*)
505 NextSubTest();
506 CPPUNIT_ASSERT( entry.SetTo(dirLink) == B_OK );
507 entry_ref ref;
508 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
509 CPPUNIT_ASSERT( node.SetTo(&ref) == B_OK );
510 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
511 //
512 NextSubTest();
513 CPPUNIT_ASSERT( entry.SetTo(nonExisting) == B_OK );
514 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
515 CPPUNIT_ASSERT( node.SetTo(&ref) == B_ENTRY_NOT_FOUND );
516 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
517 //
518 NextSubTest();
519 CPPUNIT_ASSERT( node.SetTo((entry_ref *)NULL) == B_BAD_VALUE );
520 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
521 //
522 NextSubTest();
523 CPPUNIT_ASSERT( entry.SetTo(existingFile) == B_OK );
524 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
525 CPPUNIT_ASSERT( node.SetTo(&ref) == B_OK );
526 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
527 //
528 NextSubTest();
529 CPPUNIT_ASSERT( entry.SetTo(existingDir) == B_OK );
530 CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
531 CPPUNIT_ASSERT( node.SetTo(&ref) == B_OK );
532 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
533
534 // 5. BNode(const BDirectory*, const char*)
535 NextSubTest();
536 BDirectory pathDir(dirSuperLink);
537 CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
538 CPPUNIT_ASSERT( node.SetTo(&pathDir, dirRelLink) == B_OK );
539 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
540 //
541 NextSubTest();
542 CPPUNIT_ASSERT( pathDir.SetTo(dirSuperLink) == B_OK );
543 CPPUNIT_ASSERT( node.SetTo(&pathDir, dirLink) == B_BAD_VALUE );
544 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
545 //
546 NextSubTest();
547 CPPUNIT_ASSERT( pathDir.SetTo(nonExistingSuper) == B_OK );
548 CPPUNIT_ASSERT( node.SetTo(&pathDir, nonExistingRel) == B_ENTRY_NOT_FOUND );
549 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
550 //
551 NextSubTest();
552 CPPUNIT_ASSERT( node.SetTo((BDirectory *)NULL, (const char *)NULL)
553 == B_BAD_VALUE );
554 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
555 //
556 NextSubTest();
557 CPPUNIT_ASSERT( node.SetTo((BDirectory *)NULL, dirLink) == B_BAD_VALUE );
558 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
559 //
560 NextSubTest();
561 CPPUNIT_ASSERT( pathDir.SetTo(dirSuperLink) == B_OK );
562 CPPUNIT_ASSERT( node.SetTo(&pathDir, (const char *)NULL) == B_BAD_VALUE );
563 CPPUNIT_ASSERT( node.InitCheck() == B_BAD_VALUE );
564 //
565 NextSubTest();
566 CPPUNIT_ASSERT( pathDir.SetTo(dirSuperLink) == B_OK );
567 CPPUNIT_ASSERT(node.SetTo(&pathDir, "") == B_ENTRY_NOT_FOUND);
568 CPPUNIT_ASSERT(node.InitCheck() == B_ENTRY_NOT_FOUND);
569 //
570 NextSubTest();
571 CPPUNIT_ASSERT( pathDir.SetTo(existingSuperFile) == B_OK );
572 CPPUNIT_ASSERT( node.SetTo(&pathDir, existingRelFile) == B_OK );
573 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
574 //
575 NextSubTest();
576 CPPUNIT_ASSERT( pathDir.SetTo(existingSuperDir) == B_OK );
577 CPPUNIT_ASSERT( node.SetTo(&pathDir, existingRelDir) == B_OK );
578 CPPUNIT_ASSERT( node.InitCheck() == B_OK );
579 //
580 NextSubTest();
581 CPPUNIT_ASSERT( pathDir.SetTo(tooLongSuperEntryname) == B_OK );
582 CPPUNIT_ASSERT( node.SetTo(&pathDir, tooLongRelEntryname) == B_NAME_TOO_LONG );
583 CPPUNIT_ASSERT( node.InitCheck() == B_NAME_TOO_LONG );
584 //
585 NextSubTest();
586 CPPUNIT_ASSERT( pathDir.SetTo(fileSuperDirname) == B_OK );
587 CPPUNIT_ASSERT( node.SetTo(&pathDir, fileRelDirname) == B_ENTRY_NOT_FOUND );
588 CPPUNIT_ASSERT( node.InitCheck() == B_ENTRY_NOT_FOUND );
589 }
590
591 // WriteAttributes
592 static
593 void
WriteAttributes(BNode & node,const char ** attrNames,const char ** attrValues,int32 attrCount)594 WriteAttributes(BNode &node, const char **attrNames, const char **attrValues,
595 int32 attrCount)
596 {
597 for (int32 i = 0; i < attrCount; i++) {
598 const char *attrName = attrNames[i];
599 const char *attrValue = attrValues[i];
600 int32 valueSize = strlen(attrValue) + 1;
601 CPPUNIT_ASSERT( node.WriteAttr(attrName, B_STRING_TYPE, 0, attrValue,
602 valueSize) == valueSize );
603 }
604 }
605
606 // AttrDirTest
607 void
AttrDirTest(BNode & node)608 NodeTest::AttrDirTest(BNode &node)
609 {
610 // node should not have any attributes at the beginning
611 char nameBuffer[B_ATTR_NAME_LENGTH];
612 CPPUNIT_ASSERT( node.GetNextAttrName(nameBuffer) == B_ENTRY_NOT_FOUND );
613 // add some
614 const char *attrNames[] = {
615 "attr1", "attr2", "attr3", "attr4", "attr5"
616 };
617 const char *attrValues[] = {
618 "value1", "value2", "value3", "value4", "value5"
619 };
620 int32 attrCount = sizeof(attrNames) / sizeof(const char *);
621 WriteAttributes(node, attrNames, attrValues, attrCount);
622 TestSet testSet;
623 for (int32 i = 0; i < attrCount; i++)
624 testSet.add(attrNames[i]);
625 // get all attribute names
626 // R5: We have to rewind, we wouldn't get any attribute otherwise.
627 CPPUNIT_ASSERT( node.RewindAttrs() == B_OK );
628 while (node.GetNextAttrName(nameBuffer) == B_OK)
629 CPPUNIT_ASSERT( testSet.test(nameBuffer) == true );
630 CPPUNIT_ASSERT( testSet.testDone() == true );
631 CPPUNIT_ASSERT( node.GetNextAttrName(nameBuffer) == B_ENTRY_NOT_FOUND );
632 // rewind, get one attribute, rewind again and iterate through the whole
633 // list again
634 CPPUNIT_ASSERT( node.RewindAttrs() == B_OK );
635 testSet.rewind();
636 CPPUNIT_ASSERT( node.GetNextAttrName(nameBuffer) == B_OK );
637 CPPUNIT_ASSERT( testSet.test(nameBuffer) == true );
638 CPPUNIT_ASSERT( node.RewindAttrs() == B_OK );
639 testSet.rewind();
640 while (node.GetNextAttrName(nameBuffer) == B_OK)
641 CPPUNIT_ASSERT( testSet.test(nameBuffer) == true );
642 CPPUNIT_ASSERT( testSet.testDone() == true );
643 CPPUNIT_ASSERT( node.GetNextAttrName(nameBuffer) == B_ENTRY_NOT_FOUND );
644 // bad args
645 CPPUNIT_ASSERT( node.RewindAttrs() == B_OK );
646 testSet.rewind();
647 // R5: crashs, if passing a NULL buffer
648 #if !TEST_R5
649 CPPUNIT_ASSERT( node.GetNextAttrName(NULL) == B_BAD_VALUE );
650 #endif
651 }
652
653 // AttrDirTest
654 void
AttrDirTest()655 NodeTest::AttrDirTest()
656 {
657 // uninitialized objects
658 NextSubTest();
659 TestNodes testEntries;
660 CreateUninitializedNodes(testEntries);
661 BNode *node;
662 string nodeName;
663 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
664 char nameBuffer[B_ATTR_NAME_LENGTH];
665 CPPUNIT_ASSERT( node->RewindAttrs() != B_OK );
666 CPPUNIT_ASSERT( node->GetNextAttrName(nameBuffer) != B_OK );
667 }
668 testEntries.delete_all();
669 // existing entries
670 NextSubTest();
671 CreateRWNodes(testEntries);
672 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
673 AttrDirTest(*node);
674 }
675 testEntries.delete_all();
676 }
677
678 // AttrTest
679 void
AttrTest(BNode & node)680 NodeTest::AttrTest(BNode &node)
681 {
682 // add some attributes
683 const char *attrNames[] = {
684 "attr1", "attr2", "attr3", "attr4", "attr5"
685 };
686 const char *attrValues[] = {
687 "value1", "value2", "value3", "value4", "value5"
688 };
689 const char *newAttrValues[] = {
690 "fd", "kkgkjsdhfgkjhsd", "lihuhuh", "", "alkfgnakdfjgn"
691 };
692 int32 attrCount = sizeof(attrNames) / sizeof(const char *);
693 WriteAttributes(node, attrNames, attrValues, attrCount);
694 char buffer[1024];
695 // read and check them
696 for (int32 i = 0; i < attrCount; i++) {
697 const char *attrName = attrNames[i];
698 const char *attrValue = attrValues[i];
699 int32 valueSize = strlen(attrValue) + 1;
700 CPPUNIT_ASSERT( node.ReadAttr(attrName, B_STRING_TYPE, 0, buffer,
701 sizeof(buffer)) == valueSize );
702 CPPUNIT_ASSERT( strcmp(buffer, attrValue) == 0 );
703 }
704 // write a new value for each attribute
705 WriteAttributes(node, attrNames, newAttrValues, attrCount);
706 // read and check them
707 for (int32 i = 0; i < attrCount; i++) {
708 const char *attrName = attrNames[i];
709 const char *attrValue = newAttrValues[i];
710 int32 valueSize = strlen(attrValue) + 1;
711 CPPUNIT_ASSERT( node.ReadAttr(attrName, B_STRING_TYPE, 0, buffer,
712 sizeof(buffer)) == valueSize );
713 CPPUNIT_ASSERT( strcmp(buffer, attrValue) == 0 );
714 }
715 // bad args
716 CPPUNIT_ASSERT( equals(node.ReadAttr(NULL, B_STRING_TYPE, 0, buffer,
717 sizeof(buffer)),
718 B_BAD_ADDRESS, B_BAD_VALUE) );
719 CPPUNIT_ASSERT( equals(node.ReadAttr(attrNames[0], B_STRING_TYPE, 0, NULL,
720 sizeof(buffer)),
721 B_BAD_ADDRESS, B_BAD_VALUE) );
722 CPPUNIT_ASSERT( equals(node.ReadAttr(NULL, B_STRING_TYPE, 0, NULL,
723 sizeof(buffer)),
724 B_BAD_ADDRESS, B_BAD_VALUE) );
725 CPPUNIT_ASSERT( equals(node.WriteAttr(NULL, B_STRING_TYPE, 0, buffer,
726 sizeof(buffer)),
727 B_BAD_ADDRESS, B_BAD_VALUE) );
728 CPPUNIT_ASSERT( equals(node.WriteAttr(attrNames[0], B_STRING_TYPE, 0, NULL,
729 sizeof(buffer)),
730 B_BAD_ADDRESS, B_BAD_VALUE) );
731 CPPUNIT_ASSERT( equals(node.WriteAttr(NULL, B_STRING_TYPE, 0, NULL,
732 sizeof(buffer)),
733 B_BAD_ADDRESS, B_BAD_VALUE) );
734 CPPUNIT_ASSERT( equals(node.RemoveAttr(NULL), B_BAD_ADDRESS, B_BAD_VALUE) );
735 // too long attribute name
736 // R5: Read/RemoveAttr() do not return B_NAME_TOO_LONG, but B_ENTRY_NOT_FOUND
737 // R5: WriteAttr() does not return B_NAME_TOO_LONG, but B_BAD_VALUE
738 // R5: Haiku has a max attribute size of 256, while R5's was 255, exclusive
739 // of the null terminator. See changeset 4069e1f30.
740 char tooLongAttrName[B_ATTR_NAME_LENGTH + 3];
741 memset(tooLongAttrName, 'a', B_ATTR_NAME_LENGTH + 1);
742 tooLongAttrName[B_ATTR_NAME_LENGTH + 2] = '\0';
743 CPPUNIT_ASSERT_EQUAL(
744 node.WriteAttr(tooLongAttrName, B_STRING_TYPE, 0, buffer,
745 sizeof(buffer)),
746 B_NAME_TOO_LONG);
747 CPPUNIT_ASSERT_EQUAL(
748 node.ReadAttr(tooLongAttrName, B_STRING_TYPE, 0, buffer,
749 sizeof(buffer)),
750 B_NAME_TOO_LONG);
751 CPPUNIT_ASSERT_EQUAL(node.RemoveAttr(tooLongAttrName), B_NAME_TOO_LONG);
752
753 // remove the attributes and try to read them
754 for (int32 i = 0; i < attrCount; i++) {
755 const char *attrName = attrNames[i];
756 CPPUNIT_ASSERT( node.RemoveAttr(attrName) == B_OK );
757 CPPUNIT_ASSERT( node.ReadAttr(attrName, B_STRING_TYPE, 0, buffer,
758 sizeof(buffer)) == B_ENTRY_NOT_FOUND );
759 }
760 // try to remove a non-existing attribute
761 CPPUNIT_ASSERT( node.RemoveAttr("non existing attribute")
762 == B_ENTRY_NOT_FOUND );
763 }
764
765 // AttrTest
766 void
AttrTest()767 NodeTest::AttrTest()
768 {
769 // uninitialized objects
770 NextSubTest();
771 TestNodes testEntries;
772 CreateUninitializedNodes(testEntries);
773 BNode *node;
774 string nodeName;
775 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
776 char buffer[1024];
777 CPPUNIT_ASSERT( node->ReadAttr("attr1", B_STRING_TYPE, 0, buffer,
778 sizeof(buffer)) == B_FILE_ERROR );
779 CPPUNIT_ASSERT( node->WriteAttr("attr1", B_STRING_TYPE, 0, buffer,
780 sizeof(buffer)) == B_FILE_ERROR );
781 CPPUNIT_ASSERT( node->RemoveAttr("attr1") == B_FILE_ERROR );
782 }
783 testEntries.delete_all();
784 // existing entries
785 NextSubTest();
786 CreateRWNodes(testEntries);
787 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
788 AttrTest(*node);
789 }
790 testEntries.delete_all();
791 }
792
793 // AttrRenameTest
794 void
AttrRenameTest(BNode & node)795 NodeTest::AttrRenameTest(BNode &node)
796 {
797 const char attr1[] = "StorageKit::SomeAttribute";
798 const char attr2[] = "StorageKit::AnotherAttribute";
799
800 CPPUNIT_ASSERT( node.SetTo("./") == B_OK );
801
802 // Test the case of the first attribute not existing
803 node.RemoveAttr(attr1);
804
805 #if 1
806 // The actual tests in the else block below are disabled because as of
807 // right now, BFS doesn't support attribute rename. bfs_rename_attr()
808 // always reutrns B_NOT_SUPPORTED, which means BNode::RenameAttr() will
809 // also always return that result.
810 //
811 // So until that is implemented, we'll just test for B_NOT_SUPPORTED here.
812 // Once that functionality is implemented, this test will pass and someone
813 // can remove this section.
814 CPPUNIT_ASSERT_EQUAL(node.RenameAttr(attr1, attr2), B_NOT_SUPPORTED);
815 #else
816 const char str[] = "This is my testing string and it rules your world.";
817 const int strLen = strlen(str) + 1;
818 const int dataLen = 1024;
819 char data[dataLen];
820
821 CPPUNIT_ASSERT( node.RenameAttr(attr1, attr2) == B_BAD_VALUE );
822
823 // Write an attribute, read it to verify it, rename it, read the
824 // new attribute, read the old (which fails), and then remove the new.
825 CPPUNIT_ASSERT( node.WriteAttr(attr1, B_STRING_TYPE, 0, str, strLen) == strLen );
826 CPPUNIT_ASSERT( node.ReadAttr(attr1, B_STRING_TYPE, 0, data, dataLen) == strLen );
827 CPPUNIT_ASSERT( strcmp(data, str) == 0 );
828 CPPUNIT_ASSERT( node.RenameAttr(attr1, attr2) == B_OK ); // <<< This fails with R5::BNode
829 CPPUNIT_ASSERT( node.ReadAttr(attr1, B_STRING_TYPE, 0, data, dataLen) == B_ENTRY_NOT_FOUND );
830 CPPUNIT_ASSERT( node.ReadAttr(attr2, B_STRING_TYPE, 0, data, dataLen) == strLen );
831 CPPUNIT_ASSERT( strcmp(data, str) == 0 );
832 CPPUNIT_ASSERT( node.RemoveAttr(attr2) == B_OK );
833
834 // bad args
835 CPPUNIT_ASSERT( equals(node.RenameAttr(attr1, NULL), B_BAD_ADDRESS,
836 B_BAD_VALUE) );
837 CPPUNIT_ASSERT( equals(node.RenameAttr(NULL, attr2), B_BAD_ADDRESS,
838 B_BAD_VALUE) );
839 CPPUNIT_ASSERT( equals(node.RenameAttr(NULL, NULL), B_BAD_ADDRESS,
840 B_BAD_VALUE) );
841 // too long attribute name
842 // R5: RenameAttr() returns B_BAD_VALUE instead of B_NAME_TOO_LONG
843 char tooLongAttrName[B_ATTR_NAME_LENGTH + 2];
844 memset(tooLongAttrName, 'a', B_ATTR_NAME_LENGTH);
845 tooLongAttrName[B_ATTR_NAME_LENGTH + 1] = '\0';
846 CPPUNIT_ASSERT( node.RenameAttr(attr1, tooLongAttrName)
847 == B_BAD_VALUE );
848 CPPUNIT_ASSERT( node.RenameAttr(tooLongAttrName, attr1)
849 == B_BAD_VALUE );
850 #endif
851 }
852
853
854 // AttrRenameTest
855 void
AttrRenameTest()856 NodeTest::AttrRenameTest()
857 {
858 // uninitialized objects
859 NextSubTest();
860 TestNodes testEntries;
861 CreateUninitializedNodes(testEntries);
862 BNode *node;
863 string nodeName;
864 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
865 CPPUNIT_ASSERT( node->RenameAttr("attr1", "attr2") == B_FILE_ERROR );
866 }
867 testEntries.delete_all();
868 // existing entries
869 NextSubTest();
870 CreateRWNodes(testEntries);
871 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
872 AttrRenameTest(*node);
873 }
874 testEntries.delete_all();
875 }
876
877 // AttrInfoTest
878 void
AttrInfoTest(BNode & node)879 NodeTest::AttrInfoTest(BNode &node)
880 {
881 // add some attributes
882 const char *attrNames[] = {
883 "attr1", "attr2", "attr3", "attr4", "attr5"
884 };
885 const int32 attrCount = sizeof(attrNames) / sizeof(const char*);
886 const char attrValue1[] = "This is the greatest string ever.";
887 int32 attrValue2 = 17;
888 uint64 attrValue3 = 42;
889 double attrValue4 = 435.5;
890 struct flat_entry_ref { dev_t device; ino_t directory; char name[256]; }
891 attrValue5 = { 9, 16, "Hello world!" };
892 const void *attrValues[] = {
893 attrValue1, &attrValue2, &attrValue3, &attrValue4, &attrValue5
894 };
895 attr_info attrInfos[] = {
896 { B_STRING_TYPE, sizeof(attrValue1) },
897 { B_INT32_TYPE, sizeof(attrValue2) },
898 { B_UINT64_TYPE, sizeof(attrValue3) },
899 { B_DOUBLE_TYPE, sizeof(attrValue4) },
900 { B_REF_TYPE, sizeof(attrValue5) }
901 };
902 for (int32 i = 0; i < attrCount; i++) {
903 const char *attrName = attrNames[i];
904 const void *attrValue = attrValues[i];
905 int32 valueSize = attrInfos[i].size;
906 uint32 attrType = attrInfos[i].type;
907 CPPUNIT_ASSERT( node.WriteAttr(attrName, attrType, 0, attrValue,
908 valueSize) == valueSize );
909 }
910 // get the attribute infos
911 for (int32 i = 0; i < attrCount; i++) {
912 const char *attrName = attrNames[i];
913 attr_info info;
914 CPPUNIT_ASSERT( node.GetAttrInfo(attrName, &info) == B_OK );
915 CPPUNIT_ASSERT( info == attrInfos[i] );
916 }
917 // try get an info for a non-existing attribute
918 attr_info info;
919 CPPUNIT_ASSERT( node.GetAttrInfo("non-existing attribute", &info)
920 == B_ENTRY_NOT_FOUND );
921 // bad values
922 CPPUNIT_ASSERT( equals(node.GetAttrInfo(NULL, &info), B_BAD_ADDRESS,
923 B_BAD_VALUE) );
924 CPPUNIT_ASSERT( equals(node.GetAttrInfo(attrNames[0], NULL), B_BAD_ADDRESS,
925 B_BAD_VALUE) );
926 CPPUNIT_ASSERT( equals(node.GetAttrInfo(NULL, NULL), B_BAD_ADDRESS,
927 B_BAD_VALUE) );
928 // too long attribute name
929 // R5: GetAttrInfo() does not return B_NAME_TOO_LONG
930 char tooLongAttrName[B_ATTR_NAME_LENGTH + 2];
931 memset(tooLongAttrName, 'a', B_ATTR_NAME_LENGTH);
932 tooLongAttrName[B_ATTR_NAME_LENGTH + 1] = '\0';
933 CPPUNIT_ASSERT( node.GetAttrInfo(tooLongAttrName, &info)
934 == B_ENTRY_NOT_FOUND );
935 }
936
937 // AttrInfoTest
938 void
AttrInfoTest()939 NodeTest::AttrInfoTest()
940 {
941 // uninitialized objects
942 NextSubTest();
943 TestNodes testEntries;
944 CreateUninitializedNodes(testEntries);
945 BNode *node;
946 string nodeName;
947 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
948 attr_info info;
949 CPPUNIT_ASSERT( node->GetAttrInfo("attr1", &info) == B_FILE_ERROR );
950 }
951 testEntries.delete_all();
952 // existing entries
953 NextSubTest();
954 CreateRWNodes(testEntries);
955 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
956 AttrInfoTest(*node);
957 }
958 testEntries.delete_all();
959 }
960
961 // AttrBStringTest
962 void
AttrBStringTest(BNode & node)963 NodeTest::AttrBStringTest(BNode &node)
964 {
965 // add some attributes
966 const char *attrNames[] = {
967 "attr1", "attr2", "attr3", "attr4", "attr5"
968 };
969 const char *attrValues[] = {
970 "value1", "value2", "value3", "value4", "value5"
971 };
972 const char *newAttrValues[] = {
973 "fd", "kkgkjsdhfgkjhsd", "lihuhuh", "", "alkfgnakdfjgn"
974 };
975 int32 attrCount = sizeof(attrNames) / sizeof(const char *);
976 for (int32 i = 0; i < attrCount; i++) {
977 const char *attrName = attrNames[i];
978 BString attrValue(attrValues[i]);
979 CPPUNIT_ASSERT( node.WriteAttrString(attrName, &attrValue) == B_OK );
980 }
981 // read and check them
982 for (int32 i = 0; i < attrCount; i++) {
983 const char *attrName = attrNames[i];
984 const char *attrValue = attrValues[i];
985 BString readValue;
986 CPPUNIT_ASSERT( node.ReadAttrString(attrName, &readValue) == B_OK );
987 CPPUNIT_ASSERT( readValue == attrValue );
988 }
989 // write a new value for each attribute
990 for (int32 i = 0; i < attrCount; i++) {
991 const char *attrName = attrNames[i];
992 BString attrValue(newAttrValues[i]);
993 CPPUNIT_ASSERT( node.WriteAttrString(attrName, &attrValue) == B_OK );
994 }
995 // read and check them
996 for (int32 i = 0; i < attrCount; i++) {
997 const char *attrName = attrNames[i];
998 const char *attrValue = newAttrValues[i];
999 BString readValue;
1000 CPPUNIT_ASSERT( node.ReadAttrString(attrName, &readValue) == B_OK );
1001 CPPUNIT_ASSERT( readValue == attrValue );
1002 }
1003 // bad args
1004 BString readValue;
1005 BString writeValue("test");
1006 // R5: crashes, if supplying a NULL BString
1007 #if !TEST_R5
1008 CPPUNIT_ASSERT( node.WriteAttrString(attrNames[0], NULL) == B_BAD_VALUE );
1009 CPPUNIT_ASSERT( node.ReadAttrString(attrNames[0], NULL) == B_BAD_VALUE );
1010 #endif
1011 CPPUNIT_ASSERT( equals(node.WriteAttrString(NULL, &writeValue),
1012 B_BAD_ADDRESS, B_BAD_VALUE) );
1013 CPPUNIT_ASSERT( equals(node.ReadAttrString(NULL, &readValue),
1014 B_BAD_ADDRESS, B_BAD_VALUE) );
1015 #if !TEST_R5
1016 CPPUNIT_ASSERT( node.WriteAttrString(NULL, NULL) == B_BAD_VALUE );
1017 #endif
1018 CPPUNIT_ASSERT( equals(node.ReadAttrString(NULL, NULL),
1019 B_BAD_ADDRESS, B_BAD_VALUE) );
1020 // remove the attributes and try to read them
1021 for (int32 i = 0; i < attrCount; i++) {
1022 const char *attrName = attrNames[i];
1023 CPPUNIT_ASSERT( node.RemoveAttr(attrName) == B_OK );
1024 CPPUNIT_ASSERT( node.ReadAttrString(attrName, &readValue)
1025 == B_ENTRY_NOT_FOUND );
1026 }
1027 // too long attribute name
1028 // R5: Read/WriteAttrString() do not return B_NAME_TOO_LONG
1029 char tooLongAttrName[B_ATTR_NAME_LENGTH + 2];
1030 memset(tooLongAttrName, 'a', B_ATTR_NAME_LENGTH);
1031 tooLongAttrName[B_ATTR_NAME_LENGTH + 1] = '\0';
1032 CPPUNIT_ASSERT( node.WriteAttrString(tooLongAttrName, &writeValue)
1033 == B_BAD_VALUE );
1034 CPPUNIT_ASSERT( node.ReadAttrString(tooLongAttrName, &readValue)
1035 == B_ENTRY_NOT_FOUND );
1036 }
1037
1038 // AttrBStringTest
1039 void
AttrBStringTest()1040 NodeTest::AttrBStringTest()
1041 {
1042 // uninitialized objects
1043 NextSubTest();
1044 TestNodes testEntries;
1045 CreateUninitializedNodes(testEntries);
1046 BNode *node;
1047 string nodeName;
1048 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1049 BString value("test");
1050 CPPUNIT_ASSERT( node->WriteAttrString("attr1", &value)
1051 == B_FILE_ERROR );
1052 CPPUNIT_ASSERT( node->ReadAttrString("attr1", &value)
1053 == B_FILE_ERROR );
1054 }
1055 testEntries.delete_all();
1056 // existing entries
1057 NextSubTest();
1058 CreateRWNodes(testEntries);
1059 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1060 AttrBStringTest(*node);
1061 }
1062 testEntries.delete_all();
1063 }
1064
1065 // This doesn't actually verify synching is occuring; just
1066 // checks for a B_OK return value.
1067 void
SyncTest()1068 NodeTest::SyncTest() {
1069 const char attr[] = "StorageKit::SomeAttribute";
1070 const char str[] = "This string rules your world.";
1071 const int len = strlen(str) + 1;
1072 // uninitialized objects
1073 NextSubTest();
1074 TestNodes testEntries;
1075 CreateUninitializedNodes(testEntries);
1076 BNode *node;
1077 string nodeName;
1078 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1079 CPPUNIT_ASSERT( node->Sync() == B_FILE_ERROR );
1080 }
1081 testEntries.delete_all();
1082 // existing entries
1083 NextSubTest();
1084 CreateRWNodes(testEntries);
1085 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1086 CPPUNIT_ASSERT( node->WriteAttr(attr, B_STRING_TYPE, 0, str, len)
1087 == len );
1088 CPPUNIT_ASSERT( node->Sync() == B_OK );
1089 }
1090 testEntries.delete_all();
1091 }
1092
1093 // DupTest
1094 void
DupTest(BNode & node)1095 NodeTest::DupTest(BNode &node)
1096 {
1097 int fd = node.Dup();
1098 CPPUNIT_ASSERT( fd != -1 );
1099 ::close(fd);
1100 }
1101
1102 // DupTest
1103 void
DupTest()1104 NodeTest::DupTest()
1105 {
1106 // uninitialized objects
1107 NextSubTest();
1108 TestNodes testEntries;
1109 CreateUninitializedNodes(testEntries);
1110 BNode *node;
1111 string nodeName;
1112 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1113 CPPUNIT_ASSERT( node->Dup() == -1 );
1114 }
1115 testEntries.delete_all();
1116 // existing entries
1117 NextSubTest();
1118 CreateRWNodes(testEntries);
1119 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1120 DupTest(*node);
1121 }
1122 testEntries.delete_all();
1123 }
1124
1125 // n1 and n2 should both be uninitialized. y1a and y1b should be initialized
1126 // to the same node, y2 should be initialized to a different node
1127 void
EqualityTest(BNode & n1,BNode & n2,BNode & y1a,BNode & y1b,BNode & y2)1128 NodeTest::EqualityTest(BNode &n1, BNode &n2, BNode &y1a, BNode &y1b, BNode &y2) {
1129 CPPUNIT_ASSERT( n1 == n2 );
1130 CPPUNIT_ASSERT( !(n1 != n2) );
1131 CPPUNIT_ASSERT( n1 != y2 );
1132 CPPUNIT_ASSERT( !(n1 == y2) );
1133
1134 CPPUNIT_ASSERT( y1a != n2 );
1135 CPPUNIT_ASSERT( !(y1a == n2) );
1136 CPPUNIT_ASSERT( y1a == y1b );
1137 CPPUNIT_ASSERT( !(y1a != y1b) );
1138 CPPUNIT_ASSERT( y1a != y2 );
1139 CPPUNIT_ASSERT( !(y1a == y2) );
1140
1141 CPPUNIT_ASSERT( n1 == n1 );
1142 CPPUNIT_ASSERT( !(n1 != n1) );
1143 CPPUNIT_ASSERT( y2 == y2 );
1144 CPPUNIT_ASSERT( !(y2 != y2) );
1145 }
1146
1147 // EqualityTest
1148 void
EqualityTest()1149 NodeTest::EqualityTest()
1150 {
1151 BNode n1, n2, y1a("/boot"), y1b("/boot"), y2("/");
1152
1153 EqualityTest(n1, n2, y1a, y1b, y2);
1154 }
1155
1156 // AssignmentTest
1157 void
AssignmentTest()1158 NodeTest::AssignmentTest()
1159 {
1160 BNode n1, n2, y1a("/boot"), y1b("/boot"), y2("/");
1161
1162 n1 = n1; // self n
1163 y1a = y1b; // psuedo self y
1164 y1a = y1a; // self y
1165 n2 = y2; // n = y
1166 y1b = n1; // y = n
1167 y2 = y1a; // y1 = y2
1168
1169 EqualityTest(n1, y1b, y1a, y2, n2);
1170 }
1171
1172 // Locking isn't really implemented yet...
1173 void
LockTest(BNode & node,const char * entryName)1174 NodeTest::LockTest(BNode &node, const char *entryName)
1175 {
1176 CPPUNIT_ASSERT( node.Lock() == B_OK );
1177 BNode node2(entryName);
1178 CPPUNIT_ASSERT( node2.InitCheck() == B_BUSY );
1179 CPPUNIT_ASSERT( node.Unlock() == B_OK );
1180 CPPUNIT_ASSERT( node.Unlock() == B_BAD_VALUE );
1181 CPPUNIT_ASSERT( node2.SetTo(entryName) == B_OK );
1182 // R5: Since two file descriptors exist at this point, locking is supposed
1183 // to fail according to the BeBook, but it succeeds!
1184 CPPUNIT_ASSERT( node2.Lock() == B_OK );
1185 CPPUNIT_ASSERT( node.Lock() == B_BUSY );
1186 //
1187 CPPUNIT_ASSERT( node2.Unlock() == B_OK );
1188 }
1189
1190 // Locking isn't really implemented yet...
1191 void
LockTest()1192 NodeTest::LockTest()
1193 {
1194 // uninitialized objects
1195 NextSubTest();
1196 TestNodes testEntries;
1197 CreateUninitializedNodes(testEntries);
1198 BNode *node;
1199 string nodeName;
1200 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1201 CPPUNIT_ASSERT( node->Dup() == -1 );
1202 }
1203 testEntries.delete_all();
1204 // existing entries
1205 NextSubTest();
1206 CreateRWNodes(testEntries);
1207 for (testEntries.rewind(); testEntries.getNext(node, nodeName); ) {
1208 LockTest(*node, nodeName.c_str());
1209 }
1210 testEntries.delete_all();
1211 }
1212
1213 // entry names used in tests
1214 const char *NodeTest::existingFilename = "/tmp/existing-file";
1215 const char *NodeTest::existingSuperFilename = "/tmp";
1216 const char *NodeTest::existingRelFilename = "existing-file";
1217 const char *NodeTest::existingDirname = "/tmp/existing-dir";
1218 const char *NodeTest::existingSuperDirname = "/tmp";
1219 const char *NodeTest::existingRelDirname = "existing-dir";
1220 const char *NodeTest::existingSubDirname
1221 = "/tmp/existing-dir/existing-subdir";
1222 const char *NodeTest::existingRelSubDirname = "existing-subdir";
1223 const char *NodeTest::nonExistingFilename = "/tmp/non-existing-file";
1224 const char *NodeTest::nonExistingDirname = "/tmp/non-existing-dir";
1225 const char *NodeTest::nonExistingSuperDirname = "/tmp";
1226 const char *NodeTest::nonExistingRelDirname = "non-existing-dir";
1227 const char *NodeTest::testFilename1 = "/tmp/test-file1";
1228 const char *NodeTest::testDirname1 = "/tmp/test-dir1";
1229 const char *NodeTest::tooLongEntryname =
1230 "/tmp/This is an awfully long name for an entry. It is that kind of entry "
1231 "that just can't exist due to its long name. In fact its path name is not "
1232 "too long -- a path name can contain 1024 characters -- but the name of "
1233 "the entry itself is restricted to 256 characters, which this entry's "
1234 "name does exceed.";
1235 const char *NodeTest::tooLongSuperEntryname = "/tmp";
1236 const char *NodeTest::tooLongRelEntryname =
1237 "This is an awfully long name for an entry. It is that kind of entry "
1238 "that just can't exist due to its long name. In fact its path name is not "
1239 "too long -- a path name can contain 1024 characters -- but the name of "
1240 "the entry itself is restricted to 256 characters, which this entry's "
1241 "name does exceed.";
1242 const char *NodeTest::fileDirname = "/tmp/test-file1/some-dir";
1243 const char *NodeTest::fileSuperDirname = "/tmp";
1244 const char *NodeTest::fileRelDirname = "test-file1/some-dir";
1245 const char *NodeTest::dirLinkname = "/tmp/link-to-dir1";
1246 const char *NodeTest::dirSuperLinkname = "/tmp";
1247 const char *NodeTest::dirRelLinkname = "link-to-dir1";
1248 const char *NodeTest::fileLinkname = "/tmp/link-to-file1";
1249 const char *NodeTest::fileSuperLinkname = "/tmp";
1250 const char *NodeTest::fileRelLinkname = "link-to-file1";
1251 const char *NodeTest::relDirLinkname = "/tmp/rel-link-to-dir1";
1252 const char *NodeTest::relFileLinkname = "/tmp/rel-link-to-file1";
1253 const char *NodeTest::badLinkname = "/tmp/link-to-void";
1254 const char *NodeTest::cyclicLinkname1 = "/tmp/cyclic-link1";
1255 const char *NodeTest::cyclicLinkname2 = "/tmp/cyclic-link2";
1256
1257 const char *NodeTest::allFilenames[] = {
1258 existingFilename,
1259 existingDirname,
1260 nonExistingFilename,
1261 nonExistingDirname,
1262 testFilename1,
1263 testDirname1,
1264 dirLinkname,
1265 fileLinkname,
1266 relDirLinkname,
1267 relFileLinkname,
1268 badLinkname,
1269 cyclicLinkname1,
1270 cyclicLinkname2,
1271 };
1272 const int32 NodeTest::allFilenameCount
1273 = sizeof(allFilenames) / sizeof(const char*);
1274
1275