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