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 */
47BitmapStreamTest::BitmapStreamTest(std::string name)
48	: BTestCase(name)
49{
50}
51
52/**
53 * Default destructor - no work
54 */
55BitmapStreamTest::~BitmapStreamTest()
56{
57}
58
59CppUnit::Test *
60BitmapStreamTest::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 */
89void
90BitmapStreamTest::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 */
131void
132BitmapStreamTest::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 */
191void
192BitmapStreamTest::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 */
319void
320BitmapStreamTest::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 */
409void
410BitmapStreamTest::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