1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
9cb93a386Sopenharmony_ci#include "src/core/SkTDPQueue.h"
10cb93a386Sopenharmony_ci#include "tests/Test.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_cinamespace { bool intless(const int& a, const int& b) { return a < b; } }
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cistatic void simple_test(skiatest::Reporter* reporter) {
15cb93a386Sopenharmony_ci    SkTDPQueue<int, intless> heap;
16cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.count());
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci    heap.insert(0);
19cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.count());
20cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.peek());
21cb93a386Sopenharmony_ci    heap.pop();
22cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.count());
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci    heap.insert(0);
25cb93a386Sopenharmony_ci    heap.insert(1);
26cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 2 == heap.count());
27cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.peek());
28cb93a386Sopenharmony_ci    heap.pop();
29cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.count());
30cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.peek());
31cb93a386Sopenharmony_ci    heap.pop();
32cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.count());
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci    heap.insert(2);
35cb93a386Sopenharmony_ci    heap.insert(1);
36cb93a386Sopenharmony_ci    heap.insert(0);
37cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 3 == heap.count());
38cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.peek());
39cb93a386Sopenharmony_ci    heap.pop();
40cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 2 == heap.count());
41cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.peek());
42cb93a386Sopenharmony_ci    heap.pop();
43cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.count());
44cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 2 == heap.peek());
45cb93a386Sopenharmony_ci    heap.pop();
46cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.count());
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    heap.insert(2);
49cb93a386Sopenharmony_ci    heap.insert(3);
50cb93a386Sopenharmony_ci    heap.insert(0);
51cb93a386Sopenharmony_ci    heap.insert(1);
52cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 4 == heap.count());
53cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.peek());
54cb93a386Sopenharmony_ci    heap.pop();
55cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 3 == heap.count());
56cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.peek());
57cb93a386Sopenharmony_ci    heap.pop();
58cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 2 == heap.count());
59cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 2 == heap.peek());
60cb93a386Sopenharmony_ci    heap.pop();
61cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == heap.count());
62cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 3 == heap.peek());
63cb93a386Sopenharmony_ci    heap.pop();
64cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == heap.count());
65cb93a386Sopenharmony_ci}
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_cistruct Mock {
68cb93a386Sopenharmony_ci    int fValue;
69cb93a386Sopenharmony_ci    int fPriority;
70cb93a386Sopenharmony_ci    mutable int fIndex;
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci    static bool LessP(Mock* const& a, Mock* const& b) { return a->fPriority < b->fPriority; }
73cb93a386Sopenharmony_ci    static int* PQIndex(Mock* const& mock) { return &mock->fIndex; }
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    bool operator== (const Mock& that) const {
76cb93a386Sopenharmony_ci        return fValue == that.fValue && fPriority == that.fPriority;
77cb93a386Sopenharmony_ci    }
78cb93a386Sopenharmony_ci    bool operator!= (const Mock& that) const { return !(*this == that); }
79cb93a386Sopenharmony_ci};
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_civoid random_test(skiatest::Reporter* reporter) {
82cb93a386Sopenharmony_ci    SkRandom random;
83cb93a386Sopenharmony_ci    static const Mock kSentinel = {-1, -1, -1};
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    for (int i = 0; i < 100; ++i) {
86cb93a386Sopenharmony_ci        // Create a random set of Mock objects.
87cb93a386Sopenharmony_ci        int count = random.nextULessThan(100);
88cb93a386Sopenharmony_ci        SkTDArray<Mock> array;
89cb93a386Sopenharmony_ci        array.setReserve(count);
90cb93a386Sopenharmony_ci        for (int j = 0; j < count; ++j) {
91cb93a386Sopenharmony_ci            Mock* mock = array.append();
92cb93a386Sopenharmony_ci            mock->fPriority = random.nextS();
93cb93a386Sopenharmony_ci            mock->fValue = random.nextS();
94cb93a386Sopenharmony_ci            mock->fIndex = -1;
95cb93a386Sopenharmony_ci            if (*mock == kSentinel) {
96cb93a386Sopenharmony_ci                array.pop();
97cb93a386Sopenharmony_ci                --j;
98cb93a386Sopenharmony_ci            }
99cb93a386Sopenharmony_ci        }
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci        // Stick the mock objects in the pqueue.
102cb93a386Sopenharmony_ci        SkTDPQueue<Mock*, Mock::LessP, Mock::PQIndex> pq;
103cb93a386Sopenharmony_ci        for (int j = 0; j < count; ++j) {
104cb93a386Sopenharmony_ci            pq.insert(&array[j]);
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pq.count() == array.count());
107cb93a386Sopenharmony_ci        for (int j = 0; j < count; ++j) {
108cb93a386Sopenharmony_ci            // every item should have an entry in the queue.
109cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, -1 != array[j].fIndex);
110cb93a386Sopenharmony_ci        }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci        // Begin the test.
113cb93a386Sopenharmony_ci        while (pq.count()) {
114cb93a386Sopenharmony_ci            // Make sure the top of the queue is really the highest priority.
115cb93a386Sopenharmony_ci            Mock* top = pq.peek();
116cb93a386Sopenharmony_ci            for (int k = 0; k < count; ++k) {
117cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, kSentinel == array[k] ||
118cb93a386Sopenharmony_ci                                            array[k].fPriority >= top->fPriority);
119cb93a386Sopenharmony_ci            }
120cb93a386Sopenharmony_ci            // Do one of three random actions:
121cb93a386Sopenharmony_ci            unsigned action = random.nextULessThan(3);
122cb93a386Sopenharmony_ci            switch (action) {
123cb93a386Sopenharmony_ci                case 0: { // pop the top,
124cb93a386Sopenharmony_ci                    top = pq.peek();
125cb93a386Sopenharmony_ci                    REPORTER_ASSERT(reporter, array.begin() <= top && top < array.end());
126cb93a386Sopenharmony_ci                    pq.pop();
127cb93a386Sopenharmony_ci                    *top = kSentinel;
128cb93a386Sopenharmony_ci                    break;
129cb93a386Sopenharmony_ci                }
130cb93a386Sopenharmony_ci                case 1: { // remove a random element,
131cb93a386Sopenharmony_ci                    int item;
132cb93a386Sopenharmony_ci                    do {
133cb93a386Sopenharmony_ci                        item = random.nextULessThan(count);
134cb93a386Sopenharmony_ci                    } while (array[item] == kSentinel);
135cb93a386Sopenharmony_ci                    pq.remove(&array[item]);
136cb93a386Sopenharmony_ci                    array[item] = kSentinel;
137cb93a386Sopenharmony_ci                    break;
138cb93a386Sopenharmony_ci                }
139cb93a386Sopenharmony_ci                case 2: { // or change an element's priority.
140cb93a386Sopenharmony_ci                    int item;
141cb93a386Sopenharmony_ci                    do {
142cb93a386Sopenharmony_ci                        item = random.nextULessThan(count);
143cb93a386Sopenharmony_ci                    } while (array[item] == kSentinel);
144cb93a386Sopenharmony_ci                    array[item].fPriority = random.nextS();
145cb93a386Sopenharmony_ci                    pq.priorityDidChange(&array[item]);
146cb93a386Sopenharmony_ci                    break;
147cb93a386Sopenharmony_ci                }
148cb93a386Sopenharmony_ci            }
149cb93a386Sopenharmony_ci        }
150cb93a386Sopenharmony_ci   }
151cb93a386Sopenharmony_ci}
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_civoid sort_test(skiatest::Reporter* reporter) {
154cb93a386Sopenharmony_ci    SkRandom random;
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci    SkTDPQueue<Mock *, Mock::LessP, Mock::PQIndex> pqTest;
157cb93a386Sopenharmony_ci    SkTDPQueue<Mock *, Mock::LessP, Mock::PQIndex> pqControl;
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    // Create a random set of Mock objects and populate the test queue.
160cb93a386Sopenharmony_ci    int count = random.nextULessThan(100);
161cb93a386Sopenharmony_ci    SkTDArray<Mock> testArray;
162cb93a386Sopenharmony_ci    testArray.setReserve(count);
163cb93a386Sopenharmony_ci    for (int i = 0; i < count; i++) {
164cb93a386Sopenharmony_ci        Mock *mock = testArray.append();
165cb93a386Sopenharmony_ci        mock->fPriority = random.nextS();
166cb93a386Sopenharmony_ci        mock->fValue = random.nextS();
167cb93a386Sopenharmony_ci        mock->fIndex = -1;
168cb93a386Sopenharmony_ci        pqTest.insert(&testArray[i]);
169cb93a386Sopenharmony_ci    }
170cb93a386Sopenharmony_ci
171cb93a386Sopenharmony_ci    // Stick equivalent mock objects into the control queue.
172cb93a386Sopenharmony_ci    SkTDArray<Mock> controlArray;
173cb93a386Sopenharmony_ci    controlArray.setReserve(count);
174cb93a386Sopenharmony_ci    for (int i = 0; i < count; i++) {
175cb93a386Sopenharmony_ci        Mock *mock = controlArray.append();
176cb93a386Sopenharmony_ci        mock->fPriority = testArray[i].fPriority;
177cb93a386Sopenharmony_ci        mock->fValue = testArray[i].fValue;
178cb93a386Sopenharmony_ci        mock->fIndex = -1;
179cb93a386Sopenharmony_ci        pqControl.insert(&controlArray[i]);
180cb93a386Sopenharmony_ci    }
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci    // Sort the queue
183cb93a386Sopenharmony_ci    pqTest.sort();
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_ci    // Compare elements in the queue to ensure they are in sorted order
186cb93a386Sopenharmony_ci    int prevPriority = pqTest.peek()->fPriority;
187cb93a386Sopenharmony_ci    for (int i = 0; i < count; i++) {
188cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, i <= pqTest.at(i)->fIndex);
189cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, prevPriority <= pqTest.at(i)->fPriority);
190cb93a386Sopenharmony_ci        prevPriority = pqTest.at(i)->fPriority;
191cb93a386Sopenharmony_ci    }
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci    // Verify that after sorting the queue still produces the same result as the control queue
194cb93a386Sopenharmony_ci    for (int i = 0; i < count; i++) {
195cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, *pqControl.peek() == *pqTest.peek());
196cb93a386Sopenharmony_ci        pqControl.pop();
197cb93a386Sopenharmony_ci        pqTest.pop();
198cb93a386Sopenharmony_ci    }
199cb93a386Sopenharmony_ci}
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ciDEF_TEST(TDPQueueTest, reporter) {
202cb93a386Sopenharmony_ci    simple_test(reporter);
203cb93a386Sopenharmony_ci    random_test(reporter);
204cb93a386Sopenharmony_ci    sort_test(reporter);
205cb93a386Sopenharmony_ci}
206