Example #1
0
// Test insertWindow() and windowDestroyed() by random stacking operations.
void SuperStackerTest::testStateRandom()
{
    MRestacker mrs;
    WindowVec wins;
    bool bottomFirst;

    if (optLearning)
        QSKIP("nothing to learn", SkipSingle);

    // Verify that MRestacker is born with an empty state,
    // and that setting an empty set of windows works.
    mrs.verifyState(wins);
    mrs.setState(wins, bottomFirst=false);
    QVERIFY(mrs.verifyState(wins, bottomFirst));
    mrs.setState(wins, bottomFirst=true);
    QVERIFY(mrs.verifyState(wins, bottomFirst));

    // Test until each operations is executed >= @optNRandomTests times.
    unsigned nadds = 0, nmoves = 0, nremoves = 0, nshuffles = 0;
    while (nadds < optNRandomTests
           || nmoves < optNRandomTests
           || nremoves < optNRandomTests
           || nshuffles < optNRandomTests) {
        enum test { ADD, MOVE, REMOVE, SHUFFLE, LAST } what;
        switch (what = test(random() % int(LAST))) {
        default:
            break;
        case REMOVE:
            // Exercise windowDestroyed() by removing a random window,
            // if there's any.  Otherwise ADD one.
            if (!wins.isEmpty()) {
                unsigned idx = random() % wins.count();
                mrs.windowDestroyed(wins[idx]);
                wins.remove(idx);
                QVERIFY(mrs.verifyState(wins, bottomFirst));
                nremoves++;
                break;
            }
        case MOVE:
            // Exercise configureWindow() by moving a window around,
            // or ADD:ing one if there's nothing to move.
            if (!wins.isEmpty()) {
                int idx;
                Window win, below;

                // What to move and where.
                idx = random() % wins.count();
                win = wins[idx];
                wins.remove(idx);
                idx = random() % (wins.count()+1);

                // What shall be @below?
                if (bottomFirst)
                    // BOTTOM, win1, win2, ..., winN, TOP
                    below = idx > 0 ? wins[idx-1] : None;
                else
                    // TOP, win1, win2, ..., winN, BOTTOM
                    below = idx < wins.count() ? wins[idx] : None;

                wins.insert(idx, win);
                mrs.windowConfigured(win, below);
                QVERIFY(mrs.verifyState(wins, bottomFirst));
                nmoves++;
                break;
            }
        case ADD: {
            // Exercise createWindow() by adding a new window
            // at a random place.
            int idx;
            Window win, above;

            // What to insert and where.
            do win = 1+random(); while (wins.contains(win));
            idx = random() % (wins.count()+1);

            // What shall be @above?
            if (bottomFirst)
                // BOTTOM, win1, win2, ..., winN, TOP
                above = idx < wins.count() ? wins[idx] : None;
            else
                // TOP, win1, win2, ..., winN, BOTTOM
                above = idx > 0 ? wins[idx-1] : None;

            wins.insert(idx, win);
            mrs.windowCreated(win, above);
            QVERIFY(mrs.verifyState(wins, bottomFirst));
            nadds++;
            break;
        }
        case SHUFFLE:
            // Exercise setState() by setting a random order.
            // Also change @bottomFirst randomly.
            std::random_shuffle(wins.begin(), wins.end(), libcRandom);
            mrs.setState(wins, bottomFirst = random() % 2);
            QVERIFY(mrs.verifyState(wins, bottomFirst));
            nshuffles++;
            break;
        }
    }
    qDebug("\n         "
           "tested nadds=%u, nmoves=%u, nremoves=%u, nshuffles=%u",
            nadds, nmoves, nremoves, nshuffles);
}