xref: /haiku/src/tests/kits/translation/BitmapStreamTest.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 /*****************************************************************************/
2 // Haiku Translation Kit Test
3 // Authors: Brian Matzon <brian@matzon.dk>, Michael Wilber
4 // Version:
5 //
6 // This is the Test application for BBitmapStream
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 "BitmapStreamTest.h"
34 
35 #include <TranslatorRoster.h>
36 #include <Application.h>
37 #include <Bitmap.h>
38 
39 #include <stdio.h>
40 #include <string.h>
41 
42 /* cppunit framework */
43 #include <cppunit/Test.h>
44 #include <cppunit/TestCaller.h>
45 #include <cppunit/TestSuite.h>
46 
47 /**
48  * Default constructor - no work
49  */
50 BitmapStreamTest::BitmapStreamTest(std::string name)
51 	: BTestCase(name)
52 {
53 }
54 
55 /**
56  * Default destructor - no work
57  */
58 BitmapStreamTest::~BitmapStreamTest()
59 {
60 }
61 
62 CppUnit::Test *
63 BitmapStreamTest::Suite()
64 {
65 	/* create our suite */
66 	CppUnit::TestSuite *suite = new CppUnit::TestSuite("BitmapStream");
67 	typedef CppUnit::TestCaller<BitmapStreamTest> TC;
68 
69 	/* add tests */
70 	suite->addTest(new TC("BitmapStreamTest::Constructor Test",
71 		&BitmapStreamTest::ConstructorTest));
72 
73 	suite->addTest(new TC("BitmapStreamTest::DetachBitmap Test",
74 		&BitmapStreamTest::DetachBitmapTest));
75 
76 	suite->addTest(new TC("BitmapStreamTest::Seek Test",
77 		&BitmapStreamTest::SeekTest));
78 
79 	suite->addTest(new TC("BitmapStreamTest::SetSize Test",
80 		&BitmapStreamTest::SetSizeTest));
81 
82 	suite->addTest(new TC("BitmapStreamTest::ReadWrite Test",
83 		&BitmapStreamTest::ReadWriteTest));
84 
85 	return suite;
86 }
87 
88 /**
89  * Tests:
90  * BBitmapStream(BBitmap *map = NULL)
91  */
92 void
93 BitmapStreamTest::ConstructorTest()
94 {
95 	BApplication
96 		app("application/x-vnd.Haiku-translationkit_bitmapstreamtest");
97 
98 	//BBitmapStream with no bitmap supplied
99 	NextSubTest();
100 	BBitmapStream streamEmpty;
101 	BBitmap *pbits = NULL;
102 	CPPUNIT_ASSERT(streamEmpty.Position() == 0);
103 	CPPUNIT_ASSERT(streamEmpty.Size() == 0);
104 	CPPUNIT_ASSERT(streamEmpty.DetachBitmap(&pbits) == B_ERROR);
105 	CPPUNIT_ASSERT(pbits == NULL);
106 
107 	//BBitmapStream with an empty BBitmap
108 	NextSubTest();
109 	pbits = new BBitmap(BRect(0,0,5,5), B_RGB32);
110 	CPPUNIT_ASSERT(pbits);
111 
112 	BBitmapStream *pstreamWithBits;
113 	pstreamWithBits = new BBitmapStream(pbits);
114 	CPPUNIT_ASSERT(pstreamWithBits);
115 	CPPUNIT_ASSERT(pstreamWithBits->Position() == 0);
116 	CPPUNIT_ASSERT(pstreamWithBits->Size() == 176);
117 	BBitmap *poutbits = NULL;
118 	CPPUNIT_ASSERT(pstreamWithBits->DetachBitmap(&poutbits) == B_OK);
119 	CPPUNIT_ASSERT(pbits == poutbits);
120 
121 	delete pstreamWithBits;
122 	pstreamWithBits = NULL;
123 
124 	delete pbits;
125 	pbits = NULL;
126 
127 	//constructor is also created with a value in DetachBitmapTest()
128 }
129 
130 /**
131  * Tests:
132  * status_t DetachBitmap(BBitmap **outMap)
133  */
134 void
135 BitmapStreamTest::DetachBitmapTest()
136 {
137 	BApplication
138 		app("application/x-vnd.Haiku-translationkit_bitmapstreamtest");
139 
140 	NextSubTest();
141 	BFile file("../src/tests/kits/translation/data/images/image.jpg",
142 		B_READ_ONLY);
143 	CPPUNIT_ASSERT(file.InitCheck() == B_OK);
144 
145 	//translate a file into a BBitmapStream
146 	NextSubTest();
147 	BBitmapStream *pstream = new BBitmapStream;
148 	BBitmap *pbits = NULL;
149 	BTranslatorRoster *proster = BTranslatorRoster::Default();
150 	CPPUNIT_ASSERT(proster->Translate(&file, NULL, NULL, pstream,
151 		B_TRANSLATOR_BITMAP) == B_OK);
152 	CPPUNIT_ASSERT(pstream->DetachBitmap(&pbits) == B_NO_ERROR);
153 	CPPUNIT_ASSERT(pbits);
154 	CPPUNIT_ASSERT(pbits->IsValid());
155 
156 	//B_BAD_VALUE
157 	NextSubTest();
158 	CPPUNIT_ASSERT(pstream->DetachBitmap(NULL) == B_BAD_VALUE);
159 
160 	//Attempt double detach
161 	NextSubTest();
162 	BBitmap *pdbits = NULL;
163 	CPPUNIT_ASSERT(pstream->DetachBitmap(&pdbits) == B_ERROR);
164 
165 	//make sure that deleting the stream
166 	//does not destroy the detached BBitmap
167 	NextSubTest();
168 	delete pstream;
169 	pstream = NULL;
170 	CPPUNIT_ASSERT(pbits->IsValid());
171 	CPPUNIT_ASSERT(pbits->BitsLength() > 0);
172 
173 	//create a new stream using the BBitmap
174 	//created by the first stream
175 	NextSubTest();
176 	BBitmapStream *pfullstream = new BBitmapStream(pbits);
177 	CPPUNIT_ASSERT(pfullstream->Position() == 0);
178 	CPPUNIT_ASSERT(pfullstream->Size() ==
179 		pbits->BitsLength() + sizeof(TranslatorBitmap));
180 
181 	//deleting pfullstream should also destroy
182 	//the bitmap attached to it (pbits)
183 	NextSubTest();
184 	delete pfullstream;
185 	pfullstream = NULL;
186 	CPPUNIT_ASSERT(pbits->BitsLength() == 0);
187 }
188 
189 /**
190  * Tests:
191  * ssize_t ReadAt(off_t pos, void *buffer, size_t numBytes)
192  * ssize_t WriteAt(off_t pos, void *buffer, size_t numBytes)
193  */
194 void
195 BitmapStreamTest::ReadWriteTest()
196 {
197 	NextSubTest();
198 	BApplication
199 		app("application/x-vnd.Haiku-translationkit_bitmapstreamtest");
200 	char chbuf[sizeof(TranslatorBitmap)],
201 		chheader[sizeof(TranslatorBitmap)], *pch;
202 	TranslatorBitmap sheader;
203 	BBitmapStream stream;
204 	int32 width = 5, height = 5;
205 
206 	sheader.magic = B_TRANSLATOR_BITMAP;
207 	sheader.bounds.left = 0;
208 	sheader.bounds.top = 0;
209 	sheader.bounds.right = width - 1;
210 	sheader.bounds.bottom = height - 1;
211 	sheader.rowBytes = width * 4;
212 	sheader.colors = B_RGB32;
213 	sheader.dataSize = sheader.rowBytes * height;
214 
215 	memcpy(&chheader, &sheader, sizeof(TranslatorBitmap));
216 	CPPUNIT_ASSERT(swap_data(B_UINT32_TYPE, &(chheader[0]),
217 		sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) == B_OK);
218 
219 	// Write header, 1 byte at a time
220 	NextSubTest();
221 	off_t nPos;
222 	for (nPos = 0; nPos < sizeof(TranslatorBitmap); nPos++) {
223 		pch = (char *)(&(chheader[0])) + nPos;
224 		CPPUNIT_ASSERT(stream.WriteAt(nPos, pch, 1) == 1);
225 	}
226 	// Check size
227 	NextSubTest();
228 	CPPUNIT_ASSERT(stream.Size() ==
229 		sizeof(TranslatorBitmap) + sheader.dataSize);
230 
231 	// Read header, 1 byte at a time
232 	NextSubTest();
233 	for (nPos = 0; nPos < sizeof(TranslatorBitmap); nPos++) {
234 		pch = (char *)(&(chheader[0])) + nPos;
235 		CPPUNIT_ASSERT(stream.ReadAt(nPos, &(chbuf[0]), 1) == 1);
236 		CPPUNIT_ASSERT(pch[0] == chbuf[0]);
237 	}
238 
239 	// Write header, all at once
240 	NextSubTest();
241 	pch = (char *)(&(chheader[0]));
242 	CPPUNIT_ASSERT(stream.WriteAt(0, pch,
243 		sizeof(TranslatorBitmap)) == sizeof(TranslatorBitmap));
244 	// Check size
245 	NextSubTest();
246 	CPPUNIT_ASSERT(stream.Size() ==
247 		sizeof(TranslatorBitmap) + sheader.dataSize);
248 
249 	// Read header, all at once
250 	NextSubTest();
251 	CPPUNIT_ASSERT(stream.ReadAt(0, &(chbuf[0]),
252 		sizeof(TranslatorBitmap)) == sizeof(TranslatorBitmap));
253 	CPPUNIT_ASSERT(memcmp(pch, &(chbuf[0]), sizeof(TranslatorBitmap)) == 0);
254 
255 	// Write bitmap data
256 	NextSubTest();
257 	int32 bytesLeft = sheader.dataSize;
258 	char byt = 0xCF;
259 	nPos = sizeof(TranslatorBitmap);
260 	while (bytesLeft--)
261 		CPPUNIT_ASSERT(stream.WriteAt(nPos++, &byt, 1) == 1);
262 	// Check size
263 	NextSubTest();
264 	CPPUNIT_ASSERT(stream.Size() ==
265 		sizeof(TranslatorBitmap) + sheader.dataSize);
266 
267 	// Test reading zero bytes
268 	NextSubTest();
269 	CPPUNIT_ASSERT(stream.ReadAt(stream.Size(), &(chbuf[0]), 0) == 0);
270 	CPPUNIT_ASSERT(stream.ReadAt(sheader.dataSize + 1000, &(chbuf[0]), 0) == 0);
271 	CPPUNIT_ASSERT(stream.ReadAt(-1, &(chbuf[0]), 0) == 0);
272 
273 	// Read bitmap data
274 	NextSubTest();
275 	#if !TEST_R5
276 		// This test fails with Be's version because of a bug.
277 		// Be's BBitmapStream::ReadAt() has strange behavior in cases
278 		// where the pos parameter of ReadAt() is != BBitmapStream::Position().
279 		// If BBitmapStream::Read() is used instead, it calls
280 		// BBitmapStream::ReadAt() with pos = BBitmapStream::Position(),
281 		// so, this issue is rarely a problem because Read() is most often used.
282 		bytesLeft = sheader.dataSize;
283 		nPos = sizeof(TranslatorBitmap);
284 		while (bytesLeft--) {
285 			chbuf[0] = 0x99;
286 			ssize_t rd = stream.ReadAt(nPos++, &(chbuf[0]), 1);
287 			CPPUNIT_ASSERT(rd == 1);
288 			CPPUNIT_ASSERT(chbuf[0] == byt);
289 		}
290 	#endif
291 
292 	// Send erroneous and weird data to WriteAt()
293 	NextSubTest();
294 	CPPUNIT_ASSERT(stream.WriteAt(0, &byt, 0) == 0);
295 	CPPUNIT_ASSERT(stream.WriteAt(-1, &byt, 1) == B_BAD_VALUE);
296 	CPPUNIT_ASSERT(stream.WriteAt(stream.Size(), &byt, 1) == B_BAD_VALUE);
297 	CPPUNIT_ASSERT(stream.WriteAt(stream.Size() + 1, &byt, 1) == B_BAD_VALUE);
298 	CPPUNIT_ASSERT(stream.WriteAt(0, NULL, 1) == B_BAD_VALUE);
299 
300 	// Send erroneous and weird data to ReadAt()
301 	NextSubTest();
302 	CPPUNIT_ASSERT(stream.ReadAt(0, &(chbuf[0]), 0) == 0);
303 	CPPUNIT_ASSERT(stream.ReadAt(-1, &(chbuf[0]), 1) == B_BAD_VALUE);
304 	CPPUNIT_ASSERT(stream.ReadAt(stream.Size(), &(chbuf[0]),
305 		 1) == B_ERROR);
306 	CPPUNIT_ASSERT(stream.ReadAt(stream.Size() + 1,
307 		&(chbuf[0]), 1) == B_ERROR);
308 	#if !TEST_R5
309 		// Be's version doesn't check for NULL
310 		CPPUNIT_ASSERT(stream.ReadAt(0, NULL, 1) == B_BAD_VALUE);
311 	#endif
312 
313 	// There is a segment violation with Be's version when stream is destroyed.
314 	// Don't yet know why.
315 }
316 
317 /**
318  * Tests:
319  * off_t Seek(off_t position, uint32 whence)
320  * off_t Position() const
321  */
322 void
323 BitmapStreamTest::SeekTest()
324 {
325 	BApplication
326 		app("application/x-vnd.Haiku-translationkit_bitmapstreamtest");
327 
328 	NextSubTest();
329 	BFile file("../src/tests/kits/translation/data/images/image.jpg",
330 		B_READ_ONLY);
331 	CPPUNIT_ASSERT(file.InitCheck() == B_OK);
332 
333 	//translate a file into a BBitmapStream
334 	NextSubTest();
335 	BBitmapStream stream;
336 	BTranslatorRoster *proster = BTranslatorRoster::Default();
337 	CPPUNIT_ASSERT(proster->Translate(&file, NULL, NULL, &stream,
338 		B_TRANSLATOR_BITMAP) == B_OK);
339 
340 	// Test SEEK_END
341 	NextSubTest();
342 	off_t nPos;
343 	nPos = stream.Size();
344 	CPPUNIT_ASSERT(stream.Seek(0, SEEK_END) == nPos);
345 	CPPUNIT_ASSERT(stream.Position() == nPos);
346 
347 	nPos = 0;
348 	CPPUNIT_ASSERT(stream.Seek(-stream.Size(), SEEK_END) == nPos);
349 	CPPUNIT_ASSERT(stream.Position() == nPos);
350 
351 	nPos = stream.Size() - 15;
352 	CPPUNIT_ASSERT(stream.Seek(-15, SEEK_END) == nPos);
353 	CPPUNIT_ASSERT(stream.Position() == nPos);
354 
355 	CPPUNIT_ASSERT(stream.Seek(1, SEEK_END) == B_BAD_VALUE);
356 	CPPUNIT_ASSERT(stream.Position() == nPos);
357 
358 	CPPUNIT_ASSERT(stream.Seek(-(stream.Size() + 1),
359 		SEEK_END) == B_BAD_VALUE);
360 	CPPUNIT_ASSERT(stream.Position() == nPos);
361 
362 	// Test SEEK_SET
363 	NextSubTest();
364 	nPos = 0;
365 	CPPUNIT_ASSERT(stream.Seek(0, SEEK_SET) == nPos);
366 	CPPUNIT_ASSERT(stream.Position() == nPos);
367 
368 	nPos = stream.Size();
369 	CPPUNIT_ASSERT(stream.Seek(nPos, SEEK_SET) == nPos);
370 	CPPUNIT_ASSERT(stream.Position() == nPos);
371 
372 	nPos /= 2;
373 	CPPUNIT_ASSERT(stream.Seek(nPos, SEEK_SET) == nPos);
374 	CPPUNIT_ASSERT(stream.Position() == nPos);
375 
376 	CPPUNIT_ASSERT(stream.Seek(-1, SEEK_SET) == B_BAD_VALUE);
377 	CPPUNIT_ASSERT(stream.Position() == nPos);
378 
379 	CPPUNIT_ASSERT(stream.Seek(stream.Size() + 1, SEEK_SET) == B_BAD_VALUE);
380 	CPPUNIT_ASSERT(stream.Position() == nPos);
381 
382 	// Test SEEK_CUR
383 	NextSubTest();
384 	CPPUNIT_ASSERT(stream.Seek(-nPos, SEEK_CUR) == 0);
385 	CPPUNIT_ASSERT(stream.Position() == 0);
386 
387 	nPos = stream.Size();
388 	CPPUNIT_ASSERT(stream.Seek(nPos, SEEK_CUR) == nPos);
389 	CPPUNIT_ASSERT(stream.Position() == nPos);
390 
391 	nPos -= 11;
392 	CPPUNIT_ASSERT(stream.Seek(-11, SEEK_CUR) == nPos);
393 	CPPUNIT_ASSERT(stream.Position() == nPos);
394 
395 	nPos += 8;
396 	CPPUNIT_ASSERT(stream.Seek(8, SEEK_CUR) == nPos);
397 	CPPUNIT_ASSERT(stream.Position() == nPos);
398 
399 	CPPUNIT_ASSERT(stream.Seek(-(stream.Position() + 1),
400 		SEEK_CUR) == B_BAD_VALUE);
401 	CPPUNIT_ASSERT(stream.Position() == nPos);
402 
403 	CPPUNIT_ASSERT(stream.Seek((stream.Size() - stream.Position()) + 1,
404 		SEEK_CUR) == B_BAD_VALUE);
405 	CPPUNIT_ASSERT(stream.Position() == nPos);
406 }
407 
408 /**
409  * Tests:
410  * status_t SetSize(off_t size) const
411  */
412 void
413 BitmapStreamTest::SetSizeTest()
414 {
415 	BApplication
416 		app("application/x-vnd.Haiku-translationkit_bitmapstreamtest");
417 
418 	NextSubTest();
419 	BFile file("../src/tests/kits/translation/data/images/image.jpg",
420 		B_READ_ONLY);
421 	CPPUNIT_ASSERT(file.InitCheck() == B_OK);
422 
423 	//translate a file into a BBitmapStream
424 	NextSubTest();
425 	BBitmapStream stream;
426 	BTranslatorRoster *proster = BTranslatorRoster::Default();
427 	CPPUNIT_ASSERT(proster->Translate(&file, NULL, NULL, &stream,
428 		B_TRANSLATOR_BITMAP) == B_OK);
429 
430 	// Send crap to SetSize
431 	NextSubTest();
432 	CPPUNIT_ASSERT(stream.SetSize(-1) == B_BAD_VALUE);
433 	CPPUNIT_ASSERT(stream.SetSize(stream.Size() + 1) == B_BAD_VALUE);
434 }
435