add unittests for metadata



git-svn-id: http://skia.googlecode.com/svn/trunk@1019 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-03-30 18:23:21 +00:00
Родитель 5e3496e555
Коммит e733071abe
4 изменённых файлов: 246 добавлений и 197 удалений

Просмотреть файл

@ -19,47 +19,69 @@
#include "SkScalar.h" #include "SkScalar.h"
class SkRefCnt;
class SkMetaData { class SkMetaData {
public: public:
/**
* Used to manage the life-cycle of a ptr in the metadata. This is option
* in setPtr, and is only invoked when either copying one metadata to
* another, or when the metadata is destroyed.
*
* setPtr(name, ptr, proc) {
* fPtr = proc(ptr, true);
* }
*
* copy: A = B {
* A.fPtr = B.fProc(B.fPtr, true);
* }
*
* ~SkMetaData {
* fProc(fPtr, false);
* }
*/
typedef void* (*PtrProc)(void* ptr, bool doRef);
/**
* Implements PtrProc for SkRefCnt pointers
*/
static void* RefCntProc(void* ptr, bool doRef);
SkMetaData(); SkMetaData();
SkMetaData(const SkMetaData& src); SkMetaData(const SkMetaData& src);
~SkMetaData(); ~SkMetaData();
SkMetaData& operator=(const SkMetaData& src); SkMetaData& operator=(const SkMetaData& src);
void reset(); void reset();
bool findS32(const char name[], int32_t* value = NULL) const; bool findS32(const char name[], int32_t* value = NULL) const;
bool findScalar(const char name[], SkScalar* value = NULL) const; bool findScalar(const char name[], SkScalar* value = NULL) const;
const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const; const SkScalar* findScalars(const char name[], int* count,
SkScalar values[] = NULL) const;
const char* findString(const char name[]) const; const char* findString(const char name[]) const;
bool findPtr(const char name[], void** value = NULL) const; bool findPtr(const char name[], void** value = NULL, PtrProc* = NULL) const;
bool findBool(const char name[], bool* value = NULL) const; bool findBool(const char name[], bool* value = NULL) const;
const void* findData(const char name[], size_t* byteCount = NULL) const; const void* findData(const char name[], size_t* byteCount = NULL) const;
bool hasS32(const char name[], int32_t value) const bool hasS32(const char name[], int32_t value) const {
{
int32_t v; int32_t v;
return this->findS32(name, &v) && v == value; return this->findS32(name, &v) && v == value;
} }
bool hasScalar(const char name[], SkScalar value) const bool hasScalar(const char name[], SkScalar value) const {
{ SkScalar v;
SkScalar v;
return this->findScalar(name, &v) && v == value; return this->findScalar(name, &v) && v == value;
} }
bool hasString(const char name[], const char value[]) const bool hasString(const char name[], const char value[]) const {
{
const char* v = this->findString(name); const char* v = this->findString(name);
return v == NULL && value == NULL || return v == NULL && value == NULL ||
v != NULL && value != NULL && !strcmp(v, value); v != NULL && value != NULL && !strcmp(v, value);
} }
bool hasPtr(const char name[], void* value) const bool hasPtr(const char name[], void* value) const {
{ void* v;
void* v;
return this->findPtr(name, &v) && v == value; return this->findPtr(name, &v) && v == value;
} }
bool hasBool(const char name[], bool value) const bool hasBool(const char name[], bool value) const {
{
bool v; bool v;
return this->findBool(name, &v) && v == value; return this->findBool(name, &v) && v == value;
} }
@ -69,23 +91,35 @@ public:
return NULL != ptr && len == byteCount && !memcmp(ptr, data, len); return NULL != ptr && len == byteCount && !memcmp(ptr, data, len);
} }
void setS32(const char name[], int32_t value); void setS32(const char name[], int32_t value);
void setScalar(const char name[], SkScalar value); void setScalar(const char name[], SkScalar value);
SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL); SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL);
void setString(const char name[], const char value[]); void setString(const char name[], const char value[]);
void setPtr(const char name[], void* value); void setPtr(const char name[], void* value, PtrProc proc = NULL);
void setBool(const char name[], bool value); void setBool(const char name[], bool value);
// the data is copied from the input pointer. // the data is copied from the input pointer.
void setData(const char name[], const void* data, size_t byteCount); void setData(const char name[], const void* data, size_t byteCount);
bool removeS32(const char name[]); bool removeS32(const char name[]);
bool removeScalar(const char name[]); bool removeScalar(const char name[]);
bool removeString(const char name[]); bool removeString(const char name[]);
bool removePtr(const char name[]); bool removePtr(const char name[]);
bool removeBool(const char name[]); bool removeBool(const char name[]);
bool removeData(const char name[]); bool removeData(const char name[]);
SkDEBUGCODE(static void UnitTest();) // helpers for SkRefCnt
bool findRefCnt(const char name[], SkRefCnt** ptr = NULL) {
return this->findPtr(name, reinterpret_cast<void**>(ptr));
}
bool hasRefCnt(const char name[], SkRefCnt* ptr) {
return this->hasPtr(name, ptr);
}
void setRefCnt(const char name[], SkRefCnt* ptr) {
this->setPtr(name, ptr, RefCntProc);
}
bool removeRefCnt(const char name[]) {
return this->removePtr(name);
}
enum Type { enum Type {
kS32_Type, kS32_Type,
@ -110,7 +144,7 @@ public:
/** Reset the iterator, so that calling next() will return the first /** Reset the iterator, so that calling next() will return the first
data element. This is done implicitly in the constructor. data element. This is done implicitly in the constructor.
*/ */
void reset(const SkMetaData&); void reset(const SkMetaData&);
/** Each time next is called, it returns the name of the next data element, /** Each time next is called, it returns the name of the next data element,
or null when there are no more elements. If non-null is returned, then the or null when there are no more elements. If non-null is returned, then the
@ -128,22 +162,7 @@ public:
Rec* fNext; Rec* fNext;
uint16_t fDataCount; // number of elements uint16_t fDataCount; // number of elements
uint8_t fDataLen; // sizeof a single element uint8_t fDataLen; // sizeof a single element
#ifdef SK_DEBUG
Type fType;
#else
uint8_t fType; uint8_t fType;
#endif
#ifdef SK_DEBUG
const char* fName;
union {
int32_t fS32;
SkScalar fScalar;
const char* fString;
void* fPtr;
bool fBool;
} fData;
#endif
const void* data() const { return (this + 1); } const void* data() const { return (this + 1); }
void* data() { return (this + 1); } void* data() { return (this + 1); }

Просмотреть файл

@ -16,6 +16,24 @@
*/ */
#include "SkMetaData.h" #include "SkMetaData.h"
#include "SkRefCnt.h"
struct PtrPair {
void* fPtr;
SkMetaData::PtrProc fProc;
};
void* SkMetaData::RefCntProc(void* ptr, bool doRef) {
SkASSERT(ptr);
SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr);
if (doRef) {
refcnt->ref();
} else {
refcnt->unref();
}
return ptr;
}
SkMetaData::SkMetaData() : fRec(NULL) SkMetaData::SkMetaData() : fRec(NULL)
{ {
@ -34,8 +52,13 @@ SkMetaData::~SkMetaData()
void SkMetaData::reset() void SkMetaData::reset()
{ {
Rec* rec = fRec; Rec* rec = fRec;
while (rec) while (rec) {
{ if (kPtr_Type == rec->fType) {
PtrPair* pair = (PtrPair*)rec->data();
if (pair->fProc && pair->fPtr) {
pair->fPtr = pair->fProc(pair->fPtr, false);
}
}
Rec* next = rec->fNext; Rec* next = rec->fNext;
Rec::Free(rec); Rec::Free(rec);
rec = next; rec = next;
@ -79,9 +102,9 @@ void SkMetaData::setString(const char name[], const char value[])
(void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1); (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1);
} }
void SkMetaData::setPtr(const char name[], void* ptr) void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) {
{ PtrPair pair = { ptr, proc };
(void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1); (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1);
} }
void SkMetaData::setBool(const char name[], bool value) void SkMetaData::setBool(const char name[], bool value)
@ -115,32 +138,12 @@ void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type
memcpy(rec->data(), data, dataSize * count); memcpy(rec->data(), data, dataSize * count);
memcpy(rec->name(), name, len + 1); memcpy(rec->name(), name, len + 1);
#ifdef SK_DEBUG if (kPtr_Type == type) {
rec->fName = rec->name(); PtrPair* pair = (PtrPair*)rec->data();
switch (type) { if (pair->fProc && pair->fPtr) {
case kS32_Type: pair->fPtr = pair->fProc(pair->fPtr, true);
rec->fData.fS32 = *(const int32_t*)rec->data(); }
break;
case kScalar_Type:
rec->fData.fScalar = *(const SkScalar*)rec->data();
break;
case kString_Type:
rec->fData.fString = (const char*)rec->data();
break;
case kPtr_Type:
rec->fData.fPtr = *(void**)rec->data();
break;
case kBool_Type:
rec->fData.fBool = *(const bool*)rec->data();
break;
case kData_Type:
rec->fData.fPtr = rec->data();
break;
default:
SkASSERT(!"bad type");
break;
} }
#endif
rec->fNext = fRec; rec->fNext = fRec;
fRec = rec; fRec = rec;
@ -187,14 +190,17 @@ const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar
return NULL; return NULL;
} }
bool SkMetaData::findPtr(const char name[], void** value) const bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
{
const Rec* rec = this->find(name, kPtr_Type); const Rec* rec = this->find(name, kPtr_Type);
if (rec) if (rec) {
{
SkASSERT(rec->fDataCount == 1); SkASSERT(rec->fDataCount == 1);
if (value) const PtrPair* pair = (const PtrPair*)rec->data();
*value = *(void**)rec->data(); if (ptr) {
*ptr = pair->fPtr;
}
if (proc) {
*proc = pair->fProc;
}
return true; return true;
} }
return false; return false;
@ -244,19 +250,24 @@ const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
return NULL; return NULL;
} }
bool SkMetaData::remove(const char name[], Type type) bool SkMetaData::remove(const char name[], Type type) {
{
Rec* rec = fRec; Rec* rec = fRec;
Rec* prev = NULL; Rec* prev = NULL;
while (rec) while (rec) {
{
Rec* next = rec->fNext; Rec* next = rec->fNext;
if (rec->fType == type && !strcmp(rec->name(), name)) if (rec->fType == type && !strcmp(rec->name(), name)) {
{ if (prev) {
if (prev)
prev->fNext = next; prev->fNext = next;
else } else {
fRec = next; fRec = next;
}
if (kPtr_Type == type) {
PtrPair* pair = (PtrPair*)rec->data();
if (pair->fProc && pair->fPtr) {
(void)pair->fProc(pair->fPtr, false);
}
}
Rec::Free(rec); Rec::Free(rec);
return true; return true;
} }
@ -295,28 +306,26 @@ bool SkMetaData::removeData(const char name[]) {
return this->remove(name, kData_Type); return this->remove(name, kData_Type);
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkMetaData::Iter::Iter(const SkMetaData& metadata) SkMetaData::Iter::Iter(const SkMetaData& metadata) {
{
fRec = metadata.fRec; fRec = metadata.fRec;
} }
void SkMetaData::Iter::reset(const SkMetaData& metadata) void SkMetaData::Iter::reset(const SkMetaData& metadata) {
{
fRec = metadata.fRec; fRec = metadata.fRec;
} }
const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
{
const char* name = NULL; const char* name = NULL;
if (fRec) if (fRec) {
{ if (t) {
if (t)
*t = (SkMetaData::Type)fRec->fType; *t = (SkMetaData::Type)fRec->fType;
if (count) }
if (count) {
*count = fRec->fDataCount; *count = fRec->fDataCount;
}
name = fRec->name(); name = fRec->name();
fRec = fRec->fNext; fRec = fRec->fNext;
@ -324,105 +333,13 @@ const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count)
return name; return name;
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
{
return (Rec*)sk_malloc_throw(size); return (Rec*)sk_malloc_throw(size);
} }
void SkMetaData::Rec::Free(Rec* rec) void SkMetaData::Rec::Free(Rec* rec) {
{
sk_free(rec); sk_free(rec);
} }
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
void SkMetaData::UnitTest()
{
#ifdef SK_SUPPORT_UNITTEST
SkMetaData m1;
SkASSERT(!m1.findS32("int"));
SkASSERT(!m1.findScalar("scalar"));
SkASSERT(!m1.findString("hello"));
SkASSERT(!m1.removeS32("int"));
SkASSERT(!m1.removeScalar("scalar"));
SkASSERT(!m1.removeString("hello"));
SkASSERT(!m1.removeString("true"));
SkASSERT(!m1.removeString("false"));
m1.setS32("int", 12345);
m1.setScalar("scalar", SK_Scalar1 * 42);
m1.setString("hello", "world");
m1.setPtr("ptr", &m1);
m1.setBool("true", true);
m1.setBool("false", false);
int32_t n;
SkScalar s;
m1.setScalar("scalar", SK_Scalar1/2);
SkASSERT(m1.findS32("int", &n) && n == 12345);
SkASSERT(m1.findScalar("scalar", &s) && s == SK_Scalar1/2);
SkASSERT(!strcmp(m1.findString("hello"), "world"));
SkASSERT(m1.hasBool("true", true));
SkASSERT(m1.hasBool("false", false));
Iter iter(m1);
const char* name;
static const struct {
const char* fName;
SkMetaData::Type fType;
int fCount;
} gElems[] = {
{ "int", SkMetaData::kS32_Type, 1 },
{ "scalar", SkMetaData::kScalar_Type, 1 },
{ "ptr", SkMetaData::kPtr_Type, 1 },
{ "hello", SkMetaData::kString_Type, sizeof("world") },
{ "true", SkMetaData::kBool_Type, 1 },
{ "false", SkMetaData::kBool_Type, 1 }
};
int loop = 0;
int count;
SkMetaData::Type t;
while ((name = iter.next(&t, &count)) != NULL)
{
int match = 0;
for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++)
{
if (!strcmp(name, gElems[i].fName))
{
match += 1;
SkASSERT(gElems[i].fType == t);
SkASSERT(gElems[i].fCount == count);
}
}
SkASSERT(match == 1);
loop += 1;
}
SkASSERT(loop == SK_ARRAY_COUNT(gElems));
SkASSERT(m1.removeS32("int"));
SkASSERT(m1.removeScalar("scalar"));
SkASSERT(m1.removeString("hello"));
SkASSERT(m1.removeBool("true"));
SkASSERT(m1.removeBool("false"));
SkASSERT(!m1.findS32("int"));
SkASSERT(!m1.findScalar("scalar"));
SkASSERT(!m1.findString("hello"));
SkASSERT(!m1.findBool("true"));
SkASSERT(!m1.findBool("false"));
#endif
}
#endif

112
tests/MetaDataTest.cpp Normal file
Просмотреть файл

@ -0,0 +1,112 @@
#include "Test.h"
#include "SkMetaData.h"
static void test_ptrs(skiatest::Reporter* reporter) {
SkRefCnt ref;
REPORTER_ASSERT(reporter, 1 == ref.getRefCnt());
{
SkMetaData md0, md1;
const char name[] = "refcnt";
md0.setRefCnt(name, &ref);
REPORTER_ASSERT(reporter, md0.findRefCnt(name));
REPORTER_ASSERT(reporter, md0.hasRefCnt(name, &ref));
REPORTER_ASSERT(reporter, 2 == ref.getRefCnt());
md1 = md0;
REPORTER_ASSERT(reporter, md1.findRefCnt(name));
REPORTER_ASSERT(reporter, md1.hasRefCnt(name, &ref));
REPORTER_ASSERT(reporter, 3 == ref.getRefCnt());
REPORTER_ASSERT(reporter, md0.removeRefCnt(name));
REPORTER_ASSERT(reporter, !md0.findRefCnt(name));
REPORTER_ASSERT(reporter, !md0.hasRefCnt(name, &ref));
REPORTER_ASSERT(reporter, 2 == ref.getRefCnt());
}
REPORTER_ASSERT(reporter, 1 == ref.getRefCnt());
}
static void TestMetaData(skiatest::Reporter* reporter) {
SkMetaData m1;
REPORTER_ASSERT(reporter, !m1.findS32("int"));
REPORTER_ASSERT(reporter, !m1.findScalar("scalar"));
REPORTER_ASSERT(reporter, !m1.findString("hello"));
REPORTER_ASSERT(reporter, !m1.removeS32("int"));
REPORTER_ASSERT(reporter, !m1.removeScalar("scalar"));
REPORTER_ASSERT(reporter, !m1.removeString("hello"));
REPORTER_ASSERT(reporter, !m1.removeString("true"));
REPORTER_ASSERT(reporter, !m1.removeString("false"));
m1.setS32("int", 12345);
m1.setScalar("scalar", SK_Scalar1 * 42);
m1.setString("hello", "world");
m1.setPtr("ptr", &m1);
m1.setBool("true", true);
m1.setBool("false", false);
int32_t n;
SkScalar s;
m1.setScalar("scalar", SK_Scalar1/2);
REPORTER_ASSERT(reporter, m1.findS32("int", &n) && n == 12345);
REPORTER_ASSERT(reporter, m1.findScalar("scalar", &s) && s == SK_Scalar1/2);
REPORTER_ASSERT(reporter, !strcmp(m1.findString("hello"), "world"));
REPORTER_ASSERT(reporter, m1.hasBool("true", true));
REPORTER_ASSERT(reporter, m1.hasBool("false", false));
SkMetaData::Iter iter(m1);
const char* name;
static const struct {
const char* fName;
SkMetaData::Type fType;
int fCount;
} gElems[] = {
{ "int", SkMetaData::kS32_Type, 1 },
{ "scalar", SkMetaData::kScalar_Type, 1 },
{ "ptr", SkMetaData::kPtr_Type, 1 },
{ "hello", SkMetaData::kString_Type, sizeof("world") },
{ "true", SkMetaData::kBool_Type, 1 },
{ "false", SkMetaData::kBool_Type, 1 }
};
int loop = 0;
int count;
SkMetaData::Type t;
while ((name = iter.next(&t, &count)) != NULL)
{
int match = 0;
for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++)
{
if (!strcmp(name, gElems[i].fName))
{
match += 1;
REPORTER_ASSERT(reporter, gElems[i].fType == t);
REPORTER_ASSERT(reporter, gElems[i].fCount == count);
}
}
REPORTER_ASSERT(reporter, match == 1);
loop += 1;
}
REPORTER_ASSERT(reporter, loop == SK_ARRAY_COUNT(gElems));
REPORTER_ASSERT(reporter, m1.removeS32("int"));
REPORTER_ASSERT(reporter, m1.removeScalar("scalar"));
REPORTER_ASSERT(reporter, m1.removeString("hello"));
REPORTER_ASSERT(reporter, m1.removeBool("true"));
REPORTER_ASSERT(reporter, m1.removeBool("false"));
REPORTER_ASSERT(reporter, !m1.findS32("int"));
REPORTER_ASSERT(reporter, !m1.findScalar("scalar"));
REPORTER_ASSERT(reporter, !m1.findString("hello"));
REPORTER_ASSERT(reporter, !m1.findBool("true"));
REPORTER_ASSERT(reporter, !m1.findBool("false"));
test_ptrs(reporter);
}
#include "TestClassDef.h"
DEFINE_TESTCLASS("MetaData", TestMetaDataClass, TestMetaData)

Просмотреть файл

@ -13,6 +13,7 @@ SOURCE := \
InfRectTest.cpp \ InfRectTest.cpp \
MathTest.cpp \ MathTest.cpp \
MatrixTest.cpp \ MatrixTest.cpp \
MetaDataTest.cpp \
PackBitsTest.cpp \ PackBitsTest.cpp \
PaintTest.cpp \ PaintTest.cpp \
ParsePathTest.cpp \ ParsePathTest.cpp \