1 // TranslatorTestAddOn.cpp 2 3 #include <stdio.h> 4 #include <string.h> 5 #include <Translator.h> 6 #include <OS.h> 7 #include "TranslatorTestAddOn.h" 8 9 // ##### Include headers for your tests here ##### 10 #include "bmptranslator/BMPTranslatorTest.h" 11 #include "pngtranslator/PNGTranslatorTest.h" 12 #include "stxttranslator/STXTTranslatorTest.h" 13 #include "tgatranslator/TGATranslatorTest.h" 14 #include "tifftranslator/TIFFTranslatorTest.h" 15 16 BTestSuite * 17 getTestSuite() 18 { 19 BTestSuite *suite = new BTestSuite("Translators"); 20 21 // ##### Add test suites here ##### 22 suite->addTest("BMPTranslator", BMPTranslatorTest::Suite()); 23 suite->addTest("PNGTranslator", PNGTranslatorTest::Suite()); 24 suite->addTest("STXTTranslator", STXTTranslatorTest::Suite()); 25 suite->addTest("TGATranslator", TGATranslatorTest::Suite()); 26 suite->addTest("TIFFTranslator", TIFFTranslatorTest::Suite()); 27 28 return suite; 29 } 30 31 // helper function used by multiple tests to 32 // determine if the given streams are exactly 33 // the same 34 bool 35 CompareStreams(BPositionIO &a, BPositionIO &b) 36 { 37 off_t alen = 0, blen = 0; 38 const uint32 kbuflen = 2048; 39 uint8 abuf[kbuflen], bbuf[kbuflen]; 40 41 a.Seek(0, SEEK_END); 42 alen = a.Position(); 43 b.Seek(0, SEEK_END); 44 blen = b.Position(); 45 if (alen != blen) 46 return false; 47 48 if (a.Seek(0, SEEK_SET) != 0) 49 return false; 50 if (b.Seek(0, SEEK_SET) != 0) 51 return false; 52 53 ssize_t read = 0; 54 while (alen > 0) { 55 read = a.Read(abuf, kbuflen); 56 if (read < 0) 57 return false; 58 if (b.Read(bbuf, read) != read) 59 return false; 60 61 if (memcmp(abuf, bbuf, read) != 0) 62 return false; 63 64 alen -= read; 65 } 66 67 return true; 68 } 69 70 // Check each member of translator_info to see that it matches 71 // what is expected 72 void 73 CheckTranslatorInfo(translator_info *pti, uint32 type, uint32 group, 74 float quality, float capability, const char *name, const char *mime) 75 { 76 CPPUNIT_ASSERT(pti->type == type); 77 CPPUNIT_ASSERT(pti->translator != 0); 78 CPPUNIT_ASSERT(pti->group == group); 79 CPPUNIT_ASSERT(pti->quality > quality - 0.01f && 80 pti->quality < quality + 0.01f); 81 CPPUNIT_ASSERT(pti->capability > capability - 0.01f && 82 pti->capability < capability + 0.01f); 83 CPPUNIT_ASSERT(strcmp(pti->name, name) == 0); 84 CPPUNIT_ASSERT(strcmp(pti->MIME, mime) == 0); 85 } 86 87 // Returns true if the translation_formats are 88 // identical (or nearly identical). Returns false if 89 // they are different 90 bool 91 CompareTranslationFormat(const translation_format *pleft, 92 const translation_format *pright) 93 { 94 CPPUNIT_ASSERT(pleft->MIME); 95 CPPUNIT_ASSERT(pright->MIME); 96 CPPUNIT_ASSERT(pleft->name); 97 CPPUNIT_ASSERT(pright->name); 98 99 if (pleft->group != pright->group) 100 return false; 101 if (pleft->type != pright->type) 102 return false; 103 if (pleft->quality < pright->quality - 0.01f || 104 pleft->quality > pright->quality + 0.01f) 105 return false; 106 if (pleft->capability < pright->capability - 0.01f || 107 pleft->capability > pright->capability + 0.01f) 108 return false; 109 if (strcmp(pleft->MIME, pright->MIME) != 0) 110 return false; 111 if (strcmp(pleft->name, pright->name) != 0) 112 return false; 113 114 return true; 115 } 116 117 // Apply a number of tests to a BTranslator * to a TGATranslator object 118 void 119 TestBTranslator(BTestCase *ptest, BTranslator *ptran, 120 const translation_format *pExpectedIns, uint32 nExpectedIns, 121 const translation_format *pExpectedOuts, uint32 nExpectedOuts, 122 int32 expectedVer) 123 { 124 const uint32 knmatches = 50; 125 uint8 matches[knmatches]; 126 CPPUNIT_ASSERT(nExpectedIns <= knmatches && nExpectedOuts <= knmatches); 127 128 // The translator should only have one reference 129 ptest->NextSubTest(); 130 CPPUNIT_ASSERT(ptran->ReferenceCount() == 1); 131 132 // Make sure Acquire returns a BTranslator even though its 133 // already been Acquired once 134 ptest->NextSubTest(); 135 CPPUNIT_ASSERT(ptran->Acquire() == ptran); 136 137 // Acquired twice, refcount should be 2 138 ptest->NextSubTest(); 139 CPPUNIT_ASSERT(ptran->ReferenceCount() == 2); 140 141 // Release should return ptran because it is still acquired 142 ptest->NextSubTest(); 143 CPPUNIT_ASSERT(ptran->Release() == ptran); 144 145 ptest->NextSubTest(); 146 CPPUNIT_ASSERT(ptran->ReferenceCount() == 1); 147 148 ptest->NextSubTest(); 149 CPPUNIT_ASSERT(ptran->Acquire() == ptran); 150 151 ptest->NextSubTest(); 152 CPPUNIT_ASSERT(ptran->ReferenceCount() == 2); 153 154 ptest->NextSubTest(); 155 CPPUNIT_ASSERT(ptran->Release() == ptran); 156 157 ptest->NextSubTest(); 158 CPPUNIT_ASSERT(ptran->ReferenceCount() == 1); 159 160 // A name would be nice 161 ptest->NextSubTest(); 162 const char *tranname = ptran->TranslatorName(); 163 CPPUNIT_ASSERT(tranname); 164 printf(" {%s} ", tranname); 165 166 // More info would be nice 167 ptest->NextSubTest(); 168 const char *traninfo = ptran->TranslatorInfo(); 169 CPPUNIT_ASSERT(traninfo); 170 printf(" {%s} ", traninfo); 171 172 // What version are you? 173 // (when ver == 100, that means that version is 1.00) 174 ptest->NextSubTest(); 175 int32 ver = ptran->TranslatorVersion(); 176 CPPUNIT_ASSERT(ver == expectedVer); 177 printf(" {0x%.8lx} ", ver); 178 179 // Input formats? 180 ptest->NextSubTest(); 181 { 182 printf("input:"); 183 184 int32 incount = 0; 185 const translation_format *pins = ptran->InputFormats(&incount); 186 CPPUNIT_ASSERT((unsigned)incount == nExpectedIns); 187 CPPUNIT_ASSERT(pins); 188 189 memset(matches, 0, sizeof(uint8) * nExpectedIns); 190 for (int32 i = 0; i < incount; i++) { 191 bool bmatch = false; 192 for (uint32 k = 0; bmatch == false && k < nExpectedIns; k++) { 193 bmatch = CompareTranslationFormat(pins + i, pExpectedIns + k); 194 if (bmatch) 195 matches[k] = 1; 196 } 197 198 CPPUNIT_ASSERT(bmatch); 199 } 200 201 // make sure that each expected input format was matched 202 for (uint32 i = 0; i < nExpectedIns; i++) 203 CPPUNIT_ASSERT(matches[i]); 204 } 205 206 // Output formats? 207 ptest->NextSubTest(); 208 { 209 printf("output:"); 210 211 int32 outcount = 0; 212 const translation_format *pouts = ptran->OutputFormats(&outcount); 213 CPPUNIT_ASSERT((unsigned)outcount == nExpectedOuts); 214 CPPUNIT_ASSERT(pouts); 215 216 memset(matches, 0, sizeof(uint8) * nExpectedOuts); 217 for (int32 i = 0; i < outcount; i++) { 218 bool bmatch = false; 219 for (uint32 k = 0; bmatch == false && k < nExpectedOuts; k++) { 220 bmatch = CompareTranslationFormat(pouts + i, pExpectedOuts + k); 221 if (bmatch) 222 matches[k] = 1; 223 } 224 225 CPPUNIT_ASSERT(bmatch); 226 } 227 228 // make sure that each expected input format was matched 229 for (uint32 i = 0; i < nExpectedOuts; i++) 230 CPPUNIT_ASSERT(matches[i]); 231 } 232 233 // Release should return NULL because Release has been called 234 // as many times as it has been acquired 235 ptest->NextSubTest(); 236 CPPUNIT_ASSERT(ptran->Release() == NULL); 237 ptran = NULL; 238 } 239 240 void 241 TranslatorLoadAddOnTest(const char *path, BTestCase *ptest, 242 const translation_format *pExpectedIns, uint32 nExpectedIns, 243 const translation_format *pExpectedOuts, uint32 nExpectedOuts, 244 int32 expectedVer) 245 { 246 // Make sure the add_on loads 247 ptest->NextSubTest(); 248 image_id image = load_add_on(path); 249 CPPUNIT_ASSERT(image >= 0); 250 251 // Load in function to make the object 252 ptest->NextSubTest(); 253 BTranslator *(*pMakeNthTranslator)(int32 n,image_id you,uint32 flags,...); 254 status_t err = get_image_symbol(image, "make_nth_translator", 255 B_SYMBOL_TYPE_TEXT, (void **)&pMakeNthTranslator); 256 CPPUNIT_ASSERT(!err); 257 258 // Make sure the function returns a pointer to a BTranslator 259 ptest->NextSubTest(); 260 BTranslator *ptran = pMakeNthTranslator(0, image, 0); 261 CPPUNIT_ASSERT(ptran); 262 263 // Make sure the function only returns one BTranslator 264 ptest->NextSubTest(); 265 CPPUNIT_ASSERT(!pMakeNthTranslator(1, image, 0)); 266 CPPUNIT_ASSERT(!pMakeNthTranslator(2, image, 0)); 267 CPPUNIT_ASSERT(!pMakeNthTranslator(3, image, 0)); 268 CPPUNIT_ASSERT(!pMakeNthTranslator(16, image, 0)); 269 CPPUNIT_ASSERT(!pMakeNthTranslator(1023, image, 0)); 270 271 // Run a number of tests on the BTranslator object 272 TestBTranslator(ptest, ptran, pExpectedIns, nExpectedIns, 273 pExpectedOuts, nExpectedOuts, expectedVer); 274 // NOTE: this function Release()s ptran 275 ptran = NULL; 276 277 // Unload Add-on 278 ptest->NextSubTest(); 279 CPPUNIT_ASSERT(unload_add_on(image) == B_OK); 280 } 281