Skip to content

Commit

Permalink
Expose random seed and make static test nullable (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkorbel1 authored Sep 26, 2023
1 parent f968e64 commit 3404b1f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 15 deletions.
51 changes: 43 additions & 8 deletions lib/src/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@ abstract class Test extends Component {
/// which can be manually overriden. If all random behavior in
/// the test derives from [random] object, then tests can be
/// reproduced by setting the same seed again.
static Random get random => instance._random;
///
/// This is `null` if [instance] is `null`.
static Random? get random => instance?._random;

/// The minimum level that should immediately kill the test.
///
/// This level should be greater than or equal to [failLevel].
Level killLevel = Level.SHOUT;
Level killLevel;

/// The minimum level that should cause the test to fail after completing.
///
/// A failed test will continue to run, then throw an Exception. This level
/// should be less than or equal to [killLevel].
Level failLevel = Level.SEVERE;
Level failLevel;

/// Stores whether a failure has been detected in this test.
///
Expand All @@ -51,8 +53,12 @@ abstract class Test extends Component {
/// [Exception].
bool failureDetected = false;

/// The singleton Test for this simulation.
static late Test instance;
/// The singleton [Test] for this simulation.
///
/// It is `null` if there is no currently active [Test]. It is set back to
/// `null` after a it is finished running.
static Test? get instance => _instance;
static Test? _instance;

/// The [Random] object for this [Test].
final Random _random;
Expand All @@ -65,20 +71,47 @@ abstract class Test extends Component {
/// the [Test] will not fail when those messages are emitted.
Level printLevel;

/// If selected at [Test] construction, this is the seed provided for
/// the [random] object.
final int? randomSeed;

/// Constructs a new [Test] named [name].
///
/// Only one [Test] should be created per simulation. It will set
/// the value of [random] to a new [Random] object with [randomSeed]
/// as the seed. If no [randomSeed] is specified, a random seed
/// will be selected. To rerun a test with the same randomized behavior,
/// pass the same [randomSeed] as the previous run.
Test(String name, {int? randomSeed, this.printLevel = Level.ALL})
: _random = Random(randomSeed),
Test(
String name, {
this.randomSeed,
this.printLevel = Level.ALL,
this.failLevel = Level.SEVERE,
this.killLevel = Level.SHOUT,
}) : _random = Random(randomSeed),
super(name, null) {
instance = this;
if (_instance != null) {
throw Exception('Instance of `Test` is already running!');
}

_instance = this;
configureLogger();
}

/// Resets static awareness of the [Simulator] and [Test] to a safe initial
/// state.
///
/// This includes a call to [Simulator.reset] and clearing the [instance]
/// reference to `null`.
///
/// This is important, for example, if you're running a variety of tests in
/// unit test suite.
static Future<void> reset() async {
await Simulator.reset();

_instance = null;
}

/// A handle to the subscription to the root [Logger], so that it
/// can be cancelled at the end of the test.
late final StreamSubscription<LogRecord> _loggerSubscription;
Expand Down Expand Up @@ -174,5 +207,7 @@ abstract class Test extends Component {
logger.finest('Simulation ended, test complete.');

await _loggerSubscription.cancel();

_instance = null;
}
}
4 changes: 2 additions & 2 deletions test/counter_example_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
// Author: Max Korbel <[email protected]>

import 'package:logging/logging.dart';
import 'package:rohd/rohd.dart';
import 'package:rohd_vf/rohd_vf.dart';
import 'package:test/test.dart';
import '../example/main.dart' as example;

void main() {
tearDown(() async {
await Simulator.reset();
await Test.reset();
});

test('counter example test', () async {
Expand Down
2 changes: 1 addition & 1 deletion test/pending_driver_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void main() {
});

tearDown(() async {
await Simulator.reset();
await Test.reset();
});

test('pending driver simple', () async {
Expand Down
23 changes: 21 additions & 2 deletions test/test_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ForeverObjectionTest extends Test {
}

class NormalTest extends Test {
NormalTest() : super('normalTest');
NormalTest() : super('normalTest', randomSeed: 123);
@override
Future<void> run(Phase phase) async {
unawaited(super.run(phase));
Expand Down Expand Up @@ -109,7 +109,7 @@ void main() {
});

tearDown(() async {
await Simulator.reset();
await Test.reset();
});

test('Test does not wait for objections if simulation ends', () async {
Expand Down Expand Up @@ -176,4 +176,23 @@ void main() {

expect(sawError, isFalse);
});

group('Test.instance', () {
test('test already created', () async {
NormalTest();

expect(Test.instance, isNotNull);
expect(Test.random, isNotNull);
expect(Test.instance!.randomSeed, 123);

await Test.instance!.start();

expect(Test.instance, isNull);
});

test('test not created', () {
expect(Test.instance, isNull);
expect(Test.random, isNull);
});
});
}
4 changes: 2 additions & 2 deletions test/waiter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import 'dart:async';

import 'package:rohd/rohd.dart';
import 'package:rohd_vf/src/waiter.dart';
import 'package:rohd_vf/rohd_vf.dart';
import 'package:test/test.dart';

void main() {
Expand All @@ -21,7 +21,7 @@ void main() {
});

tearDown(() async {
await Simulator.reset();
await Test.reset();
});

test('0 cycles is instant', () async {
Expand Down

0 comments on commit 3404b1f

Please sign in to comment.