Chromium Code Reviews| Index: tests/GrTRecorderTest.cpp |
| diff --git a/tests/GrTRecorderTest.cpp b/tests/GrTRecorderTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a6274644d40a6c5820c1c66244cc2e36fe546477 |
| --- /dev/null |
| +++ b/tests/GrTRecorderTest.cpp |
| @@ -0,0 +1,245 @@ |
| +/* |
| + * Copyright 2014 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#if SK_SUPPORT_GPU |
| + |
| +#include "SkMatrix.h" |
| +#include "SkString.h" |
| +#include "GrTRecorder.h" |
| +#include "Test.h" |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| +static int activeRecorderItems = 0; |
| + |
| +class IntWrapper { |
| +public: |
| + IntWrapper() {} |
| + IntWrapper(int value) : fValue(value) {} |
| + operator int() { return fValue; } |
| +private: |
| + int fValue; |
| +}; |
| + |
| +static void test_empty_back(skiatest::Reporter* reporter) { |
| + GrTRecorder<IntWrapper, int> recorder(0); |
| + |
| + REPORTER_ASSERT(reporter, recorder.empty()); |
| + |
| + for (int i = 0; i < 100; ++i) { |
| + REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder, IntWrapper, (i))); |
| + REPORTER_ASSERT(reporter, !recorder.empty()); |
| + REPORTER_ASSERT(reporter, i == recorder.back()); |
| + } |
| + |
| + REPORTER_ASSERT(reporter, !recorder.empty()); |
| + |
| + recorder.reset(); |
| + |
| + REPORTER_ASSERT(reporter, recorder.empty()); |
| +} |
| + |
| +struct ExtraData { |
| + typedef GrTRecorder<ExtraData, int> Recorder; |
| + |
| + ExtraData(int i) : fData(i) { |
| + int* extraData = this->extraData(); |
| + for (int j = 0; j < i; j++) { |
| + extraData[j] = i; |
| + } |
| + ++activeRecorderItems; |
| + } |
| + ~ExtraData() { |
| + --activeRecorderItems; |
| + } |
| + int* extraData() { |
| + return reinterpret_cast<int*>(Recorder::GetDataForItem(this)); |
| + } |
| + int fData; |
| +}; |
| + |
| +static void test_extra_data(skiatest::Reporter* reporter) { |
| + ExtraData::Recorder recorder(0); |
| + for (int i = 0; i < 100; ++i) { |
| + GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, ExtraData, (i), i * sizeof(int)); |
| + } |
| + REPORTER_ASSERT(reporter, 100 == activeRecorderItems); |
| + |
| + ExtraData::Recorder::Iter iter(recorder); |
| + for (int i = 0; i < 100; ++i) { |
| + REPORTER_ASSERT(reporter, iter.next()); |
| + REPORTER_ASSERT(reporter, i == iter->fData); |
| + for (int j = 0; j < i; j++) { |
| + REPORTER_ASSERT(reporter, i == iter->extraData()[j]); |
| + } |
| + } |
| + REPORTER_ASSERT(reporter, !iter.next()); |
| + |
| + recorder.reset(); |
| + REPORTER_ASSERT(reporter, 0 == activeRecorderItems); |
| +} |
| + |
| +enum ClassType { |
| + kBase_ClassType, |
| + kSubclass_ClassType, |
| + kSubSubclass_ClassType, |
| + kSubclassExtraData_ClassType, |
| + kSubclassEmpty_ClassType, |
| + |
| + kNumClassTypes |
| +}; |
| + |
| +class Base { |
| +public: |
| + typedef GrTRecorder<Base, void*> Recorder; |
| + |
| + Base() { |
| + fMatrix.reset(); |
| + ++activeRecorderItems; |
| + } |
| + |
| + virtual ~Base() { --activeRecorderItems; } |
| + |
| + virtual ClassType getType() { return kBase_ClassType; } |
| + |
| + virtual void validate(skiatest::Reporter* reporter) const { |
| + REPORTER_ASSERT(reporter, fMatrix.isIdentity()); |
| + } |
| + |
| +private: |
| + SkMatrix fMatrix; |
| +}; |
| + |
| +class Subclass : public Base { |
| +public: |
| + Subclass() : fString("Lorem ipsum dolor sit amet") {} |
| + |
| + virtual ClassType getType() { return kSubclass_ClassType; } |
| + |
| + virtual void validate(skiatest::Reporter* reporter) const { |
| + Base::validate(reporter); |
| + REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str())); |
| + } |
| + |
| +private: |
| + SkString fString; |
| +}; |
| + |
| +class SubSubclass : public Subclass { |
| +public: |
| + SubSubclass() : fInt(1234), fFloat(1.234f) {} |
| + |
| + virtual ClassType getType() { return kSubSubclass_ClassType; } |
| + |
| + virtual void validate(skiatest::Reporter* reporter) const { |
| + Subclass::validate(reporter); |
| + REPORTER_ASSERT(reporter, 1234 == fInt); |
| + REPORTER_ASSERT(reporter, 1.234f == fFloat); |
| + } |
| + |
| +private: |
| + int fInt; |
| + float fFloat; |
| +}; |
| + |
| +class SubclassExtraData : public Base { |
| +public: |
| + SubclassExtraData(int length) : fLength(length) { |
| + int* data = reinterpret_cast<int*>(Recorder::GetDataForItem(this)); |
| + for (int i = 0; i < fLength; ++i) { |
| + data[i] = ValueAt(i); |
|
Chris Dalton
2014/10/13 23:17:52
I still don't understand this fully, but in a rele
|
| + } |
| + } |
| + |
| + virtual ClassType getType() { return kSubclassExtraData_ClassType; } |
| + |
| + virtual void validate(skiatest::Reporter* reporter) const { |
| + Base::validate(reporter); |
| + const int* data = reinterpret_cast<const int*>(Recorder::GetDataForItem(this)); |
| + for (int i = 0; i < fLength; ++i) { |
| + REPORTER_ASSERT(reporter, ValueAt(i) == data[i]); |
| + } |
| + } |
| + |
| +private: |
| + static int ValueAt(uint64_t i) { return 123456789 + 987654321 * i; } |
| + int fLength; |
| +}; |
| + |
| +class SubclassEmpty : public Base { |
| +public: |
| + virtual ClassType getType() { return kSubclassEmpty_ClassType; } |
| +}; |
| + |
| +static void test_subclasses(skiatest::Reporter* reporter) { |
| + class Order { |
| + public: |
| + Order() { this->reset(); } |
| + void reset() { fCurrent = 0; } |
| + ClassType next() { |
| + fCurrent = 1664525 * fCurrent + 1013904223; |
| + return static_cast<ClassType>(fCurrent % kNumClassTypes); |
| + } |
| + private: |
| + uint32_t fCurrent; |
| + }; |
| + |
| + Base::Recorder recorder(1024); |
| + |
| + Order order; |
| + for (int i = 0; i < 1000; i++) { |
| + switch (order.next()) { |
| + case kBase_ClassType: |
| + GrNEW_APPEND_TO_RECORDER(recorder, Base, ()); |
| + break; |
| + |
| + case kSubclass_ClassType: |
| + GrNEW_APPEND_TO_RECORDER(recorder, Subclass, ()); |
| + break; |
| + |
| + case kSubSubclass_ClassType: |
| + GrNEW_APPEND_TO_RECORDER(recorder, SubSubclass, ()); |
| + break; |
| + |
| + case kSubclassExtraData_ClassType: |
| + GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassExtraData, (i), sizeof(int) * i); |
| + break; |
| + |
| + case kSubclassEmpty_ClassType: |
| + GrNEW_APPEND_TO_RECORDER(recorder, SubclassEmpty, ()); |
| + break; |
| + |
| + default: |
| + reporter->reportFailed(SkString("Invalid class type")); |
| + break; |
| + } |
| + } |
| + REPORTER_ASSERT(reporter, 1000 == activeRecorderItems); |
| + |
| + order.reset(); |
| + Base::Recorder::Iter iter(recorder); |
| + for (int i = 0; i < 1000; ++i) { |
| + REPORTER_ASSERT(reporter, iter.next()); |
| + REPORTER_ASSERT(reporter, order.next() == iter->getType()); |
| + iter->validate(reporter); |
| + } |
| + REPORTER_ASSERT(reporter, !iter.next()); |
| + |
| + // Don't reset the recorder. It should automatically destruct all its items. |
| +} |
| + |
| +DEF_GPUTEST(GrTRecorder, reporter, factory) { |
| + test_empty_back(reporter); |
| + |
| + test_extra_data(reporter); |
| + REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // test_extra_data should call reset(). |
| + |
| + test_subclasses(reporter); |
| + REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // Ensure ~GrTRecorder invokes dtors. |
| +} |
| + |
| +#endif |