// Copyright (c) 2024, Sudipto Chandra // All rights reserved. Check LICENSE file for details. import 'dart:isolate'; import 'dart:typed_data'; import 'package:hashlib/codecs.dart'; import 'package:hashlib/src/uuid.dart'; import 'package:test/test.dart'; @pragma('vm:entry-point') void runIsolate(dynamic inp) { final port = inp[0] as SendPort; switch (inp[1] as String) { case 'v1': return port.send(uuid.v1()); case 'v3': return port.send(uuid.v3()); case 'v4': return port.send(uuid.v4()); case 'v5': return port.send(uuid.v5()); case 'v6': return port.send(uuid.v6()); case 'v7': return port.send(uuid.v7()); case 'v8': return port.send(uuid.v8()); } throw ArgumentError('Undefined version'); } void main() { group('UUID v1', () { test("known value", () { final time = DateTime.parse('2022-02-22T14:22:22-0500').toUtc(); final clockSeq = 0x33C8; final node = 0x9F6BDECED846; final out = 'c232ab00-9414-11ec-b3c8-9f6bdeced846'; final res = uuid.v1(node: node, clockSeq: clockSeq, utc: time); expect(res, equals(out)); }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v1), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v1'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('UUID v3', () { test("known value", () { final namespace = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; final name = 'www.example.com'; final out = '5df41881-3aed-3515-88a7-2f4a814cf09e'; final res = uuid.v3(name: name, namespace: namespace); expect(res, equals(out)); }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v3), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v3'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('UUID v4', () { test("known value", () { final out = RegExp(r'........-....-4...-....-............'); final res = uuid.v4(); expect(res, matches(out)); final part4 = fromHex(res.split('-')[3]).buffer.asUint8List(); expect(part4[0] >>> 6, 2); }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v4), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v4'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('UUID v5', () { test("known value", () { final namespace = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; final name = 'www.example.com'; final out = '2ed6657d-e927-568b-95e1-2665a8aea6a2'; final res = uuid.v5(name: name, namespace: namespace); expect(res, equals(out)); }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v5), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v5'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('UUID v6', () { test("known value", () { final time = DateTime.parse('2022-02-22T14:22:22-0500').toUtc(); final clockSeq = 0x33C8; final node = 0x9F6BDECED846; final out = '1ec9414c-232a-6b00-b3c8-9f6bdeced846'; final res = uuid.v6(node: node, clockSeq: clockSeq, utc: time); expect(res, equals(out)); }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v6), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v6'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('UUID v7', () { test("known value", () { final time = DateTime.parse('2022-02-22T14:22:22-0500').toUtc(); final out = RegExp(r'017f22e2-79b0-7...-....-............'); final res = uuid.v7(utc: time); expect(res, matches(out)); final part4 = fromHex(res.split('-')[3]).buffer.asUint8List(); expect(part4[0] >>> 6, 2); }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v7), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v7'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('UUID v8', () { test("known value 1", () { final nonce = fromHex('2489E9AD2EE20E000EC932D5F69181C0'); final out = '2489e9ad-2ee2-8e00-8ec9-32d5f69181c0'; final res = uuid.v8(nonce: nonce); expect(res, equals(out)); }); test("known value 2", () { final nonce = fromHex('5c146b143c524afd938a375d0df1fbf6'); final out = '5c146b14-3c52-8afd-938a-375d0df1fbf6'; final res = uuid.v8(nonce: nonce); expect(res, equals(out)); }); test("throws argument error on invalid nonce", () { for (int i = 0; i < 20; ++i) { final nonce = Uint8List(i); if (i == 16) { uuid.v8(nonce: nonce); } else { expect( () => uuid.v8(nonce: nonce), throwsArgumentError, reason: 'length: $i', ); } } }); test('uniqueness with futures', () async { final seeds = await Future.wait(List.generate( 1000, (_) => Future.microtask(uuid.v8), )); expect(seeds.toSet().length, 1000); }); test('uniqueness with isolates', () async { final receiver = ReceivePort(); await Future.wait(List.generate( 100, (_) => Isolate.spawn( runIsolate, [receiver.sendPort, 'v8'], errorsAreFatal: true, ), )); final items = await receiver.take(100).toList(); expect(items.toSet().length, 100); }, tags: ['vm-only'], timeout: Timeout(Duration(minutes: 5))); }); group('NamespaceValue', () { final matcher = matches('........-....-....-....-............'); test('dns', () { expect(Namespace.dns.value, matcher); }); test('url', () { expect(Namespace.url.value, matcher); }); test('oid', () { expect(Namespace.oid.value, matcher); }); test('x500', () { expect(Namespace.x500.value, matcher); }); test('nil', () { expect(Namespace.nil.value, matcher); }); test('max', () { expect(Namespace.max.value, matcher); }); test('time', () { expect(Namespace.time, matcher); }); }); }