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
37const int32 kFlagsType = 'APPF';
38
39const char *kTypeAttr = "BEOS:TYPE";
40const char *kSigAttr = "BEOS:APP_SIG";
41const 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
51const int32 kSingleLaunchFlags = B_SINGLE_LAUNCH;
52const int32 kMultipleLaunchFlags = B_MULTIPLE_LAUNCH;
53const int32 kExclusiveLaunchFlags = B_EXCLUSIVE_LAUNCH;
54
55const int32 kSingleLaunchArgvOnlyFlags = B_SINGLE_LAUNCH | B_ARGV_ONLY;
56const int32 kMultipleLaunchArgvOnlyFlags = B_MULTIPLE_LAUNCH | B_ARGV_ONLY;
57const int32 kExclusiveLaunchArgvOnlyFlags = B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY;
58
59const int32 kSingleLaunchBackgroundFlags = B_SINGLE_LAUNCH | B_BACKGROUND_APP;
60const int32 kMultipleLaunchBackgroundFlags = B_MULTIPLE_LAUNCH | B_BACKGROUND_APP;
61const int32 kExclusiveLaunchBackgroundFlags = B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP;
62
63const int32 kSingleLaunchArgvOnlyBackgroundFlags = B_SINGLE_LAUNCH | B_ARGV_ONLY | B_BACKGROUND_APP;
64const int32 kMultipleLaunchArgvOnlyBackgroundFlags = B_MULTIPLE_LAUNCH | B_ARGV_ONLY | B_BACKGROUND_APP;
65const int32 kExclusiveLaunchArgvOnlyBackgroundFlags = B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY | B_BACKGROUND_APP;
66
67const int32 kQualifyingFlags[] = {
68	kSingleLaunchFlags,
69	kMultipleLaunchFlags,
70	kExclusiveLaunchFlags,
71};
72
73const 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//------------------------------------------------------------------------------
88const char *kTempDirRoot = "/tmp";
89const char *kTempDir = "/tmp/obos-recent-tests";
90const char *kTempSaveFile = "/tmp/obos-recent-tests/RosterSettingsTest";
91
92const char *kTestType1 = "text/x-vnd.obos-recent-docs-test-type-1";
93const char *kTestType2 = "text/x-vnd.obos-recent-docs-test-type-2";
94
95const char *test_types[] = {
96	kTestType1,
97	kTestType2,
98};
99
100struct 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
111enum test_doc_index {
112	kTestDocUntyped,
113	kTestDoc1Type1,
114	kTestDoc2Type1,
115	kTestDoc1Type2,
116	kTestDoc2Type2,
117};
118
119const char *test_folders[] = {
120	"test-folder-1",
121	"test-folder-2",
122	"test-folder-3",
123	"test-folder-4",
124};
125
126const 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
141status_t check_ref_count(BMessage *refMsg, int32 count);
142status_t set_test_app_attributes(const entry_ref *app, const char *sig, const int32 *flags);
143status_t launch_test_app(RecentAppsTestAppId id, const int32 *flags);
144status_t get_test_app_ref(RecentAppsTestAppId id, entry_ref *ref);
145status_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*/
160status_t
161check_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*/
191status_t
192set_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*/
239status_t
240launch_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*/
267status_t
268get_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/../kits/app/%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*/
301status_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	                OBOS: should quietly do nothing.
325*/
326void
327GetRecentTester::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	                OBOS: should quietly do nothing.
340*/
341void
342GetRecentTester::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	                OBOS: should quietly do nothing.
355*/
356void
357GetRecentTester::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*/
370void
371GetRecentTester::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*/
385void
386GetRecentTester::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*/
400void
401GetRecentTester::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*/
417void
418GetRecentTester::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*/
453void
454GetRecentTester::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*/
496void
497GetRecentTester::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*/
542void
543GetRecentTester::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	                OBOS: Returns an empty message
560*/
561void
562GetRecentTester::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	                OBOS: Returns an empty message
581*/
582void
583GetRecentTester::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*/
608void
609GetRecentTester::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*/
940void
941GetRecentTester::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*/
1019void
1020GetRecentTester::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	                OBOS: Returns an empty message
1034*/
1035void
1036GetRecentTester::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	                OBOS: Returns an empty message
1064*/
1065void
1066GetRecentTester::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*/
1100void
1101GetRecentTester::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*/
1166void
1167GetRecentTester::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
1236void
1237GetRecentTester::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
1360void
1361GetRecentTester::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 OBOS...
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
1440void
1441GetRecentTester::tearDown()
1442{
1443	// Remove the folder containing all of our test files
1444	if (BEntry(kTempDir).Exists())
1445		ExecCommand("rm -rf ", kTempDir);
1446}
1447
1448Test* 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