xref: /haiku/src/tests/add-ons/translators/bmptranslator/BMPTranslatorTest.cpp (revision dfb8c585c62977839ef1b23d60b197227de81231)
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 
27 struct 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 
35 struct 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 
49 struct 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
58 CppUnit::Test *
Suite()59 BMPTranslatorTest::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
86 void
setUp()87 BMPTranslatorTest::setUp()
88 {
89 	BTestCase::setUp();
90 }
91 
92 // tearDown
93 void
tearDown()94 BMPTranslatorTest::tearDown()
95 {
96 	BTestCase::tearDown();
97 }
98 
99 void
CheckBits_Bmp(translator_info * pti)100 CheckBits_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 
107 void
CheckBmp(translator_info * pti,const char * imageType)108 CheckBmp(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
116 struct IdentifyInfo {
117 	const char *imagePath;
118 	const char *identifyString;
119 };
120 
121 void
IdentifyTests(BMPTranslatorTest * ptest,BTranslatorRoster * proster,const IdentifyInfo * pinfo,int32 len,bool bbits)122 IdentifyTests(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 
165 void
IdentifyTest()166 BMPTranslatorTest::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
862 struct TranslatePaths {
863 	const char *bmpPath;
864 	const char *bitsPath;
865 };
866 
867 void
TranslateTests(BMPTranslatorTest * ptest,BTranslatorRoster * proster,const TranslatePaths * paths,int32 len,bool bbmpinput)868 TranslateTests(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 
945 void
TranslateTest()946 BMPTranslatorTest::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
1071 void
ConfigMessageTest()1072 BMPTranslatorTest::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
1116 translation_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
1136 translation_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 
1155 void
LoadAddOnTest()1156 BMPTranslatorTest::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