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