1/*****************************************************************************/
2// Haiku Translation Kit Test
3// Author: Brian Matzon <brian@matzon.dk>
4// Version: 0.1.0
5//
6// This is the Test application for BTranslatorRoster
7//
8//
9// This application and all source files used in its construction, except
10// where noted, are licensed under the MIT License, and have been written
11// and are:
12//
13// Copyright (c) 2002 Haiku Project
14//
15// Permission is hereby granted, free of charge, to any person obtaining a
16// copy of this software and associated documentation files (the "Software"),
17// to deal in the Software without restriction, including without limitation
18// the rights to use, copy, modify, merge, publish, distribute, sublicense,
19// and/or sell copies of the Software, and to permit persons to whom the
20// Software is furnished to do so, subject to the following conditions:
21//
22// The above copyright notice and this permission notice shall be included
23// in all copies or substantial portions of the Software.
24//
25// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31// DEALINGS IN THE SOFTWARE.
32/*****************************************************************************/
33#include "TranslatorRosterTest.h"
34
35#include <stdio.h>
36#include <string.h>
37
38#include <Application.h>
39#include <Archivable.h>
40#include <File.h>
41#include <Message.h>
42#include <OS.h>
43#include <TranslatorFormats.h>
44
45/* cppunit framework */
46#include <cppunit/Test.h>
47#include <cppunit/TestCaller.h>
48#include <cppunit/TestSuite.h>
49
50/**
51 * TestCase constructor - no work
52 */
53TranslatorRosterTest::TranslatorRosterTest(std::string name)
54	: BTestCase(name)
55{
56}
57
58/**
59 * Default destructor - no work
60 */
61TranslatorRosterTest::~TranslatorRosterTest()
62{
63}
64
65CppUnit::Test *
66TranslatorRosterTest::Suite()
67{
68	/* create our suite */
69	CppUnit::TestSuite *suite = new CppUnit::TestSuite("TranslatorRoster");
70
71	/* add suckers */
72	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
73		"TranslatorRosterTest::Initialize Test",
74		&TranslatorRosterTest::InitializeTest));
75
76	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
77		"TranslatorRosterTest::Constructor Test",
78		&TranslatorRosterTest::ConstructorTest));
79
80	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
81		"TranslatorRosterTest::Default Test",
82		&TranslatorRosterTest::DefaultTest));
83
84	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
85		"TranslatorRosterTest::Instantiate Test",
86		&TranslatorRosterTest::InstantiateTest));
87
88	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
89		"TranslatorRosterTest::Version Test",
90		&TranslatorRosterTest::VersionTest));
91
92	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
93		"TranslatorRosterTest::AddTranslators Test",
94		&TranslatorRosterTest::AddTranslatorsTest));
95
96	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
97		"TranslatorRosterTest::Archive Test",
98		&TranslatorRosterTest::ArchiveTest));
99
100	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
101		"TranslatorRosterTest::GetAllTranslators Test",
102		&TranslatorRosterTest::GetAllTranslatorsTest));
103
104	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
105		"TranslatorRosterTest::GetConfigurationMessage Test",
106		&TranslatorRosterTest::GetConfigurationMessageTest));
107
108	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
109		"TranslatorRosterTest::GetInputFormats Test",
110		&TranslatorRosterTest::GetInputFormatsTest));
111
112	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
113		"TranslatorRosterTest::GetOutputFormats Test",
114		&TranslatorRosterTest::GetOutputFormatsTest));
115
116	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
117		"TranslatorRosterTest::GetTranslatorInfo Test",
118		&TranslatorRosterTest::GetTranslatorInfoTest));
119
120	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
121		"TranslatorRosterTest::GetTranslators Test",
122		&TranslatorRosterTest::GetTranslatorsTest));
123
124	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
125		"TranslatorRosterTest::Identify Test",
126		&TranslatorRosterTest::IdentifyTest));
127
128	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
129		"TranslatorRosterTest::MakeConfigurationView Test",
130		&TranslatorRosterTest::MakeConfigurationViewTest));
131
132	suite->addTest(new CppUnit::TestCaller<TranslatorRosterTest>(
133		"TranslatorRosterTest::Translate Test",
134		&TranslatorRosterTest::TranslateTest));
135
136	return suite;
137}
138
139/**
140 * Tries to aquire the default roster
141 */
142void
143TranslatorRosterTest::InitializeTest()
144{
145	//aquire default roster
146	NextSubTest();
147	BTranslatorRoster *proster = BTranslatorRoster::Default();
148	CPPUNIT_ASSERT(proster);
149}
150
151/**
152 * Construct proster using different kinds of constructors
153 */
154void
155TranslatorRosterTest::ConstructorTest()
156{
157	//shared instance of TranslatorRoster
158	BTranslatorRoster *proster;
159
160	// Create TranslatorRoster using noargs constructor
161	// (GetAllTranslatorsTest also tests this constructor)
162	NextSubTest();
163	proster = new BTranslatorRoster();
164	CPPUNIT_ASSERT(proster != NULL);
165	delete proster;
166	proster = NULL;
167
168	//Create TranslatorRoster using BMessage constructor
169	NextSubTest();
170	BMessage translator_message;
171	translator_message.AddString("be:translator_path",
172		"/boot/home/config/add-ons/Translators");
173	proster = new BTranslatorRoster(&translator_message);
174	CPPUNIT_ASSERT(proster != NULL);
175
176	// Make sure the correct number of translators were loaded
177	NextSubTest();
178	int32 nloaded = -42;
179	translator_id *pids = NULL;
180	CPPUNIT_ASSERT(proster->GetAllTranslators(&pids, &nloaded) == B_NO_ERROR);
181	CPPUNIT_ASSERT(nloaded > 0);
182	CPPUNIT_ASSERT(pids != NULL);
183
184	// Make sure the correct translators were loaded
185	NextSubTest();
186	const char *kaTranslatorNames[] = {
187		"TGA Images",
188		"MNGTranslator",
189		"BMP Images",
190		"TestBmpTranslator",
191		"BBitmap Images",
192		"GIMPPatternHandler"
193	};
194	int32 naCounts[sizeof(kaTranslatorNames) /
195		sizeof(const char *)] = { 0 };
196	CPPUNIT_ASSERT(nloaded == sizeof(kaTranslatorNames) /
197		sizeof(const char *));
198
199	for (int32 i = 0; i < nloaded; i++) {
200		const char *kTranslatorName, *kTranslatorInfo;
201		int32 nTranslatorVersion;
202
203		CPPUNIT_ASSERT(pids[i] > 0);
204
205		kTranslatorName = kTranslatorInfo = NULL;
206		nTranslatorVersion = -246;
207
208		proster->GetTranslatorInfo(pids[i], &kTranslatorName,
209			&kTranslatorInfo, &nTranslatorVersion);
210
211		CPPUNIT_ASSERT(kTranslatorName);
212		CPPUNIT_ASSERT(kTranslatorInfo);
213		CPPUNIT_ASSERT(nTranslatorVersion > 0);
214
215		// make sure that the translator matches
216		// one from the list
217		int32 npresent = 0;
218		for (int32 k = 0; k < nloaded; k++) {
219			if (!strcmp(kaTranslatorNames[k], kTranslatorName)) {
220				npresent++;
221				naCounts[k]++;
222			}
223		}
224		CPPUNIT_ASSERT(npresent == 1);
225	}
226
227	// make certain that each translator in kaTranslatorNames
228	// is loaded exactly once
229	for (int32 i = 0; i < nloaded; i++)
230		CPPUNIT_ASSERT(naCounts[i] == 1);
231
232	delete proster;
233	proster = NULL;
234}
235
236/**
237 * Tests:
238 * BTranslatorRoster *Default()
239 */
240void
241TranslatorRosterTest::DefaultTest()
242{
243	NextSubTest();
244	BTranslatorRoster *proster = BTranslatorRoster::Default();
245	CPPUNIT_ASSERT(proster != NULL);
246	// TODO: actually check if all the right translators are loaded
247
248	// delete the default BTranslatorRoster
249	// (may not always be the appropriate thing to do,
250	// but it should work without blowing up)
251	NextSubTest();
252	delete proster;
253	proster = NULL;
254
255	// If the default BTranslatorRoster was not
256	// deleted properly, it would likely show up in
257	// this test or the next
258	NextSubTest();
259	proster = BTranslatorRoster::Default();
260	CPPUNIT_ASSERT(proster);
261
262	// Make sure the default BTranslatorRoster works
263	// after a delete has been performed
264	// TODO: actually check if all the right translators are loaded
265	NextSubTest();
266	translator_id *pids = NULL;
267	int32 ncount = -1;
268	CPPUNIT_ASSERT(proster->GetAllTranslators(&pids, &ncount) == B_OK);
269	CPPUNIT_ASSERT(pids);
270	CPPUNIT_ASSERT(ncount > 0);
271	delete[] pids;
272	pids = NULL;
273
274	// Delete again to be sure that it still won't blow up
275	NextSubTest();
276	delete proster;
277	proster = NULL;
278}
279
280/**
281 * Tests:
282 * BTranslatorRoster *Instantiate(BMessage *from)
283 *
284 * @return B_OK if everything went ok, B_ERROR if not
285 */
286// ArchiveTest() also tests BTranslatorRoster::Instantiate()
287void
288TranslatorRosterTest::InstantiateTest()
289{
290	//shared instance of TranslatorRoster
291	BTranslatorRoster* proster = NULL;
292	BMessage bmsg;
293
294	//create BTranslatorRoster using empty message (must return NULL)
295	NextSubTest();
296	proster = dynamic_cast<BTranslatorRoster *>
297		(BTranslatorRoster::Instantiate(&bmsg));
298	CPPUNIT_ASSERT(proster == NULL);
299	delete proster;
300	proster = NULL;
301
302	// BMessage containing a single Translator to load
303	NextSubTest();
304	status_t result;
305	result = bmsg.AddString("class", "BTranslatorRoster");
306	CPPUNIT_ASSERT(result == B_OK);
307	result = bmsg.AddString("be:translator_path",
308		"/boot/home/config/add-ons/Translators/BMPTranslator");
309	CPPUNIT_ASSERT(result == B_OK);
310	proster = dynamic_cast<BTranslatorRoster *>
311		(BTranslatorRoster::Instantiate(&bmsg));
312	CPPUNIT_ASSERT(proster);
313
314	translator_id *pids = NULL;
315	int32 ncount = -1;
316	result = proster->GetAllTranslators(&pids, &ncount);
317	CPPUNIT_ASSERT(result == B_OK);
318	CPPUNIT_ASSERT(pids);
319	CPPUNIT_ASSERT(ncount == 1);
320	const char *strName = NULL, *strInfo = NULL;
321	int32 nversion = -1;
322	result = proster->GetTranslatorInfo(pids[0], &strName, &strInfo,
323		&nversion);
324	CPPUNIT_ASSERT(result == B_OK);
325	CPPUNIT_ASSERT(strName);
326	CPPUNIT_ASSERT(strInfo);
327	CPPUNIT_ASSERT(nversion > 0);
328	CPPUNIT_ASSERT(strcmp("BMP Images", strName) == 0);
329	delete proster;
330	proster = NULL;
331
332	// BMessage is valid, but does not contain any translators
333	NextSubTest();
334	result = bmsg.MakeEmpty();
335	CPPUNIT_ASSERT(result == B_OK);
336	result = bmsg.AddString("class", "BTranslatorRoster");
337	CPPUNIT_ASSERT(result == B_OK);
338	proster = dynamic_cast<BTranslatorRoster *>
339		(BTranslatorRoster::Instantiate(&bmsg));
340	CPPUNIT_ASSERT(proster);
341	delete proster;
342	proster = NULL;
343
344	// TODO: add a case with a BMessage containing multiple Translators to load
345
346	// slightly corrupt BMessage, Instantiate
347	// should fail because class information is missing
348	NextSubTest();
349	result = bmsg.MakeEmpty();
350	CPPUNIT_ASSERT(result == B_OK);
351	result = bmsg.AddString("be:translator_path",
352		"/boot/home/config/add-ons/Translators/BMPTranslator");
353	CPPUNIT_ASSERT(result == B_OK);
354	proster = dynamic_cast<BTranslatorRoster *>
355		(BTranslatorRoster::Instantiate(&bmsg));
356	CPPUNIT_ASSERT(proster == NULL);
357	delete proster;
358	proster = NULL;
359}
360
361/**
362 * Tests:
363 * const char *Version(int32 *outCurVersion, int32 *outMinVersion,
364 * int32 *inAppVersion = B_TRANSLATION_CURRENT_VERSION)
365 *
366 * @return B_OK if everything went ok, B_ERROR if not
367 */
368void
369TranslatorRosterTest::VersionTest()
370{
371#if 0
372	NextSubTest();
373	int32 outCurVersion = 0;
374	int32 outMinVersion = 0;
375	const char* info = NULL;
376
377	info = BTranslatorRoster::Version(&outCurVersion, &outMinVersion);
378	CPPUNIT_ASSERT(info != NULL);
379	CPPUNIT_ASSERT(outCurVersion > 0);
380	CPPUNIT_ASSERT(outMinVersion > 0);
381#endif
382}
383
384//
385// Compares proster to the default BTranslatorRoster to
386// ensure that they have the same translators and the
387// same number of translators
388//
389void
390CompareWithDefault(BTranslatorRoster *proster)
391{
392	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
393	CPPUNIT_ASSERT(pDefRoster);
394
395	translator_id *pInstids = NULL, *pDefids = NULL;
396	int32 instcount = 0, defcount = 0, ndummy = 0;
397	const char *strDefName = NULL, *strInstName = NULL, *strDummy = NULL;
398
399	CPPUNIT_ASSERT(proster->GetAllTranslators(&pInstids, &instcount) == B_OK);
400	CPPUNIT_ASSERT(pInstids);
401	CPPUNIT_ASSERT(instcount > 0);
402
403	CPPUNIT_ASSERT(pDefRoster->GetAllTranslators(&pDefids, &defcount) == B_OK);
404	CPPUNIT_ASSERT(pDefids);
405	CPPUNIT_ASSERT(defcount > 0);
406	CPPUNIT_ASSERT(defcount == instcount);
407
408	// make sure that every translator that is in the default
409	// BTranslatorRoster is in proster, once and only once
410	for (int32 i = 0; i < defcount; i++) {
411		int32 matches;
412		matches = 0;
413		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(pDefids[i], &strDefName,
414			&strDummy, &ndummy) == B_OK);
415		CPPUNIT_ASSERT(strDefName);
416		for (int32 k = 0; k < instcount; k++) {
417			CPPUNIT_ASSERT(proster->GetTranslatorInfo(pInstids[k],
418				&strInstName, &strDummy, &ndummy) == B_OK);
419			CPPUNIT_ASSERT(strInstName);
420
421			if (strcmp(strDefName, strInstName) == 0)
422				matches++;
423		}
424		CPPUNIT_ASSERT(matches == 1);
425	}
426
427	delete[] pInstids;
428	pInstids = NULL;
429	delete[] pDefids;
430	pDefids = NULL;
431}
432
433/**
434 * Tests:
435 * virtual status_t AddTranslators(const char *load_path = NULL)
436 *
437 * @return B_OK if everything went ok, B_ERROR if not
438 */
439void
440TranslatorRosterTest::AddTranslatorsTest()
441{
442	//create basic translatorroster
443	NextSubTest();
444	BTranslatorRoster* proster = new BTranslatorRoster();
445	CPPUNIT_ASSERT(proster);
446	CPPUNIT_ASSERT(proster->AddTranslators(
447		"/boot/home/config/add-ons/Translators/:"
448		"/system/add-ons/Translators/") == B_OK);
449
450	NextSubTest();
451	int32 instcount = 0;
452	translator_id* translators = NULL;
453	proster->GetAllTranslators(&translators, &instcount);
454	CPPUNIT_ASSERT(translators);
455	CPPUNIT_ASSERT(instcount > 0);
456	// TODO: count the number of files in all of the directories specified
457	// TODO: above and make certain that it matches instcount
458	delete[] translators;
459	translators = NULL;
460
461	//delete and create new, this time don't specify path
462	NextSubTest();
463	delete proster;
464	proster = new BTranslatorRoster();
465	CPPUNIT_ASSERT(proster->AddTranslators() == B_OK);
466
467	// make sure that every translator in the Default BTranslatorRoster is in
468	// proster, and make certain that it is in there ONLY ONCE
469	NextSubTest();
470	CompareWithDefault(proster);
471	delete proster;
472	proster = NULL;
473}
474
475/**
476 * Tests:
477 * virtual status_t Archive(BMessage *into, bool deep = true) const
478 *
479 * @return B_OK if everything went ok, B_ERROR if not
480 */
481void
482TranslatorRosterTest::ArchiveTest()
483{
484	NextSubTest();
485	//archive default, and count entries (must be more than 1!)
486	BMessage translator_message;
487	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
488	CPPUNIT_ASSERT(pDefRoster);
489	CPPUNIT_ASSERT(pDefRoster->Archive(&translator_message) == B_OK);
490
491	// make sure instantiate makes an "exact" copy of the default translator
492	NextSubTest();
493	BTranslatorRoster *proster = NULL;
494	proster = dynamic_cast<BTranslatorRoster *>
495		(BTranslatorRoster::Instantiate(&translator_message));
496	CPPUNIT_ASSERT(proster);
497
498	// make sure that every translator in the pDefRoster is in
499	// proster, and make certain that it is in there ONLY ONCE
500	NextSubTest();
501	CompareWithDefault(proster);
502	delete proster;
503	proster = NULL;
504}
505
506/**
507 * Tests:
508 * virtual status_t GetAllTranslators(translator_id **outList, int32 *outCount)
509 *
510 * @return B_OK if everything went ok, B_ERROR if not
511 */
512void
513TranslatorRosterTest::GetAllTranslatorsTest()
514{
515	// bad parameters
516	NextSubTest();
517	int32 nloaded = 42;
518	translator_id* pids = NULL;
519	BTranslatorRoster roster;
520	CPPUNIT_ASSERT(roster.GetAllTranslators(NULL, &nloaded) == B_BAD_VALUE);
521	CPPUNIT_ASSERT(nloaded == 42);
522	CPPUNIT_ASSERT(roster.GetAllTranslators(&pids, NULL) == B_BAD_VALUE);
523	CPPUNIT_ASSERT(pids == NULL);
524	CPPUNIT_ASSERT(roster.GetAllTranslators(NULL, NULL) == B_BAD_VALUE);
525
526	// no translators
527	NextSubTest();
528	CPPUNIT_ASSERT(
529		roster.GetAllTranslators(&pids, &nloaded) == B_NO_ERROR);
530	CPPUNIT_ASSERT(nloaded == 0);
531	delete[] pids;
532	pids = NULL;
533
534	// default translators
535	NextSubTest();
536	nloaded = 42;
537	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
538	CPPUNIT_ASSERT(
539		pDefRoster->GetAllTranslators(&pids, &nloaded) == B_NO_ERROR);
540	CPPUNIT_ASSERT(nloaded > 0);
541	CPPUNIT_ASSERT(pids != NULL);
542
543	// Make sure the correct translators were loaded
544	NextSubTest();
545	const char *kaTranslatorNames[] = {
546		"Gobe MS-WORD Translator",
547		"Gobe Text Translator",
548		"TIFF Images",
549		"Gobe SYLK Translator",
550		"StyledEdit Files",
551		"Gobe RTF Translator",
552		"PPM Images",
553		"JPEG Images",
554		"Gobe HTML Translator",
555		"Gobe Excel Translator",
556		"TGA Images",
557		"MNGTranslator",
558		"GIMPPatternHandler",
559		"TestBmpTranslator",
560		"BMP Images",
561		"BBitmap Images"
562	};
563	CPPUNIT_ASSERT(nloaded == sizeof(kaTranslatorNames) /
564		sizeof(const char *));
565
566	for (int32 i = 0; i < nloaded; i++) {
567		const char *kTranslatorName, *kTranslatorInfo;
568		int32 nTranslatorVersion;
569
570		CPPUNIT_ASSERT(pids[i] > 0);
571
572		kTranslatorName = kTranslatorInfo = NULL;
573		nTranslatorVersion = -246;
574
575		pDefRoster->GetTranslatorInfo(pids[i], &kTranslatorName,
576			&kTranslatorInfo, &nTranslatorVersion);
577
578		CPPUNIT_ASSERT(kTranslatorName);
579		CPPUNIT_ASSERT(kTranslatorInfo);
580		CPPUNIT_ASSERT(nTranslatorVersion > 0);
581
582		// make sure each translator is loaded exactly once
583		// no more, no less
584		int32 npassed = 0;
585		for (int32 k = 0; k < nloaded; k++) {
586			if (!strcmp(kaTranslatorNames[k], kTranslatorName))
587				npassed++;
588		}
589		CPPUNIT_ASSERT(npassed == 1);
590	}
591
592	delete[] pids;
593	pids = NULL;
594}
595
596/**
597 * Tests:
598 * virtual status_t GetConfigurationMessage(translator_id forTranslator,
599 * BMessage *ioExtension)
600 *
601 * @return B_OK if everything went ok, B_ERROR if not
602 */
603void
604TranslatorRosterTest::GetConfigurationMessageTest()
605{
606	NextSubTest();
607	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
608	CPPUNIT_ASSERT(pDefRoster);
609
610	NextSubTest();
611	//get id for a translator (just use the first one)
612	int32 num_translators = -1;
613	translator_id* translators = NULL;
614	CPPUNIT_ASSERT(pDefRoster->GetAllTranslators(&translators,
615		&num_translators) == B_OK);
616	CPPUNIT_ASSERT(translators);
617	CPPUNIT_ASSERT(num_translators > 0);
618
619	NextSubTest();
620	translator_id translatorid = translators[0];
621	delete[] translators;
622	translators = NULL;
623	//get conf for invalid translator
624	BMessage translator_message;
625	CPPUNIT_ASSERT(pDefRoster->GetConfigurationMessage(-1,
626		&translator_message) == B_NO_TRANSLATOR);
627	CPPUNIT_ASSERT(translator_message.IsEmpty());
628
629	//get conf for invalid ioExtension (BMessage)
630	NextSubTest();
631	CPPUNIT_ASSERT(
632		pDefRoster->GetConfigurationMessage(translatorid, NULL) == B_BAD_VALUE);
633
634	//get config for actual translator
635	NextSubTest();
636	CPPUNIT_ASSERT(translator_message.MakeEmpty() == B_OK);
637	CPPUNIT_ASSERT(pDefRoster->GetConfigurationMessage(translatorid,
638		&translator_message) == B_OK);
639}
640
641// Code used by both GetInputFormatsTest and GetOutputFormatsTest
642void
643GetInputOutputFormatsTest(TranslatorRosterTest *prt, bool binput)
644{
645	prt->NextSubTest();
646	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
647	CPPUNIT_ASSERT(pDefRoster);
648
649	prt->NextSubTest();
650	translator_id* translators = NULL;
651	int32 num_translators = -1;
652	CPPUNIT_ASSERT(pDefRoster->GetAllTranslators(&translators,
653		&num_translators) == B_OK);
654	CPPUNIT_ASSERT(translators);
655	CPPUNIT_ASSERT(num_translators > 0);
656
657	// Run get Input/output format test on each translator
658	for (int32 i = 0; i < num_translators; i++) {
659		const translation_format *fmts = NULL;
660		int32 num_fmts = -1;
661		status_t result;
662		prt->NextSubTest();
663		if (binput)
664			result = pDefRoster->GetInputFormats(translators[i], &fmts,
665				&num_fmts);
666		else
667			result = pDefRoster->GetOutputFormats(translators[i], &fmts,
668				&num_fmts);
669		CPPUNIT_ASSERT(result == B_OK);
670
671		// test input/output formats
672		CPPUNIT_ASSERT(num_fmts >= 0);
673		CPPUNIT_ASSERT(num_fmts == 0 || fmts);
674		for (int32 k = 0; k < num_fmts; k++) {
675			CPPUNIT_ASSERT(fmts[k].type);
676			CPPUNIT_ASSERT(fmts[k].group);
677			CPPUNIT_ASSERT(fmts[k].quality >= 0 && fmts[k].quality <= 1);
678			CPPUNIT_ASSERT(fmts[k].capability >= 0 && fmts[k].capability <= 1);
679			CPPUNIT_ASSERT(strlen(fmts[k].MIME) >= 0);
680			CPPUNIT_ASSERT(strlen(fmts[k].name) > 0);
681		}
682	}
683	delete[] translators;
684	translators = NULL;
685}
686
687/**
688 * Tests:
689 * virtual status_t GetInputFormats(translator_id forTranslator,
690 * const translation_format **outFormats, int32 *outNumFormats)
691 *
692 * @return B_OK if everything went ok, B_ERROR if not
693 */
694void
695TranslatorRosterTest::GetInputFormatsTest()
696{
697	GetInputOutputFormatsTest(this, true);
698}
699
700/**
701 * Tests:
702 * virtual status_t GetOutputFormats(translator_id forTranslator,
703 * const translation_format **outFormats, int32 *outNumFormats)
704 *
705 * @return B_OK if everything went ok, B_ERROR if not
706 */
707void
708TranslatorRosterTest::GetOutputFormatsTest()
709{
710	GetInputOutputFormatsTest(this, false);
711}
712
713/**
714 * Tests:
715 * virtual status_t GetTranslatorInfo(translator_id forTranslator,
716 * const char **outName, const char **outInfo, int32 *outVersion)
717 *
718 * @return B_OK if everything went ok, B_ERROR if not
719 */
720void
721TranslatorRosterTest::GetTranslatorInfoTest()
722{
723	NextSubTest();
724	translator_id* translators = NULL;
725	int32 num_translators = -1;
726	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
727	CPPUNIT_ASSERT(pDefRoster);
728
729	NextSubTest();
730	CPPUNIT_ASSERT(pDefRoster->GetAllTranslators(&translators,
731		&num_translators) == B_OK);
732	CPPUNIT_ASSERT(translators);
733	CPPUNIT_ASSERT(num_translators > 0);
734	for (int32 i = 0; i < num_translators; i++) {
735		const char *outName = NULL;
736		const char *outInfo = NULL;
737		int32 outVersion = -1;
738
739		NextSubTest();
740		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(-1, &outName, &outInfo,
741			&outVersion) == B_NO_TRANSLATOR);
742
743		// B_BAD_VALUE cases
744		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(translators[i],
745			NULL, &outInfo, &outVersion) == B_BAD_VALUE);
746		CPPUNIT_ASSERT(outInfo == NULL && outVersion == -1);
747
748		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(translators[i],
749			&outName, NULL, &outVersion) == B_BAD_VALUE);
750		CPPUNIT_ASSERT(outName == NULL && outVersion == -1);
751
752		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(translators[i],
753			&outName, &outInfo, NULL) == B_BAD_VALUE);
754		CPPUNIT_ASSERT(outName == NULL && outInfo == NULL);
755
756		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(translators[i],
757			NULL, NULL, NULL) == B_BAD_VALUE);
758
759		// Good values
760		CPPUNIT_ASSERT(pDefRoster->GetTranslatorInfo(translators[i],
761			&outName, &outInfo, &outVersion) == B_OK);
762		CPPUNIT_ASSERT(outName);
763	}
764	delete[] translators;
765	translators = NULL;
766}
767
768void
769CheckTranslatorInfo(translator_info *pinfo, int32 nitems)
770{
771	for (int32 k = 0; k < nitems; k++) {
772		CPPUNIT_ASSERT(pinfo[k].translator > 0);
773		CPPUNIT_ASSERT(pinfo[k].type);
774		CPPUNIT_ASSERT(pinfo[k].group);
775		CPPUNIT_ASSERT(pinfo[k].quality >= 0 && pinfo[k].quality <= 1);
776		CPPUNIT_ASSERT(pinfo[k].capability >= 0 && pinfo[k].capability <= 1);
777		CPPUNIT_ASSERT(strlen(pinfo[k].MIME) >= 0);
778		CPPUNIT_ASSERT(strlen(pinfo[k].name) > 0);
779	}
780}
781
782/**
783 * Tests:
784 * virtual status_t GetTranslators(BPositionIO *inSource,
785 * BMessage *ioExtension, translator_info **outInfo, int32 *outNumInfo,
786 * uint32 inHintType = 0, const char *inHintMIME = NULL, uint32 inWantType = 0)
787 *
788 * @return B_OK if everything went ok, B_ERROR if not
789 */
790void
791TranslatorRosterTest::GetTranslatorsTest()
792{
793	NextSubTest();
794	BApplication app(
795		"application/x-vnd.OpenBeOS-translationkit_translatorrostertest");
796	//open image to get a translator for
797	BFile image("../src/tests/kits/translation/data/images/image.png",
798		B_READ_ONLY);
799	CPPUNIT_ASSERT(image.InitCheck() == B_OK);
800
801	BFile garbled("../src/tests/kits/translation/data/garbled_data",
802		B_READ_ONLY);
803	CPPUNIT_ASSERT(garbled.InitCheck() == B_OK);
804
805	NextSubTest();
806	translator_info* pinfo = NULL;
807	int32 outCount = -1;
808	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
809	CPPUNIT_ASSERT(pDefRoster);
810
811	//get translator, specifying wrong args
812	NextSubTest();
813	CPPUNIT_ASSERT(pDefRoster->GetTranslators(&garbled, NULL, NULL,
814		&outCount) == B_BAD_VALUE);
815
816	//get translator, specifying wrong args
817	NextSubTest();
818	CPPUNIT_ASSERT(pDefRoster->GetTranslators(&garbled, NULL, &pinfo,
819		NULL) == B_BAD_VALUE);
820
821	//get translator for garbled data
822	NextSubTest();
823	CPPUNIT_ASSERT(pDefRoster->GetTranslators(&garbled, NULL, &pinfo,
824		&outCount) == B_NO_TRANSLATOR);
825
826	//get translator for image
827	NextSubTest();
828	CPPUNIT_ASSERT(pDefRoster->GetTranslators(&image, NULL, &pinfo,
829		&outCount) == B_OK);
830	CPPUNIT_ASSERT(outCount > 0);
831	CheckTranslatorInfo(pinfo, outCount);
832	delete[] pinfo;
833	pinfo = NULL;
834	outCount = -1;
835
836	//specify a valid BMessage
837	NextSubTest();
838	BMessage bmsg;
839	CPPUNIT_ASSERT(
840		bmsg.AddBool(B_TRANSLATOR_EXT_DATA_ONLY, true) == B_OK);
841	CPPUNIT_ASSERT(pDefRoster->GetTranslators(&image, &bmsg, &pinfo,
842		&outCount, 0, NULL, B_TRANSLATOR_BITMAP) == B_OK);
843	CPPUNIT_ASSERT(outCount > 0);
844	CheckTranslatorInfo(pinfo, outCount);
845	delete[] pinfo;
846	pinfo = NULL;
847}
848
849/**
850 * Tests:
851 * virtual status_t Identify(BPositionIO *inSource, BMessage *ioExtension,
852 * translator_info *outInfo, uint32 inHintType = 0,
853 * const char *inHintMIME = NULL, uint32 inWantType = 0)
854 *
855 * @return B_OK if everything went ok, B_ERROR if not
856 */
857void
858TranslatorRosterTest::IdentifyTest()
859{
860	NextSubTest();
861	BApplication app(
862		"application/x-vnd.OpenBeOS-translationkit_translatorrostertest");
863	//open image to get a translator for
864	BFile image("../src/tests/kits/translation/data/images/image.png",
865		B_READ_ONLY);
866	CPPUNIT_ASSERT(image.InitCheck() == B_OK);
867
868	BFile garbled("../src/tests/kits/translation/data/garbled_data",
869		B_READ_ONLY);
870	CPPUNIT_ASSERT(garbled.InitCheck() == B_OK);
871
872	NextSubTest();
873	translator_info info;
874	memset(&info, 0, sizeof(translator_info));
875	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
876	CPPUNIT_ASSERT(pDefRoster);
877
878	//get translator, specifying wrong args
879	NextSubTest();
880	CPPUNIT_ASSERT(pDefRoster->Identify(&garbled, NULL, NULL) == B_BAD_VALUE);
881
882	//get translator for garbled data
883	NextSubTest();
884	CPPUNIT_ASSERT(pDefRoster->Identify(&garbled, NULL,
885		&info) == B_NO_TRANSLATOR);
886
887	//get translator for image
888	NextSubTest();
889	memset(&info, 0, sizeof(translator_info));
890	CPPUNIT_ASSERT(pDefRoster->Identify(&image, NULL, &info) == B_OK);
891	CheckTranslatorInfo(&info, 1);
892
893	//supply desired output type
894	NextSubTest();
895	memset(&info, 0, sizeof(translator_info));
896	CPPUNIT_ASSERT(pDefRoster->Identify(&image, NULL, &info,
897		0, NULL, B_TRANSLATOR_BITMAP) == B_OK);
898	CheckTranslatorInfo(&info, 1);
899
900	// TODO: Add a test where I actually use pinfo and a BMessage
901	// TODO: and check their contents
902}
903
904/**
905 * Tests:
906 * virtual status_t MakeConfigurationView(translator_id forTranslator,
907 * BMessage *ioExtension, BView **outView, BRect *outExtent)
908 *
909 * @return B_OK if everything went ok, B_ERROR if not
910 */
911void
912TranslatorRosterTest::MakeConfigurationViewTest()
913{
914	//create invalid rect - if it is valid after the
915	//MakeConfigurationView call the test has succeded
916	NextSubTest();
917	BApplication app(
918		"application/x-vnd.OpenBeOS-translationkit_translatorrostertest");
919	BRect extent(-1, -1, -1, -1);
920	//create config view
921	BView *view = NULL;
922	translator_id *translators = NULL;
923	int32 num_translators = -1;
924	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
925	CPPUNIT_ASSERT(pDefRoster);
926
927	NextSubTest();
928	CPPUNIT_ASSERT(
929		pDefRoster->GetAllTranslators(&translators, &num_translators) == B_OK);
930	CPPUNIT_ASSERT(translators);
931	CPPUNIT_ASSERT(num_translators > 0);
932
933	// bad parameters
934	NextSubTest();
935	CPPUNIT_ASSERT(pDefRoster->MakeConfigurationView(translators[0], NULL,
936		&view, NULL) == B_BAD_VALUE);
937	CPPUNIT_ASSERT(pDefRoster->MakeConfigurationView(translators[0], NULL,
938		NULL, &extent) == B_BAD_VALUE);
939	CPPUNIT_ASSERT(pDefRoster->MakeConfigurationView(translators[0], NULL,
940		NULL, NULL) == B_BAD_VALUE);
941
942	// bad translator id
943	NextSubTest();
944	CPPUNIT_ASSERT(pDefRoster->MakeConfigurationView(-1, NULL, &view,
945		&extent) == B_NO_TRANSLATOR);
946
947	// should work
948	NextSubTest();
949	CPPUNIT_ASSERT(pDefRoster->MakeConfigurationView(translators[0], NULL,
950		&view, &extent) == B_OK);
951	CPPUNIT_ASSERT(extent.IsValid() == true);
952
953	// TODO: Add a test that uses a valid BMessage with actual settings in it
954
955	//clean up after ourselves
956	delete[] translators;
957	translators = NULL;
958}
959
960/**
961 * Tests:
962 * virtual status_t Translate(BPositionIO *inSource,
963 * const translator_info *inInfo, BMessage *ioExtension,
964 * BPositionIO *outDestination, uint32 inWantOutType,
965 * uint32 inHintType = 0, const char *inHintMIME = NULL)
966 *
967 * virtual status_t Translate(translator_id inTranslator,
968 * BPositionIO *inSource, BMessage *ioExtension,
969 * BPositionIO *outDestination, uint32 inWantOutType)
970 *
971 * @return B_OK if everything went ok, B_ERROR if not
972 */
973void
974TranslatorRosterTest::TranslateTest()
975{
976	NextSubTest();
977	BApplication app(
978		"application/x-vnd.OpenBeOS-translationkit_translatorrostertest");
979	//input
980	BFile input("../src/tests/kits/translation/data/images/image.jpg",
981		B_READ_ONLY);
982	CPPUNIT_ASSERT(input.InitCheck() == B_OK);
983
984	//temp file for generic format
985	NextSubTest();
986	BFile temp("/tmp/TranslatorRosterTest.temp",
987		B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
988	CPPUNIT_ASSERT(temp.InitCheck() == B_OK);
989
990	//output file
991	NextSubTest();
992	BFile output("../src/tests/kits/translation/data/images/image.out.tga",
993		B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
994	CPPUNIT_ASSERT(output.InitCheck() == B_OK);
995
996	//get default translators
997	NextSubTest();
998	BTranslatorRoster *pDefRoster = BTranslatorRoster::Default();
999	CPPUNIT_ASSERT(pDefRoster != NULL);
1000
1001	//translate to generic
1002	NextSubTest();
1003	CPPUNIT_ASSERT(pDefRoster->Translate(&input, NULL, NULL, &temp,
1004		B_TRANSLATOR_BITMAP) == B_OK);
1005
1006	//translate to specific
1007	NextSubTest();
1008	CPPUNIT_ASSERT(pDefRoster->Translate(&temp, NULL, NULL, &output,
1009		B_TGA_FORMAT) == B_OK);
1010
1011	// TODO: add Translate using ioExtension BMessage and whatever
1012	// TODO: the other NULL parameter is
1013}
1014
1015int
1016main()
1017{
1018	//needed by MakeConfigurationView
1019	TranslatorRosterTest test;
1020	test.InitializeTest();
1021	test.ConstructorTest();
1022	test.DefaultTest();
1023	test.InstantiateTest();
1024	test.VersionTest();
1025	test.AddTranslatorsTest();
1026	test.ArchiveTest();
1027
1028	return 0;
1029}
1030