// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Dart test program for testing stopwatch support.

library stopwatch_test;

import "package:expect/expect.dart";

class StopwatchTest {
  static bool checkTicking(Stopwatch sw) {
    Expect.isFalse(sw.isRunning);
    sw.start();
    Expect.isTrue(sw.isRunning);
    for (int i = 0; i < 1000000; i++) {
      int.parse(i.toString());
      if (sw.elapsedTicks > 0) {
        break;
      }
    }
    return sw.elapsedTicks > 0;
  }

  static bool checkStopping(Stopwatch sw) {
    sw.stop();
    Expect.isFalse(sw.isRunning);
    int v1 = sw.elapsedTicks;
    Expect.isTrue(v1 > 0); // Expect a non-zero elapsed time.
    Stopwatch sw2 = new Stopwatch(); // Used for verification.
    sw2.start();
    Expect.isTrue(sw2.isRunning);
    int sw2LastElapsed = 0;
    for (int i = 0; i < 100000; i++) {
      int.parse(i.toString());
      int v2 = sw.elapsedTicks;
      if (v1 != v2) {
        return false;
      }
      // If sw2 elapsed twice then sw must have advanced too if it wasn't
      // stopped.
      if (sw2LastElapsed > 0 && sw2.elapsedTicks > sw2LastElapsed) {
        break;
      }
      sw2LastElapsed = sw2.elapsedTicks;
    }
    // The test only makes sense if measurable time elapsed and elapsed time
    // on the stopped Stopwatch did not increase.
    Expect.isTrue(sw2.elapsedTicks > 0);
    return true;
  }

  static checkRestart() {
    Stopwatch sw = new Stopwatch();
    Expect.isFalse(sw.isRunning);
    sw.start();
    Expect.isTrue(sw.isRunning);
    for (int i = 0; i < 100000; i++) {
      int.parse(i.toString());
      if (sw.elapsedTicks > 0) {
        break;
      }
    }
    sw.stop();
    Expect.isFalse(sw.isRunning);
    int initial = sw.elapsedTicks;
    sw.start();
    Expect.isTrue(sw.isRunning);
    for (int i = 0; i < 100000; i++) {
      int.parse(i.toString());
      if (sw.elapsedTicks > initial) {
        break;
      }
    }
    sw.stop();
    Expect.isFalse(sw.isRunning);
    Expect.isTrue(sw.elapsedTicks > initial);
  }

  static checkReset() {
    Stopwatch sw = new Stopwatch();
    Expect.isFalse(sw.isRunning);
    sw.start();
    Expect.isTrue(sw.isRunning);
    for (int i = 0; i < 100000; i++) {
      int.parse(i.toString());
      if (sw.elapsedTicks > 0) {
        break;
      }
    }
    sw.stop();
    Expect.isFalse(sw.isRunning);
    sw.reset();
    Expect.isFalse(sw.isRunning);
    Expect.equals(0, sw.elapsedTicks);
    sw.start();
    Expect.isTrue(sw.isRunning);
    for (int i = 0; i < 100000; i++) {
      int.parse(i.toString());
      if (sw.elapsedTicks > 0) {
        break;
      }
    }
    sw.reset();
    Expect.isTrue(sw.isRunning);
    for (int i = 0; i < 100000; i++) {
      int.parse(i.toString());
      if (sw.elapsedTicks > 0) {
        break;
      }
    }
    sw.stop();
    Expect.isFalse(sw.isRunning);
    Expect.isTrue(sw.elapsedTicks > 0);
  }

  static testMain() {
    Stopwatch sw = new Stopwatch();
    Expect.isTrue(checkTicking(sw));
    Expect.isTrue(checkStopping(sw));
    checkRestart();
    checkReset();
  }
}

main() {
  StopwatchTest.testMain();
}
