| 1 | import 'dart:math'; |
| 2 | |
| 3 | import 'package:bitcoin_base/bitcoin_base.dart'; |
| 4 | import 'package:cw_bitcoin/output_ordering.dart'; |
| 5 | import 'package:flutter_test/flutter_test.dart'; |
| 6 | |
| 7 | void main() { |
| 8 | group('orderOutputs', () { |
| 9 | test('none preserves the given order', () { |
| 10 | final outputs = [0, 1, 2, 3, 4]; |
| 11 | expect(orderOutputs(outputs, BitcoinOrdering.none), outputs); |
| 12 | }); |
| 13 | |
| 14 | test('does not mutate the input list', () { |
| 15 | final outputs = [0, 1, 2, 3, 4]; |
| 16 | orderOutputs(outputs, BitcoinOrdering.shuffle, rng: Random(1)); |
| 17 | expect(outputs, [0, 1, 2, 3, 4]); |
| 18 | }); |
| 19 | |
| 20 | test('returns a new list instance', () { |
| 21 | final outputs = [0, 1, 2]; |
| 22 | expect(identical(orderOutputs(outputs, BitcoinOrdering.none), outputs), isFalse); |
| 23 | }); |
| 24 | |
| 25 | test('shuffle preserves the multiset of outputs', () { |
| 26 | final outputs = [0, 1, 2, 3, 4, 5, 6, 7]; |
| 27 | final shuffled = orderOutputs(outputs, BitcoinOrdering.shuffle, rng: Random(7)); |
| 28 | expect(shuffled.length, outputs.length); |
| 29 | expect(shuffled.toSet(), outputs.toSet()); |
| 30 | }); |
| 31 | |
| 32 | test('shuffle is deterministic for a given seed', () { |
| 33 | final outputs = [0, 1, 2, 3, 4, 5]; |
| 34 | final a = orderOutputs(outputs, BitcoinOrdering.shuffle, rng: Random(42)); |
| 35 | final b = orderOutputs(outputs, BitcoinOrdering.shuffle, rng: Random(42)); |
| 36 | expect(a, b); |
| 37 | }); |
| 38 | |
| 39 | test('shuffle does not keep the change output deterministically last', () { |
| 40 | // Last element (99) models the change output, appended last today. |
| 41 | final outputs = [0, 1, 2, 3, 99]; |
| 42 | final changePositions = <int>{}; |
| 43 | for (var seed = 0; seed < 50; seed++) { |
| 44 | final shuffled = orderOutputs(outputs, BitcoinOrdering.shuffle, rng: Random(seed)); |
| 45 | changePositions.add(shuffled.indexOf(99)); |
| 46 | } |
| 47 | // Across seeds the change lands in more than one position, and not always last. |
| 48 | expect(changePositions.length, greaterThan(1)); |
| 49 | expect(changePositions, isNot(equals({outputs.length - 1}))); |
| 50 | }); |
| 51 | }); |
| 52 | } |