1// BMPTranslatorTest.cpp
2#include "BMPTranslatorTest.h"
3#include <cppunit/Test.h>
4#include <cppunit/TestCaller.h>
5#include <cppunit/TestSuite.h>
6#include <stdio.h>
7#include <string.h>
8#include <unistd.h>
9#include <image.h>
10#include <Application.h>
11#include <Translator.h>
12#include <TranslatorFormats.h>
13#include <TranslatorRoster.h>
14#include <Message.h>
15#include <View.h>
16#include <Rect.h>
17#include <File.h>
18#include <DataIO.h>
19#include <Errors.h>
20#include <OS.h>
21#include "TranslatorTestAddOn.h"
22
23#define BMP_NO_COMPRESS 0
24#define BMP_RLE8_COMPRESS 1
25#define BMP_RLE4_COMPRESS 2
26
27struct BMPFileHeader {
28	// for both MS and OS/2 BMP formats
29	uint16 magic;			// = 'BM'
30	uint32 fileSize;		// file size in bytes
31	uint32 reserved;		// equals 0
32	uint32 dataOffset;		// file offset to actual image
33};
34
35struct MSInfoHeader {
36	uint32 size;			// size of this struct (40)
37	uint32 width;			// bitmap width
38	uint32 height;			// bitmap height
39	uint16 planes;			// number of planes, always 1?
40	uint16 bitsperpixel;	// bits per pixel, (1,4,8,16 or 24)
41	uint32 compression;		// type of compression
42	uint32 imagesize;		// size of image data if compressed
43	uint32 xpixperm;		// horizontal pixels per meter
44	uint32 ypixperm;		// vertical pixels per meter
45	uint32 colorsused;		// number of actually used colors
46	uint32 colorsimportant;	// number of important colors, zero = all
47};
48
49struct OS2InfoHeader {
50	uint32 size;			// size of this struct (12)
51	uint16 width;			// bitmap width
52	uint16 height;			// bitmap height
53	uint16 planes;			// number of planes, always 1?
54	uint16 bitsperpixel;	// bits per pixel, (1,4,8,16 or 24)
55};
56
57// Suite
58CppUnit::Test *
59BMPTranslatorTest::Suite()
60{
61	CppUnit::TestSuite *suite = new CppUnit::TestSuite();
62	typedef CppUnit::TestCaller<BMPTranslatorTest> TC;
63
64	suite->addTest(
65		new TC("BMPTranslator IdentifyTest",
66			&BMPTranslatorTest::IdentifyTest));
67
68	suite->addTest(
69		new TC("BMPTranslator TranslateTest",
70			&BMPTranslatorTest::TranslateTest));
71
72	suite->addTest(
73		new TC("BMPTranslator ConfigMessageTest",
74			&BMPTranslatorTest::ConfigMessageTest));
75
76#if !TEST_R5
77	suite->addTest(
78		new TC("BMPTranslator LoadAddOnTest",
79			&BMPTranslatorTest::LoadAddOnTest));
80#endif
81
82	return suite;
83}
84
85// setUp
86void
87BMPTranslatorTest::setUp()
88{
89	BTestCase::setUp();
90}
91
92// tearDown
93void
94BMPTranslatorTest::tearDown()
95{
96	BTestCase::tearDown();
97}
98
99void
100CheckBits_Bmp(translator_info *pti)
101{
102	CheckTranslatorInfo(pti, B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP,
103		0.4f, 0.6f, "Be Bitmap Format (BMPTranslator)",
104		"image/x-be-bitmap");
105}
106
107void
108CheckBmp(translator_info *pti, const char *imageType)
109{
110	CheckTranslatorInfo(pti, B_BMP_FORMAT, B_TRANSLATOR_BITMAP,
111		0.4f, 0.8f, imageType, "image/x-bmp");
112}
113
114// coveniently group path of image with
115// the expected Identify() string for that image
116struct IdentifyInfo {
117	const char *imagePath;
118	const char *identifyString;
119};
120
121void
122IdentifyTests(BMPTranslatorTest *ptest, BTranslatorRoster *proster,
123	const IdentifyInfo *pinfo, int32 len, bool bbits)
124{
125	translator_info ti;
126	printf(" [%d] ", (int) bbits);
127
128	for (int32 i = 0; i < len; i++) {
129		ptest->NextSubTest();
130		BFile file;
131		printf(" [%s] ", pinfo[i].imagePath);
132		CPPUNIT_ASSERT(file.SetTo(pinfo[i].imagePath, B_READ_ONLY) == B_OK);
133
134		// Identify (output: B_TRANSLATOR_ANY_TYPE)
135		ptest->NextSubTest();
136		memset(&ti, 0, sizeof(translator_info));
137		CPPUNIT_ASSERT(proster->Identify(&file, NULL, &ti) == B_OK);
138		if (bbits)
139			CheckBits_Bmp(&ti);
140		else
141			CheckBmp(&ti, pinfo[i].identifyString);
142
143		// Identify (output: B_TRANSLATOR_BITMAP)
144		ptest->NextSubTest();
145		memset(&ti, 0, sizeof(translator_info));
146		CPPUNIT_ASSERT(proster->Identify(&file, NULL, &ti, 0, NULL,
147			B_TRANSLATOR_BITMAP) == B_OK);
148		if (bbits)
149			CheckBits_Bmp(&ti);
150		else
151			CheckBmp(&ti, pinfo[i].identifyString);
152
153		// Identify (output: B_BMP_FORMAT)
154		ptest->NextSubTest();
155		memset(&ti, 0, sizeof(translator_info));
156		CPPUNIT_ASSERT(proster->Identify(&file, NULL, &ti, 0, NULL,
157			B_BMP_FORMAT) == B_OK);
158		if (bbits)
159			CheckBits_Bmp(&ti);
160		else
161			CheckBmp(&ti, pinfo[i].identifyString);
162	}
163}
164
165void
166BMPTranslatorTest::IdentifyTest()
167{
168	// Init
169	NextSubTest();
170	status_t result = B_ERROR;
171	BTranslatorRoster *proster = new BTranslatorRoster();
172	CPPUNIT_ASSERT(proster);
173	CPPUNIT_ASSERT(proster->AddTranslators(
174		"/boot/home/config/add-ons/Translators/BMPTranslator") == B_OK);
175	BFile wronginput("../src/tests/kits/translation/data/images/image.jpg",
176		B_READ_ONLY);
177	CPPUNIT_ASSERT(wronginput.InitCheck() == B_OK);
178
179	// Identify (bad input, output types)
180	NextSubTest();
181	translator_info ti;
182	memset(&ti, 0, sizeof(translator_info));
183	result = proster->Identify(&wronginput, NULL, &ti, 0,
184		NULL, B_TRANSLATOR_TEXT);
185	CPPUNIT_ASSERT(result == B_NO_TRANSLATOR);
186	CPPUNIT_ASSERT(ti.type == 0 && ti.translator == 0);
187
188	// Identify (wrong type of input data)
189	NextSubTest();
190	memset(&ti, 0, sizeof(translator_info));
191	result = proster->Identify(&wronginput, NULL, &ti);
192	CPPUNIT_ASSERT(result == B_NO_TRANSLATOR);
193	CPPUNIT_ASSERT(ti.type == 0 && ti.translator == 0);
194
195	// empty
196	NextSubTest();
197	BMallocIO mallempty;
198	CPPUNIT_ASSERT(proster->Identify(&mallempty, NULL, &ti) == B_NO_TRANSLATOR);
199
200	// weird, non-image data
201	NextSubTest();
202	const char *strmonkey = "monkey monkey monkey";
203	BMemoryIO memmonkey(strmonkey, strlen(strmonkey));
204	CPPUNIT_ASSERT(proster->Identify(&memmonkey, NULL, &ti) == B_NO_TRANSLATOR);
205
206	// abreviated BMPFileHeader
207	NextSubTest();
208	BMPFileHeader fheader;
209	fheader.magic = 'MB';
210	fheader.fileSize = 1028;
211	BMallocIO mallabrev;
212	CPPUNIT_ASSERT(mallabrev.Write(&fheader.magic, 2) == 2);
213	CPPUNIT_ASSERT(mallabrev.Write(&fheader.fileSize, 4) == 4);
214	CPPUNIT_ASSERT(proster->Identify(&mallabrev, NULL, &ti) == B_NO_TRANSLATOR);
215
216	// Write out the MS and OS/2 headers with various fields being corrupt, only one
217	// corrupt field at a time, also do abrev test for MS header and OS/2 header
218	NextSubTest();
219	fheader.magic = 'MB';
220	fheader.fileSize = 53; // bad value, too small to contain all of MS header data
221		// bad values in this field can be, and are ignored by some Windows image viewers
222	fheader.reserved = 0;
223	fheader.dataOffset = 54;
224	MSInfoHeader msheader;
225	msheader.size = 40;
226	msheader.width = 5;
227	msheader.height = 5;
228	msheader.planes = 1;
229	msheader.bitsperpixel = 24;
230	msheader.compression = BMP_NO_COMPRESS;
231	msheader.imagesize = 0;
232	msheader.xpixperm = 23275;
233	msheader.ypixperm = 23275;
234	msheader.colorsused = 0;
235	msheader.colorsimportant = 0;
236	BMallocIO mallbadfs;
237	CPPUNIT_ASSERT(mallbadfs.Write(&fheader.magic, 2) == 2);
238	CPPUNIT_ASSERT(mallbadfs.Write(&fheader.fileSize, 4) == 4);
239	CPPUNIT_ASSERT(mallbadfs.Write(&fheader.reserved, 4) == 4);
240	CPPUNIT_ASSERT(mallbadfs.Write(&fheader.dataOffset, 4) == 4);
241	CPPUNIT_ASSERT(mallbadfs.Write(&msheader, 40) == 40);
242	CPPUNIT_ASSERT(proster->Identify(&mallbadfs, NULL, &ti) == B_OK);
243
244	NextSubTest();
245	fheader.magic = 'MB';
246	fheader.fileSize = 1028;
247	fheader.reserved = 7; // bad value, should be zero
248	fheader.dataOffset = 54;
249	msheader.size = 40;
250	msheader.width = 5;
251	msheader.height = 5;
252	msheader.planes = 1;
253	msheader.bitsperpixel = 24;
254	msheader.compression = BMP_NO_COMPRESS;
255	msheader.imagesize = 0;
256	msheader.xpixperm = 23275;
257	msheader.ypixperm = 23275;
258	msheader.colorsused = 0;
259	msheader.colorsimportant = 0;
260	BMallocIO mallbadr;
261	CPPUNIT_ASSERT(mallbadr.Write(&fheader.magic, 2) == 2);
262	CPPUNIT_ASSERT(mallbadr.Write(&fheader.fileSize, 4) == 4);
263	CPPUNIT_ASSERT(mallbadr.Write(&fheader.reserved, 4) == 4);
264	CPPUNIT_ASSERT(mallbadr.Write(&fheader.dataOffset, 4) == 4);
265	CPPUNIT_ASSERT(mallbadr.Write(&msheader, 40) == 40);
266	CPPUNIT_ASSERT(proster->Identify(&mallbadr, NULL, &ti) == B_NO_TRANSLATOR);
267
268	NextSubTest();
269	fheader.magic = 'MB';
270	fheader.fileSize = 1028;
271	fheader.reserved = 0;
272	fheader.dataOffset = 53; // bad value, for MS format, needs to be at least 54
273	msheader.size = 40;
274	msheader.width = 5;
275	msheader.height = 5;
276	msheader.planes = 1;
277	msheader.bitsperpixel = 24;
278	msheader.compression = BMP_NO_COMPRESS;
279	msheader.imagesize = 0;
280	msheader.xpixperm = 23275;
281	msheader.ypixperm = 23275;
282	msheader.colorsused = 0;
283	msheader.colorsimportant = 0;
284	BMallocIO mallbaddo1;
285	CPPUNIT_ASSERT(mallbaddo1.Write(&fheader.magic, 2) == 2);
286	CPPUNIT_ASSERT(mallbaddo1.Write(&fheader.fileSize, 4) == 4);
287	CPPUNIT_ASSERT(mallbaddo1.Write(&fheader.reserved, 4) == 4);
288	CPPUNIT_ASSERT(mallbaddo1.Write(&fheader.dataOffset, 4) == 4);
289	CPPUNIT_ASSERT(mallbaddo1.Write(&msheader, 40) == 40);
290	CPPUNIT_ASSERT(proster->Identify(&mallbaddo1, NULL, &ti) == B_NO_TRANSLATOR);
291
292	NextSubTest();
293	fheader.magic = 'MB';
294	fheader.fileSize = 1028;
295	fheader.reserved = 0;
296	fheader.dataOffset = 25; // bad value, for OS/2 format, needs to be at least 26
297	OS2InfoHeader os2header;
298	os2header.size = 12;
299	os2header.width = 5;
300	os2header.height = 5;
301	os2header.planes = 1;
302	os2header.bitsperpixel = 24;
303	BMallocIO mallbaddo2;
304	CPPUNIT_ASSERT(mallbaddo2.Write(&fheader.magic, 2) == 2);
305	CPPUNIT_ASSERT(mallbaddo2.Write(&fheader.fileSize, 4) == 4);
306	CPPUNIT_ASSERT(mallbaddo2.Write(&fheader.reserved, 4) == 4);
307	CPPUNIT_ASSERT(mallbaddo2.Write(&fheader.dataOffset, 4) == 4);
308	CPPUNIT_ASSERT(mallbaddo2.Write(&os2header, 12) == 12);
309	CPPUNIT_ASSERT(proster->Identify(&mallbaddo2, NULL, &ti) == B_NO_TRANSLATOR);
310
311	NextSubTest();
312	fheader.magic = 'MB';
313	fheader.fileSize = 1028;
314	fheader.reserved = 0;
315	fheader.dataOffset = 1029; // bad value, larger than the fileSize
316		// Ignore the fileSize: if it is the case that the actual file size is
317		// less than the dataOffset field, the translation will error out appropriately.
318		// Assume the fileSize has nothing to do with the actual size of the file
319	os2header.size = 12;
320	os2header.width = 5;
321	os2header.height = 5;
322	os2header.planes = 1;
323	os2header.bitsperpixel = 24;
324	BMallocIO mallbaddo3;
325	CPPUNIT_ASSERT(mallbaddo3.Write(&fheader.magic, 2) == 2);
326	CPPUNIT_ASSERT(mallbaddo3.Write(&fheader.fileSize, 4) == 4);
327	CPPUNIT_ASSERT(mallbaddo3.Write(&fheader.reserved, 4) == 4);
328	CPPUNIT_ASSERT(mallbaddo3.Write(&fheader.dataOffset, 4) == 4);
329	CPPUNIT_ASSERT(mallbaddo3.Write(&os2header, 12) == 12);
330	CPPUNIT_ASSERT(proster->Identify(&mallbaddo3, NULL, &ti) == B_OK);
331
332	NextSubTest();
333	fheader.magic = 'MB';
334	fheader.fileSize = 1028;
335	fheader.reserved = 0;
336	fheader.dataOffset = 26;
337	os2header.size = 12;
338	os2header.width = 5;
339	os2header.height = 5;
340	os2header.planes = 1;
341	os2header.bitsperpixel = 24;
342	BMallocIO mallos2abrev;
343	CPPUNIT_ASSERT(mallos2abrev.Write(&fheader.magic, 2) == 2);
344	CPPUNIT_ASSERT(mallos2abrev.Write(&fheader.fileSize, 4) == 4);
345	CPPUNIT_ASSERT(mallos2abrev.Write(&fheader.reserved, 4) == 4);
346	CPPUNIT_ASSERT(mallos2abrev.Write(&fheader.dataOffset, 4) == 4);
347	CPPUNIT_ASSERT(mallos2abrev.Write(&os2header, 1) == 1); // only 1 byte of the os2 header included
348	CPPUNIT_ASSERT(proster->Identify(&mallos2abrev, NULL, &ti) == B_NO_TRANSLATOR);
349
350	NextSubTest();
351	fheader.magic = 'MB';
352	fheader.fileSize = 1028;
353	fheader.reserved = 0;
354	fheader.dataOffset = 26;
355	os2header.size = 12;
356	os2header.width = 5;
357	os2header.height = 5;
358	os2header.planes = 1;
359	os2header.bitsperpixel = 24;
360	BMallocIO mallos2abrev2;
361	CPPUNIT_ASSERT(mallos2abrev2.Write(&fheader.magic, 2) == 2);
362	CPPUNIT_ASSERT(mallos2abrev2.Write(&fheader.fileSize, 4) == 4);
363	CPPUNIT_ASSERT(mallos2abrev2.Write(&fheader.reserved, 4) == 4);
364	CPPUNIT_ASSERT(mallos2abrev2.Write(&fheader.dataOffset, 4) == 4);
365	CPPUNIT_ASSERT(mallos2abrev2.Write(&os2header, 5) == 5); // most of the os2 header missing
366	CPPUNIT_ASSERT(proster->Identify(&mallos2abrev2, NULL, &ti) == B_NO_TRANSLATOR);
367
368	NextSubTest();
369	fheader.magic = 'MB';
370	fheader.fileSize = 1028;
371	fheader.reserved = 0;
372	fheader.dataOffset = 54;
373	msheader.size = 40;
374	msheader.width = 5;
375	msheader.height = 5;
376	msheader.planes = 1;
377	msheader.bitsperpixel = 24;
378	msheader.compression = BMP_NO_COMPRESS;
379	msheader.imagesize = 0;
380	msheader.xpixperm = 23275;
381	msheader.ypixperm = 23275;
382	msheader.colorsused = 0;
383	msheader.colorsimportant = 0;
384	BMallocIO mallmsabrev1;
385	CPPUNIT_ASSERT(mallmsabrev1.Write(&fheader.magic, 2) == 2);
386	CPPUNIT_ASSERT(mallmsabrev1.Write(&fheader.fileSize, 4) == 4);
387	CPPUNIT_ASSERT(mallmsabrev1.Write(&fheader.reserved, 4) == 4);
388	CPPUNIT_ASSERT(mallmsabrev1.Write(&fheader.dataOffset, 4) == 4);
389	CPPUNIT_ASSERT(mallmsabrev1.Write(&msheader, 1) == 1); // only 1 byte of ms header written
390	CPPUNIT_ASSERT(proster->Identify(&mallmsabrev1, NULL, &ti) == B_NO_TRANSLATOR);
391
392	NextSubTest();
393	fheader.magic = 'MB';
394	fheader.fileSize = 1028;
395	fheader.reserved = 0;
396	fheader.dataOffset = 54;
397	msheader.size = 40;
398	msheader.width = 5;
399	msheader.height = 5;
400	msheader.planes = 1;
401	msheader.bitsperpixel = 24;
402	msheader.compression = BMP_NO_COMPRESS;
403	msheader.imagesize = 0;
404	msheader.xpixperm = 23275;
405	msheader.ypixperm = 23275;
406	msheader.colorsused = 0;
407	msheader.colorsimportant = 0;
408	BMallocIO mallmsabrev2;
409	CPPUNIT_ASSERT(mallmsabrev2.Write(&fheader.magic, 2) == 2);
410	CPPUNIT_ASSERT(mallmsabrev2.Write(&fheader.fileSize, 4) == 4);
411	CPPUNIT_ASSERT(mallmsabrev2.Write(&fheader.reserved, 4) == 4);
412	CPPUNIT_ASSERT(mallmsabrev2.Write(&fheader.dataOffset, 4) == 4);
413	CPPUNIT_ASSERT(mallmsabrev2.Write(&msheader, 15) == 15); // less than half of ms header written
414	CPPUNIT_ASSERT(proster->Identify(&mallmsabrev2, NULL, &ti) == B_NO_TRANSLATOR);
415
416	NextSubTest();
417	fheader.magic = 'MB';
418	fheader.fileSize = 1028;
419	fheader.reserved = 0;
420	fheader.dataOffset = 54;
421	msheader.size = 39; // size too small for MS format
422	msheader.width = 5;
423	msheader.height = 5;
424	msheader.planes = 1;
425	msheader.bitsperpixel = 24;
426	msheader.compression = BMP_NO_COMPRESS;
427	msheader.imagesize = 0;
428	msheader.xpixperm = 23275;
429	msheader.ypixperm = 23275;
430	msheader.colorsused = 0;
431	msheader.colorsimportant = 0;
432	BMallocIO mallmssize;
433	CPPUNIT_ASSERT(mallmssize.Write(&fheader.magic, 2) == 2);
434	CPPUNIT_ASSERT(mallmssize.Write(&fheader.fileSize, 4) == 4);
435	CPPUNIT_ASSERT(mallmssize.Write(&fheader.reserved, 4) == 4);
436	CPPUNIT_ASSERT(mallmssize.Write(&fheader.dataOffset, 4) == 4);
437	CPPUNIT_ASSERT(mallmssize.Write(&msheader, 40) == 40);
438	CPPUNIT_ASSERT(proster->Identify(&mallmssize, NULL, &ti) == B_NO_TRANSLATOR);
439
440	NextSubTest();
441	fheader.magic = 'MB';
442	fheader.fileSize = 1028;
443	fheader.reserved = 0;
444	fheader.dataOffset = 54;
445	msheader.size = 41; // size too large for MS format
446	msheader.width = 5;
447	msheader.height = 5;
448	msheader.planes = 1;
449	msheader.bitsperpixel = 24;
450	msheader.compression = BMP_NO_COMPRESS;
451	msheader.imagesize = 0;
452	msheader.xpixperm = 23275;
453	msheader.ypixperm = 23275;
454	msheader.colorsused = 0;
455	msheader.colorsimportant = 0;
456	BMallocIO mallmssize2;
457	CPPUNIT_ASSERT(mallmssize2.Write(&fheader.magic, 2) == 2);
458	CPPUNIT_ASSERT(mallmssize2.Write(&fheader.fileSize, 4) == 4);
459	CPPUNIT_ASSERT(mallmssize2.Write(&fheader.reserved, 4) == 4);
460	CPPUNIT_ASSERT(mallmssize2.Write(&fheader.dataOffset, 4) == 4);
461	CPPUNIT_ASSERT(mallmssize2.Write(&msheader, 40) == 40);
462	CPPUNIT_ASSERT(proster->Identify(&mallmssize2, NULL, &ti) == B_NO_TRANSLATOR);
463
464	NextSubTest();
465	fheader.magic = 'MB';
466	fheader.fileSize = 1028;
467	fheader.reserved = 0;
468	fheader.dataOffset = 26;
469	os2header.size = 11; // os2 header size should be 12
470	os2header.width = 5;
471	os2header.height = 5;
472	os2header.planes = 1;
473	os2header.bitsperpixel = 24;
474	BMallocIO mallos2size;
475	CPPUNIT_ASSERT(mallos2size.Write(&fheader.magic, 2) == 2);
476	CPPUNIT_ASSERT(mallos2size.Write(&fheader.fileSize, 4) == 4);
477	CPPUNIT_ASSERT(mallos2size.Write(&fheader.reserved, 4) == 4);
478	CPPUNIT_ASSERT(mallos2size.Write(&fheader.dataOffset, 4) == 4);
479	CPPUNIT_ASSERT(mallos2size.Write(&os2header, 12) == 12);
480	CPPUNIT_ASSERT(proster->Identify(&mallos2size, NULL, &ti) == B_NO_TRANSLATOR);
481
482	NextSubTest();
483	fheader.magic = 'MB';
484	fheader.fileSize = 1028;
485	fheader.reserved = 0;
486	fheader.dataOffset = 26;
487	os2header.size = 13; // os2 header size should be 12
488	os2header.width = 5;
489	os2header.height = 5;
490	os2header.planes = 1;
491	os2header.bitsperpixel = 24;
492	BMallocIO mallos2size2;
493	CPPUNIT_ASSERT(mallos2size2.Write(&fheader.magic, 2) == 2);
494	CPPUNIT_ASSERT(mallos2size2.Write(&fheader.fileSize, 4) == 4);
495	CPPUNIT_ASSERT(mallos2size2.Write(&fheader.reserved, 4) == 4);
496	CPPUNIT_ASSERT(mallos2size2.Write(&fheader.dataOffset, 4) == 4);
497	CPPUNIT_ASSERT(mallos2size2.Write(&os2header, 12) == 12);
498	CPPUNIT_ASSERT(proster->Identify(&mallos2size2, NULL, &ti) == B_NO_TRANSLATOR);
499
500	NextSubTest();
501	fheader.magic = 'MB';
502	fheader.fileSize = 1028;
503	fheader.reserved = 0;
504	fheader.dataOffset = 54;
505	msheader.size = 40;
506	msheader.width = 0; // width of zero is ridiculous
507	msheader.height = 5;
508	msheader.planes = 1;
509	msheader.bitsperpixel = 24;
510	msheader.compression = BMP_NO_COMPRESS;
511	msheader.imagesize = 0;
512	msheader.xpixperm = 23275;
513	msheader.ypixperm = 23275;
514	msheader.colorsused = 0;
515	msheader.colorsimportant = 0;
516	BMallocIO mallmswidth;
517	CPPUNIT_ASSERT(mallmswidth.Write(&fheader.magic, 2) == 2);
518	CPPUNIT_ASSERT(mallmswidth.Write(&fheader.fileSize, 4) == 4);
519	CPPUNIT_ASSERT(mallmswidth.Write(&fheader.reserved, 4) == 4);
520	CPPUNIT_ASSERT(mallmswidth.Write(&fheader.dataOffset, 4) == 4);
521	CPPUNIT_ASSERT(mallmswidth.Write(&msheader, 40) == 40);
522	CPPUNIT_ASSERT(proster->Identify(&mallmswidth, NULL, &ti) == B_NO_TRANSLATOR);
523
524	NextSubTest();
525	fheader.magic = 'MB';
526	fheader.fileSize = 1028;
527	fheader.reserved = 0;
528	fheader.dataOffset = 26;
529	os2header.size = 12;
530	os2header.width = 0; // width of zero is ridiculous
531	os2header.height = 5;
532	os2header.planes = 1;
533	os2header.bitsperpixel = 24;
534	BMallocIO mallos2width;
535	CPPUNIT_ASSERT(mallos2width.Write(&fheader.magic, 2) == 2);
536	CPPUNIT_ASSERT(mallos2width.Write(&fheader.fileSize, 4) == 4);
537	CPPUNIT_ASSERT(mallos2width.Write(&fheader.reserved, 4) == 4);
538	CPPUNIT_ASSERT(mallos2width.Write(&fheader.dataOffset, 4) == 4);
539	CPPUNIT_ASSERT(mallos2width.Write(&os2header, 12) == 12);
540	CPPUNIT_ASSERT(proster->Identify(&mallos2width, NULL, &ti) == B_NO_TRANSLATOR);
541
542	NextSubTest();
543	fheader.magic = 'MB';
544	fheader.fileSize = 1028;
545	fheader.reserved = 0;
546	fheader.dataOffset = 54;
547	msheader.size = 40;
548	msheader.width = 5;
549	msheader.height = 0; // zero is not a good value
550	msheader.planes = 1;
551	msheader.bitsperpixel = 24;
552	msheader.compression = BMP_NO_COMPRESS;
553	msheader.imagesize = 0;
554	msheader.xpixperm = 23275;
555	msheader.ypixperm = 23275;
556	msheader.colorsused = 0;
557	msheader.colorsimportant = 0;
558	BMallocIO mallmsheight;
559	CPPUNIT_ASSERT(mallmsheight.Write(&fheader.magic, 2) == 2);
560	CPPUNIT_ASSERT(mallmsheight.Write(&fheader.fileSize, 4) == 4);
561	CPPUNIT_ASSERT(mallmsheight.Write(&fheader.reserved, 4) == 4);
562	CPPUNIT_ASSERT(mallmsheight.Write(&fheader.dataOffset, 4) == 4);
563	CPPUNIT_ASSERT(mallmsheight.Write(&msheader, 40) == 40);
564	CPPUNIT_ASSERT(proster->Identify(&mallmsheight, NULL, &ti) == B_NO_TRANSLATOR);
565
566	NextSubTest();
567	fheader.magic = 'MB';
568	fheader.fileSize = 1028;
569	fheader.reserved = 0;
570	fheader.dataOffset = 26;
571	os2header.size = 12;
572	os2header.width = 5;
573	os2header.height = 0; // bad value
574	os2header.planes = 1;
575	os2header.bitsperpixel = 24;
576	BMallocIO mallos2height;
577	CPPUNIT_ASSERT(mallos2height.Write(&fheader.magic, 2) == 2);
578	CPPUNIT_ASSERT(mallos2height.Write(&fheader.fileSize, 4) == 4);
579	CPPUNIT_ASSERT(mallos2height.Write(&fheader.reserved, 4) == 4);
580	CPPUNIT_ASSERT(mallos2height.Write(&fheader.dataOffset, 4) == 4);
581	CPPUNIT_ASSERT(mallos2height.Write(&os2header, 12) == 12);
582	CPPUNIT_ASSERT(proster->Identify(&mallos2height, NULL, &ti) == B_NO_TRANSLATOR);
583
584	NextSubTest();
585	fheader.magic = 'MB';
586	fheader.fileSize = 1028;
587	fheader.reserved = 0;
588	fheader.dataOffset = 54;
589	msheader.size = 40;
590	msheader.width = 5;
591	msheader.height = 5;
592	msheader.planes = 0; // should always be 1
593	msheader.bitsperpixel = 24;
594	msheader.compression = BMP_NO_COMPRESS;
595	msheader.imagesize = 0;
596	msheader.xpixperm = 23275;
597	msheader.ypixperm = 23275;
598	msheader.colorsused = 0;
599	msheader.colorsimportant = 0;
600	BMallocIO mallmsplanes;
601	CPPUNIT_ASSERT(mallmsplanes.Write(&fheader.magic, 2) == 2);
602	CPPUNIT_ASSERT(mallmsplanes.Write(&fheader.fileSize, 4) == 4);
603	CPPUNIT_ASSERT(mallmsplanes.Write(&fheader.reserved, 4) == 4);
604	CPPUNIT_ASSERT(mallmsplanes.Write(&fheader.dataOffset, 4) == 4);
605	CPPUNIT_ASSERT(mallmsplanes.Write(&msheader, 40) == 40);
606	CPPUNIT_ASSERT(proster->Identify(&mallmsplanes, NULL, &ti) == B_NO_TRANSLATOR);
607
608	NextSubTest();
609	fheader.magic = 'MB';
610	fheader.fileSize = 1028;
611	fheader.reserved = 0;
612	fheader.dataOffset = 54;
613	msheader.size = 40;
614	msheader.width = 5;
615	msheader.height = 5;
616	msheader.planes = 2; // should always be 1
617	msheader.bitsperpixel = 24;
618	msheader.compression = BMP_NO_COMPRESS;
619	msheader.imagesize = 0;
620	msheader.xpixperm = 23275;
621	msheader.ypixperm = 23275;
622	msheader.colorsused = 0;
623	msheader.colorsimportant = 0;
624	BMallocIO mallmsplanes2;
625	CPPUNIT_ASSERT(mallmsplanes2.Write(&fheader.magic, 2) == 2);
626	CPPUNIT_ASSERT(mallmsplanes2.Write(&fheader.fileSize, 4) == 4);
627	CPPUNIT_ASSERT(mallmsplanes2.Write(&fheader.reserved, 4) == 4);
628	CPPUNIT_ASSERT(mallmsplanes2.Write(&fheader.dataOffset, 4) == 4);
629	CPPUNIT_ASSERT(mallmsplanes2.Write(&msheader, 40) == 40);
630	CPPUNIT_ASSERT(proster->Identify(&mallmsplanes2, NULL, &ti) == B_NO_TRANSLATOR);
631
632	NextSubTest();
633	fheader.magic = 'MB';
634	fheader.fileSize = 1028;
635	fheader.reserved = 0;
636	fheader.dataOffset = 26;
637	os2header.size = 12;
638	os2header.width = 5;
639	os2header.height = 5;
640	os2header.planes = 0; // should always be 1
641	os2header.bitsperpixel = 24;
642	BMallocIO mallos2planes;
643	CPPUNIT_ASSERT(mallos2planes.Write(&fheader.magic, 2) == 2);
644	CPPUNIT_ASSERT(mallos2planes.Write(&fheader.fileSize, 4) == 4);
645	CPPUNIT_ASSERT(mallos2planes.Write(&fheader.reserved, 4) == 4);
646	CPPUNIT_ASSERT(mallos2planes.Write(&fheader.dataOffset, 4) == 4);
647	CPPUNIT_ASSERT(mallos2planes.Write(&os2header, 12) == 12);
648	CPPUNIT_ASSERT(proster->Identify(&mallos2planes, NULL, &ti) == B_NO_TRANSLATOR);
649
650	NextSubTest();
651	fheader.magic = 'MB';
652	fheader.fileSize = 1028;
653	fheader.reserved = 0;
654	fheader.dataOffset = 26;
655	os2header.size = 12;
656	os2header.width = 5;
657	os2header.height = 5;
658	os2header.planes = 2; // should always be 1
659	os2header.bitsperpixel = 24;
660	BMallocIO mallos2planes2;
661	CPPUNIT_ASSERT(mallos2planes2.Write(&fheader.magic, 2) == 2);
662	CPPUNIT_ASSERT(mallos2planes2.Write(&fheader.fileSize, 4) == 4);
663	CPPUNIT_ASSERT(mallos2planes2.Write(&fheader.reserved, 4) == 4);
664	CPPUNIT_ASSERT(mallos2planes2.Write(&fheader.dataOffset, 4) == 4);
665	CPPUNIT_ASSERT(mallos2planes2.Write(&os2header, 12) == 12);
666	CPPUNIT_ASSERT(proster->Identify(&mallos2planes2, NULL, &ti) == B_NO_TRANSLATOR);
667
668	// makes sure invalid bit depths aren't recognized
669	const uint16 bitdepths[] = { 0, 2, 3, 5, 6, 7, 9, 23, 25, 31, 33 };
670	const int32 knbitdepths = sizeof(bitdepths) / sizeof(uint16);
671	for (int32 i = 0; i < knbitdepths; i++) {
672		NextSubTest();
673		fheader.magic = 'MB';
674		fheader.fileSize = 1028;
675		fheader.reserved = 0;
676		fheader.dataOffset = 54;
677		msheader.size = 40;
678		msheader.width = 5;
679		msheader.height = 5;
680		msheader.planes = 1;
681		msheader.bitsperpixel = bitdepths[i];
682		msheader.compression = BMP_NO_COMPRESS;
683		msheader.imagesize = 0;
684		msheader.xpixperm = 23275;
685		msheader.ypixperm = 23275;
686		msheader.colorsused = 0;
687		msheader.colorsimportant = 0;
688		BMallocIO mallmsbitdepth;
689		mallmsbitdepth.Seek(0, SEEK_SET);
690		CPPUNIT_ASSERT(mallmsbitdepth.Write(&fheader.magic, 2) == 2);
691		CPPUNIT_ASSERT(mallmsbitdepth.Write(&fheader.fileSize, 4) == 4);
692		CPPUNIT_ASSERT(mallmsbitdepth.Write(&fheader.reserved, 4) == 4);
693		CPPUNIT_ASSERT(mallmsbitdepth.Write(&fheader.dataOffset, 4) == 4);
694		CPPUNIT_ASSERT(mallmsbitdepth.Write(&msheader, 40) == 40);
695		CPPUNIT_ASSERT(proster->Identify(&mallmsbitdepth, NULL, &ti) == B_NO_TRANSLATOR);
696
697		NextSubTest();
698		fheader.magic = 'MB';
699		fheader.fileSize = 1028;
700		fheader.reserved = 0;
701		fheader.dataOffset = 26;
702		os2header.size = 12;
703		os2header.width = 5;
704		os2header.height = 5;
705		os2header.planes = 1;
706		os2header.bitsperpixel = bitdepths[i];
707		BMallocIO mallos2bitdepth;
708		mallos2bitdepth.Seek(0, SEEK_SET);
709		CPPUNIT_ASSERT(mallos2bitdepth.Write(&fheader.magic, 2) == 2);
710		CPPUNIT_ASSERT(mallos2bitdepth.Write(&fheader.fileSize, 4) == 4);
711		CPPUNIT_ASSERT(mallos2bitdepth.Write(&fheader.reserved, 4) == 4);
712		CPPUNIT_ASSERT(mallos2bitdepth.Write(&fheader.dataOffset, 4) == 4);
713		CPPUNIT_ASSERT(mallos2bitdepth.Write(&os2header, 12) == 12);
714		CPPUNIT_ASSERT(proster->Identify(&mallos2bitdepth, NULL, &ti) == B_NO_TRANSLATOR);
715	}
716
717	// makes sure invalid compression values aren't recognized
718	const uint16 cbitdepths[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 23, 24, 25, 31, 32, 33 };
719	const uint32 compvalues[] = { BMP_RLE4_COMPRESS, BMP_RLE8_COMPRESS, 3, 4, 5, 10 };
720	const int32 kncdepths = sizeof(cbitdepths) / sizeof(uint16);
721	const int32 kncomps = sizeof(compvalues) / sizeof(uint32);
722	for (int32 i = 0; i < kncomps; i++)
723		for (int32 n = 0; n < kncdepths; n++) {
724			if (!(compvalues[i] == BMP_RLE4_COMPRESS && cbitdepths[n] == 4) &&
725				!(compvalues[i] == BMP_RLE8_COMPRESS && cbitdepths[n] == 8)) {
726				NextSubTest();
727				fheader.magic = 'MB';
728				fheader.fileSize = 1028;
729				fheader.reserved = 0;
730				fheader.dataOffset = 54;
731				msheader.size = 40;
732				msheader.width = 5;
733				msheader.height = 5;
734				msheader.planes = 1;
735				msheader.bitsperpixel = cbitdepths[n];
736				msheader.compression = compvalues[i];
737				msheader.imagesize = 0;
738				msheader.xpixperm = 23275;
739				msheader.ypixperm = 23275;
740				msheader.colorsused = 0;
741				msheader.colorsimportant = 0;
742				BMallocIO mallmscomp;
743				mallmscomp.Seek(0, SEEK_SET);
744				CPPUNIT_ASSERT(mallmscomp.Write(&fheader.magic, 2) == 2);
745				CPPUNIT_ASSERT(mallmscomp.Write(&fheader.fileSize, 4) == 4);
746				CPPUNIT_ASSERT(mallmscomp.Write(&fheader.reserved, 4) == 4);
747				CPPUNIT_ASSERT(mallmscomp.Write(&fheader.dataOffset, 4) == 4);
748				CPPUNIT_ASSERT(mallmscomp.Write(&msheader, 40) == 40);
749				CPPUNIT_ASSERT(proster->Identify(&mallmscomp, NULL, &ti)
750					== B_NO_TRANSLATOR);
751			}
752		}
753
754	// too many colorsused test!
755	const uint16 colordepths[] = { 1, 4, 8, 24, 32 };
756	const int32 kncolordepths = sizeof(colordepths) / sizeof(uint16);
757	for (int32 i = 0; i < kncolordepths; i++) {
758		NextSubTest();
759		fheader.magic = 'BM';
760		fheader.fileSize = 1028;
761		fheader.reserved = 0;
762		fheader.dataOffset = 54;
763		msheader.size = 40;
764		msheader.width = 5;
765		msheader.height = 5;
766		msheader.planes = 1;
767		msheader.bitsperpixel = colordepths[i];
768		msheader.compression = BMP_NO_COMPRESS;
769		msheader.imagesize = 0;
770		msheader.xpixperm = 23275;
771		msheader.ypixperm = 23275;
772		msheader.colorsused = 0; //(1 << colordepths[i])/* + 1*/;
773		msheader.colorsimportant = 0; //(1 << colordepths[i])/* + 1*/;
774		BMallocIO mallmscolors;
775		mallmscolors.Seek(0, SEEK_SET);
776		CPPUNIT_ASSERT(mallmscolors.Write(&fheader.magic, 2) == 2);
777		CPPUNIT_ASSERT(mallmscolors.Write(&fheader.fileSize, 4) == 4);
778		CPPUNIT_ASSERT(mallmscolors.Write(&fheader.reserved, 4) == 4);
779		CPPUNIT_ASSERT(mallmscolors.Write(&fheader.dataOffset, 4) == 4);
780		CPPUNIT_ASSERT(mallmscolors.Write(&msheader, 40) == 40);
781		CPPUNIT_ASSERT(proster->Identify(&mallmscolors, NULL, &ti) == B_NO_TRANSLATOR);
782	}
783
784	// Identify (successfully identify the following files)
785	const IdentifyInfo aBitsPaths[] = {
786		{ "/boot/home/resources/bmp/b_cmap8.bits", "" },
787		{ "/boot/home/resources/bmp/b_gray1-2.bits", "" },
788		{ "/boot/home/resources/bmp/b_gray1.bits", "" },
789		{ "/boot/home/resources/bmp/b_rgb15.bits", "" },
790		{ "/boot/home/resources/bmp/b_rgb16.bits", "" },
791		{ "/boot/home/resources/bmp/b_rgb32.bits", "" },
792		{ "/boot/home/resources/bmp/blocks.bits", "" },
793		{ "/boot/home/resources/bmp/gnome_beer.bits", "" },
794		{ "/boot/home/resources/bmp/vsmall.bits", "" }
795	};
796	const IdentifyInfo aBmpPaths[] = {
797		{ "/boot/home/resources/bmp/blocks_24bit.bmp",
798			"BMP image (MS format, 24 bits)" },
799		{ "/boot/home/resources/bmp/blocks_4bit_rle.bmp",
800			"BMP image (MS format, 4 bits, RLE)" },
801		{ "/boot/home/resources/bmp/blocks_8bit_rle.bmp",
802			"BMP image (MS format, 8 bits, RLE)" },
803		{ "/boot/home/resources/bmp/color_scribbles_1bit.bmp",
804			"BMP image (MS format, 1 bits)" },
805		{ "/boot/home/resources/bmp/color_scribbles_1bit_os2.bmp",
806			"BMP image (OS/2 format, 1 bits)" },
807		{ "/boot/home/resources/bmp/color_scribbles_24bit.bmp",
808			"BMP image (MS format, 24 bits)" },
809		{ "/boot/home/resources/bmp/color_scribbles_24bit_os2.bmp",
810			"BMP image (OS/2 format, 24 bits)" },
811		{ "/boot/home/resources/bmp/color_scribbles_4bit.bmp",
812			"BMP image (MS format, 4 bits)" },
813		{ "/boot/home/resources/bmp/color_scribbles_4bit_os2.bmp",
814			"BMP image (OS/2 format, 4 bits)" },
815		{ "/boot/home/resources/bmp/color_scribbles_4bit_rle.bmp",
816			"BMP image (MS format, 4 bits, RLE)" },
817		{ "/boot/home/resources/bmp/color_scribbles_8bit.bmp",
818			"BMP image (MS format, 8 bits)" },
819		{ "/boot/home/resources/bmp/color_scribbles_8bit_os2.bmp",
820			"BMP image (OS/2 format, 8 bits)" },
821		{ "/boot/home/resources/bmp/color_scribbles_8bit_rle.bmp",
822			"BMP image (MS format, 8 bits, RLE)" },
823		{ "/boot/home/resources/bmp/gnome_beer_24bit.bmp",
824			"BMP image (MS format, 24 bits)" },
825		{ "/boot/home/resources/bmp/vsmall_1bit.bmp",
826			"BMP image (MS format, 1 bits)" },
827		{ "/boot/home/resources/bmp/vsmall_1bit_os2.bmp",
828			"BMP image (OS/2 format, 1 bits)" },
829		{ "/boot/home/resources/bmp/vsmall_24bit.bmp",
830			"BMP image (MS format, 24 bits)" },
831		{ "/boot/home/resources/bmp/vsmall_24bit_os2.bmp",
832			"BMP image (OS/2 format, 24 bits)" },
833		{ "/boot/home/resources/bmp/vsmall_4bit.bmp",
834			"BMP image (MS format, 4 bits)" },
835		{ "/boot/home/resources/bmp/vsmall_4bit_os2.bmp",
836			"BMP image (OS/2 format, 4 bits)" },
837		{ "/boot/home/resources/bmp/vsmall_4bit_rle.bmp",
838			"BMP image (MS format, 4 bits, RLE)" },
839		{ "/boot/home/resources/bmp/vsmall_8bit.bmp",
840			"BMP image (MS format, 8 bits)" },
841		{ "/boot/home/resources/bmp/vsmall_8bit_os2.bmp",
842			"BMP image (OS/2 format, 8 bits)" },
843		{ "/boot/home/resources/bmp/vsmall_8bit_rle.bmp",
844			"BMP image (MS format, 8 bits, RLE)" },
845		{ "/boot/home/resources/bmp/b_rgb32(32).bmp",
846			"BMP image (MS format, 32 bits)" },
847		{ "/boot/home/resources/bmp/double_click_bmap.bmp",
848			"BMP image (MS format, 24 bits)" }
849	};
850
851	IdentifyTests(this, proster, aBmpPaths,
852		sizeof(aBmpPaths) / sizeof(IdentifyInfo), false);
853	IdentifyTests(this, proster, aBitsPaths,
854		sizeof(aBitsPaths) / sizeof(IdentifyInfo), true);
855
856	delete proster;
857	proster = NULL;
858}
859
860// coveniently group path of bmp image with
861// path of bits image that it should translate to
862struct TranslatePaths {
863	const char *bmpPath;
864	const char *bitsPath;
865};
866
867void
868TranslateTests(BMPTranslatorTest *ptest, BTranslatorRoster *proster,
869	const TranslatePaths *paths, int32 len, bool bbmpinput)
870{
871	// Perform translations on every file in the array
872	for (int32 i = 0; i < len; i++) {
873		// Setup input files
874		ptest->NextSubTest();
875		BFile bmpfile, bitsfile, *pinput;
876		CPPUNIT_ASSERT(bmpfile.SetTo(paths[i].bmpPath, B_READ_ONLY) == B_OK);
877		CPPUNIT_ASSERT(bitsfile.SetTo(paths[i].bitsPath, B_READ_ONLY) == B_OK);
878		if (bbmpinput) {
879			printf(" [%s] ", paths[i].bmpPath);
880			pinput = &bmpfile;
881		} else {
882			printf(" [%s] ", paths[i].bitsPath);
883			pinput = &bitsfile;
884		}
885
886		BMallocIO mallio, dmallio;
887
888		// Convert to B_TRANSLATOR_ANY_TYPE (should be B_TRANSLATOR_BITMAP)
889		ptest->NextSubTest();
890		CPPUNIT_ASSERT(mallio.Seek(0, SEEK_SET) == 0);
891		CPPUNIT_ASSERT(mallio.SetSize(0) == B_OK);
892		CPPUNIT_ASSERT(proster->Translate(pinput, NULL, NULL, &mallio,
893			B_TRANSLATOR_ANY_TYPE) == B_OK);
894		CPPUNIT_ASSERT(CompareStreams(mallio, bitsfile) == true);
895
896		// Convert to B_TRANSLATOR_BITMAP
897		ptest->NextSubTest();
898		CPPUNIT_ASSERT(mallio.Seek(0, SEEK_SET) == 0);
899		CPPUNIT_ASSERT(mallio.SetSize(0) == B_OK);
900		CPPUNIT_ASSERT(proster->Translate(pinput, NULL, NULL, &mallio,
901			B_TRANSLATOR_BITMAP) == B_OK);
902		CPPUNIT_ASSERT(CompareStreams(mallio, bitsfile) == true);
903
904		// Convert bits mallio to B_TRANSLATOR_BITMAP dmallio
905		ptest->NextSubTest();
906		CPPUNIT_ASSERT(dmallio.Seek(0, SEEK_SET) == 0);
907		CPPUNIT_ASSERT(dmallio.SetSize(0) == B_OK);
908		CPPUNIT_ASSERT(proster->Translate(&mallio, NULL, NULL, &dmallio,
909			B_TRANSLATOR_BITMAP) == B_OK);
910		CPPUNIT_ASSERT(CompareStreams(dmallio, bitsfile) == true);
911
912		// Only perform the following tests if the BMP is not
913		// an OS/2 format BMP image.
914		// (Need to write special testing for OS/2 images)
915		if (!strstr(paths[i].bmpPath, "os2")) {
916			// Convert to B_BMP_FORMAT
917			ptest->NextSubTest();
918			CPPUNIT_ASSERT(mallio.Seek(0, SEEK_SET) == 0);
919			CPPUNIT_ASSERT(mallio.SetSize(0) == B_OK);
920			CPPUNIT_ASSERT(proster->Translate(pinput, NULL, NULL, &mallio,
921				B_BMP_FORMAT) == B_OK);
922			CPPUNIT_ASSERT(CompareStreams(mallio, bmpfile) == true);
923
924			// Convert BMP mallio to B_TRANSLATOR_BITMAP dmallio
925			if (bbmpinput) {
926				ptest->NextSubTest();
927				CPPUNIT_ASSERT(dmallio.Seek(0, SEEK_SET) == 0);
928				CPPUNIT_ASSERT(dmallio.SetSize(0) == B_OK);
929				CPPUNIT_ASSERT(proster->Translate(&mallio, NULL, NULL, &dmallio,
930					B_TRANSLATOR_BITMAP) == B_OK);
931				CPPUNIT_ASSERT(CompareStreams(dmallio, bitsfile) == true);
932			}
933
934			// Convert BMP mallio to B_BMP_FORMAT dmallio
935			ptest->NextSubTest();
936			CPPUNIT_ASSERT(dmallio.Seek(0, SEEK_SET) == 0);
937			CPPUNIT_ASSERT(dmallio.SetSize(0) == B_OK);
938			CPPUNIT_ASSERT(proster->Translate(&mallio, NULL, NULL, &dmallio,
939				B_BMP_FORMAT) == B_OK);
940			CPPUNIT_ASSERT(CompareStreams(dmallio, bmpfile) == true);
941		}
942	}
943}
944
945void
946BMPTranslatorTest::TranslateTest()
947{
948	BApplication
949		app("application/x-vnd.OpenBeOS-BMPTranslatorTest");
950
951	// Init
952	NextSubTest();
953	status_t result = B_ERROR;
954	off_t filesize = -1;
955	BTranslatorRoster *proster = new BTranslatorRoster();
956	CPPUNIT_ASSERT(proster);
957	CPPUNIT_ASSERT(proster->AddTranslators(
958		"/boot/home/config/add-ons/Translators/BMPTranslator") == B_OK);
959	BFile wronginput("../src/tests/kits/translation/data/images/image.jpg",
960		B_READ_ONLY);
961	CPPUNIT_ASSERT(wronginput.InitCheck() == B_OK);
962	BFile output("/tmp/bmp_test.out", B_WRITE_ONLY |
963		B_CREATE_FILE | B_ERASE_FILE);
964	CPPUNIT_ASSERT(output.InitCheck() == B_OK);
965
966	// Translate (bad input, output types)
967	NextSubTest();
968	result = proster->Translate(&wronginput, NULL, NULL, &output,
969		B_TRANSLATOR_TEXT);
970	CPPUNIT_ASSERT(result == B_NO_TRANSLATOR);
971	CPPUNIT_ASSERT(output.GetSize(&filesize) == B_OK);
972	CPPUNIT_ASSERT(filesize == 0);
973
974	// Translate (wrong type of input data)
975	NextSubTest();
976	result = proster->Translate(&wronginput, NULL, NULL, &output,
977		B_BMP_FORMAT);
978	CPPUNIT_ASSERT(result == B_NO_TRANSLATOR);
979	CPPUNIT_ASSERT(output.GetSize(&filesize) == B_OK);
980	CPPUNIT_ASSERT(filesize == 0);
981
982	// Translate (wrong type of input, B_TRANSLATOR_ANY_TYPE output)
983	NextSubTest();
984	result = proster->Translate(&wronginput, NULL, NULL, &output,
985		B_TRANSLATOR_ANY_TYPE);
986	CPPUNIT_ASSERT(result == B_NO_TRANSLATOR);
987	CPPUNIT_ASSERT(output.GetSize(&filesize) == B_OK);
988	CPPUNIT_ASSERT(filesize == 0);
989
990	// For translating BMP images to bits
991	const TranslatePaths aBmpInput[] = {
992		{ "/boot/home/resources/bmp/blocks_24bit.bmp",
993			"/boot/home/resources/bmp/blocks.bits" },
994		{ "/boot/home/resources/bmp/blocks_4bit_rle.bmp",
995			"/boot/home/resources/bmp/blocks.bits" },
996		{ "/boot/home/resources/bmp/blocks_8bit_rle.bmp",
997			"/boot/home/resources/bmp/blocks.bits" },
998		{ "/boot/home/resources/bmp/color_scribbles_1bit.bmp",
999			"/boot/home/resources/bmp/color_scribbles_1bit.bits" },
1000		{ "/boot/home/resources/bmp/color_scribbles_1bit_os2.bmp",
1001			"/boot/home/resources/bmp/color_scribbles_1bit.bits" },
1002		{ "/boot/home/resources/bmp/color_scribbles_24bit.bmp",
1003			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1004		{ "/boot/home/resources/bmp/color_scribbles_24bit_os2.bmp",
1005			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1006		{ "/boot/home/resources/bmp/color_scribbles_4bit.bmp",
1007			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1008		{ "/boot/home/resources/bmp/color_scribbles_4bit_os2.bmp",
1009			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1010		{ "/boot/home/resources/bmp/color_scribbles_4bit_rle.bmp",
1011			"/boot/home/resources/bmp/color_scribbles_4bit_rle.bits" },
1012		{ "/boot/home/resources/bmp/color_scribbles_8bit.bmp",
1013			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1014		{ "/boot/home/resources/bmp/color_scribbles_8bit_os2.bmp",
1015			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1016		{ "/boot/home/resources/bmp/color_scribbles_8bit_rle.bmp",
1017			"/boot/home/resources/bmp/color_scribbles_24bit.bits" },
1018		{ "/boot/home/resources/bmp/gnome_beer_24bit.bmp",
1019			"/boot/home/resources/bmp/gnome_beer.bits" },
1020		{ "/boot/home/resources/bmp/vsmall_1bit.bmp",
1021			"/boot/home/resources/bmp/vsmall.bits" },
1022		{ "/boot/home/resources/bmp/vsmall_1bit_os2.bmp",
1023			"/boot/home/resources/bmp/vsmall.bits" },
1024		{ "/boot/home/resources/bmp/vsmall_24bit.bmp",
1025			"/boot/home/resources/bmp/vsmall.bits" },
1026		{ "/boot/home/resources/bmp/vsmall_24bit_os2.bmp",
1027			"/boot/home/resources/bmp/vsmall.bits" },
1028		{ "/boot/home/resources/bmp/vsmall_4bit.bmp",
1029			"/boot/home/resources/bmp/vsmall.bits" },
1030		{ "/boot/home/resources/bmp/vsmall_4bit_os2.bmp",
1031			"/boot/home/resources/bmp/vsmall.bits" },
1032		{ "/boot/home/resources/bmp/vsmall_4bit_rle.bmp",
1033			"/boot/home/resources/bmp/vsmall.bits" },
1034		{ "/boot/home/resources/bmp/vsmall_8bit.bmp",
1035			"/boot/home/resources/bmp/vsmall.bits" },
1036		{ "/boot/home/resources/bmp/vsmall_8bit_os2.bmp",
1037			"/boot/home/resources/bmp/vsmall.bits" },
1038		{ "/boot/home/resources/bmp/vsmall_8bit_rle.bmp",
1039			"/boot/home/resources/bmp/vsmall.bits" },
1040		{ "/boot/home/resources/bmp/b_rgb32(32).bmp",
1041			"/boot/home/resources/bmp/b_rgb32.bits" }
1042	};
1043
1044	// For translating bits images to BMP
1045	const TranslatePaths aBitsInput[] = {
1046		{ "/boot/home/resources/bmp/b_gray1-2.bmp",
1047			"/boot/home/resources/bmp/b_gray1-2.bits" },
1048		{ "/boot/home/resources/bmp/b_gray1.bmp",
1049			"/boot/home/resources/bmp/b_gray1.bits" },
1050		{ "/boot/home/resources/bmp/b_rgb15.bmp",
1051			"/boot/home/resources/bmp/b_rgb15.bits" },
1052		{ "/boot/home/resources/bmp/b_rgb16.bmp",
1053			"/boot/home/resources/bmp/b_rgb16.bits" },
1054		{ "/boot/home/resources/bmp/b_rgb32(24).bmp",
1055			"/boot/home/resources/bmp/b_rgb32.bits" },
1056		{ "/boot/home/resources/bmp/b_cmap8.bmp",
1057			"/boot/home/resources/bmp/b_cmap8.bits" }
1058	};
1059
1060	TranslateTests(this, proster, aBmpInput,
1061		sizeof(aBmpInput) / sizeof(TranslatePaths), true);
1062	TranslateTests(this, proster, aBitsInput,
1063		sizeof(aBitsInput) / sizeof(TranslatePaths), false);
1064
1065	delete proster;
1066	proster = NULL;
1067}
1068
1069// Make certain that the BMPTranslator does not
1070// provide a configuration message
1071void
1072BMPTranslatorTest::ConfigMessageTest()
1073{
1074	// Init
1075	NextSubTest();
1076	BTranslatorRoster *proster = new BTranslatorRoster();
1077	CPPUNIT_ASSERT(proster);
1078	CPPUNIT_ASSERT(proster->AddTranslators(
1079		"/boot/home/config/add-ons/Translators/BMPTranslator") == B_OK);
1080
1081	// GetAllTranslators
1082	NextSubTest();
1083	translator_id tid, *pids = NULL;
1084	int32 count = 0;
1085	CPPUNIT_ASSERT(proster->GetAllTranslators(&pids, &count) == B_OK);
1086	CPPUNIT_ASSERT(pids);
1087	CPPUNIT_ASSERT(count == 1);
1088	tid = pids[0];
1089	delete[] pids;
1090	pids = NULL;
1091
1092	// GetConfigurationMessage
1093	NextSubTest();
1094	BMessage msg;
1095	CPPUNIT_ASSERT(proster->GetConfigurationMessage(tid, &msg) == B_OK);
1096	CPPUNIT_ASSERT(!msg.IsEmpty());
1097
1098	// B_TRANSLATOR_EXT_HEADER_ONLY
1099	NextSubTest();
1100	bool bheaderonly = true;
1101	CPPUNIT_ASSERT(
1102		msg.FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly) == B_OK);
1103	CPPUNIT_ASSERT(bheaderonly == false);
1104
1105	// B_TRANSLATOR_EXT_DATA_ONLY
1106	NextSubTest();
1107	bool bdataonly = true;
1108	CPPUNIT_ASSERT(
1109		msg.FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataonly) == B_OK);
1110	CPPUNIT_ASSERT(bdataonly == false);
1111}
1112
1113#if !TEST_R5
1114
1115// The input formats that this translator is supposed to support
1116translation_format gBMPInputFormats[] = {
1117	{
1118		B_TRANSLATOR_BITMAP,
1119		B_TRANSLATOR_BITMAP,
1120		0.4f, // quality
1121		0.6f, // capability
1122		"image/x-be-bitmap",
1123		"Be Bitmap Format (BMPTranslator)"
1124	},
1125	{
1126		B_BMP_FORMAT,
1127		B_TRANSLATOR_BITMAP,
1128		0.4f,
1129		0.8f,
1130		"image/x-bmp",
1131		"BMP image"
1132	}
1133};
1134
1135// The output formats that this translator is supposed to support
1136translation_format gBMPOutputFormats[] = {
1137	{
1138		B_TRANSLATOR_BITMAP,
1139		B_TRANSLATOR_BITMAP,
1140		0.4f, // quality
1141		0.6f, // capability
1142		"image/x-be-bitmap",
1143		"Be Bitmap Format (BMPTranslator)"
1144	},
1145	{
1146		B_BMP_FORMAT,
1147		B_TRANSLATOR_BITMAP,
1148		0.4f,
1149		0.8f,
1150		"image/x-bmp",
1151		"BMP image (MS format)"
1152	}
1153};
1154
1155void
1156BMPTranslatorTest::LoadAddOnTest()
1157{
1158	TranslatorLoadAddOnTest("/boot/home/config/add-ons/Translators/BMPTranslator",
1159		this,
1160		gBMPInputFormats, sizeof(gBMPInputFormats) / sizeof(translation_format),
1161		gBMPOutputFormats, sizeof(gBMPOutputFormats) / sizeof(translation_format),
1162		B_TRANSLATION_MAKE_VERSION(1,0,0));
1163}
1164
1165#endif // #if !TEST_R5
1166