1363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
2363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger/*
3363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Copyright 2012 Google Inc.
4363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger *
5363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
6363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * found in the LICENSE file.
7363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */
8363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "Test.h"
9363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkBitmap.h"
11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkBitmapChecksummer.h"
12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkChecksum.h"
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkCityHash.h"
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkColor.h"
15363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// Word size that is large enough to hold results of any checksum type.
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergertypedef uint64_t checksum_result;
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergernamespace skiatest {
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    class ChecksumTestClass : public Test {
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    public:
22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        static Test* Factory(void*) {return SkNEW(ChecksumTestClass); }
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    protected:
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        virtual void onGetName(SkString* name) { name->set("Checksum"); }
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        virtual void onRun(Reporter* reporter) {
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->fReporter = reporter;
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            RunTest();
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    private:
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        enum Algorithm {
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kSkChecksum,
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kSkCityHash32,
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kSkCityHash64
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        };
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Call Compute(data, size) on the appropriate checksum algorithm,
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // depending on this->fWhichAlgorithm.
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        checksum_result ComputeChecksum(const char *data, size_t size) {
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            switch(fWhichAlgorithm) {
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case kSkChecksum:
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT_MESSAGE(fReporter,
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                        reinterpret_cast<uintptr_t>(data) % 4 == 0,
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                        "test data pointer is not 32-bit aligned");
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT_MESSAGE(fReporter, SkIsAlign4(size),
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                        "test data size is not 32-bit aligned");
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return SkChecksum::Compute(reinterpret_cast<const uint32_t *>(data), size);
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case kSkCityHash32:
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return SkCityHash::Compute32(data, size);
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case kSkCityHash64:
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return SkCityHash::Compute64(data, size);
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            default:
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkString message("fWhichAlgorithm has unknown value ");
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                message.appendf("%d", fWhichAlgorithm);
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fReporter->reportFailed(message);
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // we never get here
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return 0;
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Confirm that the checksum algorithm (specified by fWhichAlgorithm)
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // generates the same results if called twice over the same data.
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void TestChecksumSelfConsistency(size_t buf_size) {
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkAutoMalloc storage(buf_size);
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            char* ptr = reinterpret_cast<char *>(storage.get());
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            GetTestDataChecksum(8, 0) ==
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            GetTestDataChecksum(8, 0));
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            GetTestDataChecksum(8, 0) !=
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            GetTestDataChecksum(8, 1));
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            sk_bzero(ptr, buf_size);
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            checksum_result prev = 0;
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // assert that as we change values (from 0 to non-zero) in
77363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // our buffer, we get a different value
78363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            for (size_t i = 0; i < buf_size; ++i) {
79363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                ptr[i] = (i & 0x7f) + 1; // need some non-zero value here
80363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // Try checksums of different-sized chunks, but always
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // 32-bit aligned and big enough to contain all the
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // nonzero bytes.  (Remaining bytes will still be zero
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // from the initial sk_bzero() call.)
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                size_t checksum_size = (((i/4)+1)*4);
86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT(fReporter, checksum_size <= buf_size);
87363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                checksum_result curr = ComputeChecksum(ptr, checksum_size);
89363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT(fReporter, prev != curr);
90363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                checksum_result again = ComputeChecksum(ptr, checksum_size);
91363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                REPORTER_ASSERT(fReporter, again == curr);
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                prev = curr;
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Return the checksum of a buffer of bytes 'len' long.
97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The pattern of values within the buffer will be consistent
98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // for every call, based on 'seed'.
99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        checksum_result GetTestDataChecksum(size_t len, char seed=0) {
100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkAutoMalloc storage(len);
101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            char* start = reinterpret_cast<char *>(storage.get());
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            char* ptr = start;
103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            for (size_t i = 0; i < len; ++i) {
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                *ptr++ = ((seed+i) & 0x7f);
105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            checksum_result result = ComputeChecksum(start, len);
107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return result;
108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Fill in bitmap with test data.
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void CreateTestBitmap(SkBitmap &bitmap, SkBitmap::Config config, int width, int height,
112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              SkColor color) {
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            bitmap.setConfig(config, width, height);
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, bitmap.allocPixels());
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            bitmap.setIsOpaque(true);
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            bitmap.eraseColor(color);
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void RunTest() {
120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Test self-consistency of checksum algorithms.
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkChecksum;
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            TestChecksumSelfConsistency(128);
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkCityHash32;
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            TestChecksumSelfConsistency(128);
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkCityHash64;
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            TestChecksumSelfConsistency(128);
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Test checksum results that should be consistent across
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // versions and platforms.
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkChecksum;
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0);
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkCityHash32;
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0xdc56d17a);
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(4)   == 0x616e1132);
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(8)   == 0xeb0fd2d6);
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(128) == 0x5321e430);
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(132) == 0x924a10e4);
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(256) == 0xd4de9dc9);
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(260) == 0xecf0325d);
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkCityHash64;
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0x9ae16a3b2f90404fULL);
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(4)   == 0x82bffd898958e540ULL);
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(8)   == 0xad5a13e1e8e93b98ULL);
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(128) == 0x10b153630af1f395ULL);
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(132) == 0x7db71dc4adcc6647ULL);
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(256) == 0xeee763519b91b010ULL);
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter, GetTestDataChecksum(260) == 0x2fe19e0b2239bc23ULL);
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // TODO: note the weakness exposed by these collisions...
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // We need to improve the SkChecksum algorithm.
151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // We would prefer that these asserts FAIL!
152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Filed as https://code.google.com/p/skia/issues/detail?id=981
153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // ('SkChecksum algorithm allows for way too many collisions')
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fWhichAlgorithm = kSkChecksum;
155363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                GetTestDataChecksum(128) == GetTestDataChecksum(256));
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
158363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                GetTestDataChecksum(132) == GetTestDataChecksum(260));
159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Test SkBitmapChecksummer
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkBitmap bitmap;
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // initial test case
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            CreateTestBitmap(bitmap, SkBitmap::kARGB_8888_Config, 333, 555, SK_ColorBLUE);
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            SkBitmapChecksummer::Compute64(bitmap) == 0x18f9df68b1b02f38ULL);
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // same pixel data but different dimensions should yield a different checksum
167363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            CreateTestBitmap(bitmap, SkBitmap::kARGB_8888_Config, 555, 333, SK_ColorBLUE);
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            SkBitmapChecksummer::Compute64(bitmap) == 0x6b0298183f786c8eULL);
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // same dimensions but different color should yield a different checksum
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            CreateTestBitmap(bitmap, SkBitmap::kARGB_8888_Config, 555, 333, SK_ColorGREEN);
172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
173363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            SkBitmapChecksummer::Compute64(bitmap) == 0xc6b4b3f6fadaaf37ULL);
174363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // same pixel colors in a different config should yield the same checksum
175363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            CreateTestBitmap(bitmap, SkBitmap::kARGB_4444_Config, 555, 333, SK_ColorGREEN);
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            REPORTER_ASSERT(fReporter,
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            SkBitmapChecksummer::Compute64(bitmap) == 0xc6b4b3f6fadaaf37ULL);
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Reporter* fReporter;
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Algorithm fWhichAlgorithm;
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
184363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static TestRegistry gReg(ChecksumTestClass::Factory);
185363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
186