void printWindows (const dz::Grabber * grabber) { typedef std::vector<dz::WindowInfo> WindowVec; WindowVec windows; dz::WindowInfo::populate(&windows); std::cout << "Window count: " << windows.size() << std::endl; for (WindowVec::const_iterator i = windows.begin(); i != windows.end(); i++) { const dz::WindowInfo & win (*i); std::cout << "Window " << win.id << " pid: " << win.pid << " title: " << win.title << " area: " << win.area << std::endl; } }
// Test some hairy stackings. static void presetTests(const WindowVec *fromStack, const MRestacker *fromState) { unsigned nmanual = 0; if (managedWindows.count() < 10) QSKIP("at least 10 windows needed", SkipSingle); // (0)(1, 4, 8)(2, 7)(3, 5, 6)(9) nmanual += mantest(QVector<unsigned>() << 0 << 8 << 7 << 6 << 1 << 3 << 5 << 2 << 4 << 9, fromStack, fromState); // (0, 4, 5)(9, 2, 1)(3)(8, 7, 6) nmanual += mantest(QVector<unsigned>() << 5 << 2 << 9 << 3 << 0 << 4 << 7 << 8 << 6 << 1, fromStack, fromState); // (0, 9, 2, 1, 4, 5)(3)(8, 7, 6) nmanual += mantest(QVector<unsigned>() << 5 << 2 << 9 << 3 << 1 << 4 << 7 << 8 << 6 << 0, fromStack, fromState); qDebug("tested %u g*i permutations", nmanual); verifyStats(fromStack ? &testPresetComparativeStats : &testPresetStandaloneStats, 0); printStats(); }
// Test rotating restackings, ie. when some windows are lowered // to the bottom from the top or vica versa. static void rotationTests(const WindowVec *fromStack, const MRestacker *fromState) { unsigned nrots = 0; MRestacker::WindowStack stack; // const LearntStatsTbl *stats = fromStack // ? &testRotationsComparativeStats : &testRotationsStandaloneStats; // Test all possible rotations of @managedWindows[0], [0:1], [0:2], ... while (stack.count() < managedWindows.count()) { stack.append(managedWindows[stack.count()]); nrots += rottest(stack, fromStack, fromState); // Just for fun test the reverse too. MRestacker::WindowStack reverse; while (reverse.count() < stack.count()) reverse.prepend(stack[reverse.count()]); nrots += rottest(reverse, fromStack, fromState); // FIXME: stats don't match because aggressive is chosen more often due // to naiveOpsFinder(). It makes little sense to compare exact stats anyway, // it'd be better to check only the number of configures generated... // verifyStats(stats, stack.count()-1); } qDebug("tested %u rotations", nrots); printStats(); }
// Test random stackings. static void randomTest(const WindowVec *fromStack, const MRestacker *fromState) { if (optLearning) QSKIP("nothing to learn", SkipSingle); // Generate @nrandom random permutations of @managedWindows. MRestacker::WindowStack stack(managedWindows.toList()); for (unsigned i = 0; i < optNRandomTests; i++) { std::random_shuffle(stack.begin(), stack.end(), libcRandom); dotest(stack, fromStack, fromState); } qDebug("tested %u random permutations", optNRandomTests); printStats(); }
// Open @Dpy, create @fakeRoot and @optNWindows @managedWindows. void SuperStackerTest::initTestCase() { if (!optHeadless) { Dpy = XOpenDisplay(NULL); if (!Dpy) qWarning("couldn't connect to X, degrading to headless mode"); } // Create @managedWindows. if (Dpy != NULL) { fakeRoot = XCreateSimpleWindow(Dpy, DefaultRootWindow(Dpy), 0, 0, 100, 100, 0, 0, 0); QVERIFY(fakeRoot != None); for (int i = 0; i < optNWindows; i++) managedWindows << XCreateSimpleWindow(Dpy, fakeRoot, 0, 0, 100, 100, 0, 0, 0); QVERIFY(!managedWindows.contains(None)); // Randomize the reference order to make sure that the superstacker // doesn't depend on the XIDs. std::random_shuffle(managedWindows.begin(), managedWindows.end(), libcRandom); referenceRestack(managedWindows); } else { // Make up a bunch of unique XID:s. qDebug("initializing headless mode"); while (managedWindows.count() < optNWindows) { Window win = 1 + random(); if (!managedWindows.contains(win)) managedWindows << win; } } // Initialize MRestacker and tell it what windows are managed. testRestacker.init(Dpy, fakeRoot); testRestacker.setState(managedWindows); QVERIFY(testRestacker.verifyState(managedWindows)); if (Dpy) QVERIFY(testRestacker.verifyState()); QVERIFY(testRestacker.getState() == managedWindows.toList()); }
// 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); }