// TranslatorTestAddOn.cpp #include #include #include #include #include "TranslatorTestAddOn.h" // ##### Include headers for your tests here ##### #include "bmptranslator/BMPTranslatorTest.h" #include "pngtranslator/PNGTranslatorTest.h" #include "stxttranslator/STXTTranslatorTest.h" #include "tgatranslator/TGATranslatorTest.h" #include "tifftranslator/TIFFTranslatorTest.h" BTestSuite * getTestSuite() { BTestSuite *suite = new BTestSuite("Translators"); // ##### Add test suites here ##### suite->addTest("BMPTranslator", BMPTranslatorTest::Suite()); suite->addTest("PNGTranslator", PNGTranslatorTest::Suite()); suite->addTest("STXTTranslator", STXTTranslatorTest::Suite()); suite->addTest("TGATranslator", TGATranslatorTest::Suite()); suite->addTest("TIFFTranslator", TIFFTranslatorTest::Suite()); return suite; } // helper function used by multiple tests to // determine if the given streams are exactly // the same bool CompareStreams(BPositionIO &a, BPositionIO &b) { off_t alen = 0, blen = 0; const uint32 kbuflen = 2048; uint8 abuf[kbuflen], bbuf[kbuflen]; a.Seek(0, SEEK_END); alen = a.Position(); b.Seek(0, SEEK_END); blen = b.Position(); if (alen != blen) return false; if (a.Seek(0, SEEK_SET) != 0) return false; if (b.Seek(0, SEEK_SET) != 0) return false; ssize_t read = 0; while (alen > 0) { read = a.Read(abuf, kbuflen); if (read < 0) return false; if (b.Read(bbuf, read) != read) return false; if (memcmp(abuf, bbuf, read) != 0) return false; alen -= read; } return true; } // Check each member of translator_info to see that it matches // what is expected void CheckTranslatorInfo(translator_info *pti, uint32 type, uint32 group, float quality, float capability, const char *name, const char *mime) { CPPUNIT_ASSERT(pti->type == type); CPPUNIT_ASSERT(pti->translator != 0); CPPUNIT_ASSERT(pti->group == group); CPPUNIT_ASSERT(pti->quality > quality - 0.01f && pti->quality < quality + 0.01f); CPPUNIT_ASSERT(pti->capability > capability - 0.01f && pti->capability < capability + 0.01f); CPPUNIT_ASSERT(strcmp(pti->name, name) == 0); CPPUNIT_ASSERT(strcmp(pti->MIME, mime) == 0); } // Returns true if the translation_formats are // identical (or nearly identical). Returns false if // they are different bool CompareTranslationFormat(const translation_format *pleft, const translation_format *pright) { CPPUNIT_ASSERT(pleft->MIME); CPPUNIT_ASSERT(pright->MIME); CPPUNIT_ASSERT(pleft->name); CPPUNIT_ASSERT(pright->name); if (pleft->group != pright->group) return false; if (pleft->type != pright->type) return false; if (pleft->quality < pright->quality - 0.01f || pleft->quality > pright->quality + 0.01f) return false; if (pleft->capability < pright->capability - 0.01f || pleft->capability > pright->capability + 0.01f) return false; if (strcmp(pleft->MIME, pright->MIME) != 0) return false; if (strcmp(pleft->name, pright->name) != 0) return false; return true; } // Apply a number of tests to a BTranslator * to a TGATranslator object void TestBTranslator(BTestCase *ptest, BTranslator *ptran, const translation_format *pExpectedIns, uint32 nExpectedIns, const translation_format *pExpectedOuts, uint32 nExpectedOuts, int32 expectedVer) { const uint32 knmatches = 50; uint8 matches[knmatches]; CPPUNIT_ASSERT(nExpectedIns <= knmatches && nExpectedOuts <= knmatches); // The translator should only have one reference ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->ReferenceCount() == 1); // Make sure Acquire returns a BTranslator even though its // already been Acquired once ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->Acquire() == ptran); // Acquired twice, refcount should be 2 ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->ReferenceCount() == 2); // Release should return ptran because it is still acquired ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->Release() == ptran); ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->ReferenceCount() == 1); ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->Acquire() == ptran); ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->ReferenceCount() == 2); ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->Release() == ptran); ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->ReferenceCount() == 1); // A name would be nice ptest->NextSubTest(); const char *tranname = ptran->TranslatorName(); CPPUNIT_ASSERT(tranname); printf(" {%s} ", tranname); // More info would be nice ptest->NextSubTest(); const char *traninfo = ptran->TranslatorInfo(); CPPUNIT_ASSERT(traninfo); printf(" {%s} ", traninfo); // What version are you? // (when ver == 100, that means that version is 1.00) ptest->NextSubTest(); int32 ver = ptran->TranslatorVersion(); CPPUNIT_ASSERT(ver == expectedVer); printf(" {0x%.8lx} ", ver); // Input formats? ptest->NextSubTest(); { printf("input:"); int32 incount = 0; const translation_format *pins = ptran->InputFormats(&incount); CPPUNIT_ASSERT((unsigned)incount == nExpectedIns); CPPUNIT_ASSERT(pins); memset(matches, 0, sizeof(uint8) * nExpectedIns); for (int32 i = 0; i < incount; i++) { bool bmatch = false; for (uint32 k = 0; bmatch == false && k < nExpectedIns; k++) { bmatch = CompareTranslationFormat(pins + i, pExpectedIns + k); if (bmatch) matches[k] = 1; } CPPUNIT_ASSERT(bmatch); } // make sure that each expected input format was matched for (uint32 i = 0; i < nExpectedIns; i++) CPPUNIT_ASSERT(matches[i]); } // Output formats? ptest->NextSubTest(); { printf("output:"); int32 outcount = 0; const translation_format *pouts = ptran->OutputFormats(&outcount); CPPUNIT_ASSERT((unsigned)outcount == nExpectedOuts); CPPUNIT_ASSERT(pouts); memset(matches, 0, sizeof(uint8) * nExpectedOuts); for (int32 i = 0; i < outcount; i++) { bool bmatch = false; for (uint32 k = 0; bmatch == false && k < nExpectedOuts; k++) { bmatch = CompareTranslationFormat(pouts + i, pExpectedOuts + k); if (bmatch) matches[k] = 1; } CPPUNIT_ASSERT(bmatch); } // make sure that each expected input format was matched for (uint32 i = 0; i < nExpectedOuts; i++) CPPUNIT_ASSERT(matches[i]); } // Release should return NULL because Release has been called // as many times as it has been acquired ptest->NextSubTest(); CPPUNIT_ASSERT(ptran->Release() == NULL); ptran = NULL; } void TranslatorLoadAddOnTest(const char *path, BTestCase *ptest, const translation_format *pExpectedIns, uint32 nExpectedIns, const translation_format *pExpectedOuts, uint32 nExpectedOuts, int32 expectedVer) { // Make sure the add_on loads ptest->NextSubTest(); image_id image = load_add_on(path); CPPUNIT_ASSERT(image >= 0); // Load in function to make the object ptest->NextSubTest(); BTranslator *(*pMakeNthTranslator)(int32 n,image_id you,uint32 flags,...); status_t err = get_image_symbol(image, "make_nth_translator", B_SYMBOL_TYPE_TEXT, (void **)&pMakeNthTranslator); CPPUNIT_ASSERT(!err); // Make sure the function returns a pointer to a BTranslator ptest->NextSubTest(); BTranslator *ptran = pMakeNthTranslator(0, image, 0); CPPUNIT_ASSERT(ptran); // Make sure the function only returns one BTranslator ptest->NextSubTest(); CPPUNIT_ASSERT(!pMakeNthTranslator(1, image, 0)); CPPUNIT_ASSERT(!pMakeNthTranslator(2, image, 0)); CPPUNIT_ASSERT(!pMakeNthTranslator(3, image, 0)); CPPUNIT_ASSERT(!pMakeNthTranslator(16, image, 0)); CPPUNIT_ASSERT(!pMakeNthTranslator(1023, image, 0)); // Run a number of tests on the BTranslator object TestBTranslator(ptest, ptran, pExpectedIns, nExpectedIns, pExpectedOuts, nExpectedOuts, expectedVer); // NOTE: this function Release()s ptran ptran = NULL; // Unload Add-on ptest->NextSubTest(); CPPUNIT_ASSERT(unload_add_on(image) == B_OK); }