xref: /haiku/src/tests/kits/app/broster/GetRecentTester.cpp (revision d4e4909c6a3fe4290b78be2b78035c4774e3ff18)
1 //------------------------------------------------------------------------------
2 //	GetRecentTester.cpp
3 //
4 //------------------------------------------------------------------------------
5 
6 // Standard Includes -----------------------------------------------------------
7 #include <stdio.h>
8 
9 // System Includes -------------------------------------------------------------
10 #include <Directory.h>
11 #include <Entry.h>
12 #include <File.h>
13 #include <fs_attr.h>
14 #include <Message.h>
15 #include <Node.h>
16 #include <Roster.h>
17 
18 #ifdef TEST_OBOS
19 #include <RosterPrivate.h>
20 #endif
21 
22 // Project Includes ------------------------------------------------------------
23 #include <TestShell.h>
24 #include <TestUtils.h>
25 #include <cppunit/TestAssert.h>
26 
27 // Local Includes --------------------------------------------------------------
28 #include "GetRecentTester.h"
29 #include "testapps/RecentAppsTestApp.h"
30 
31 // Local Defines ---------------------------------------------------------------
32 
33 //------------------------------------------------------------------------------
34 // Attribute names and types
35 //------------------------------------------------------------------------------
36 
37 const int32 kFlagsType = 'APPF';
38 
39 const char *kTypeAttr = "BEOS:TYPE";
40 const char *kSigAttr = "BEOS:APP_SIG";
41 const char *kFlagsAttr = "BEOS:APP_FLAGS";
42 
43 #ifndef B_MIME_STRING_TYPE
44 #define B_MIME_STRING_TYPE 'MIMS'
45 #endif
46 
47 //------------------------------------------------------------------------------
48 // BEOS:APP_FLAGS attributes
49 //------------------------------------------------------------------------------
50 
51 const int32 kSingleLaunchFlags = B_SINGLE_LAUNCH;
52 const int32 kMultipleLaunchFlags = B_MULTIPLE_LAUNCH;
53 const int32 kExclusiveLaunchFlags = B_EXCLUSIVE_LAUNCH;
54 
55 const int32 kSingleLaunchArgvOnlyFlags = B_SINGLE_LAUNCH | B_ARGV_ONLY;
56 const int32 kMultipleLaunchArgvOnlyFlags = B_MULTIPLE_LAUNCH | B_ARGV_ONLY;
57 const int32 kExclusiveLaunchArgvOnlyFlags = B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY;
58 
59 const int32 kSingleLaunchBackgroundFlags = B_SINGLE_LAUNCH | B_BACKGROUND_APP;
60 const int32 kMultipleLaunchBackgroundFlags = B_MULTIPLE_LAUNCH | B_BACKGROUND_APP;
61 const int32 kExclusiveLaunchBackgroundFlags = B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP;
62 
63 const int32 kSingleLaunchArgvOnlyBackgroundFlags = B_SINGLE_LAUNCH | B_ARGV_ONLY | B_BACKGROUND_APP;
64 const int32 kMultipleLaunchArgvOnlyBackgroundFlags = B_MULTIPLE_LAUNCH | B_ARGV_ONLY | B_BACKGROUND_APP;
65 const int32 kExclusiveLaunchArgvOnlyBackgroundFlags = B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY | B_BACKGROUND_APP;
66 
67 const int32 kQualifyingFlags[] = {
68 	kSingleLaunchFlags,
69 	kMultipleLaunchFlags,
70 	kExclusiveLaunchFlags,
71 };
72 
73 const int32 kNonQualifyingFlags[] = {
74 	kSingleLaunchArgvOnlyFlags,
75 	kMultipleLaunchArgvOnlyFlags,
76 	kExclusiveLaunchArgvOnlyFlags,
77 	kSingleLaunchBackgroundFlags,
78 	kMultipleLaunchBackgroundFlags,
79 	kExclusiveLaunchBackgroundFlags,
80 	kSingleLaunchArgvOnlyBackgroundFlags,
81 	kMultipleLaunchArgvOnlyBackgroundFlags,
82 	kExclusiveLaunchArgvOnlyBackgroundFlags,
83 };
84 
85 //------------------------------------------------------------------------------
86 // Temporary files
87 //------------------------------------------------------------------------------
88 const char *kTempDirRoot = "/tmp";
89 const char *kTempDir = "/tmp/obos-recent-tests";
90 const char *kTempSaveFile = "/tmp/obos-recent-tests/RosterSettingsTest";
91 
92 const char *kTestType1 = "text/x-vnd.obos-recent-docs-test-type-1";
93 const char *kTestType2 = "text/x-vnd.obos-recent-docs-test-type-2";
94 
95 const char *test_types[] = {
96 	kTestType1,
97 	kTestType2,
98 };
99 
100 struct test_doc {
101 	const char *name;
102 	const char *type;
103 } test_docs[] = {
104 	{ "first-file-of-type-1", kTestType1 },
105 	{ "second-file-of-type-1", kTestType1 },
106 	{ "first-file-of-type-2", kTestType2 },
107 	{ "second-file-of-type-2", kTestType2 },
108 	{ "untyped", NULL },
109 };
110 
111 enum test_doc_index {
112 	kTestDocUntyped,
113 	kTestDoc1Type1,
114 	kTestDoc2Type1,
115 	kTestDoc1Type2,
116 	kTestDoc2Type2,
117 };
118 
119 const char *test_folders[] = {
120 	"test-folder-1",
121 	"test-folder-2",
122 	"test-folder-3",
123 	"test-folder-4",
124 };
125 
126 const char *test_sigs[] = {
127 	"application/x-vnd.obos-recent-tests-1",
128 	"imposter/this-is-not-an-app-sig-now-is-it?",
129 	"application/x-vnd.obos-recent-tests-3",
130 	"application/x-vnd.obos-recent-tests-app-sig-4",
131 	"application/x-vnd.obos-recent-tests-5",
132 	"application/x-vnd.obos-recent-tests-6",
133 	"application/x-vnd.obos-recent-tests-7",
134 	"application/x-vnd.obos-recent-tests-8",
135 };
136 
137 //------------------------------------------------------------------------------
138 // Functions
139 //------------------------------------------------------------------------------
140 
141 status_t check_ref_count(BMessage *refMsg, int32 count);
142 status_t set_test_app_attributes(const entry_ref *app, const char *sig, const int32 *flags);
143 status_t launch_test_app(RecentAppsTestAppId id, const int32 *flags);
144 status_t get_test_app_ref(RecentAppsTestAppId id, entry_ref *ref);
145 status_t get_test_ref(test_doc_index index, entry_ref *ref);
146 
147 
148 // Globals ---------------------------------------------------------------------
149 
150 //------------------------------------------------------------------------------
151 
152 /*! \brief Verifies that the given BMessage has a \c "refs" field
153 	containing \a count B_REF_TYPE entries.
154 
155 	\return
156 	- \c B_OK: The predicate is true
157 	- \c B_ERROR: The predicate is false
158 	- other error code: An error occured
159 */
160 status_t
161 check_ref_count(BMessage *refMsg, int32 count)
162 {
163 	type_code type;
164 	int32 realCount;
165 	status_t err = refMsg ? B_OK : B_BAD_VALUE;
166 
167 	if (!err)
168 		err = refMsg->GetInfo("refs", &type, &realCount);
169 	if (!err) {
170 		err = realCount == count ? B_OK : B_ERROR;
171 		if (!err)
172 			err = type == B_REF_TYPE ? B_OK : B_ERROR;
173 	} else if (err == B_NAME_NOT_FOUND && count == 0) {
174 		err = B_OK;
175 	}
176 
177 	return err;
178 }
179 
180 /*! \brief Sets or unsets \c BEOS:APP_SIG and \c BEOS:APP_FLAGS attributes for
181 	the given entry (which is assumed to be an application).
182 
183 	\param app The entry to modify
184 	\param sig If \c non-NULL, the given signature should be written to the entry's
185 	           \c BEOS:APP_SIG attribute. If \c NULL, said attribute should be
186 	           removed if it exists.
187 	\param sig If \c non-NULL, the given flags should be written to the entry's
188 	           \c BEOS:APP_FLAG attribute. If \c NULL, said attribute should be
189 	           removed if it exists.
190 */
191 status_t
192 set_test_app_attributes(const entry_ref *app, const char *sig, const int32 *flags)
193 {
194 	BNode node;
195 	attr_info info;
196 	status_t err = app ? B_OK : B_BAD_VALUE;
197 
198 	// Open a node on the given app
199 	if (!err)
200 		err = node.SetTo(app);
201 	// Write/remove the appropriate attributes
202 	if (!err) {
203 		if (sig) {
204 			// Set the attribute
205 			ssize_t bytes = node.WriteAttr(kSigAttr, B_MIME_STRING_TYPE, 0, sig, strlen(sig)+1);
206 			if (bytes >= 0)
207 				err = bytes == (ssize_t)strlen(sig)+1 ? B_OK : B_FILE_ERROR;
208 			else
209 				err = bytes;
210 		} else {
211 			// See if the attribute exists and thus needs to be removed
212 			if (node.GetAttrInfo(kSigAttr, &info) == B_OK)
213 				err = node.RemoveAttr(kSigAttr);
214 		}
215 	}
216 	if (!err) {
217 		if (flags) {
218 			// Set the attribute
219 			ssize_t bytes = node.WriteAttr(kFlagsAttr, kFlagsType, 0, flags, sizeof(int32));
220 			if (bytes >= 0)
221 				err = bytes == sizeof(int32) ? B_OK : B_FILE_ERROR;
222 			else
223 				err = bytes;
224 		} else {
225 			// See if the attribute exists and thus needs to be removed
226 			if (node.GetAttrInfo(kFlagsAttr, &info) == B_OK)
227 				err = node.RemoveAttr(kFlagsAttr);
228 		}
229 	}
230 	return err;
231 }
232 
233 /*! \brief Launches the given test app after first setting the application entry's
234 	\c BEOS:APP_FLAGS attribute as specified.
235 
236 	See RecentAppsTestApp.h for more info on RecentAppsTestAppId, and see
237 	set_test_app_attributes() for more info on the nature of the \a flags argument.
238 */
239 status_t
240 launch_test_app(RecentAppsTestAppId id, const int32 *flags)
241 {
242 	entry_ref ref;
243 	status_t err = get_test_app_ref(id, &ref);
244 	std::string sig;
245 	// Set the attributes
246 	if (!err) {
247 		err = set_test_app_attributes(&ref, kRecentAppsTestAppSigs[id], flags);
248 	}
249 	// Launch the app
250 	if (!err) {
251 		BRoster roster;
252 		err = roster.Launch(&ref);
253 //		err = roster.Launch(kRecentAppsTestAppSigs[id]);
254 	}
255 	// Give it time to do its thing
256 	if (!err)
257 		snooze(250000);
258 	return err;
259 }
260 
261 /*! \brief Returns an entry_ref for the given test app in \a ref.
262 
263 	\param id The id of the app of interest
264 	\param ref Pointer to a pre-allocated \c entry_ref structure
265 	           into which the result is set.
266 */
267 status_t
268 get_test_app_ref(RecentAppsTestAppId id, entry_ref *ref)
269 {
270 	const char *testDir = BTestShell::GlobalTestDir();
271 	BEntry entry;
272 
273 	status_t err = ref ? B_OK : B_BAD_VALUE;
274 	if (!err)
275 		err = testDir ? B_OK : B_NAME_NOT_FOUND;
276 	if (!err) {
277 		char path[B_PATH_NAME_LENGTH];
278 		sprintf(path, "%s/%s%s", testDir, kRecentAppsTestAppFilenames[id],
279 #if TEST_R5
280 		"_r5"
281 #else
282 		""
283 #endif
284 		);
285 		err = entry.SetTo(path);
286 	}
287 	if (!err)
288 		err = entry.GetRef(ref);
289 	return err;
290 }
291 
292 /* \brief Fetches an entry_ref for the given test document
293 
294 	The file is assumed to reside in the directory specified
295 	by \c kTempDir.
296 
297 	\param leafname the name of the file with no path information
298 	\param ref pointer to a pre-allocated entry_ref into which the
299 	           result is stored
300 */
301 status_t get_test_ref(const char *leafname, entry_ref *ref)
302 {
303 	BEntry entry;
304 
305 	status_t err = leafname && ref ? B_OK : B_BAD_VALUE;
306 	if (!err) {
307 		char path[B_PATH_NAME_LENGTH];
308 		sprintf(path, "%s/%s", kTempDir, leafname);
309 		err = entry.SetTo(path);
310 	}
311 	if (!err)
312 		err = entry.GetRef(ref);
313 	return err;
314 }
315 
316 //------------------------------------------------------------------------------
317 // GetRecentApps()
318 //------------------------------------------------------------------------------
319 
320 /*
321 	void GetRecentApps(BMessage *refList, int32 maxCount)
322 	@case A1		refList is NULL; maxCount < 0
323 	@results		R5: crashes
324 	                Haiku: should quietly do nothing.
325 */
326 void
327 GetRecentTester::GetRecentAppsTestA1()
328 {
329 #if !TEST_R5
330 	BRoster roster;
331 	roster.GetRecentApps(NULL, -10);
332 #endif
333 }
334 
335 /*
336 	void GetRecentApps(BMessage *refList, int32 maxCount)
337 	@case A1		refList is NULL; maxCount == 0
338 	@results		R5: crashes
339 	                Haiku: should quietly do nothing.
340 */
341 void
342 GetRecentTester::GetRecentAppsTestA2()
343 {
344 #if !TEST_R5
345 	BRoster roster;
346 	roster.GetRecentApps(NULL, 0);
347 #endif
348 }
349 
350 /*
351 	void GetRecentApps(BMessage *refList, int32 maxCount)
352 	@case A1		refList is NULL; maxCount > 0
353 	@results		R5: crashes
354 	                Haiku: should quietly do nothing.
355 */
356 void
357 GetRecentTester::GetRecentAppsTestA3()
358 {
359 #if !TEST_R5
360 	BRoster roster;
361 	roster.GetRecentApps(NULL, 10);
362 #endif
363 }
364 
365 /*
366 	void GetRecentApps(BMessage *refList, int32 maxCount)
367 	@case A1		refList is valid; maxCount < 0
368 	@results		Should return zero recent apps
369 */
370 void
371 GetRecentTester::GetRecentAppsTestB1()
372 {
373 	BRoster roster;
374 	BMessage msg;
375 	CHK(launch_test_app(kControlApp, &kMultipleLaunchFlags) == B_OK);
376 	roster.GetRecentApps(&msg, -1);
377 	CHK(check_ref_count(&msg, 0) == B_OK);
378 }
379 
380 /*
381 	void GetRecentApps(BMessage *refList, int32 maxCount)
382 	@case A1		refList is valid; maxCount == 0
383 	@results		Should return zero recent apps
384 */
385 void
386 GetRecentTester::GetRecentAppsTestB2()
387 {
388 	BRoster roster;
389 	BMessage msg;
390 	CHK(launch_test_app(kControlApp, &kMultipleLaunchFlags) == B_OK);
391 	roster.GetRecentApps(&msg, 0);
392 	CHK(check_ref_count(&msg, 0) == B_OK);
393 }
394 
395 /*
396 	void GetRecentApps(BMessage *refList, int32 maxCount)
397 	@case A1		refList is valid; maxCount > 0
398 	@results		Should return maxCount apps
399 */
400 void
401 GetRecentTester::GetRecentAppsTestB3()
402 {
403 	BRoster roster;
404 	BMessage msg;
405 	CHK(launch_test_app(kControlApp, &kMultipleLaunchFlags) == B_OK);
406 	roster.GetRecentApps(&msg, 1);
407 	CHK(check_ref_count(&msg, 1) == B_OK);
408 }
409 
410 /*
411 	void GetRecentApps(BMessage *refList, int32 maxCount)
412 	@case C1		Our control app is launched, followed by an application
413 	                with no BEOS:APP_FLAGS attribute.
414 	@results		The latter application should *not* appear at the top
415 					of the recent apps list.
416 */
417 void
418 GetRecentTester::GetRecentAppsTestC1()
419 {
420 	BRoster roster;
421 	BMessage msg;
422 	entry_ref ref;
423 	entry_ref appRef1;
424 	entry_ref appRef2;
425 
426 	// Launch an app that *will* show up in the list
427 	NextSubTest();
428 	CHK(launch_test_app(kControlApp, &kMultipleLaunchFlags) == B_OK);
429 	roster.GetRecentApps(&msg, 1);
430 	CHK(msg.FindRef("refs", 0, &ref) == B_OK);
431 	CHK(get_test_app_ref(kControlApp, &appRef1) == B_OK);
432 	CHK(appRef1 == ref);
433 
434 	// Now launch an app with no app flags attribute that
435 	// therefore shouldn't show up in the list
436 	NextSubTest();
437 	CHK(launch_test_app(kEmptyApp, NULL) == B_OK);
438 	msg.MakeEmpty();
439 	roster.GetRecentApps(&msg, 5);
440 	CHK(msg.FindRef("refs", 0, &ref) == B_OK);
441 	CHK(get_test_app_ref(kEmptyApp, &appRef2) == B_OK);
442 	CHK(appRef2 != ref);
443 	CHK(appRef1 == ref);
444 }
445 
446 /*
447 	void GetRecentApps(BMessage *refList, int32 maxCount)
448 	@case C1		Our control app is launched, followed by an application
449 	                with a non-qualifying BEOS:APP_FLAGS attribute.
450 	@results		The latter application should *not* appear at the top
451 					of the recent apps list.
452 */
453 void
454 GetRecentTester::GetRecentAppsTestC2()
455 {
456 	uint count = sizeof(kNonQualifyingFlags) / sizeof(int32);
457 	for (uint i = 0; i < count; i++) {
458 		BRoster roster;
459 		BMessage msg;
460 		entry_ref ref1;
461 		entry_ref ref2;
462 		entry_ref appRef1;
463 		entry_ref appRef2;
464 
465 		// Launch an app that *will* show up in the list
466 		NextSubTest();
467 		CHK(launch_test_app(kControlApp, &kMultipleLaunchFlags) == B_OK);
468 		roster.GetRecentApps(&msg, 1);
469 		CHK(msg.FindRef("refs", 0, &ref1) == B_OK);
470 		CHK(get_test_app_ref(kControlApp, &appRef1) == B_OK);
471 		CHK(appRef1 == ref1);
472 
473 		// Now launch an app with a non-qualifying app flags attribute that
474 		// therefore shouldn't show up in the list
475 		NextSubTest();
476 		CHK(launch_test_app(kNonQualifyingApp, &kNonQualifyingFlags[i]) == B_OK);
477 		msg.MakeEmpty();
478 		roster.GetRecentApps(&msg, 10);	// Ask for 10, as R5 doesn't always return as many as requested
479 		CHK(msg.FindRef("refs", 0, &ref1) == B_OK);
480 		CHK(msg.FindRef("refs", 1, &ref2) == B_OK);
481 		CHK(get_test_app_ref(kNonQualifyingApp, &appRef2) == B_OK);
482 		CHK(appRef2 != ref1);
483 		CHK(appRef2 != ref2);
484 		CHK(appRef1 == ref1);
485 		CHK(appRef1 != ref2);
486 	}
487 }
488 
489 /*
490 	void GetRecentApps(BMessage *refList, int32 maxCount)
491 	@case C3		Application with a non-qualifying BEOS:APP_FLAGS
492 	                attribute is launched.
493 	@results		Said application should *not* appear at the top
494 					of the recent apps list.
495 */
496 void
497 GetRecentTester::GetRecentAppsTestC3()
498 {
499 	uint count = sizeof(kQualifyingFlags) / sizeof(int32);
500 	for (uint i = 0; i < count; i++) {
501 		BRoster roster;
502 		BMessage msg;
503 		entry_ref ref1;
504 		entry_ref ref2;
505 		entry_ref appRef1;
506 		entry_ref appRef2;
507 
508 		// Launch an app that *will* show up in the list
509 		NextSubTest();
510 		CHK(launch_test_app(kControlApp, &kMultipleLaunchFlags) == B_OK);
511 		roster.GetRecentApps(&msg, 1);
512 		CHK(msg.FindRef("refs", 0, &ref1) == B_OK);
513 		CHK(get_test_app_ref(kControlApp, &appRef1) == B_OK);
514 		CHK(appRef1 == ref1);
515 
516 		// Now launch an app with a qualifying app flags attribute that
517 		// therefore *should* show up in the list
518 		NextSubTest();
519 		CHK(launch_test_app(kQualifyingApp, &kQualifyingFlags[i]) == B_OK);
520 		msg.MakeEmpty();
521 		roster.GetRecentApps(&msg, 5);
522 		CHK(msg.FindRef("refs", 0, &ref1) == B_OK);
523 		CHK(msg.FindRef("refs", 1, &ref2) == B_OK);
524 		CHK(get_test_app_ref(kQualifyingApp, &appRef2) == B_OK);
525 		CHK(appRef2 == ref1);
526 		CHK(appRef2 != ref2);
527 		CHK(appRef1 != ref1);
528 		CHK(appRef1 == ref2);
529 	}
530 }
531 
532 //------------------------------------------------------------------------------
533 // GetRecentDocuments()
534 //------------------------------------------------------------------------------
535 
536 /*
537 	void GetRecentDocuments(BMessage *refList, int32 maxCount,
538 	                        const char *fileType, const char *appSig)
539 	@case 1			refList is NULL; all other params are valid
540 	@results		Should quietly do nothing.
541 */
542 void
543 GetRecentTester::GetRecentDocumentsTest1()
544 {
545 // R5 crashes if refList is NULL
546 #if !TEST_R5
547 	BRoster roster;
548 	roster.GetRecentDocuments(NULL, 1);
549 	roster.GetRecentDocuments(NULL, 1, &test_types[0], 1, NULL);
550 #endif
551 }
552 
553 /*
554 	void GetRecentDocuments(BMessage *refList, int32 maxCount,
555 	                        const char *fileType, const char *appSig)
556 	@case 2			refList is non-NULL, maxCount is zero, fileType and
557 	                appSig are NULL.
558 	@results		R5: Returns one recent document.
559 	                Haiku: Returns an empty message
560 */
561 void
562 GetRecentTester::GetRecentDocumentsTest2()
563 {
564 	BRoster roster;
565 	BMessage msg;
566 	roster.GetRecentDocuments(&msg, 0);
567 #if TEST_R5
568 	CHK(check_ref_count(&msg, 1) == B_OK);
569 #else
570 	CHK(check_ref_count(&msg, 0) == B_OK);
571 #endif
572 }
573 
574 /*
575 	void GetRecentDocuments(BMessage *refList, int32 maxCount,
576 	                        const char *fileType, const char *appSig)
577 	@case 3			refList is non-NULL, maxCount is negative, fileType and
578 	                appSig are NULL.
579 	@results		R5: Returns one recent document.
580 	                Haiku: Returns an empty message
581 */
582 void
583 GetRecentTester::GetRecentDocumentsTest3()
584 {
585 	BRoster roster;
586 	BMessage msg;
587 	roster.GetRecentDocuments(&msg, -1);
588 #if TEST_R5
589 	CHK(check_ref_count(&msg, 1) == B_OK);
590 #else
591 	CHK(check_ref_count(&msg, 0) == B_OK);
592 #endif
593 }
594 
595 /*
596 	void GetRecentDocuments(BMessage *refList, int32 maxCount,
597 	                        const char *fileType, const char *appSig)
598 	@case 4			Four recent docs are added, with each pair having matching
599 	                app sigs and each pair of docs with-non matching app sigs
600 	                having matching file types. Get it?
601 	@results		When no app sig and a count of 4 is specified, the four folders
602 					in reverse order are returned.
603 					When the first app sig and a count of 4 is specified, the two
604 					folders that match that sig are returned.
605 					When the second app sig and a count of 4 is specified, the two
606 					folders that match that sig are returned.
607 */
608 void
609 GetRecentTester::GetRecentDocumentsTest4()
610 {
611 	entry_ref doc1;	// type1, sig1
612 	entry_ref doc2;	// type1, sig2
613 	entry_ref doc3;	// type2, sig1
614 	entry_ref doc4;	// type2, sig2
615 	entry_ref doc5;	// untyped, sig3
616 	entry_ref recent1;
617 	entry_ref recent2;
618 	entry_ref recent3;
619 	entry_ref recent4;
620 	entry_ref recent5;
621 	BRoster roster;
622 	BMessage msg;
623 
624 //	ExecCommand("ls -l ", kTempDir);
625 
626 	// Add four entries with two different app sigs (note that
627 	// docs 0 & 1 and 2 & 3 have matching file types). Then
628 	// add an untyped entry with a totally different app sig.
629 	CHK(get_test_ref(test_docs[0].name, &doc1) == B_OK);
630 	CHK(get_test_ref(test_docs[1].name, &doc2) == B_OK);
631 	CHK(get_test_ref(test_docs[2].name, &doc3) == B_OK);
632 	CHK(get_test_ref(test_docs[3].name, &doc4) == B_OK);
633 	CHK(get_test_ref(test_docs[4].name, &doc5) == B_OK);
634 	roster.AddToRecentDocuments(&doc1, test_sigs[0]);
635 	roster.AddToRecentDocuments(&doc2, test_sigs[1]);
636 	roster.AddToRecentDocuments(&doc3, test_sigs[0]);
637 	roster.AddToRecentDocuments(&doc4, test_sigs[1]);
638 	roster.AddToRecentDocuments(&doc5, test_sigs[2]);
639 
640 	// NULL type, NULL sig
641 	NextSubTest();
642 	roster.GetRecentDocuments(&msg, 5);
643 //	msg.PrintToStream();
644 	CHK(check_ref_count(&msg, 5) == B_OK);
645 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
646 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
647 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
648 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
649 	CHK(msg.FindRef("refs", 4, &recent5) == B_OK);
650 	CHK(recent1 == doc5);
651 	CHK(recent2 == doc4);
652 	CHK(recent3 == doc3);
653 	CHK(recent4 == doc2);
654 	CHK(recent5 == doc1);
655 
656 	// type1, NULL sig
657 	NextSubTest();
658 	roster.GetRecentDocuments(&msg, 5, test_types[0]);
659 //	msg.PrintToStream();
660 	CHK(check_ref_count(&msg, 2) == B_OK);
661 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
662 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
663 	CHK(recent1 == doc2);
664 	CHK(recent2 == doc1);
665 
666 	// type2, NULL sig
667 	NextSubTest();
668 	roster.GetRecentDocuments(&msg, 5, test_types[1]);
669 //	msg.PrintToStream();
670 	CHK(check_ref_count(&msg, 2) == B_OK);
671 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
672 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
673 	CHK(recent1 == doc4);
674 	CHK(recent2 == doc3);
675 
676 	// [type1], NULL sig
677 	NextSubTest();
678 	roster.GetRecentDocuments(&msg, 5, &test_types[0], 1, NULL);
679 //	msg.PrintToStream();
680 	CHK(check_ref_count(&msg, 2) == B_OK);
681 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
682 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
683 	CHK(recent1 == doc2);
684 	CHK(recent2 == doc1);
685 
686 	// [type2], NULL sig
687 	NextSubTest();
688 	roster.GetRecentDocuments(&msg, 5, &test_types[1], 1, NULL);
689 //	msg.PrintToStream();
690 	CHK(check_ref_count(&msg, 2) == B_OK);
691 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
692 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
693 	CHK(recent1 == doc4);
694 	CHK(recent2 == doc3);
695 
696 	// [type1, type2], NULL sig
697 	NextSubTest();
698 	roster.GetRecentDocuments(&msg, 5, test_types, 2, NULL);
699 //	msg.PrintToStream();
700 	CHK(check_ref_count(&msg, 4) == B_OK);
701 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
702 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
703 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
704 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
705 	CHK(recent1 == doc4);
706 	CHK(recent2 == doc3);
707 	CHK(recent3 == doc2);
708 	CHK(recent4 == doc1);
709 
710 //----------------------------------------------------------
711 
712 	// NULL type, sig1
713 	NextSubTest();
714 	roster.GetRecentDocuments(&msg, 5, NULL, test_sigs[0]);
715 //	msg.PrintToStream();
716 	CHK(check_ref_count(&msg, 2) == B_OK);
717 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
718 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
719 	CHK(recent1 == doc3);
720 	CHK(recent2 == doc1);
721 
722 	// NULL type, sig2
723 	NextSubTest();
724 	roster.GetRecentDocuments(&msg, 5, NULL, test_sigs[1]);
725 //	msg.PrintToStream();
726 	CHK(check_ref_count(&msg, 2) == B_OK);
727 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
728 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
729 	CHK(recent1 == doc4);
730 	CHK(recent2 == doc2);
731 
732 	// NULL type, sig3
733 	NextSubTest();
734 	roster.GetRecentDocuments(&msg, 5, NULL, test_sigs[2]);
735 //	msg.PrintToStream();
736 	CHK(check_ref_count(&msg, 1) == B_OK);
737 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
738 	CHK(recent1 == doc5);
739 
740 	// type1, sig1
741 	NextSubTest();
742 	roster.GetRecentDocuments(&msg, 5, test_types[0], test_sigs[0]);
743 //	msg.PrintToStream();
744 	CHK(check_ref_count(&msg, 3) == B_OK);
745 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
746 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
747 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
748 	CHK(recent1 == doc3);
749 	CHK(recent2 == doc2);
750 	CHK(recent3 == doc1);
751 
752 	// type1, sig2
753 	NextSubTest();
754 	roster.GetRecentDocuments(&msg, 5, test_types[0], test_sigs[1]);
755 //	msg.PrintToStream();
756 	CHK(check_ref_count(&msg, 3) == B_OK);
757 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
758 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
759 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
760 	CHK(recent1 == doc4);
761 	CHK(recent2 == doc2);
762 	CHK(recent3 == doc1);
763 
764 	// type1, sig3
765 	NextSubTest();
766 	roster.GetRecentDocuments(&msg, 5, test_types[0], test_sigs[2]);
767 //	msg.PrintToStream();
768 	CHK(check_ref_count(&msg, 3) == B_OK);
769 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
770 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
771 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
772 	CHK(recent1 == doc5);
773 	CHK(recent2 == doc2);
774 	CHK(recent3 == doc1);
775 
776 	// type2, sig1
777 	NextSubTest();
778 	roster.GetRecentDocuments(&msg, 5, test_types[1], test_sigs[0]);
779 //	msg.PrintToStream();
780 	CHK(check_ref_count(&msg, 3) == B_OK);
781 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
782 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
783 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
784 	CHK(recent1 == doc4);
785 	CHK(recent2 == doc3);
786 	CHK(recent3 == doc1);
787 
788 	// type2, sig2
789 	NextSubTest();
790 	roster.GetRecentDocuments(&msg, 5, test_types[1], test_sigs[1]);
791 //	msg.PrintToStream();
792 	CHK(check_ref_count(&msg, 3) == B_OK);
793 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
794 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
795 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
796 	CHK(recent1 == doc4);
797 	CHK(recent2 == doc3);
798 	CHK(recent3 == doc2);
799 
800 	// type2, sig3
801 	NextSubTest();
802 	roster.GetRecentDocuments(&msg, 5, test_types[1], test_sigs[2]);
803 //	msg.PrintToStream();
804 	CHK(check_ref_count(&msg, 3) == B_OK);
805 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
806 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
807 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
808 	CHK(recent1 == doc5);
809 	CHK(recent2 == doc4);
810 	CHK(recent3 == doc3);
811 
812 
813 //---------
814 
815 	// [type1], sig1
816 	NextSubTest();
817 	roster.GetRecentDocuments(&msg, 5, &test_types[0], 1, test_sigs[0]);
818 //	msg.PrintToStream();
819 	CHK(check_ref_count(&msg, 3) == B_OK);
820 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
821 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
822 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
823 	CHK(recent1 == doc3);
824 	CHK(recent2 == doc2);
825 	CHK(recent3 == doc1);
826 
827 	// [type1], sig2
828 	NextSubTest();
829 	roster.GetRecentDocuments(&msg, 5, &test_types[0], 1, test_sigs[1]);
830 //	msg.PrintToStream();
831 	CHK(check_ref_count(&msg, 3) == B_OK);
832 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
833 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
834 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
835 	CHK(recent1 == doc4);
836 	CHK(recent2 == doc2);
837 	CHK(recent3 == doc1);
838 
839 	// [type1], sig3
840 	NextSubTest();
841 	roster.GetRecentDocuments(&msg, 5, &test_types[0], 1, test_sigs[2]);
842 //	msg.PrintToStream();
843 	CHK(check_ref_count(&msg, 3) == B_OK);
844 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
845 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
846 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
847 	CHK(recent1 == doc5);
848 	CHK(recent2 == doc2);
849 	CHK(recent3 == doc1);
850 
851 	// [type2], sig1
852 	NextSubTest();
853 	roster.GetRecentDocuments(&msg, 5, &test_types[1], 1, test_sigs[0]);
854 //	msg.PrintToStream();
855 	CHK(check_ref_count(&msg, 3) == B_OK);
856 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
857 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
858 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
859 	CHK(recent1 == doc4);
860 	CHK(recent2 == doc3);
861 	CHK(recent3 == doc1);
862 
863 	// [type2], sig2
864 	NextSubTest();
865 	roster.GetRecentDocuments(&msg, 5, &test_types[1], 1, test_sigs[1]);
866 //	msg.PrintToStream();
867 	CHK(check_ref_count(&msg, 3) == B_OK);
868 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
869 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
870 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
871 	CHK(recent1 == doc4);
872 	CHK(recent2 == doc3);
873 	CHK(recent3 == doc2);
874 
875 	// [type2], sig3
876 	NextSubTest();
877 	roster.GetRecentDocuments(&msg, 5, &test_types[1], 1, test_sigs[2]);
878 //	msg.PrintToStream();
879 	CHK(check_ref_count(&msg, 3) == B_OK);
880 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
881 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
882 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
883 	CHK(recent1 == doc5);
884 	CHK(recent2 == doc4);
885 	CHK(recent3 == doc3);
886 
887 	// [type1, type2], sig1
888 	NextSubTest();
889 	roster.GetRecentDocuments(&msg, 5, test_types, 2, test_sigs[0]);
890 //	msg.PrintToStream();
891 	CHK(check_ref_count(&msg, 4) == B_OK);
892 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
893 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
894 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
895 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
896 	CHK(recent1 == doc4);
897 	CHK(recent2 == doc3);
898 	CHK(recent3 == doc2);
899 	CHK(recent4 == doc1);
900 
901 	// [type1, type2], sig2
902 	NextSubTest();
903 	roster.GetRecentDocuments(&msg, 5, test_types, 2, test_sigs[1]);
904 //	msg.PrintToStream();
905 	CHK(check_ref_count(&msg, 4) == B_OK);
906 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
907 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
908 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
909 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
910 	CHK(recent1 == doc4);
911 	CHK(recent2 == doc3);
912 	CHK(recent3 == doc2);
913 	CHK(recent4 == doc1);
914 
915 	// [type1, type2], sig3
916 	NextSubTest();
917 	roster.GetRecentDocuments(&msg, 5, test_types, 2, test_sigs[2]);
918 //	msg.PrintToStream();
919 	CHK(check_ref_count(&msg, 5) == B_OK);
920 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
921 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
922 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
923 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
924 	CHK(msg.FindRef("refs", 4, &recent5) == B_OK);
925 	CHK(recent1 == doc5);
926 	CHK(recent2 == doc4);
927 	CHK(recent3 == doc3);
928 	CHK(recent4 == doc2);
929 	CHK(recent5 == doc1);
930 }
931 
932 /*
933 	void GetRecentDocuments(BMessage *refList, int32 maxCount,
934 	                        const char *fileType, const char *appSig)
935 	@case 5			Six recent folders are added, two of which are duplicates
936 	                under different app sigs.
937 	@results		A request for the four duplicates should return the
938 	                four non-duplicates.
939 */
940 void
941 GetRecentTester::GetRecentDocumentsTest5()
942 {
943 	entry_ref doc1;
944 	entry_ref doc2;
945 	entry_ref doc3;
946 	entry_ref doc4;
947 	entry_ref recent1;
948 	entry_ref recent2;
949 	entry_ref recent3;
950 	entry_ref recent4;
951 	BRoster roster;
952 	BMessage msg;
953 
954 	// Add two entries twice with different app sigs
955 	CHK(get_test_ref(test_docs[0].name, &doc1) == B_OK);
956 	CHK(get_test_ref(test_docs[1].name, &doc2) == B_OK);
957 	CHK(get_test_ref(test_docs[2].name, &doc3) == B_OK);
958 	CHK(get_test_ref(test_docs[3].name, &doc4) == B_OK);
959 	roster.AddToRecentDocuments(&doc1, test_sigs[4]);
960 	roster.AddToRecentDocuments(&doc2, test_sigs[5]);
961 	roster.AddToRecentDocuments(&doc3, test_sigs[4]);
962 	roster.AddToRecentDocuments(&doc4, test_sigs[5]);
963 	roster.AddToRecentDocuments(&doc3, test_sigs[6]);
964 	roster.AddToRecentDocuments(&doc4, test_sigs[7]);
965 
966 	// Verify our duplicates exist
967 	NextSubTest();
968 	roster.GetRecentDocuments(&msg, 1, NULL, test_sigs[7]);
969 //	msg.PrintToStream();
970 	CHK(check_ref_count(&msg, 1) == B_OK);
971 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
972 	CHK(recent1 == doc4);
973 
974 	NextSubTest();
975 	roster.GetRecentDocuments(&msg, 1, NULL, test_sigs[6]);
976 //	msg.PrintToStream();
977 	CHK(check_ref_count(&msg, 1) == B_OK);
978 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
979 	CHK(recent1 == doc3);
980 
981 	NextSubTest();
982 	roster.GetRecentDocuments(&msg, 1, NULL, test_sigs[5]);
983 //	msg.PrintToStream();
984 	CHK(check_ref_count(&msg, 1) == B_OK);
985 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
986 	CHK(recent1 == doc4);
987 
988 	NextSubTest();
989 	roster.GetRecentDocuments(&msg, 1, NULL, test_sigs[4]);
990 //	msg.PrintToStream();
991 	CHK(check_ref_count(&msg, 1) == B_OK);
992 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
993 	CHK(recent1 == doc3);
994 
995 	// Verify that duplicates are not returned
996 	NextSubTest();
997 	roster.GetRecentDocuments(&msg, 4);
998 //	msg.PrintToStream();
999 	CHK(check_ref_count(&msg, 4) == B_OK);
1000 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1001 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1002 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
1003 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
1004 	CHK(recent1 == doc4);
1005 	CHK(recent2 == doc3);
1006 	CHK(recent3 == doc2);
1007 	CHK(recent4 == doc1);
1008 }
1009 
1010 //------------------------------------------------------------------------------
1011 // GetRecentFolders()
1012 //------------------------------------------------------------------------------
1013 
1014 /*
1015 	void GetRecentFolders(BMessage *refList, int32 maxCount, const char *appSig)
1016 	@case 1			refList is NULL; maxCount is valid, appSig is NULL.
1017 	@results		Should quietly do nothing.
1018 */
1019 void
1020 GetRecentTester::GetRecentFoldersTest1()
1021 {
1022 // R5 crashes if refList is NULL
1023 #if !TEST_R5
1024 	BRoster roster;
1025 	roster.GetRecentFolders(NULL, 1);
1026 #endif
1027 }
1028 
1029 /*
1030 	void GetRecentFolders(BMessage *refList, int32 maxCount, const char *appSig)
1031 	@case 2		refList is valid, maxCount is negative, appSig is NULL.
1032 	@results		R5: Returns one recent document.
1033 	                Haiku: Returns an empty message
1034 */
1035 void
1036 GetRecentTester::GetRecentFoldersTest2()
1037 {
1038 	entry_ref folder1;
1039 	entry_ref folder2;
1040 	entry_ref recent1;
1041 	entry_ref recent2;
1042 	BRoster roster;
1043 	BMessage msg;
1044 
1045 	CHK(get_test_ref(test_folders[0], &folder1) == B_OK);
1046 	CHK(get_test_ref(test_folders[1], &folder2) == B_OK);
1047 	roster.AddToRecentFolders(&folder1, NULL);
1048 	roster.GetRecentFolders(&msg, -1);
1049 //	msg.PrintToStream();
1050 #ifdef TEST_R5
1051 	CHK(check_ref_count(&msg, 1) == B_OK);
1052 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1053 	CHK(recent1 == folder1);
1054 #else
1055 	CHK(check_ref_count(&msg, 0) == B_OK);
1056 #endif
1057 }
1058 
1059 /*
1060 	void GetRecentFolders(BMessage *refList, int32 maxCount, const char *appSig)
1061 	@case 3			refList is valid, maxCount is zero, appSig is NULL.
1062 	@results		R5: Returns one recent document.
1063 	                Haiku: Returns an empty message
1064 */
1065 void
1066 GetRecentTester::GetRecentFoldersTest3()
1067 {
1068 	entry_ref folder1;
1069 	entry_ref folder2;
1070 	entry_ref recent1;
1071 	entry_ref recent2;
1072 	BRoster roster;
1073 	BMessage msg;
1074 
1075 	CHK(get_test_ref(test_folders[0], &folder1) == B_OK);
1076 	CHK(get_test_ref(test_folders[1], &folder2) == B_OK);
1077 	roster.AddToRecentFolders(&folder1, NULL);
1078 	roster.GetRecentFolders(&msg, 0);
1079 //	msg.PrintToStream();
1080 #ifdef TEST_R5
1081 	CHK(check_ref_count(&msg, 1) == B_OK);
1082 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1083 	CHK(recent1 == folder1);
1084 #else
1085 	CHK(check_ref_count(&msg, 0) == B_OK);
1086 #endif
1087 }
1088 
1089 /*
1090 	void GetRecentFolders(BMessage *refList, int32 maxCount, const char *appSig)
1091 	@case 4			Four recent folders are added, with each pair having matching
1092 	                app sigs.
1093 	@results		When no app sig and a count of 4 is specified, the four folders
1094 					in reverse order are returned.
1095 					When the first app sig and a count of 4 is specified, the two
1096 					folders that match that sig are returned.
1097 					When the second app sig and a count of 4 is specified, the two
1098 					folders that match that sig are returned.
1099 */
1100 void
1101 GetRecentTester::GetRecentFoldersTest4()
1102 {
1103 	entry_ref folder1;
1104 	entry_ref folder2;
1105 	entry_ref folder3;
1106 	entry_ref folder4;
1107 	entry_ref recent1;
1108 	entry_ref recent2;
1109 	entry_ref recent3;
1110 	entry_ref recent4;
1111 	BRoster roster;
1112 	BMessage msg;
1113 
1114 //	ExecCommand("ls -l ", kTempDir);
1115 
1116 	// Add four entries with two different app sigs
1117 	CHK(get_test_ref(test_folders[0], &folder1) == B_OK);
1118 	CHK(get_test_ref(test_folders[1], &folder2) == B_OK);
1119 	CHK(get_test_ref(test_folders[2], &folder3) == B_OK);
1120 	CHK(get_test_ref(test_folders[3], &folder4) == B_OK);
1121 	roster.AddToRecentFolders(&folder1, test_sigs[0]);
1122 	roster.AddToRecentFolders(&folder2, test_sigs[1]);
1123 	roster.AddToRecentFolders(&folder3, test_sigs[0]);
1124 	roster.AddToRecentFolders(&folder4, test_sigs[1]);
1125 
1126 	NextSubTest();
1127 	roster.GetRecentFolders(&msg, 4, NULL);
1128 //	msg.PrintToStream();
1129 	CHK(check_ref_count(&msg, 4) == B_OK);
1130 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1131 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1132 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
1133 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
1134 	CHK(recent1 == folder4);
1135 	CHK(recent2 == folder3);
1136 	CHK(recent3 == folder2);
1137 	CHK(recent4 == folder1);
1138 
1139 	NextSubTest();
1140 	roster.GetRecentFolders(&msg, 4, test_sigs[0]);
1141 //	msg.PrintToStream();
1142 	CHK(check_ref_count(&msg, 2) == B_OK);
1143 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1144 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1145 	CHK(recent1 == folder3);
1146 	CHK(recent2 == folder1);
1147 
1148 	NextSubTest();
1149 	msg.MakeEmpty();
1150 	roster.GetRecentFolders(&msg, 4, test_sigs[1]);
1151 //	msg.PrintToStream();
1152 	CHK(check_ref_count(&msg, 2) == B_OK);
1153 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1154 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1155 	CHK(recent1 == folder4);
1156 	CHK(recent2 == folder2);
1157 }
1158 
1159 /*
1160 	void GetRecentFolders(BMessage *refList, int32 maxCount, const char *appSig)
1161 	@case 5			Six recent folders are added, two of which are duplicates
1162 	                under different app sigs.
1163 	@results		A request for the four duplicates should return the
1164 	                four non-duplicates.
1165 */
1166 void
1167 GetRecentTester::GetRecentFoldersTest5()
1168 {
1169 	entry_ref folder1;
1170 	entry_ref folder2;
1171 	entry_ref folder3;
1172 	entry_ref folder4;
1173 	entry_ref recent1;
1174 	entry_ref recent2;
1175 	entry_ref recent3;
1176 	entry_ref recent4;
1177 	BRoster roster;
1178 	BMessage msg;
1179 
1180 	// Add two entries twice with different app sigs
1181 	CHK(get_test_ref(test_folders[0], &folder1) == B_OK);
1182 	CHK(get_test_ref(test_folders[1], &folder2) == B_OK);
1183 	CHK(get_test_ref(test_folders[2], &folder3) == B_OK);
1184 	CHK(get_test_ref(test_folders[3], &folder4) == B_OK);
1185 	roster.AddToRecentFolders(&folder1, test_sigs[4]);
1186 	roster.AddToRecentFolders(&folder2, test_sigs[5]);
1187 	roster.AddToRecentFolders(&folder3, test_sigs[4]);
1188 	roster.AddToRecentFolders(&folder4, test_sigs[5]);
1189 	roster.AddToRecentFolders(&folder3, test_sigs[6]);
1190 	roster.AddToRecentFolders(&folder4, test_sigs[7]);
1191 
1192 	// Verify our duplicates exist
1193 	NextSubTest();
1194 	roster.GetRecentFolders(&msg, 1, test_sigs[7]);
1195 //	msg.PrintToStream();
1196 	CHK(check_ref_count(&msg, 1) == B_OK);
1197 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1198 	CHK(recent1 == folder4);
1199 
1200 	NextSubTest();
1201 	roster.GetRecentFolders(&msg, 1, test_sigs[6]);
1202 //	msg.PrintToStream();
1203 	CHK(check_ref_count(&msg, 1) == B_OK);
1204 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1205 	CHK(recent1 == folder3);
1206 
1207 	NextSubTest();
1208 	roster.GetRecentFolders(&msg, 1, test_sigs[5]);
1209 //	msg.PrintToStream();
1210 	CHK(check_ref_count(&msg, 1) == B_OK);
1211 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1212 	CHK(recent1 == folder4);
1213 
1214 	NextSubTest();
1215 	roster.GetRecentFolders(&msg, 1, test_sigs[4]);
1216 //	msg.PrintToStream();
1217 	CHK(check_ref_count(&msg, 1) == B_OK);
1218 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1219 	CHK(recent1 == folder3);
1220 
1221 	// Verify that duplicates are not returned
1222 	NextSubTest();
1223 	roster.GetRecentFolders(&msg, 4, NULL);
1224 //	msg.PrintToStream();
1225 	CHK(check_ref_count(&msg, 4) == B_OK);
1226 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1227 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1228 	CHK(msg.FindRef("refs", 2, &recent3) == B_OK);
1229 	CHK(msg.FindRef("refs", 3, &recent4) == B_OK);
1230 	CHK(recent1 == folder4);
1231 	CHK(recent2 == folder3);
1232 	CHK(recent3 == folder2);
1233 	CHK(recent4 == folder1);
1234 }
1235 
1236 void
1237 GetRecentTester::RecentListsLoadSaveClearTest()
1238 {
1239 #ifdef TEST_R5
1240 	Outputf("(no tests actually performed for R5 version)\n");
1241 #else
1242 	entry_ref doc1;
1243 	entry_ref doc2;
1244 	entry_ref folder1;
1245 	entry_ref folder2;
1246 	entry_ref app1;
1247 	entry_ref app2;
1248 	const char *appSig1 = kRecentAppsTestAppSigs[kQualifyingApp];
1249 	const char *appSig2 = kRecentAppsTestAppSigs[kControlApp];
1250 	entry_ref recent1;
1251 	entry_ref recent2;
1252 	BRoster roster;
1253 	BMessage msg;
1254 
1255 	//--------------------------------------------------------------------
1256 	// Add a few docs, folders, and apps. Check that they're there.
1257 	// Save the to disk. Clear. Check that the lists are empty.
1258 	// Load from disk. Check that things look like they used
1259 	// to.
1260 	//--------------------------------------------------------------------
1261 
1262 	// Add
1263 	CHK(get_test_ref(test_docs[0].name, &doc1) == B_OK);
1264 	CHK(get_test_ref(test_docs[1].name, &doc2) == B_OK);
1265 	CHK(get_test_ref(test_folders[0], &folder1) == B_OK);
1266 	CHK(get_test_ref(test_folders[1], &folder2) == B_OK);
1267 	CHK(get_test_app_ref(kQualifyingApp, &app1) == B_OK);
1268 	CHK(get_test_app_ref(kControlApp, &app2) == B_OK);
1269 	CHK(set_test_app_attributes(&app1, kRecentAppsTestAppSigs[kQualifyingApp],
1270 	    &kMultipleLaunchFlags) == B_OK);
1271 	CHK(set_test_app_attributes(&app2, kRecentAppsTestAppSigs[kControlApp],
1272 	    &kMultipleLaunchFlags) == B_OK);
1273 	roster.AddToRecentDocuments(&doc1, test_sigs[0]);
1274 	roster.AddToRecentDocuments(&doc2, test_sigs[1]);
1275 	roster.AddToRecentFolders(&folder1, test_sigs[0]);
1276 	roster.AddToRecentFolders(&folder2, test_sigs[1]);
1277 	BRoster::Private(roster).AddToRecentApps(appSig1);
1278 	BRoster::Private(roster).AddToRecentApps(appSig2);
1279 
1280 	// Check #1
1281 	NextSubTest();
1282 	msg.MakeEmpty();
1283 	roster.GetRecentDocuments(&msg, 2);
1284 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1285 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1286 	CHK(recent1 == doc2);
1287 	CHK(recent2 == doc1);
1288 
1289 	NextSubTest();
1290 	msg.MakeEmpty();
1291 	roster.GetRecentFolders(&msg, 2);
1292 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1293 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1294 	CHK(recent1 == folder2);
1295 	CHK(recent2 == folder1);
1296 
1297 	NextSubTest();
1298 	msg.MakeEmpty();
1299 	roster.GetRecentApps(&msg, 2);
1300 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1301 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1302 	CHK(recent1 == app2);
1303 	CHK(recent2 == app1);
1304 
1305 	// Save to disk and clear
1306 	NextSubTest();
1307 	BRoster::Private(roster).SaveRecentLists(kTempSaveFile);
1308 	BRoster::Private(roster).ClearRecentDocuments();
1309 	BRoster::Private(roster).ClearRecentFolders();
1310 	BRoster::Private(roster).ClearRecentApps();
1311 
1312 	// Check #2
1313 	NextSubTest();
1314 	msg.MakeEmpty();
1315 	roster.GetRecentDocuments(&msg, 2);
1316 	CHK(check_ref_count(&msg, 0) == B_OK);
1317 
1318 	NextSubTest();
1319 	msg.MakeEmpty();
1320 	roster.GetRecentFolders(&msg, 2);
1321 	CHK(check_ref_count(&msg, 0) == B_OK);
1322 
1323 	NextSubTest();
1324 	msg.MakeEmpty();
1325 	roster.GetRecentApps(&msg, 2);
1326 	CHK(check_ref_count(&msg, 0) == B_OK);
1327 
1328 	// Load back from disk
1329 	NextSubTest();
1330 	BRoster::Private(roster).LoadRecentLists(kTempSaveFile);
1331 
1332 	// Check #3
1333 	NextSubTest();
1334 	msg.MakeEmpty();
1335 	roster.GetRecentDocuments(&msg, 2);
1336 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1337 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1338 	CHK(recent1 == doc2);
1339 	CHK(recent2 == doc1);
1340 
1341 	NextSubTest();
1342 	msg.MakeEmpty();
1343 	roster.GetRecentFolders(&msg, 2);
1344 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1345 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1346 	CHK(recent1 == folder2);
1347 	CHK(recent2 == folder1);
1348 
1349 	NextSubTest();
1350 	msg.MakeEmpty();
1351 	roster.GetRecentApps(&msg, 2);
1352 	CHK(msg.FindRef("refs", 0, &recent1) == B_OK);
1353 	CHK(msg.FindRef("refs", 1, &recent2) == B_OK);
1354 	CHK(recent1 == app2);
1355 	CHK(recent2 == app1);
1356 #endif	// ifdef TEST_R5 else
1357 }
1358 
1359 
1360 void
1361 GetRecentTester::setUp()
1362 {
1363 	status_t err = B_OK;
1364 	BDirectory tempDir;
1365 
1366 	// Create our base folder for test entries
1367 	if (!BEntry(kTempDir).Exists()) {
1368 		BDirectory rootDir;
1369 		err = rootDir.SetTo(kTempDirRoot);
1370 		if (!err)
1371 			err = rootDir.CreateDirectory(kTempDir, &tempDir);
1372 		if (!err)
1373 			err = tempDir.InitCheck();
1374 		if (err) {
1375 			printf("WARNING: Unable to create temp directory for BRoster::GetRecent*() tests, error "
1376 			       "== 0x%lx. It's entirely possible that most of these tests will fail because "
1377 			       "of this\n", err);
1378 			return;
1379 		}
1380 	}
1381 
1382 	// Create our test documents
1383 	if (!err) {
1384 		int count = sizeof(test_docs) / sizeof(test_doc);
1385 		for (int i = 0; !err && i < count; i++) {
1386 			BFile file;
1387 
1388 			char filename[B_PATH_NAME_LENGTH];
1389 			sprintf(filename, "%s/%s", kTempDir, test_docs[i].name);
1390 			ExecCommand("touch ", filename);
1391 			err = file.SetTo(filename, B_READ_WRITE);
1392 
1393 // For some reason, only the first CreateFile() call works with R5. None
1394 // work with Haiku...
1395 /*
1396 			err = tempDir.CreateFile(test_docs[i].name, &file);
1397 			if (!err)
1398 				err = file.InitCheck();
1399 */
1400 
1401 			// Write its type (if necessary)
1402 			if (!err && test_docs[i].type) {
1403 				int len = strlen(test_docs[i].type)+1;
1404 				ssize_t bytes = file.WriteAttr(kTypeAttr, B_MIME_STRING_TYPE, 0,
1405 					test_docs[i].type, len);
1406 				if (bytes >= 0)
1407 					err = bytes == len ? B_OK : B_FILE_ERROR;
1408 				else
1409 					err = bytes;
1410 			}
1411 		}
1412 	}
1413 
1414 	// Create our test folders
1415 	if (!err) {
1416 		int count = sizeof(test_folders) / sizeof(char*);
1417 		for (int i = 0; !err && i < count; i++) {
1418 
1419 			// For some reason, only the first CreateFile() call works with R5
1420 			char dirname[B_PATH_NAME_LENGTH];
1421 			sprintf(dirname, "%s/%s", kTempDir, test_folders[i]);
1422 			if (!BEntry(dirname).Exists())
1423 				ExecCommand("mkdir ", dirname);
1424 /*
1425 			err = tempDir.CreateDirectory(test_folders[i], NULL);
1426 			if (err == B_FILE_EXISTS)
1427 				err = B_OK;
1428 */
1429 		}
1430 	}
1431 
1432 	// Let the user know if we hit an error
1433 	if (err) {
1434 		printf("WARNING: Error encountered while creating test files and/or folders, error "
1435 		       "code == 0x%lx. It's entirely possible that most or all of these tests will "
1436 		       "fail now because of this\n", err);
1437 	}
1438 }
1439 
1440 void
1441 GetRecentTester::tearDown()
1442 {
1443 	// Remove the folder containing all of our test files
1444 	if (BEntry(kTempDir).Exists())
1445 		ExecCommand("rm -rf ", kTempDir);
1446 }
1447 
1448 Test* GetRecentTester::Suite()
1449 {
1450 	TestSuite* SuiteOfTests = new TestSuite;
1451 
1452 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestA1);
1453 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestA2);
1454 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestA3);
1455 
1456 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestB1);
1457 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestB2);
1458 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestB3);
1459 
1460 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestC1);
1461 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestC2);
1462 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentAppsTestC3);
1463 
1464 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentDocumentsTest1);
1465 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentDocumentsTest2);
1466 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentDocumentsTest3);
1467 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentDocumentsTest4);
1468 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentDocumentsTest5);
1469 
1470 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentFoldersTest1);
1471 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentFoldersTest2);
1472 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentFoldersTest3);
1473 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentFoldersTest4);
1474 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, GetRecentFoldersTest5);
1475 
1476 	ADD_TEST4(BRoster, SuiteOfTests, GetRecentTester, RecentListsLoadSaveClearTest);
1477 
1478 	return SuiteOfTests;
1479 }
1480 
1481