90 lines
3 KiB
Dart
90 lines
3 KiB
Dart
|
|
import 'dart:typed_data';
|
||
|
|
|
||
|
|
import 'package:serverpod_offline_sync/src/database/merge_utils/unique_resolver.dart';
|
||
|
|
import 'package:test/test.dart';
|
||
|
|
import 'package:uuid/uuid.dart';
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
group('Given byte values such as a bytea column holds,', () {
|
||
|
|
final bytes = Uint8List.fromList(List.generate(4096, (i) => i % 251));
|
||
|
|
|
||
|
|
test(
|
||
|
|
'when comparing equal and differing bytes, '
|
||
|
|
'then they compare by content.',
|
||
|
|
() {
|
||
|
|
final same = Uint8List.fromList(bytes);
|
||
|
|
final changed = Uint8List.fromList(bytes)..[4000] ^= 1;
|
||
|
|
final shorter = Uint8List.sublistView(bytes, 0, 4095);
|
||
|
|
|
||
|
|
expect(projectionValuesEqual(bytes, same), isTrue);
|
||
|
|
expect(projectionValuesEqual(bytes, changed), isFalse);
|
||
|
|
expect(projectionValuesEqual(bytes, shorter), isFalse);
|
||
|
|
expect(projectionValuesEqual(bytes, null), isFalse);
|
||
|
|
},
|
||
|
|
);
|
||
|
|
|
||
|
|
test(
|
||
|
|
'when comparing payloads alike in their first 16 bytes, '
|
||
|
|
'then they are not taken for the same UUID.',
|
||
|
|
() {
|
||
|
|
final payload = Uint8List.fromList('{"schemaVersion":1,"a":1}'.codeUnits);
|
||
|
|
final other = Uint8List.fromList('{"schemaVersion":1,"a":2}'.codeUnits);
|
||
|
|
|
||
|
|
expect(tryUuidValue(payload), isNull);
|
||
|
|
expect(
|
||
|
|
canonicalProjectionValue(payload),
|
||
|
|
isNot(canonicalProjectionValue(other)),
|
||
|
|
);
|
||
|
|
},
|
||
|
|
);
|
||
|
|
|
||
|
|
test(
|
||
|
|
'when comparing many payloads of a few kilobytes, '
|
||
|
|
'then it takes no more than a moment.',
|
||
|
|
() {
|
||
|
|
final same = Uint8List.fromList(bytes);
|
||
|
|
final watch = Stopwatch()..start();
|
||
|
|
for (var i = 0; i < 1000; i++) {
|
||
|
|
projectionValuesEqual(bytes, same);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Byte by byte through a failing UUID parse, this took minutes.
|
||
|
|
expect(watch.elapsed, lessThan(const Duration(seconds: 2)));
|
||
|
|
},
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
group('Given UUIDs in their forms,', () {
|
||
|
|
final uuid = const Uuid().v7obj();
|
||
|
|
|
||
|
|
test(
|
||
|
|
'when comparing a UUID with its string and its bytes, '
|
||
|
|
'then they are the same.',
|
||
|
|
() {
|
||
|
|
expect(tryUuidValue(uuid.uuid), uuid);
|
||
|
|
expect(tryUuidValue(Uint8List.fromList(uuid.toBytes())), uuid);
|
||
|
|
expect(projectionValuesEqual(uuid, uuid.uuid), isTrue);
|
||
|
|
expect(projectionValuesEqual(uuid.uuid, uuid), isTrue);
|
||
|
|
expect(
|
||
|
|
projectionValuesEqual(Uint8List.fromList(uuid.toBytes()), uuid),
|
||
|
|
isTrue,
|
||
|
|
);
|
||
|
|
},
|
||
|
|
);
|
||
|
|
|
||
|
|
test(
|
||
|
|
'when comparing what is no UUID, '
|
||
|
|
'then it is none and compares as itself.',
|
||
|
|
() {
|
||
|
|
expect(tryUuidValue('not a uuid'), isNull);
|
||
|
|
expect(tryUuidValue('x' * 36), isNull);
|
||
|
|
expect(tryUuidValue(42), isNull);
|
||
|
|
expect(tryUuidValue(DateTime.utc(2026)), isNull);
|
||
|
|
expect(projectionValuesEqual(42, 42), isTrue);
|
||
|
|
expect(projectionValuesEqual(42, 43), isFalse);
|
||
|
|
expect(projectionValuesEqual([1, 'a'], [1, 'a']), isTrue);
|
||
|
|
expect(projectionValuesEqual({'a': 1}, {'a': 2}), isFalse);
|
||
|
|
},
|
||
|
|
);
|
||
|
|
});
|
||
|
|
}
|