diff --git a/lib/src/usage_impl.dart b/lib/src/usage_impl.dart index 1cbaf89..3e2e0f3 100644 --- a/lib/src/usage_impl.dart +++ b/lib/src/usage_impl.dart @@ -7,8 +7,7 @@ library usage_impl; import 'dart:async'; import 'dart:math' as math; -import 'package:uuid/uuid.dart'; - +import 'uuid.dart'; import '../usage.dart'; final int _MAX_EXCEPTION_LENGTH = 100; @@ -154,7 +153,7 @@ abstract class AnalyticsImpl implements Analytics { void _initClientId() { if (_clientId == null) { - properties['clientId'] = new Uuid().v4(); + properties['clientId'] = new Uuid().generateV4(); } } diff --git a/lib/src/uuid.dart b/lib/src/uuid.dart new file mode 100644 index 0000000..66e99ac --- /dev/null +++ b/lib/src/uuid.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2014, 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. + +/** + * A UUID generator library. + */ +library usage.uuid; + +import 'dart:math' show Random; + +/** + * A UUID generator. This will generate unique IDs in the format: + * + * f47ac10b-58cc-4372-a567-0e02b2c3d479 + * + * The generated uuids are 128 bit numbers encoded in a specific string format. + * + * For more information, see + * http://en.wikipedia.org/wiki/Universally_unique_identifier. + */ +class Uuid { + Random _random = new Random(); + + /** + * Generate a version 4 (random) uuid. This is a uuid scheme that only uses + * random numbers as the source of the generated uuid. + */ + String generateV4() { + // Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12. + int special = 8 + _random.nextInt(4); + + return + '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}-' + '${_bitsDigits(16, 4)}-' + '4${_bitsDigits(12, 3)}-' + '${_printDigits(special, 1)}${_bitsDigits(12, 3)}-' + '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}'; + } + + String _bitsDigits(int bitCount, int digitCount) => + _printDigits(_generateBits(bitCount), digitCount); + + int _generateBits(int bitCount) => _random.nextInt(1 << bitCount); + + String _printDigits(int value, int count) => + value.toRadixString(16).padLeft(count, '0'); +} diff --git a/pubspec.yaml b/pubspec.yaml index 8ed1242..2c5cc30 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,9 +8,6 @@ description: A Google Analytics wrapper for both command-line and web apps. homepage: https://github.com/dart-lang/usage author: Dart Team -dependencies: - uuid: '>=0.4.0 <0.5.0' - dev_dependencies: browser: any grinder: any diff --git a/test/all.dart b/test/all.dart index 9d4dd3c..393640a 100644 --- a/test/all.dart +++ b/test/all.dart @@ -8,10 +8,12 @@ import 'hit_types_test.dart' as hit_types_test; import 'usage_test.dart' as usage_test; import 'usage_impl_test.dart' as usage_impl_test; import 'usage_impl_io_test.dart' as usage_impl_io_test; +import 'uuid_test.dart' as uuid_test; void main() { hit_types_test.defineTests(); usage_test.defineTests(); usage_impl_test.defineTests(); usage_impl_io_test.defineTests(); + uuid_test.defineTests(); } diff --git a/test/uuid_test.dart b/test/uuid_test.dart new file mode 100644 index 0000000..cdde2b6 --- /dev/null +++ b/test/uuid_test.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2014, 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. + +library usage.uuid_test; + +import 'package:unittest/unittest.dart'; +import 'package:usage/src/uuid.dart'; + +void defineTests() { + group('uuid', () { + // xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + test('simple', () { + Uuid uuid = new Uuid(); + String result = uuid.generateV4(); + expect(result.length, 36); + expect(result[8], '-'); + expect(result[13], '-'); + expect(result[18], '-'); + expect(result[23], '-'); + }); + + test('can parse', () { + Uuid uuid = new Uuid(); + String result = uuid.generateV4(); + expect(int.parse(result.substring(0, 8), radix: 16), isNotNull); + expect(int.parse(result.substring(9, 13), radix: 16), isNotNull); + expect(int.parse(result.substring(14, 18), radix: 16), isNotNull); + expect(int.parse(result.substring(19, 23), radix: 16), isNotNull); + expect(int.parse(result.substring(24, 36), radix: 16), isNotNull); + }); + + test('special bits', () { + Uuid uuid = new Uuid(); + String result = uuid.generateV4(); + expect(result[14], '4'); + expect(result[19].toLowerCase(), isIn('89ab')); + + result = uuid.generateV4(); + expect(result[19].toLowerCase(), isIn('89ab')); + + result = uuid.generateV4(); + expect(result[19].toLowerCase(), isIn('89ab')); + }); + + test('is pretty random', () { + Set set = new Set(); + + Uuid uuid = new Uuid(); + for (int i = 0; i < 64; i++) { + String val = uuid.generateV4(); + expect(set, isNot(contains(val))); + set.add(val); + } + + uuid = new Uuid(); + for (int i = 0; i < 64; i++) { + String val = uuid.generateV4(); + expect(set, isNot(contains(val))); + set.add(val); + } + + uuid = new Uuid(); + for (int i = 0; i < 64; i++) { + String val = uuid.generateV4(); + expect(set, isNot(contains(val))); + set.add(val); + } + }); + }); +} diff --git a/test/web_test.dart b/test/web_test.dart index 4388760..cb73c31 100644 --- a/test/web_test.dart +++ b/test/web_test.dart @@ -13,6 +13,7 @@ import 'package:unittest/unittest.dart'; import 'hit_types_test.dart' as hit_types_test; import 'usage_test.dart' as usage_test; import 'usage_impl_test.dart' as usage_impl_test; +import 'uuid_test.dart' as uuid_test; // TODO: get the tests running in content_shell @@ -24,6 +25,7 @@ void main() { hit_types_test.defineTests(); usage_test.defineTests(); usage_impl_test.defineTests(); + uuid_test.defineTests(); // Define some web specfic tests. defineWebTests();