diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c07f7bffe..a32586d85 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -20,7 +20,7 @@ jobs: pub global activate test_coverage pub global run test_coverage --exclude "**/js/**" working-directory: hive - - uses: codecov/codecov-action@v1.0.0 + - uses: codecov/codecov-action@v1.0.0 with: - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} file: hive/coverage/lcov.info diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55b7e48d4..f36b6e0f9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,12 +5,10 @@ on: [push, pull_request] jobs: test-hive: runs-on: ubuntu-latest - strategy: matrix: test-platform: [vm, chrome] - dart-channel: [stable, unstable] - + dart-channel: [unstable] steps: - uses: actions/checkout@v1 - name: Install Dart @@ -25,15 +23,18 @@ jobs: run: | export PATH="$PATH:/usr/lib/dart/bin" pub get - pub run test -p ${{ matrix.test-platform }} + pub run --no-sound-null-safety test -p ${{ matrix.test-platform }} working-directory: hive check-score: - if: false runs-on: ubuntu-latest + strategy: + matrix: + package: [hive, hive_generator, hive_flutter] steps: - uses: actions/checkout@v1 - - uses: axel-op/dart_package_analyzer@stable + - uses: axel-op/dart-package-analyzer@v3 with: githubToken: ${{ secrets.GITHUB_TOKEN }} + relativePath: ${{ matrix.package }} minAnnotationLevel: warning diff --git a/hive/CHANGELOG.md b/hive/CHANGELOG.md index ae0f28dd1..76f07bbf2 100644 --- a/hive/CHANGELOG.md +++ b/hive/CHANGELOG.md @@ -1,16 +1,45 @@ +# 2.0.0 + +### Fixes + +- Stable null-safety version + +# 1.6.0-nullsafety.2 + +### Fixes + +- Added `defaultValue` property to `@HiveField()` annotation - [#557](https://github.com/hivedb/hive/pull/557) + +# 1.6.0-nullsafety.1 + +### Fixes + +- Changed `meta` dependency version to `^1.3.0-nullsafety` to support null-safety + +# 1.6.0-nullsafety.0 + +### Breaking changes + +- Migrate to null-safety - [#521](https://github.com/hivedb/hive/pull/521) +- Update minimum Dart sdk constraint to 2.12.0-0. +- In order to generate null-safe code use hive_generator >= 0.9.0-nullsafety.0 + # 1.5.0-pre ### Enhancements + - Timezone support for DateTime - [#419](https://github.com/hivedb/hive/issues/419) # 1.4.4+1 ### Fixes + - Browser support for `BackendManager.boxExists(boxName, path)` - [#451](https://github.com/hivedb/hive/issues/451) # 1.4.4 ### Fixes + - Edge browser support - [#357](https://github.com/hivedb/hive/issues/357) # 1.4.3 @@ -27,70 +56,85 @@ # 1.4.2 ### Fixes + - Fixed dependency issues and minor improvements # 1.4.1+1 ### Other + - Added docs to all public members # 1.4.1 ### Enhancements + - Minor performance improvements ### Fixes + - When a database operation failed, subsequent operations would not be performed ### Other + - Fixed GitHub homepage path # 1.4.0+1 ### Enhancements + - Minor performance improvements ### Fixes + - Allow more versions of `crypto` # 1.4.0 ### Enhancements + - ~1000% encryption / decryption performance improvement - Added option to implement custom encryption algorithm - Added `box.valuesBetween(startKey, endKey)` - Allow tree shaking to drop encryption engine if no encryption is used ### Fixes + - `Hive.deleteBoxFromDisk()` did not work for boxes with upper-case names ### More + - Deprecated `encryptionKey` parameter. Use `Hive.openBox('name', encryptionCipher: HiveAesCipher(yourKey))`. - Dropped `pointycastle` dependency - Dropped `path` dependency # 1.3.0 -*Use latest version of `hive_generator`* +_Use latest version of `hive_generator`_ ### Breaking changes + - `TypeAdapters` and `@HiveType()` now require a `typeId` - `Hive.registerAdapter()` does not need a `typeId` anymore. - Removed `BinaryReader.readAsciiString()` - Removed `BinaryWriter.writeAsciiString()` ### Enhancements + - New documentation with tutorials and live code ### Fixes + - `box.clear()` resets auto increment counter ### More + - Not calling `Hive.init()` results in better exception # 1.2.0 ### Breaking changes + - Removed the `Hive.path` getter - Removed `Hive.openBoxFromBytes()` (use the `bytes` parameter of `Hive.openBox()` instead) - `LazyBox` and `Box` now have a common parent class: `BoxBase` @@ -99,6 +143,7 @@ - Box name bug resolved (more information below) ### Enhancements + - Support for relationships, `HiveLists` (see docs for details) - Support for inheritance - Lazy boxes can now have a type argument `LazyBox` @@ -107,6 +152,7 @@ - Improved documentation ### Fixes + - `HiveObjects` have not been initialized correctly in lazy boxes - Fixed bug where uppercase box name resulted in an uppercase filename - Fixed compaction bug which caused corrupted boxes @@ -114,9 +160,11 @@ - Fixed bug where not all `BoxEvent`s have been broadcasted ### More + - Changed type of `encryptionKey` from `Uint8List` to `List` ### Important: + Due to a bug in previous Hive versions, boxes whose name contains uppercase characters were stored in a file that also contains upper case characters (e.g. 'myBox' -> 'myBox.hive'). To avoid different behavior on case sensitive file systems, Hive should store files with lower case names. This bug has been resolved in version 1.2.0. @@ -127,52 +175,63 @@ This also applies to the web version. # 1.1.1 ### Breaking changes + - `object.delete()` now throws exception if object is not stored in a box ### Fixes + - Fixed bug where `object.save()` would fail on subsequent calls # 1.1.0+2 ### Fixes + - Fixed bug that it was not possible to open typed boxes (`Box`) # 1.1.0+1 ### Fixes + - Fixed bug that corrupted boxes were not detected # 1.1.0 ### Breaking changes + - Changed return type of `addAll()` from `List` to `Iterable`. - Removed the option to register `TypeAdapters` for a specific box. E.g. `box.registerTypeAdapter()`. - `getAt()`, `putAt()`, `deleteAt()` and `keyAt()` no longer allow indices out of range. ### Enhancements + - Added `HiveObject` - Boxes have now an optional type parameter `Box` - Support opening boxes from assets ### Fixes + - Fixed bug which was caused by not awaiting write operations - Fixed bug where custom compaction strategy was not applied - Hive now locks box files while they are open to prevent concurrent access from multiple processes ### More + - Improved performance of `putAll()`, `deleteAll()`, `add()`, `addAll()` - Changed `values` parameter of `addAll()` from `List` to `Iterable` - Improved documentation - Preparation for queries # 1.0.0 + - First stable release # 0.5.1+1 + - Change `keys` parameter of `deleteAll` from `List` to `Iterable` - Fixed bug in `BinaryWriter` # 0.5.1 + - Fixed `Hive.init()` bug in browser - Fixed a bug with large lists or strings - Improved box opening time in the browser @@ -181,6 +240,7 @@ This also applies to the web version. - Added integration tests # 0.5.0 + - Added `keyComparator` parameter for custom key order - Added `isEmpty` and `isNotEmpty` getters to box - Added support for reading and writing subclasses @@ -194,13 +254,16 @@ This also applies to the web version. - **Breaking:** Binary format changed # 0.4.1+1 + - Document all public APIs - Fixed flutter_web error # 0.4.1 + - Allow different versions of the `path` package # 0.4.0 + - Added `BigInt` support - Added `compactionStrategy` parameter - Added automatic crash recovery @@ -217,9 +280,11 @@ This also applies to the web version. - **Breaking:** API changes # 0.3.0+1 + - Bugfix: `Hive['yourBox']` didn't work with uppercase box names # 0.3.0 + - Big step towards stable API - Support for transactions - Annotations for hive_generator @@ -229,6 +294,7 @@ This also applies to the web version. - **Breaking:** Binary format changed # 0.2.0 + - Support for dart2js - Improved performance - Added `inMemory` option @@ -237,7 +303,9 @@ This also applies to the web version. - **Breaking:** Removed Migrator # 0.1.1 + - Downgrade to `meta: ^1.1.6` to support flutter # 0.1.0 + - First release diff --git a/hive/README.md b/hive/README.md index 731135956..a77f2c8e1 100644 --- a/hive/README.md +++ b/hive/README.md @@ -3,7 +3,7 @@

Fast, Enjoyable & Secure NoSQL Database

-[![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/hivedb/hive/Dart%20CI/master?label=tests&labelColor=333940&logo=github)](https://github.com/hivedb/hive/actions) [![Codecov branch](https://img.shields.io/codecov/c/github/hivedb/hive/master?labelColor=333940&logo=codecov&logoColor=white)](https://codecov.io/gh/hivedb/hive) [![Pub Version](https://img.shields.io/pub/v/hive?label=pub.dev&labelColor=333940&logo=dart)](https://pub.dev/packages/hive) [![GitHub](https://img.shields.io/github/license/hivedb/hive?color=%23007A88&labelColor=333940&logo=apache)](https://github.com/hivedb/hive/blob/master/LICENSE) +[![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/hivedb/hive/Dart%20CI/nndb?label=tests&labelColor=333940&logo=github)](https://github.com/hivedb/hive/actions) [![Codecov branch](https://img.shields.io/codecov/c/github/hivedb/hive/nndb?labelColor=333940&logo=codecov&logoColor=white)](https://codecov.io/gh/hivedb/hive) [![Pub Version](https://img.shields.io/pub/v/hive?label=pub.dev&labelColor=333940&logo=dart)](https://pub.dev/packages/hive) [![GitHub](https://img.shields.io/github/license/hivedb/hive?color=%23007A88&labelColor=333940&logo=apache)](https://github.com/hivedb/hive/blob/master/LICENSE) Hive is a lightweight and blazing fast key-value database written in pure Dart. Inspired by [Bitcask](https://en.wikipedia.org/wiki/Bitcask). @@ -18,8 +18,8 @@ Hive is a lightweight and blazing fast key-value database written in pure Dart. - 🎈 **NO** native dependencies - 🔋 Batteries included - ## Getting Started + Check out the [Quick Start](https://docs.hivedb.dev) documentation to get started. ## Usage @@ -71,6 +71,7 @@ print(box.getAt(0)) // Dave - 30 ``` ## Hive ❤️ Flutter + Hive was written with Flutter in mind. It is a perfect fit if you need a lightweight datastore for your app. After adding the required dependencies and initializing Hive, you can use Hive in your project: ```dart @@ -97,18 +98,16 @@ class SettingsPage extends StatelessWidget { Boxes are cached and therefore fast enough to be used directly in the `build()` method of Flutter widgets. - ## Benchmark -|1000 read iterations |1000 write iterations| -|:------------:|:------------:| -| ![](https://raw.githubusercontent.com/hivedb/hive/master/.github/benchmark_read.png) | ![](https://raw.githubusercontent.com/hivedb/hive/master/.github/benchmark_write.png) | +| 1000 read iterations | 1000 write iterations | +| :--------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------: | +| ![](https://raw.githubusercontent.com/hivedb/hive/master/.github/benchmark_read.png) | ![](https://raw.githubusercontent.com/hivedb/hive/master/.github/benchmark_write.png) | | SharedPreferences is on par with Hive when it comes to read performance. SQLite performs much worse. | Hive greatly outperforms SQLite and SharedPreferences when it comes to writing or deleting. | The benchmark was performed on a Oneplus 6T with Android Q. You can [run the benchmark yourself](https://github.com/hivedb/hive_benchmark). -*Take this benchmark with a grain of salt. It is very hard to compare databases objectively since they were made for different purposes. - +\*Take this benchmark with a grain of salt. It is very hard to compare databases objectively since they were made for different purposes. ### Licence diff --git a/hive/example/lib/main.dart b/hive/example/lib/main.dart index 45a479186..25c8564cb 100644 --- a/hive/example/lib/main.dart +++ b/hive/example/lib/main.dart @@ -6,6 +6,8 @@ part 'main.g.dart'; @HiveType(typeId: 1) class Person { + Person({required this.name, required this.age, required this.friends}); + @HiveField(0) String name; @@ -29,10 +31,11 @@ void main() async { var box = await Hive.openBox('testBox'); - var person = Person() - ..name = 'Dave' - ..age = 22 - ..friends = ['Linda', 'Marc', 'Anne']; + var person = Person( + name: 'Dave', + age: 22, + friends: ['Linda', 'Marc', 'Anne'], + ); await box.put('dave', person); diff --git a/hive/example/lib/main.g.dart b/hive/example/lib/main.g.dart index 98875ee53..5c486bddf 100644 --- a/hive/example/lib/main.g.dart +++ b/hive/example/lib/main.g.dart @@ -8,18 +8,19 @@ part of 'main.dart'; class PersonAdapter extends TypeAdapter { @override - final typeId = 1; + final int typeId = 1; @override Person read(BinaryReader reader) { - var numOfFields = reader.readByte(); - var fields = { - for (var i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; - return Person() - ..name = fields[0] as String - ..age = fields[1] as int - ..friends = (fields[2] as List)?.cast(); + return Person( + name: fields[0] as String, + age: fields[1] as int, + friends: (fields[2] as List).cast(), + ); } @override @@ -33,4 +34,14 @@ class PersonAdapter extends TypeAdapter { ..writeByte(2) ..write(obj.friends); } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is PersonAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; } diff --git a/hive/example/pubspec.yaml b/hive/example/pubspec.yaml index 91ee7a1bb..497bea585 100644 --- a/hive/example/pubspec.yaml +++ b/hive/example/pubspec.yaml @@ -5,4 +5,13 @@ dependencies: dev_dependencies: hive_generator: any - build_runner: any \ No newline at end of file + build_runner: any + +environment: + sdk: '>=2.12.0-0 <3.0.0' + +dependency_overrides: + hive: + path: ../ + hive_generator: + path: ../../hive_generator \ No newline at end of file diff --git a/hive/lib/src/adapters/ignored_type_adapter.dart b/hive/lib/src/adapters/ignored_type_adapter.dart index 69f07e24e..c4cabfaf6 100644 --- a/hive/lib/src/adapters/ignored_type_adapter.dart +++ b/hive/lib/src/adapters/ignored_type_adapter.dart @@ -1,14 +1,14 @@ import 'package:hive/hive.dart'; /// Not part of public API -class IgnoredTypeAdapter implements TypeAdapter { +class IgnoredTypeAdapter implements TypeAdapter { const IgnoredTypeAdapter([this.typeId = 0]); @override final int typeId; @override - T read(BinaryReader reader) => null; + T? read(BinaryReader reader) => null; @override void write(BinaryWriter writer, obj) {} diff --git a/hive/lib/src/annotations/hive_field.dart b/hive/lib/src/annotations/hive_field.dart index 29c5966d9..f49498c0e 100644 --- a/hive/lib/src/annotations/hive_field.dart +++ b/hive/lib/src/annotations/hive_field.dart @@ -5,5 +5,24 @@ class HiveField { /// The index of this field. final int index; - const HiveField(this.index); + /// Set `true` to use this enum value as default value instead of null in + /// null-safety. + /// + /// This property currently only used for enum types. In future might be used + /// for other properties too. If the defaultValue is not provided the first + /// enum will be used as default value. + /// + /// ```dart + /// @HiveType(typeId: 1) + /// enum MyEnum { + /// @HiveField(0) + /// apple, + /// + /// @HiveField(1, defaultValue: true) + /// pear + /// } + /// ``` + final bool defaultValue; + + const HiveField(this.index, {this.defaultValue = false}); } diff --git a/hive/lib/src/annotations/hive_type.dart b/hive/lib/src/annotations/hive_type.dart index 23fba7ecb..6b4c9c6d4 100644 --- a/hive/lib/src/annotations/hive_type.dart +++ b/hive/lib/src/annotations/hive_type.dart @@ -6,7 +6,7 @@ class HiveType { final int typeId; /// The name of the generated adapter. - final String adapterName; + final String? adapterName; /// This parameter can be used to keep track of old fieldIds which must not /// be reused. The generator will throw an error if a legacy fieldId is @@ -15,7 +15,7 @@ class HiveType { /// If [adapterName] is not set, it'll be `"YourClass" + "Adapter"`. const HiveType({ - @required this.typeId, + required this.typeId, this.adapterName, //this.legacyFieldIds, }); diff --git a/hive/lib/src/backend/js/backend_manager.dart b/hive/lib/src/backend/js/backend_manager.dart index c755860a5..b86d8f9b2 100644 --- a/hive/lib/src/backend/js/backend_manager.dart +++ b/hive/lib/src/backend/js/backend_manager.dart @@ -9,11 +9,11 @@ import 'package:hive/src/backend/storage_backend.dart'; class BackendManager implements BackendManagerInterface { @override Future open( - String name, String path, bool crashRecovery, HiveCipher cipher) async { + String name, String? path, bool crashRecovery, HiveCipher? cipher) async { var db = - await window.indexedDB.open(name, version: 1, onUpgradeNeeded: (e) { + await window.indexedDB!.open(name, version: 1, onUpgradeNeeded: (e) { var db = e.target.result as Database; - if (!db.objectStoreNames.contains('box')) { + if (!db.objectStoreNames!.contains('box')) { db.createObjectStore('box'); } }); @@ -22,17 +22,17 @@ class BackendManager implements BackendManagerInterface { } @override - Future deleteBox(String name, String path) { - return window.indexedDB.deleteDatabase(name); + Future deleteBox(String name, String? path) { + return window.indexedDB!.deleteDatabase(name); } @override - Future boxExists(String name, String path) async { + Future boxExists(String name, String? path) async { // https://stackoverflow.com/a/17473952 try { var _exists = true; - await window.indexedDB.open(name, version: 1, onUpgradeNeeded: (e) { - e.target.transaction.abort(); + await window.indexedDB!.open(name, version: 1, onUpgradeNeeded: (e) { + e.target.transaction!.abort(); _exists = false; }); return _exists; diff --git a/hive/lib/src/backend/js/storage_backend_js.dart b/hive/lib/src/backend/js/storage_backend_js.dart index 77a9d53fd..92bf9b257 100644 --- a/hive/lib/src/backend/js/storage_backend_js.dart +++ b/hive/lib/src/backend/js/storage_backend_js.dart @@ -1,8 +1,8 @@ import 'dart:async'; import 'dart:html'; import 'dart:indexed_db'; -import 'dart:typed_data'; import 'dart:js_util'; +import 'dart:typed_data'; import 'package:hive/hive.dart'; import 'package:hive/src/backend/storage_backend.dart'; @@ -10,21 +10,23 @@ import 'package:hive/src/binary/binary_reader_impl.dart'; import 'package:hive/src/binary/binary_writer_impl.dart'; import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/box/keystore.dart'; +import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:meta/meta.dart'; /// Handles all IndexedDB related tasks class StorageBackendJs extends StorageBackend { static const _bytePrefix = [0x90, 0xA9]; final Database _db; - final HiveCipher _cipher; + final HiveCipher? _cipher; TypeRegistry _registry; /// Not part of public API - StorageBackendJs(this._db, this._cipher, [this._registry]); + StorageBackendJs(this._db, this._cipher, + [this._registry = TypeRegistryImpl.nullImpl]); @override - String get path => null; + String? get path => null; @override bool supportsCompaction = false; @@ -62,7 +64,7 @@ class StorageBackendJs extends StorageBackend { if (_cipher == null) { frameWriter.write(value); } else { - frameWriter.writeEncrypted(value, _cipher); + frameWriter.writeEncrypted(value, _cipher!); } var bytes = frameWriter.toBytes(); @@ -81,7 +83,7 @@ class StorageBackendJs extends StorageBackend { if (_cipher == null) { return reader.read(); } else { - return reader.readEncrypted(_cipher); + return reader.readEncrypted(_cipher!); } } else { return bytes; @@ -108,10 +110,10 @@ class StorageBackendJs extends StorageBackend { var completer = Completer>(); var request = getStore(false).getAllKeys(null); request.onSuccess.listen((_) { - completer.complete(request.result as List); + completer.complete(request.result as List?); }); request.onError.listen((_) { - completer.completeError(request.error); + completer.completeError(request.error!); }); return completer.future; } else { @@ -132,7 +134,7 @@ class StorageBackendJs extends StorageBackend { completer.complete(values); }); request.onError.listen((_) { - completer.completeError(request.error); + completer.completeError(request.error!); }); return completer.future; } else { @@ -197,6 +199,6 @@ class StorageBackendJs extends StorageBackend { @override Future deleteFromDisk() { - return window.indexedDB.deleteDatabase(_db.name); + return window.indexedDB!.deleteDatabase(_db.name!); } } diff --git a/hive/lib/src/backend/storage_backend.dart b/hive/lib/src/backend/storage_backend.dart index f89b9dc85..61786e6f4 100644 --- a/hive/lib/src/backend/storage_backend.dart +++ b/hive/lib/src/backend/storage_backend.dart @@ -9,7 +9,7 @@ export 'package:hive/src/backend/stub/backend_manager.dart' /// Abstract storage backend abstract class StorageBackend { /// The path where the database is stored - String get path; + String? get path; /// Whether the database can be compacted bool get supportsCompaction; @@ -43,8 +43,8 @@ abstract class BackendManagerInterface { String name, String path, bool crashRecovery, HiveCipher cipher); /// Deletes database - Future deleteBox(String name, String path); + Future deleteBox(String name, String? path); /// Checks if box exists - Future boxExists(String name, String path); + Future boxExists(String name, String? path); } diff --git a/hive/lib/src/backend/storage_backend_memory.dart b/hive/lib/src/backend/storage_backend_memory.dart index 2fb5bc96e..55ec4e2a3 100644 --- a/hive/lib/src/backend/storage_backend_memory.dart +++ b/hive/lib/src/backend/storage_backend_memory.dart @@ -8,26 +8,32 @@ import 'package:hive/src/box/keystore.dart'; /// In-memory Storage backend class StorageBackendMemory extends StorageBackend { - final HiveCipher _cipher; + final HiveCipher? _cipher; final FrameHelper _frameHelper; - Uint8List _bytes; + Uint8List? _bytes; /// Not part of public API - StorageBackendMemory(this._bytes, this._cipher) - : _frameHelper = FrameHelper(); + StorageBackendMemory(Uint8List? bytes, this._cipher) + : _bytes = bytes, + _frameHelper = FrameHelper(); @override - String get path => null; + String? get path => null; @override bool supportsCompaction = false; @override - Future initialize(TypeRegistry registry, Keystore keystore, bool lazy) { - var recoveryOffset = - _frameHelper.framesFromBytes(_bytes, keystore, registry, _cipher); + Future initialize( + TypeRegistry registry, Keystore? keystore, bool lazy) { + var recoveryOffset = _frameHelper.framesFromBytes( + _bytes!, // Initialized at constructor and nulled after initialization + keystore, + registry, + _cipher, + ); if (recoveryOffset != -1) { throw HiveError('Wrong checksum in bytes. Box may be corrupted.'); diff --git a/hive/lib/src/backend/stub/backend_manager.dart b/hive/lib/src/backend/stub/backend_manager.dart index 84502ec4d..5723ac930 100644 --- a/hive/lib/src/backend/stub/backend_manager.dart +++ b/hive/lib/src/backend/stub/backend_manager.dart @@ -5,17 +5,17 @@ import 'package:hive/src/backend/storage_backend.dart'; class BackendManager implements BackendManagerInterface { @override Future open( - String name, String path, bool crashRecovery, HiveCipher cipher) { + String name, String? path, bool crashRecovery, HiveCipher? cipher) { throw UnimplementedError(); } @override - Future deleteBox(String name, String path) { + Future deleteBox(String name, String? path) { throw UnimplementedError(); } @override - Future boxExists(String name, String path) { + Future boxExists(String name, String? path) { throw UnimplementedError(); } } diff --git a/hive/lib/src/backend/vm/backend_manager.dart b/hive/lib/src/backend/vm/backend_manager.dart index 8dc92fccc..9c19effe6 100644 --- a/hive/lib/src/backend/vm/backend_manager.dart +++ b/hive/lib/src/backend/vm/backend_manager.dart @@ -11,7 +11,7 @@ class BackendManager implements BackendManagerInterface { @override Future open( - String name, String path, bool crashRecovery, HiveCipher cipher) async { + String name, String? path, bool crashRecovery, HiveCipher? cipher) async { if (path == null) { throw HiveError('You need to initialize Hive or ' 'provide a path to store the box.'); @@ -50,7 +50,8 @@ class BackendManager implements BackendManagerInterface { } @override - Future deleteBox(String name, String path) async { + Future deleteBox(String name, String? path) async { + ArgumentError.checkNotNull(path, 'path'); await _deleteFileIfExists(File('$path$_delimiter$name.hive')); await _deleteFileIfExists(File('$path$_delimiter$name.hivec')); await _deleteFileIfExists(File('$path$_delimiter$name.lock')); @@ -63,7 +64,8 @@ class BackendManager implements BackendManagerInterface { } @override - Future boxExists(String name, String path) async { + Future boxExists(String name, String? path) async { + ArgumentError.checkNotNull(path, 'path'); return await File('$path$_delimiter$name.hive').exists() || await File('$path$_delimiter$name.hivec').exists() || await File('$path$_delimiter$name.lock').exists(); diff --git a/hive/lib/src/backend/vm/storage_backend_vm.dart b/hive/lib/src/backend/vm/storage_backend_vm.dart index 8010ca65f..07a9ca956 100644 --- a/hive/lib/src/backend/vm/storage_backend_vm.dart +++ b/hive/lib/src/backend/vm/storage_backend_vm.dart @@ -18,22 +18,26 @@ class StorageBackendVm extends StorageBackend { final File _file; final File _lockFile; final bool _crashRecovery; - final HiveCipher _cipher; + final HiveCipher? _cipher; final FrameIoHelper _frameHelper; final ReadWriteSync _sync; /// Not part of public API + /// + /// Not `late final` for testing @visibleForTesting - RandomAccessFile readRaf; + late RandomAccessFile readRaf; /// Not part of public API + /// + /// Not `late final` for testing @visibleForTesting - RandomAccessFile writeRaf; + late RandomAccessFile writeRaf; /// Not part of public API @visibleForTesting - RandomAccessFile lockRaf; + late RandomAccessFile lockRaf; /// Not part of public API @visibleForTesting @@ -41,7 +45,7 @@ class StorageBackendVm extends StorageBackend { /// Not part of public API @visibleForTesting - TypeRegistry registry; + late final TypeRegistry registry; bool _compactionScheduled = false; @@ -100,7 +104,7 @@ class StorageBackendVm extends StorageBackend { return _sync.syncRead(() async { await readRaf.setPosition(frame.offset); - var bytes = await readRaf.read(frame.length); + var bytes = await readRaf.read(frame.length!); var reader = BinaryReaderImpl(bytes, registry); var readFrame = reader.readFrame(cipher: _cipher, lazy: false); @@ -132,7 +136,7 @@ class StorageBackendVm extends StorageBackend { for (var frame in frames) { frame.offset = writeOffset; - writeOffset += frame.length; + writeOffset += frame.length!; } }); } @@ -166,12 +170,12 @@ class StorageBackendVm extends StorageBackend { reader.skip(skip); } - if (reader.remainingInBuffer < frame.length) { - if (await reader.loadBytes(frame.length) < frame.length) { + if (reader.remainingInBuffer < frame.length!) { + if (await reader.loadBytes(frame.length!) < frame.length!) { throw HiveError('Could not compact box: Unexpected EOF.'); } } - await writer.write(reader.viewBytes(frame.length)); + await writer.write(reader.viewBytes(frame.length!)); } await writer.flush(); } finally { @@ -187,7 +191,7 @@ class StorageBackendVm extends StorageBackend { for (var frame in sortedFrames) { if (frame.offset == -1) continue; frame.offset = offset; - offset += frame.length; + offset += frame.length!; } _compactionScheduled = false; }); diff --git a/hive/lib/src/binary/binary_reader.dart b/hive/lib/src/binary/binary_reader.dart index 4bc0041f4..486792b0e 100644 --- a/hive/lib/src/binary/binary_reader.dart +++ b/hive/lib/src/binary/binary_reader.dart @@ -47,55 +47,55 @@ abstract class BinaryReader { /// /// If [byteCount] is not provided, it is read first. String readString([ - int byteCount, + int? byteCount, Converter, String> decoder = utf8Decoder, ]); /// Read a list of bytes with [length]. /// /// If [length] is not provided, it is read first. - Uint8List readByteList([int length]); + Uint8List readByteList([int? length]); /// Read a list of integers with [length]. /// /// If [length] is not provided, it is read first. - List readIntList([int length]); + List readIntList([int? length]); /// Read a list of doubles with [length]. /// /// If [length] is not provided, it is read first. - List readDoubleList([int length]); + List readDoubleList([int? length]); /// Read a list of booleans with [length]. /// /// If [length] is not provided, it is read first. - List readBoolList([int length]); + List readBoolList([int? length]); /// Read a list of Strings with [length]. /// /// If [length] is not provided, it is read first. List readStringList([ - int length, + int? length, Converter, String> decoder = utf8Decoder, ]); /// Read a list with [length]. /// /// If [length] is not provided, it is read first. - List readList([int length]); + List readList([int? length]); /// Read a map with [length] entries. /// /// If [length] is not provided, it is read first. - Map readMap([int length]); + Map readMap([int? length]); /// Read and decode any value. /// /// If [typeId] is not provided, it is read first. - dynamic read([int typeId]); + dynamic read([int? typeId]); /// Read a [HiveList] with [length]. /// /// If [length] is not provided, it is read first. - HiveList readHiveList([int length]); + HiveList readHiveList([int? length]); } diff --git a/hive/lib/src/binary/binary_reader_impl.dart b/hive/lib/src/binary/binary_reader_impl.dart index f7c4b3423..b2926d4ec 100644 --- a/hive/lib/src/binary/binary_reader_impl.dart +++ b/hive/lib/src/binary/binary_reader_impl.dart @@ -19,7 +19,7 @@ class BinaryReaderImpl extends BinaryReader { int _offset = 0; /// Not part of public API - BinaryReaderImpl(this._buffer, TypeRegistry typeRegistry, [int bufferLength]) + BinaryReaderImpl(this._buffer, TypeRegistry typeRegistry, [int? bufferLength]) : _byteData = ByteData.view(_buffer.buffer, _buffer.offsetInBytes), _bufferLength = bufferLength ?? _buffer.length, _bufferLimit = bufferLength ?? _buffer.length, @@ -129,7 +129,7 @@ class BinaryReaderImpl extends BinaryReader { @override String readString( - [int byteCount, + [int? byteCount, Converter, String> decoder = BinaryReader.utf8Decoder]) { byteCount ??= readUint32(); var view = viewBytes(byteCount); @@ -137,7 +137,7 @@ class BinaryReaderImpl extends BinaryReader { } @override - Uint8List readByteList([int length]) { + Uint8List readByteList([int? length]) { length ??= readUint32(); _requireBytes(length); var byteList = _buffer.sublist(_offset, _offset + length); @@ -146,11 +146,11 @@ class BinaryReaderImpl extends BinaryReader { } @override - List readIntList([int length]) { + List readIntList([int? length]) { length ??= readUint32(); _requireBytes(length * 8); var byteData = _byteData; - var list = []..length = length; + var list = List.filled(length, 0); for (var i = 0; i < length; i++) { list[i] = byteData.getFloat64(_offset, Endian.little).toInt(); _offset += 8; @@ -159,11 +159,11 @@ class BinaryReaderImpl extends BinaryReader { } @override - List readDoubleList([int length]) { + List readDoubleList([int? length]) { length ??= readUint32(); _requireBytes(length * 8); var byteData = _byteData; - var list = []..length = length; + var list = List.filled(length, 0.0); for (var i = 0; i < length; i++) { list[i] = byteData.getFloat64(_offset, Endian.little); _offset += 8; @@ -172,10 +172,10 @@ class BinaryReaderImpl extends BinaryReader { } @override - List readBoolList([int length]) { + List readBoolList([int? length]) { length ??= readUint32(); _requireBytes(length); - var list = []..length = length; + var list = List.filled(length, false); for (var i = 0; i < length; i++) { list[i] = _buffer[_offset++] > 0; } @@ -184,10 +184,10 @@ class BinaryReaderImpl extends BinaryReader { @override List readStringList( - [int length, + [int? length, Converter, String> decoder = BinaryReader.utf8Decoder]) { length ??= readUint32(); - var list = []..length = length; + var list = List.filled(length, ''); for (var i = 0; i < length; i++) { list[i] = readString(null, decoder); } @@ -195,9 +195,9 @@ class BinaryReaderImpl extends BinaryReader { } @override - List readList([int length]) { + List readList([int? length]) { length ??= readUint32(); - var list = []..length = length; + var list = List.filled(length, null); for (var i = 0; i < length; i++) { list[i] = read(); } @@ -205,7 +205,7 @@ class BinaryReaderImpl extends BinaryReader { } @override - Map readMap([int length]) { + Map readMap([int? length]) { length ??= readUint32(); var map = {}; for (var i = 0; i < length; i++) { @@ -228,11 +228,11 @@ class BinaryReaderImpl extends BinaryReader { } @override - HiveList readHiveList([int length]) { + HiveList readHiveList([int? length]) { length ??= readUint32(); var boxNameLength = readByte(); var boxName = String.fromCharCodes(viewBytes(boxNameLength)); - var keys = List(length); + var keys = List.filled(length, null); for (var i = 0; i < length; i++) { keys[i] = readKey(); } @@ -241,7 +241,8 @@ class BinaryReaderImpl extends BinaryReader { } /// Not part of public API - Frame readFrame({HiveCipher cipher, bool lazy = false, int frameOffset}) { + Frame? readFrame( + {HiveCipher? cipher, bool lazy = false, int frameOffset = 0}) { if (availableBytes < 4) return null; var frameLength = readUint32(); @@ -287,7 +288,7 @@ class BinaryReaderImpl extends BinaryReader { } @override - dynamic read([int typeId]) { + dynamic read([int? typeId]) { typeId ??= readByte(); switch (typeId) { case FrameValueType.nullT: diff --git a/hive/lib/src/binary/binary_writer_impl.dart b/hive/lib/src/binary/binary_writer_impl.dart index 82f93a7bd..a2aa7096d 100644 --- a/hive/lib/src/binary/binary_writer_impl.dart +++ b/hive/lib/src/binary/binary_writer_impl.dart @@ -16,7 +16,7 @@ class BinaryWriterImpl extends BinaryWriter { final TypeRegistryImpl _typeRegistry; Uint8List _buffer = Uint8List(_initBufferSize); - ByteData _byteDataInstance; + ByteData? _byteDataInstance; int _offset = 0; @@ -24,7 +24,7 @@ class BinaryWriterImpl extends BinaryWriter { @pragma('dart2js:tryInline') ByteData get _byteData { _byteDataInstance ??= ByteData.view(_buffer.buffer); - return _byteDataInstance; + return _byteDataInstance!; } /// Not part of public API @@ -55,6 +55,8 @@ class BinaryWriterImpl extends BinaryWriter { @pragma('vm:prefer-inline') @pragma('dart2js:tryInline') void _addBytes(List bytes) { + ArgumentError.checkNotNull(bytes); + var length = bytes.length; _reserveBytes(length); _buffer.setRange(_offset, _offset + length, bytes); @@ -65,15 +67,16 @@ class BinaryWriterImpl extends BinaryWriter { @pragma('dart2js:tryInline') @override void writeByte(int byte) { - if (byte == null) { - throw ArgumentError.notNull(); - } + ArgumentError.checkNotNull(byte); + _reserveBytes(1); _buffer[_offset++] = byte; } @override void writeWord(int value) { + ArgumentError.checkNotNull(value); + _reserveBytes(2); _buffer[_offset++] = value; _buffer[_offset++] = value >> 8; @@ -81,9 +84,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeInt32(int value) { - if (value == null) { - throw ArgumentError.notNull(); - } + ArgumentError.checkNotNull(value); + _reserveBytes(4); _byteData.setInt32(_offset, value, Endian.little); _offset += 4; @@ -93,6 +95,8 @@ class BinaryWriterImpl extends BinaryWriter { @pragma('dart2js:tryInline') @override void writeUint32(int value) { + ArgumentError.checkNotNull(value); + _reserveBytes(4); _buffer.writeUint32(_offset, value); _offset += 4; @@ -105,9 +109,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeDouble(double value) { - if (value == null) { - throw ArgumentError.notNull(); - } + ArgumentError.checkNotNull(value); + _reserveBytes(8); _byteData.setFloat64(_offset, value, Endian.little); _offset += 8; @@ -115,6 +118,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeBool(bool value) { + ArgumentError.checkNotNull(value); + writeByte(value ? 1 : 0); } @@ -124,6 +129,8 @@ class BinaryWriterImpl extends BinaryWriter { bool writeByteCount = true, Converter> encoder = BinaryWriter.utf8Encoder, }) { + ArgumentError.checkNotNull(value); + var bytes = encoder.convert(value); if (writeByteCount) { writeUint32(bytes.length); @@ -133,6 +140,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeByteList(List bytes, {bool writeLength = true}) { + ArgumentError.checkNotNull(bytes); + if (writeLength) { writeUint32(bytes.length); } @@ -141,6 +150,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeIntList(List list, {bool writeLength = true}) { + ArgumentError.checkNotNull(list); + var length = list.length; if (writeLength) { writeUint32(length); @@ -155,6 +166,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeDoubleList(List list, {bool writeLength = true}) { + ArgumentError.checkNotNull(list); + var length = list.length; if (writeLength) { writeUint32(length); @@ -169,6 +182,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeBoolList(List list, {bool writeLength = true}) { + ArgumentError.checkNotNull(list); + var length = list.length; if (writeLength) { writeUint32(length); @@ -185,6 +200,8 @@ class BinaryWriterImpl extends BinaryWriter { bool writeLength = true, Converter> encoder = BinaryWriter.utf8Encoder, }) { + ArgumentError.checkNotNull(list); + if (writeLength) { writeUint32(list.length); } @@ -197,6 +214,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeList(List list, {bool writeLength = true}) { + ArgumentError.checkNotNull(list); + if (writeLength) { writeUint32(list.length); } @@ -207,6 +226,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeMap(Map map, {bool writeLength = true}) { + ArgumentError.checkNotNull(map); + if (writeLength) { writeUint32(map.length); } @@ -218,6 +239,8 @@ class BinaryWriterImpl extends BinaryWriter { /// Not part of public API void writeKey(dynamic key) { + ArgumentError.checkNotNull(key); + if (key is String) { writeByte(FrameKeyType.asciiStringT); writeByte(key.length); @@ -230,6 +253,8 @@ class BinaryWriterImpl extends BinaryWriter { @override void writeHiveList(HiveList list, {bool writeLength = true}) { + ArgumentError.checkNotNull(list); + if (writeLength) { writeUint32(list.length); } @@ -242,7 +267,9 @@ class BinaryWriterImpl extends BinaryWriter { } /// Not part of public API - int writeFrame(Frame frame, {HiveCipher cipher}) { + int writeFrame(Frame frame, {HiveCipher? cipher}) { + ArgumentError.checkNotNull(frame); + var startOffset = _offset; _reserveBytes(4); _offset += 4; // reserve bytes for length diff --git a/hive/lib/src/binary/frame.dart b/hive/lib/src/binary/frame.dart index 9c8b2937a..4f1861e82 100644 --- a/hive/lib/src/binary/frame.dart +++ b/hive/lib/src/binary/frame.dart @@ -16,7 +16,7 @@ class Frame { final bool lazy; /// Not part of public API - int length; + int? length; /// Not part of public API int offset = -1; diff --git a/hive/lib/src/binary/frame_helper.dart b/hive/lib/src/binary/frame_helper.dart index 5a83c3b5e..f65a397cc 100644 --- a/hive/lib/src/binary/frame_helper.dart +++ b/hive/lib/src/binary/frame_helper.dart @@ -7,8 +7,12 @@ import 'package:hive/src/box/keystore.dart'; /// Not part of public API class FrameHelper { /// Not part of public API - int framesFromBytes(Uint8List bytes, Keystore keystore, TypeRegistry registry, - HiveCipher cipher) { + int framesFromBytes( + Uint8List bytes, + Keystore? keystore, + TypeRegistry registry, + HiveCipher? cipher, + ) { var reader = BinaryReaderImpl(bytes, registry); while (reader.availableBytes != 0) { @@ -21,7 +25,7 @@ class FrameHelper { ); if (frame == null) return frameOffset; - keystore.insert(frame, notify: false); + keystore!.insert(frame, notify: false); } return -1; diff --git a/hive/lib/src/box/box.dart b/hive/lib/src/box/box.dart index e2862ef89..697667868 100644 --- a/hive/lib/src/box/box.dart +++ b/hive/lib/src/box/box.dart @@ -31,10 +31,10 @@ abstract class Box implements BoxBase { /// /// If [defaultValue] is specified, it is returned in case the key does not /// exist. - E get(dynamic key, {E defaultValue}); + E? get(dynamic key, {E? defaultValue}); /// Returns the value associated with the n-th key. - E getAt(int index); + E? getAt(int index); /// Returns a map which contains all key - value pairs of the box. Map toMap(); diff --git a/hive/lib/src/box/box_base.dart b/hive/lib/src/box/box_base.dart index 59041a779..0644b43d3 100644 --- a/hive/lib/src/box/box_base.dart +++ b/hive/lib/src/box/box_base.dart @@ -43,7 +43,7 @@ abstract class BoxBase { bool get isOpen; /// The location of the box in the file system. In the browser, this is null. - String get path; + String? get path; /// Whether this box is lazy or not. /// diff --git a/hive/lib/src/box/box_base_impl.dart b/hive/lib/src/box/box_base_impl.dart index 0408f9752..368ab6584 100644 --- a/hive/lib/src/box/box_base_impl.dart +++ b/hive/lib/src/box/box_base_impl.dart @@ -7,6 +7,8 @@ import 'package:meta/meta.dart'; /// Not part of public API abstract class BoxBaseImpl implements BoxBase { + static BoxBase nullImpl() => _NullBoxBase(); + @override final String name; @@ -21,9 +23,11 @@ abstract class BoxBaseImpl implements BoxBase { final StorageBackend backend; /// Not part of public API + /// + /// Not `late final` for testing @protected @visibleForTesting - Keystore keystore; + late Keystore keystore; bool _open = true; @@ -31,7 +35,7 @@ abstract class BoxBaseImpl implements BoxBase { BoxBaseImpl( this.hive, this.name, - KeyComparator keyComparator, + KeyComparator? keyComparator, this._compactionStrategy, this.backend, ) { @@ -45,7 +49,7 @@ abstract class BoxBaseImpl implements BoxBase { bool get isOpen => _open; @override - String get path => backend.path; + String? get path => backend.path; @override Iterable get keys { @@ -82,7 +86,7 @@ abstract class BoxBaseImpl implements BoxBase { @override dynamic keyAt(int index) { checkOpen(); - return keystore.getAt(index).key; + return keystore.getAt(index)!.key; } /// Not part of public API @@ -121,12 +125,12 @@ abstract class BoxBaseImpl implements BoxBase { @override Future putAt(int index, E value) { - return putAll({keystore.getAt(index).key: value}); + return putAll({keystore.getAt(index)!.key: value}); } @override Future deleteAt(int index) { - return deleteAll([keystore.getAt(index).key]); + return delete(keystore.getAt(index)!.key); } @override @@ -180,3 +184,74 @@ abstract class BoxBaseImpl implements BoxBase { await backend.deleteFromDisk(); } } + +class _NullBoxBase implements BoxBase { + @override + Never add(E value) => throw UnimplementedError(); + + @override + Never addAll(Iterable values) => throw UnimplementedError(); + + @override + Never clear() => throw UnimplementedError(); + + @override + Never close() => throw UnimplementedError(); + + @override + Never compact() => throw UnimplementedError(); + + @override + Never containsKey(key) => throw UnimplementedError(); + + @override + Never delete(key) => throw UnimplementedError(); + + @override + Never deleteAll(Iterable keys) => throw UnimplementedError(); + + @override + Never deleteAt(int index) => throw UnimplementedError(); + + @override + Never deleteFromDisk() => throw UnimplementedError(); + + @override + Never get isEmpty => throw UnimplementedError(); + + @override + Never get isNotEmpty => throw UnimplementedError(); + + @override + Never get isOpen => throw UnimplementedError(); + + @override + Never keyAt(int index) => throw UnimplementedError(); + + @override + Never get keys => throw UnimplementedError(); + + @override + Never get lazy => throw UnimplementedError(); + + @override + Never get length => throw UnimplementedError(); + + @override + Never get name => throw UnimplementedError(); + + @override + Never get path => throw UnimplementedError(); + + @override + Never put(key, E value) => throw UnimplementedError(); + + @override + Never putAll(Map entries) => throw UnimplementedError(); + + @override + Never putAt(int index, E value) => throw UnimplementedError(); + + @override + Never watch({key}) => throw UnimplementedError(); +} diff --git a/hive/lib/src/box/box_impl.dart b/hive/lib/src/box/box_impl.dart index 97552a663..5c84cd077 100644 --- a/hive/lib/src/box/box_impl.dart +++ b/hive/lib/src/box/box_impl.dart @@ -13,7 +13,7 @@ class BoxImpl extends BoxBaseImpl implements Box { BoxImpl( HiveImpl hive, String name, - KeyComparator keyComparator, + KeyComparator? keyComparator, CompactionStrategy compactionStrategy, StorageBackend backend, ) : super(hive, name, keyComparator, compactionStrategy, backend); @@ -36,12 +36,12 @@ class BoxImpl extends BoxBaseImpl implements Box { } @override - E get(dynamic key, {E defaultValue}) { + E? get(dynamic key, {E? defaultValue}) { checkOpen(); var frame = keystore.get(key); if (frame != null) { - return frame.value as E; + return frame.value as E?; } else { if (defaultValue != null && defaultValue is HiveObject) { defaultValue.init(key, this); @@ -51,10 +51,10 @@ class BoxImpl extends BoxBaseImpl implements Box { } @override - E getAt(int index) { + E? getAt(int index) { checkOpen(); - return keystore.getAt(index).value as E; + return keystore.getAt(index)?.value as E?; } @override diff --git a/hive/lib/src/box/keystore.dart b/hive/lib/src/box/keystore.dart index 4fddfe99c..b02c12493 100644 --- a/hive/lib/src/box/keystore.dart +++ b/hive/lib/src/box/keystore.dart @@ -11,6 +11,8 @@ import 'package:hive/src/object/hive_object.dart'; import 'package:hive/src/util/indexable_skip_list.dart'; import 'package:meta/meta.dart'; +import 'box_base_impl.dart'; + /// Not part of public API class KeyTransaction { /// The values that have been added @@ -40,18 +42,18 @@ class Keystore { var _autoIncrement = -1; /// Not part of public API - Keystore(this._box, this._notifier, KeyComparator keyComparator) + Keystore(this._box, this._notifier, KeyComparator? keyComparator) : _store = IndexableSkipList(keyComparator ?? defaultKeyComparator); /// Not part of public API factory Keystore.debug({ Iterable frames = const [], - BoxBase box, - ChangeNotifier notifier, + BoxBase? box, + ChangeNotifier? notifier, KeyComparator keyComparator = defaultKeyComparator, }) { - var keystore = - Keystore(box, notifier ?? ChangeNotifier(), keyComparator); + var keystore = Keystore(box ?? BoxBaseImpl.nullImpl(), + notifier ?? ChangeNotifier(), keyComparator); for (var frame in frames) { keystore.insert(frame); } @@ -101,14 +103,14 @@ class Keystore { /// Not part of public API @pragma('vm:prefer-inline') @pragma('dart2js:tryInline') - Frame get(dynamic key) { + Frame? get(dynamic key) { return _store.get(key); } /// Not part of public API @pragma('vm:prefer-inline') @pragma('dart2js:tryInline') - Frame getAt(int index) { + Frame? getAt(int index) { return _store.getAt(index); } @@ -144,9 +146,9 @@ class Keystore { } /// Not part of public API - Frame insert(Frame frame, {bool notify = true}) { + Frame? insert(Frame frame, {bool notify = true}) { var value = frame.value; - Frame deletedFrame; + Frame? deletedFrame; if (!frame.deleted) { var key = frame.key; @@ -214,17 +216,17 @@ class Keystore { var deletedFrame = canceled.deleted[key]; for (var t in transactions) { if (t.deleted.containsKey(key)) { - t.deleted[key] = deletedFrame; + t.deleted[key] = deletedFrame!; continue deleted_loop; } if (t.added.contains(key)) { - t.deleted[key] = deletedFrame; + t.deleted[key] = deletedFrame!; continue deleted_loop; } } _store.insert(key, deletedFrame); - _notifier.notify(deletedFrame); + _notifier.notify(deletedFrame!); } added_loop: @@ -256,7 +258,6 @@ class Keystore { for (var frame in frameList) { if (frame.value is HiveObject) { - // ignore: invalid_use_of_protected_member (frame.value as HiveObject).dispose(); } _notifier.notify(Frame.deleted(frame.key)); diff --git a/hive/lib/src/box/lazy_box.dart b/hive/lib/src/box/lazy_box.dart index 57619238a..d08176d6b 100644 --- a/hive/lib/src/box/lazy_box.dart +++ b/hive/lib/src/box/lazy_box.dart @@ -8,8 +8,8 @@ abstract class LazyBox extends BoxBase { /// /// If [defaultValue] is specified, it is returned in case the key does not /// exist. - Future get(dynamic key, {E defaultValue}); + Future get(dynamic key, {E? defaultValue}); /// Returns the value associated with the n-th key. - Future getAt(int index); + Future getAt(int index); } diff --git a/hive/lib/src/box/lazy_box_impl.dart b/hive/lib/src/box/lazy_box_impl.dart index 7ce1258b9..d522cb22d 100644 --- a/hive/lib/src/box/lazy_box_impl.dart +++ b/hive/lib/src/box/lazy_box_impl.dart @@ -14,7 +14,7 @@ class LazyBoxImpl extends BoxBaseImpl implements LazyBox { LazyBoxImpl( HiveImpl hive, String name, - KeyComparator keyComparator, + KeyComparator? keyComparator, CompactionStrategy compactionStrategy, StorageBackend backend, ) : super(hive, name, keyComparator, compactionStrategy, backend); @@ -23,7 +23,7 @@ class LazyBoxImpl extends BoxBaseImpl implements LazyBox { final bool lazy = true; @override - Future get(dynamic key, {E defaultValue}) async { + Future get(dynamic key, {E? defaultValue}) async { checkOpen(); var frame = keystore.get(key); @@ -33,7 +33,7 @@ class LazyBoxImpl extends BoxBaseImpl implements LazyBox { if (value is HiveObject) { value.init(key, this); } - return value as E; + return value as E?; } else { if (defaultValue != null && defaultValue is HiveObject) { defaultValue.init(key, this); @@ -43,7 +43,7 @@ class LazyBoxImpl extends BoxBaseImpl implements LazyBox { } @override - Future getAt(int index) { + Future getAt(int index) { return get(keystore.keyAt(index)); } diff --git a/hive/lib/src/crypto/aes_cbc_pkcs7.dart b/hive/lib/src/crypto/aes_cbc_pkcs7.dart index a4cab50b9..c200e2909 100644 --- a/hive/lib/src/crypto/aes_cbc_pkcs7.dart +++ b/hive/lib/src/crypto/aes_cbc_pkcs7.dart @@ -8,8 +8,10 @@ class AesCbcPkcs7 { final Uint8List _keyBytes; - List _encryptionKey; - List _decryptionKey; + late final List _encryptionKey = + AesEngine.generateWorkingKey(_keyBytes, true); + late final List _decryptionKey = + AesEngine.generateWorkingKey(_keyBytes, false); /// Not part of public API AesCbcPkcs7(this._keyBytes); @@ -17,8 +19,6 @@ class AesCbcPkcs7 { /// Not part of public API int encrypt(Uint8List iv, Uint8List inp, int inpOff, int inpLength, Uint8List out, int outOff) { - _encryptionKey ??= AesEngine.generateWorkingKey(_keyBytes, true); - var cbcV = Uint8List.fromList(iv); var inputBlocks = (inpLength + aesBlockSize) ~/ aesBlockSize; @@ -53,8 +53,6 @@ class AesCbcPkcs7 { /// Not part of public API int decrypt(Uint8List iv, Uint8List inp, int inpOff, int inpLength, Uint8List out, int outOff) { - _decryptionKey ??= AesEngine.generateWorkingKey(_keyBytes, false); - var inputBlocks = (inpLength + aesBlockSize - 1) ~/ aesBlockSize; var offset = 0; diff --git a/hive/lib/src/crypto/crc32.dart b/hive/lib/src/crypto/crc32.dart index c0efb4032..88f5d65bf 100644 --- a/hive/lib/src/crypto/crc32.dart +++ b/hive/lib/src/crypto/crc32.dart @@ -7,7 +7,7 @@ class Crc32 { Uint8List bytes, { int crc = 0, int offset = 0, - int length, + int? length, }) { crc = crc ^ 0xffffffff; diff --git a/hive/lib/src/crypto/hive_aes_cipher.dart b/hive/lib/src/crypto/hive_aes_cipher.dart index ee36a5f44..b8bf06f59 100644 --- a/hive/lib/src/crypto/hive_aes_cipher.dart +++ b/hive/lib/src/crypto/hive_aes_cipher.dart @@ -4,9 +4,9 @@ part of hive; class HiveAesCipher implements HiveCipher { static final _ivRandom = Random.secure(); - AesCbcPkcs7 _cipher; + late final AesCbcPkcs7 _cipher; - int _keyCrc; + late final int _keyCrc; /// Create a cipher with the given [key]. HiveAesCipher(List key) { diff --git a/hive/lib/src/hive.dart b/hive/lib/src/hive.dart index fe5e450a2..d88720d5f 100644 --- a/hive/lib/src/hive.dart +++ b/hive/lib/src/hive.dart @@ -13,13 +13,13 @@ abstract class HiveInterface implements TypeRegistry { /// parameters are being ignored. Future> openBox( String name, { - HiveCipher encryptionCipher, + HiveCipher? encryptionCipher, KeyComparator keyComparator = defaultKeyComparator, CompactionStrategy compactionStrategy = defaultCompactionStrategy, bool crashRecovery = true, - String path, - Uint8List bytes, - @deprecated List encryptionKey, + String? path, + Uint8List? bytes, + @deprecated List? encryptionKey, }); /// Opens a lazy box. @@ -28,12 +28,12 @@ abstract class HiveInterface implements TypeRegistry { /// parameters are being ignored. Future> openLazyBox( String name, { - HiveCipher encryptionCipher, + HiveCipher? encryptionCipher, KeyComparator keyComparator = defaultKeyComparator, CompactionStrategy compactionStrategy = defaultCompactionStrategy, bool crashRecovery = true, - String path, - @deprecated List encryptionKey, + String? path, + @deprecated List? encryptionKey, }); /// Returns a previously opened box. diff --git a/hive/lib/src/hive_impl.dart b/hive/lib/src/hive_impl.dart index 5a211e743..ecf52a541 100644 --- a/hive/lib/src/hive_impl.dart +++ b/hive/lib/src/hive_impl.dart @@ -27,7 +27,7 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { /// Not part of public API @visibleForTesting - String homePath; + String? homePath; /// Not part of public API HiveImpl() : _manager = BackendManager() { @@ -64,15 +64,13 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { Future> _openBox( String name, bool lazy, - HiveCipher cipher, + HiveCipher? cipher, KeyComparator comparator, CompactionStrategy compaction, bool recovery, - String path, - Uint8List bytes, + String? path, + Uint8List? bytes, ) async { - assert(comparator != null); - assert(compaction != null); assert(path == null || bytes == null); assert(name.length <= 255 && name.isAscii, 'Box names need to be ASCII Strings with a max length of 255.'); @@ -130,13 +128,13 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { @override Future> openBox( String name, { - HiveCipher encryptionCipher, + HiveCipher? encryptionCipher, KeyComparator keyComparator = defaultKeyComparator, CompactionStrategy compactionStrategy = defaultCompactionStrategy, bool crashRecovery = true, - String path, - Uint8List bytes, - @deprecated List encryptionKey, + String? path, + Uint8List? bytes, + @deprecated List? encryptionKey, }) async { if (encryptionKey != null) { encryptionCipher = HiveAesCipher(encryptionKey); @@ -148,12 +146,12 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { @override Future> openLazyBox( String name, { - HiveCipher encryptionCipher, + HiveCipher? encryptionCipher, KeyComparator keyComparator = defaultKeyComparator, CompactionStrategy compactionStrategy = defaultCompactionStrategy, bool crashRecovery = true, - String path, - @deprecated List encryptionKey, + String? path, + @deprecated List? encryptionKey, }) async { if (encryptionKey != null) { encryptionCipher = HiveAesCipher(encryptionKey); @@ -162,7 +160,7 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { compactionStrategy, crashRecovery, path, null) as LazyBox; } - BoxBase _getBoxInternal(String name, [bool lazy]) { + BoxBase _getBoxInternal(String name, [bool? lazy]) { var lowerCaseName = name.toLowerCase(); var box = _boxes[lowerCaseName]; if (box != null) { @@ -181,7 +179,7 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { } /// Not part of public API - BoxBase getBoxWithoutCheckInternal(String name) { + BoxBase? getBoxWithoutCheckInternal(String name) { var lowerCaseName = name.toLowerCase(); return _boxes[lowerCaseName]; } @@ -215,7 +213,7 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { } @override - Future deleteBoxFromDisk(String name, {String path}) async { + Future deleteBoxFromDisk(String name, {String? path}) async { var lowerCaseName = name.toLowerCase(); var box = _boxes[lowerCaseName]; if (box != null) { @@ -240,7 +238,7 @@ class HiveImpl extends TypeRegistryImpl implements HiveInterface { } @override - Future boxExists(String name, {String path}) async { + Future boxExists(String name, {String? path}) async { var lowerCaseName = name.toLowerCase(); return await _manager.boxExists(lowerCaseName, path ?? homePath); } diff --git a/hive/lib/src/io/buffered_file_reader.dart b/hive/lib/src/io/buffered_file_reader.dart index 9f5114b99..e52f73ab2 100644 --- a/hive/lib/src/io/buffered_file_reader.dart +++ b/hive/lib/src/io/buffered_file_reader.dart @@ -11,8 +11,11 @@ class BufferedFileReader { static const defaultChunkSize = 1000 * 64; /// Not part of public API + /// + /// Nullable because of testing. [loadBytes] can throw if the count is not in + /// the buffer. @visibleForTesting - final RandomAccessFile file; + final RandomAccessFile? file; /// Not part of public API @visibleForTesting @@ -75,7 +78,7 @@ class BufferedFileReader { } _bufferOffset = 0; - var readBytes = await file.readInto(buffer, remaining); + var readBytes = await file!.readInto(buffer, remaining); _bufferSize = remaining + readBytes; _fileOffset += readBytes; diff --git a/hive/lib/src/io/frame_io_helper.dart b/hive/lib/src/io/frame_io_helper.dart index c964fb16a..4ba08dc51 100644 --- a/hive/lib/src/io/frame_io_helper.dart +++ b/hive/lib/src/io/frame_io_helper.dart @@ -6,6 +6,7 @@ import 'package:hive/src/binary/binary_reader_impl.dart'; import 'package:hive/src/binary/frame_helper.dart'; import 'package:hive/src/box/keystore.dart'; import 'package:hive/src/io/buffered_file_reader.dart'; +import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:meta/meta.dart'; /// Not part of public API @@ -24,7 +25,7 @@ class FrameIoHelper extends FrameHelper { /// Not part of public API Future keysFromFile( - String path, Keystore keystore, HiveCipher cipher) async { + String path, Keystore keystore, HiveCipher? cipher) async { var raf = await openFile(path); var fileReader = BufferedFileReader(raf); try { @@ -36,7 +37,7 @@ class FrameIoHelper extends FrameHelper { /// Not part of public API Future framesFromFile(String path, Keystore keystore, - TypeRegistry registry, HiveCipher cipher) async { + TypeRegistry registry, HiveCipher? cipher) async { var bytes = await readFile(path); return framesFromBytes(bytes as Uint8List, keystore, registry, cipher); } @@ -45,11 +46,11 @@ class FrameIoHelper extends FrameHelper { class _KeyReader { final BufferedFileReader fileReader; - BinaryReaderImpl _reader; + late BinaryReaderImpl _reader; _KeyReader(this.fileReader); - Future readKeys(Keystore keystore, HiveCipher cipher) async { + Future readKeys(Keystore keystore, HiveCipher? cipher) async { await _load(4); while (true) { var frameOffset = fileReader.offset; @@ -87,7 +88,7 @@ class _KeyReader { Future _load(int bytes) async { var loadedBytes = await fileReader.loadBytes(bytes); var buffer = fileReader.peekBytes(loadedBytes); - _reader = BinaryReaderImpl(buffer, null); + _reader = BinaryReaderImpl(buffer, TypeRegistryImpl.nullImpl); return loadedBytes; } diff --git a/hive/lib/src/object/hive_list.dart b/hive/lib/src/object/hive_list.dart index 27155f378..72561f01b 100644 --- a/hive/lib/src/object/hive_list.dart +++ b/hive/lib/src/object/hive_list.dart @@ -5,7 +5,7 @@ part of hive; abstract class HiveList extends HiveCollection implements List { /// Create a new HiveList which can contain HiveObjects from [box]. - factory HiveList(Box box, {List objects}) => + factory HiveList(Box box, {List? objects}) => HiveListImpl(box, objects: objects); /// Disposes this list. It is important to call this method when the list is diff --git a/hive/lib/src/object/hive_list_impl.dart b/hive/lib/src/object/hive_list_impl.dart index c5c947c62..baa6a0649 100644 --- a/hive/lib/src/object/hive_list_impl.dart +++ b/hive/lib/src/object/hive_list_impl.dart @@ -14,20 +14,20 @@ class HiveListImpl /// Not part of public API final String boxName; - final List _keys; + final List? _keys; HiveInterface _hive = Hive; - List _delegate; + List? _delegate; - Box _box; + Box? _box; bool _invalidated = false; bool _disposed = false; /// Not part of public API - HiveListImpl(Box box, {List objects}) + HiveListImpl(Box box, {List? objects}) : boxName = box.name, _keys = null, _delegate = [], @@ -38,12 +38,12 @@ class HiveListImpl } /// Not part of public API - HiveListImpl.lazy(this.boxName, List keys) : _keys = keys; + HiveListImpl.lazy(this.boxName, List? keys) : _keys = keys; @override Iterable get keys { if (_delegate == null) { - return _keys; + return _keys!; } else { return super.keys; } @@ -60,10 +60,10 @@ class HiveListImpl throw HiveError('The box "$boxName" is a lazy box. ' 'You can only use HiveLists with normal boxes.'); } else { - _box = box as Box; + _box = box; } } - return _box; + return _box!; } @override @@ -74,7 +74,7 @@ class HiveListImpl if (_invalidated) { var retained = []; - for (var obj in _delegate) { + for (var obj in _delegate!) { if (obj.isInHiveList(this)) { retained.add(obj); } @@ -83,7 +83,7 @@ class HiveListImpl _invalidated = false; } else if (_delegate == null) { var list = []; - for (var key in _keys) { + for (var key in _keys!) { if (box.containsKey(key)) { var obj = box.get(key) as E; obj.linkHiveList(this); @@ -93,13 +93,13 @@ class HiveListImpl _delegate = list; } - return _delegate; + return _delegate!; } @override void dispose() { if (_delegate != null) { - for (var element in _delegate) { + for (var element in _delegate!) { element.unlinkHiveList(this); } _delegate = null; @@ -116,19 +116,16 @@ class HiveListImpl } void _checkElementIsValid(E obj) { - if (obj == null) { - throw HiveError('HiveLists must not contain null elements.'); - } else if (obj.box != box) { + if (obj.box != box) { throw HiveError('HiveObjects needs to be in the box "$boxName".'); } } @override set length(int newLength) { - var delegate = this.delegate; if (newLength < delegate.length) { for (var i = newLength; i < delegate.length; i++) { - delegate[i]?.unlinkHiveList(this); + delegate[i].unlinkHiveList(this); } } delegate.length = newLength; @@ -142,7 +139,7 @@ class HiveListImpl var oldValue = delegate[index]; delegate[index] = value; - oldValue?.unlinkHiveList(this); + oldValue.unlinkHiveList(this); } @override @@ -156,8 +153,6 @@ class HiveListImpl void addAll(Iterable iterable) { for (var element in iterable) { _checkElementIsValid(element); - } - for (var element in iterable) { element.linkHiveList(this); } delegate.addAll(iterable); @@ -166,7 +161,7 @@ class HiveListImpl @override HiveList castHiveList() { if (_delegate != null) { - return HiveListImpl(box, objects: _delegate.cast()); + return HiveListImpl(box, objects: _delegate!.cast()); } else { return HiveListImpl.lazy(boxName, _keys); } diff --git a/hive/lib/src/object/hive_object.dart b/hive/lib/src/object/hive_object.dart index 79c680e53..8bd86d9f3 100644 --- a/hive/lib/src/object/hive_object.dart +++ b/hive/lib/src/object/hive_object.dart @@ -9,7 +9,7 @@ part 'hive_object_internal.dart'; /// Extend `HiveObject` to add useful methods to the objects you want to store /// in Hive abstract class HiveObject { - BoxBase _box; + BoxBase? _box; dynamic _key; @@ -18,7 +18,7 @@ abstract class HiveObject { /// Get the box in which this object is stored. Returns `null` if object has /// not been added to a box yet. - BoxBase get box => _box; + BoxBase? get box => _box; /// Get the key associated with this object. Returns `null` if object has /// not been added to a box yet. @@ -33,13 +33,13 @@ abstract class HiveObject { /// Persists this object. Future save() { _requireInitialized(); - return _box.put(_key, this); + return _box!.put(_key, this); } /// Deletes this object from the box it is stored in. Future delete() { _requireInitialized(); - return _box.delete(_key); + return _box!.delete(_key); } /// Returns whether this object is currently stored in a box. @@ -48,8 +48,8 @@ abstract class HiveObject { /// whether this instance is actually stored in the box. bool get isInBox { if (_box != null) { - if (_box.lazy) { - return _box.containsKey(_key); + if (_box!.lazy) { + return _box!.containsKey(_key); } else { return true; } diff --git a/hive/lib/src/object/hive_object_internal.dart b/hive/lib/src/object/hive_object_internal.dart index 780965de9..c4d5c0e12 100644 --- a/hive/lib/src/object/hive_object_internal.dart +++ b/hive/lib/src/object/hive_object_internal.dart @@ -39,7 +39,9 @@ extension HiveObjectInternal on HiveObject { /// Not part of public API void unlinkHiveList(HiveList list) { - if (--_hiveLists[list] <= 0) { + final currentIndex = _hiveLists[list]!; + final newIndex = _hiveLists[list] = currentIndex - 1; + if (newIndex <= 0) { _hiveLists.remove(list); } } diff --git a/hive/lib/src/registry/type_registry_impl.dart b/hive/lib/src/registry/type_registry_impl.dart index 95ae2acfd..a66cd752d 100644 --- a/hive/lib/src/registry/type_registry_impl.dart +++ b/hive/lib/src/registry/type_registry_impl.dart @@ -2,25 +2,60 @@ import 'package:hive/hive.dart'; import 'package:hive/src/adapters/ignored_type_adapter.dart'; import 'package:meta/meta.dart'; -class _ResolvedAdapter { +/// Not part of public API +/// +/// Needed to codegen the TypeRegistry mock +@visibleForTesting +class ResolvedAdapter { final TypeAdapter adapter; final int typeId; - _ResolvedAdapter(this.adapter, this.typeId); + ResolvedAdapter(this.adapter, this.typeId); bool matches(dynamic value) => value is T; } +class _NullTypeRegistry implements TypeRegistryImpl { + const _NullTypeRegistry(); + + @override + Never get _typeAdapters => throw UnimplementedError(); + + @override + Never findAdapterForTypeId(int typeId) => throw UnimplementedError(); + + @override + Never findAdapterForValue(value) => throw UnimplementedError(); + + @override + Never ignoreTypeId(int typeId) => throw UnimplementedError(); + + @override + Never isAdapterRegistered(int typeId, {bool internal = false}) => + throw UnimplementedError(); + + @override + Never registerAdapter(TypeAdapter adapter, + {bool internal = false, bool override = false}) => + throw UnimplementedError(); + + @override + Never resetAdapters() => throw UnimplementedError(); +} + /// Not part of public API class TypeRegistryImpl implements TypeRegistry { + /// Not part of public API + static const TypeRegistryImpl nullImpl = _NullTypeRegistry(); + /// Not part of public API @visibleForTesting static const reservedTypeIds = 32; - final _typeAdapters = {}; + final _typeAdapters = {}; /// Not part of public API - _ResolvedAdapter findAdapterForValue(dynamic value) { + ResolvedAdapter? findAdapterForValue(dynamic value) { for (var adapter in _typeAdapters.values) { if (adapter.matches(value)) return adapter; } @@ -28,7 +63,7 @@ class TypeRegistryImpl implements TypeRegistry { } /// Not part of public API - _ResolvedAdapter findAdapterForTypeId(int typeId) { + ResolvedAdapter? findAdapterForTypeId(int typeId) { return _typeAdapters[typeId]; } @@ -62,7 +97,7 @@ class TypeRegistryImpl implements TypeRegistry { } } - var resolved = _ResolvedAdapter(adapter, typeId); + var resolved = ResolvedAdapter(adapter, typeId); _typeAdapters[typeId] = resolved; } diff --git a/hive/lib/src/util/delegating_list_view_mixin.dart b/hive/lib/src/util/delegating_list_view_mixin.dart index 27aa031bf..43cc86c54 100644 --- a/hive/lib/src/util/delegating_list_view_mixin.dart +++ b/hive/lib/src/util/delegating_list_view_mixin.dart @@ -32,7 +32,7 @@ abstract class DelegatingListViewMixin implements List { List cast() => delegate.cast(); @override - bool contains(Object element) => delegate.contains(element); + bool contains(Object? element) => delegate.contains(element); @override E elementAt(int index) => delegate.elementAt(index); @@ -45,7 +45,7 @@ abstract class DelegatingListViewMixin implements List { delegate.expand(f); @override - E firstWhere(bool Function(E element) test, {E Function() orElse}) => + E firstWhere(bool Function(E element) test, {E Function()? orElse}) => delegate.firstWhere(test, orElse: orElse); @override @@ -62,7 +62,7 @@ abstract class DelegatingListViewMixin implements List { Iterable getRange(int start, int end) => delegate.getRange(start, end); @override - int indexOf(Object element, [int start = 0]) => + int indexOf(Object? element, [int start = 0]) => delegate.indexOf(element as E, start); @override @@ -82,15 +82,15 @@ abstract class DelegatingListViewMixin implements List { String join([String separator = '']) => delegate.join(separator); @override - int lastIndexOf(Object element, [int start]) => + int lastIndexOf(Object? element, [int? start]) => delegate.lastIndexOf(element as E, start); @override - int lastIndexWhere(bool Function(E element) test, [int start]) => + int lastIndexWhere(bool Function(E element) test, [int? start]) => delegate.lastIndexWhere(test, start); @override - E lastWhere(bool Function(E element) test, {E Function() orElse}) => + E lastWhere(bool Function(E element) test, {E Function()? orElse}) => delegate.lastWhere(test, orElse: orElse); @override @@ -106,7 +106,7 @@ abstract class DelegatingListViewMixin implements List { E get single => delegate.single; @override - E singleWhere(bool Function(E element) test, {E Function() orElse}) => + E singleWhere(bool Function(E element) test, {E Function()? orElse}) => delegate.singleWhere(test, orElse: orElse); @override @@ -117,7 +117,7 @@ abstract class DelegatingListViewMixin implements List { delegate.skipWhile(test); @override - List sublist(int start, [int end]) => delegate.sublist(start, end); + List sublist(int start, [int? end]) => delegate.sublist(start, end); @override Iterable take(int count) => delegate.take(count); diff --git a/hive/lib/src/util/indexable_skip_list.dart b/hive/lib/src/util/indexable_skip_list.dart index 46474be07..4cd86739d 100644 --- a/hive/lib/src/util/indexable_skip_list.dart +++ b/hive/lib/src/util/indexable_skip_list.dart @@ -8,7 +8,7 @@ class IndexableSkipList { final _Node _head = _Node( null, null, - List(_maxHeight), + List.filled(_maxHeight, null), List.filled(_maxHeight, 0), ); @@ -21,7 +21,7 @@ class IndexableSkipList { int _length = 0; /// Not part of public API - IndexableSkipList(this._comparator, [Random random]) + IndexableSkipList(this._comparator, [Random? random]) : _random = random ?? Random(); /// Not part of public API @@ -34,7 +34,7 @@ class IndexableSkipList { Iterable get values => _ValueIterable(_head); /// Not part of public API - V insert(K key, V value) { + V? insert(K key, V? value) { var existingNode = _getNode(key); if (existingNode != null) { var oldValue = existingNode.value; @@ -54,7 +54,7 @@ class IndexableSkipList { var newNode = _Node( key, value, - List(newLevel + 1), + List.filled(newLevel + 1, null), List.filled(newLevel + 1, 0), ); @@ -63,7 +63,7 @@ class IndexableSkipList { for (var level = _height - 1; level >= 0; level--) { while (true) { var next = current.next[level]; - if (next == null || _comparator(key, next.key) < 0) break; + if (next == null || _comparator(key, next.key!) < 0) break; current = next; } @@ -83,7 +83,7 @@ class IndexableSkipList { // CHANGE 3 - Calculate the width of the level var width = 0; var node = current.next[level - 1]; - while (node != null && _comparator(key, node.key) >= 0) { + while (node != null && _comparator(key, node.key!) >= 0) { width += node.width[level - 1]; node = node.next[level - 1]; } @@ -112,7 +112,7 @@ class IndexableSkipList { } /// Not part of public API - V delete(K key) { + V? delete(K key) { var node = _getNode(key); if (node == null) return null; @@ -121,7 +121,7 @@ class IndexableSkipList { for (var level = _height - 1; level >= 0; level--) { while (true) { var next = current.next[level]; - if (next == null || _comparator(key, next.key) <= 0) break; + if (next == null || _comparator(key, next.key!) <= 0) break; current = next; } @@ -152,7 +152,7 @@ class IndexableSkipList { /// Not part of public API @pragma('vm:prefer-inline') @pragma('dart2js:tryInline') - V get(K key) => _getNode(key)?.value; + V? get(K key) => _getNode(key)?.value; /// Not part of public API // TODO: write test @@ -164,19 +164,19 @@ class IndexableSkipList { return _ValueIterable(virtualHead); } - _Node _getNode(K key) { + _Node? _getNode(K key) { var prev = _head; - _Node node; + _Node? node; for (var i = _height - 1; i >= 0; i--) { node = prev.next[i]; - while (node != null && _comparator(key, node.key) > 0) { + while (node != null && _comparator(key, node.key!) > 0) { prev = node; node = node.next[i]; } } - if (node != null && _comparator(key, node.key) == 0) { + if (node != null && _comparator(key, node.key!) == 0) { return node; } return null; @@ -185,18 +185,18 @@ class IndexableSkipList { /// Not part of public API @pragma('vm:prefer-inline') @pragma('dart2js:tryInline') - V getAt(int index) => _getNodeAt(index).value; + V? getAt(int index) => _getNodeAt(index).value; /// Not part of public API @pragma('vm:prefer-inline') @pragma('dart2js:tryInline') - K getKeyAt(int index) => _getNodeAt(index).key; + K? getKeyAt(int index) => _getNodeAt(index).key; _Node _getNodeAt(int index) { RangeError.checkValidIndex(index, this); var prev = _head; - _Node node; + _Node? node; for (var level = _height - 1; level >= 0; level--) { node = prev.next[level]; @@ -207,7 +207,7 @@ class IndexableSkipList { } } - return node; + return node!; } /// Not part of public API @@ -222,11 +222,11 @@ class IndexableSkipList { } class _Node { - final K key; + final K? key; - V value; + V? value; - final List<_Node> next; + final List<_Node?> next; final List width; @@ -236,23 +236,23 @@ class _Node { } abstract class _Iterator implements Iterator { - _Node node; + _Node? node; _Iterator(this.node); @override - bool moveNext() => (node = node.next[0]) != null; + bool moveNext() => (node = node!.next[0]) != null; } class _KeyIterator extends _Iterator { - _KeyIterator(_Node node) : super(node); + _KeyIterator(_Node node) : super(node); @override - K get current => node.key; + K get current => node!.key!; } class _KeyIterable extends IterableBase { - final _Node head; + final _Node head; _KeyIterable(this.head); @@ -261,14 +261,14 @@ class _KeyIterable extends IterableBase { } class _ValueIterator extends _Iterator { - _ValueIterator(_Node node) : super(node); + _ValueIterator(_Node node) : super(node); @override - V get current => node.value; + V get current => node!.value!; } class _ValueIterable extends IterableBase { - final _Node head; + final _Node head; _ValueIterable(this.head); diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index ae99385b5..6b078c22d 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,20 +1,21 @@ name: hive description: Lightweight and blazing fast key-value database written in pure Dart. Strongly encrypted using AES-256. -version: 1.5.0-pre +version: 2.0.0 homepage: https://github.com/hivedb/hive/tree/master/hive documentation: https://docs.hivedb.dev/ environment: - sdk: ">=2.6.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: - meta: ^1.1.7 - crypto: ">=2.1.0 <3.0.0" + meta: ^1.3.0 + crypto: ^3.0.0 dev_dependencies: - test: ^1.9.4 - mockito: ^4.1.1 + test: ^1.15.7 + # TODO: Fix & update mockito version + mockito: 5.0.0-nullsafety.5 pedantic: ^1.9.0 - dartx: ">=0.2.0 <1.0.0" - path: ^1.6.4 - pointycastle: ^1.0.2 \ No newline at end of file + path: ^1.7.0 + pointycastle: ^2.0.0 + build_runner: ^1.10.0 diff --git a/hive/test/integration/date_time_adapter_upgrade.dart b/hive/test/integration/date_time_adapter_upgrade.dart index 0a8dc175d..4047ab49c 100644 --- a/hive/test/integration/date_time_adapter_upgrade.dart +++ b/hive/test/integration/date_time_adapter_upgrade.dart @@ -5,7 +5,7 @@ import 'package:test/test.dart'; void main() { group('upgrading DateTimeAdapter to DateTimeWithTimeZoneAdapter', () { group('TypeRegistry', () { - TypeRegistryImpl registry; + late TypeRegistryImpl registry; setUp(() { registry = TypeRegistryImpl(); @@ -18,19 +18,19 @@ void main() { }); test('uses DateTimeWithTimeZoneAdapter for writing new values', () { - var result = registry.findAdapterForValue(DateTime.now()); + var result = registry.findAdapterForValue(DateTime.now())!; expect(result, isNotNull); expect(result.adapter, isA()); }); test('uses DateTimeWithTimeZoneAdapter for reading if typeId = 18', () { - var result = registry.findAdapterForTypeId(18); + var result = registry.findAdapterForTypeId(18)!; expect(result, isNotNull); expect(result.adapter, isA()); }); test('uses DateTimeAdapter for reading if typeId = 16', () { - var result = registry.findAdapterForTypeId(16); + var result = registry.findAdapterForTypeId(16)!; expect(result, isNotNull); expect(result.adapter, isA()); }); diff --git a/hive/test/integration/hive_list_test.dart b/hive/test/integration/hive_list_test.dart index 50a191e8e..0cd52a80e 100644 --- a/hive/test/integration/hive_list_test.dart +++ b/hive/test/integration/hive_list_test.dart @@ -7,9 +7,9 @@ import 'package:test/test.dart'; import 'integration.dart'; class _TestObject extends HiveObject { - String name; + String? name; - HiveList<_TestObject> list; + HiveList<_TestObject>? list; _TestObject(this.name); @@ -23,8 +23,8 @@ class _TestObjectAdapter extends TypeAdapter<_TestObject> { @override _TestObject read(BinaryReader reader) { - return _TestObject(reader.read() as String) - ..list = (reader.read() as HiveList)?.castHiveList(); + return _TestObject(reader.read() as String?) + ..list = (reader.read() as HiveList?)?.castHiveList(); } @override @@ -47,26 +47,26 @@ void main() { for (var i = 0; i < 100; i++) { var element = _TestObject('element$i'); await box.add(element); - obj.list.add(element); + obj.list!.add(element); } await obj.save(); box = (await box.reopen()) as Box<_TestObject>; - obj = box.get('obj'); + obj = box.get('obj')!; (obj.list as HiveListImpl).debugHive = hive; for (var i = 0; i < 100; i++) { - expect(obj.list[i].name, 'element$i'); + expect(obj.list![i].name, 'element$i'); } - await obj.list[99].delete(); - expect(obj.list.length, 99); + await obj.list![99].delete(); + expect(obj.list!.length, 99); - await obj.list[50].delete(); - expect(obj.list[50].name, 'element51'); + await obj.list![50].delete(); + expect(obj.list![50].name, 'element51'); - await obj.list[0].delete(); - expect(obj.list[0].name, 'element1'); + await obj.list![0].delete(); + expect(obj.list![0].name, 'element1'); }, timeout: longTimeout); } diff --git a/hive/test/integration/hive_object_test.dart b/hive/test/integration/hive_object_test.dart index d2664f630..13f1453e4 100644 --- a/hive/test/integration/hive_object_test.dart +++ b/hive/test/integration/hive_object_test.dart @@ -52,10 +52,10 @@ Future _performTest(bool lazy) async { await obj2.delete(); box = await box.reopen(); - obj1 = await box.get(0) as _TestObject; - obj2 = await box.get('someKey') as _TestObject; - expect(obj1.name, 'test1 updated'); - expect(obj2, null); + final newObj1 = await box.get(0) as _TestObject; + final newObj2 = await box.get('someKey') as _TestObject?; + expect(newObj1.name, 'test1 updated'); + expect(newObj2, null); await box.close(); } diff --git a/hive/test/integration/integration.dart b/hive/test/integration/integration.dart index 945be934c..290eea42c 100644 --- a/hive/test/integration/integration.dart +++ b/hive/test/integration/integration.dart @@ -19,14 +19,14 @@ Future createHive() async { } Future> openBox(bool lazy, - {HiveInterface hive, List encryptionKey}) async { + {HiveInterface? hive, List? encryptionKey}) async { hive ??= HiveImpl(); if (!isBrowser) { var dir = await getTempDir(); hive.init(dir.path); } var id = Random().nextInt(99999999); - HiveCipher cipher; + HiveCipher? cipher; if (encryptionKey != null) { cipher = HiveAesCipher(encryptionKey); } @@ -39,11 +39,11 @@ Future> openBox(bool lazy, } } -extension BoxBaseX on BoxBase { - Future> reopen({List encryptionKey}) async { +extension BoxBaseX on BoxBase { + Future> reopen({List? encryptionKey}) async { await close(); var hive = (this as BoxBaseImpl).hive; - HiveCipher cipher; + HiveCipher? cipher; if (encryptionKey != null) { cipher = HiveAesCipher(encryptionKey); } diff --git a/hive/test/integration/put_large_lists_test.dart b/hive/test/integration/put_large_lists_test.dart index 7b313b985..caf75a0db 100644 --- a/hive/test/integration/put_large_lists_test.dart +++ b/hive/test/integration/put_large_lists_test.dart @@ -7,12 +7,13 @@ import 'integration.dart'; Future _performTest(bool lazy) async { var box = await openBox(lazy); - var stringList = List.filled(1000000, 'test', growable: true)..add(null); + var nullableStringList = List.filled(1000000, 'test', growable: true) + ..add(null); var doubleList = List.filled(1000000, 1.212312); var byteList = Uint8List.fromList(List.filled(1000000, 123)); for (var i = 0; i < 5; i++) { - await box.put('stringList$i', stringList); + await box.put('stringList$i', nullableStringList); await box.put('doubleList$i', doubleList); await box.put('byteList$i', byteList); } @@ -23,7 +24,7 @@ Future _performTest(bool lazy) async { var readDoubleList = await await box.get('doubleList$i'); var readByteList = await await box.get('byteList$i'); - expect(readStringList, stringList); + expect(readStringList, nullableStringList); expect(readDoubleList, doubleList); expect(readByteList, byteList); } diff --git a/hive/test/integration/recovery_test.dart b/hive/test/integration/recovery_test.dart index aec52d1d8..f19e7ca2f 100644 --- a/hive/test/integration/recovery_test.dart +++ b/hive/test/integration/recovery_test.dart @@ -28,7 +28,7 @@ Future _performTest(bool lazy) async { var boxFile = File(path.join(dir.path, 'testbox$i.hive')); await boxFile.writeAsBytes(subBytes); - var subFrames = frames.takeWhile((f) => f.offset + f.length <= i + 1); + var subFrames = frames.takeWhile((f) => f.offset + f.length! <= i + 1); var subKeystore = Keystore.debug(frames: subFrames); if (lazy) { var box = await hive.openLazyBox('testbox$i'); diff --git a/hive/test/tests/adapters/big_int_adapter_test.dart b/hive/test/tests/adapters/big_int_adapter_test.dart index 3018274cf..63be3fc80 100644 --- a/hive/test/tests/adapters/big_int_adapter_test.dart +++ b/hive/test/tests/adapters/big_int_adapter_test.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:hive/src/adapters/big_int_adapter.dart'; import 'package:hive/src/binary/binary_reader_impl.dart'; import 'package:hive/src/binary/binary_writer_impl.dart'; +import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:test/test.dart'; void main() { @@ -12,7 +13,7 @@ void main() { var numberStr = '123456789123456789'; var bytes = Uint8List.fromList([numberStr.length, ...numberStr.codeUnits]); - var reader = BinaryReaderImpl(bytes, null); + var reader = BinaryReaderImpl(bytes, TypeRegistryImpl.nullImpl); expect(BigIntAdapter().read(reader), BigInt.parse(numberStr)); }); @@ -20,14 +21,14 @@ void main() { var numberStr = '-123456789123456789'; var bytes = Uint8List.fromList([numberStr.length, ...numberStr.codeUnits]); - var reader = BinaryReaderImpl(bytes, null); + var reader = BinaryReaderImpl(bytes, TypeRegistryImpl.nullImpl); expect(BigIntAdapter().read(reader), BigInt.parse(numberStr)); }); }); test('writes BigInts', () { var numberStr = '123456789123456789'; - var writer = BinaryWriterImpl(null); + var writer = BinaryWriterImpl(TypeRegistryImpl.nullImpl); BigIntAdapter().write(writer, BigInt.parse(numberStr)); expect(writer.toBytes(), [numberStr.length, ...numberStr.codeUnits]); }); diff --git a/hive/test/tests/adapters/date_time_adapter_test.dart b/hive/test/tests/adapters/date_time_adapter_test.dart index fc07229a6..1a1db5937 100644 --- a/hive/test/tests/adapters/date_time_adapter_test.dart +++ b/hive/test/tests/adapters/date_time_adapter_test.dart @@ -8,7 +8,7 @@ void main() { group('DateTimeAdapter', () { test('.read()', () { var now = DateTime.now(); - var binaryReader = BinaryReaderMock(); + var binaryReader = MockBinaryReader(); when(binaryReader.readInt()).thenReturn(now.millisecondsSinceEpoch); var date = DateTimeAdapter().read(binaryReader); @@ -18,7 +18,7 @@ void main() { test('.write()', () { var now = DateTime.now(); - var binaryWriter = BinaryWriterMock(); + var binaryWriter = MockBinaryWriter(); DateTimeAdapter().write(binaryWriter, now); verify(binaryWriter.writeInt(now.millisecondsSinceEpoch)); @@ -29,7 +29,7 @@ void main() { group('.read()', () { test('local', () { var now = DateTime.now(); - var binaryReader = BinaryReaderMock(); + var binaryReader = MockBinaryReader(); when(binaryReader.readInt()).thenReturn(now.millisecondsSinceEpoch); when(binaryReader.readBool()).thenReturn(false); @@ -40,7 +40,7 @@ void main() { test('UTC', () { var now = DateTime.now().toUtc(); - var binaryReader = BinaryReaderMock(); + var binaryReader = MockBinaryReader(); when(binaryReader.readInt()).thenReturn(now.millisecondsSinceEpoch); when(binaryReader.readBool()).thenReturn(true); @@ -54,7 +54,7 @@ void main() { group('.write()', () { test('local', () { var now = DateTime.now(); - var binaryWriter = BinaryWriterMock(); + var binaryWriter = MockBinaryWriter(); DateTimeWithTimezoneAdapter().write(binaryWriter, now); verifyInOrder([ @@ -65,7 +65,7 @@ void main() { test('UTC', () { var now = DateTime.now().toUtc(); - var binaryWriter = BinaryWriterMock(); + var binaryWriter = MockBinaryWriter(); DateTimeWithTimezoneAdapter().write(binaryWriter, now); verifyInOrder([ diff --git a/hive/test/tests/adapters/ignored_type_adapter_test.dart b/hive/test/tests/adapters/ignored_type_adapter_test.dart index e11519a5c..e590babf6 100644 --- a/hive/test/tests/adapters/ignored_type_adapter_test.dart +++ b/hive/test/tests/adapters/ignored_type_adapter_test.dart @@ -7,14 +7,14 @@ import '../mocks.dart'; void main() { group('IgnoredTypeAdapter', () { test('.read()', () { - var binaryReader = BinaryReaderMock(); + var binaryReader = MockBinaryReader(); var value = IgnoredTypeAdapter().read(binaryReader); verifyNever(binaryReader.read()); expect(value, null); }); test('.write()', () { - var binaryWriter = BinaryWriterMock(); + var binaryWriter = MockBinaryWriter(); IgnoredTypeAdapter().write(binaryWriter, 42); verifyNever(binaryWriter.writeInt(42)); }); diff --git a/hive/test/tests/backend/js/backend_manager_test.dart b/hive/test/tests/backend/js/backend_manager_test.dart index e0e317c23..1807ec0ab 100644 --- a/hive/test/tests/backend/js/backend_manager_test.dart +++ b/hive/test/tests/backend/js/backend_manager_test.dart @@ -6,10 +6,10 @@ import 'package:hive/src/backend/js/backend_manager.dart'; import 'package:test/test.dart'; Future _openDb() async { - return await window.indexedDB.open('testBox', version: 1, + return await window.indexedDB!.open('testBox', version: 1, onUpgradeNeeded: (e) { var db = e.target.result as Database; - if (!db.objectStoreNames.contains('box')) { + if (!db.objectStoreNames!.contains('box')) { db.createObjectStore('box'); } }); diff --git a/hive/test/tests/backend/js/storage_backend_js_test.dart b/hive/test/tests/backend/js/storage_backend_js_test.dart index db1bb8872..c51cb93b3 100644 --- a/hive/test/tests/backend/js/storage_backend_js_test.dart +++ b/hive/test/tests/backend/js/storage_backend_js_test.dart @@ -11,23 +11,24 @@ import 'package:hive/src/binary/binary_writer_impl.dart'; import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/box/change_notifier.dart'; import 'package:hive/src/box/keystore.dart'; +import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:test/test.dart'; import '../../frames.dart'; +late final Database _nullDatabase; StorageBackendJs _getBackend({ - Database db, - HiveCipher cipher, - TypeRegistry registry, + Database? db, + HiveCipher? cipher, + TypeRegistry registry = TypeRegistryImpl.nullImpl, }) { - return StorageBackendJs(db, cipher, registry); + return StorageBackendJs(db ?? _nullDatabase, cipher, registry); } -Future _openDb() async { - return await window.indexedDB.open('testBox', version: 1, - onUpgradeNeeded: (e) { +Future _openDb([String name = 'testBox']) async { + return await window.indexedDB!.open(name, version: 1, onUpgradeNeeded: (e) { var db = e.target.result as Database; - if (!db.objectStoreNames.contains('box')) { + if (!db.objectStoreNames!.contains('box')) { db.createObjectStore('box'); } }); @@ -45,7 +46,8 @@ Future _getDbWith(Map content) async { return db; } -void main() { +void main() async { + _nullDatabase = await _openDb('nullTestBox'); group('StorageBackendJs', () { test('.path', () { expect(_getBackend().path, null); @@ -68,7 +70,7 @@ void main() { }); test('crypto', () { - var backend = StorageBackendJs(null, testCipher, testRegistry); + var backend = StorageBackendJs(_nullDatabase, testCipher, testRegistry); var i = 0; for (var frame in testFrames) { var buffer = backend.encodeValue(frame) as ByteBuffer; @@ -85,11 +87,12 @@ void main() { 'key': Uint8List.fromList([1, 2, 3]), 'otherKey': null }); - var backend = StorageBackendJs(null, null); + var backend = StorageBackendJs(_nullDatabase, null); var encoded = Uint8List.view(backend.encodeValue(frame) as ByteBuffer); - var writer = BinaryWriterImpl(null)..write(frame.value); + var writer = BinaryWriterImpl(TypeRegistryImpl.nullImpl) + ..write(frame.value); expect(encoded, [0x90, 0xA9, ...writer.toBytes()]); }); @@ -99,7 +102,8 @@ void main() { var encoded = Uint8List.view(backend.encodeValue(frame) as ByteBuffer); - var writer = BinaryWriterImpl(null)..write(frame.value); + var writer = BinaryWriterImpl(TypeRegistryImpl.nullImpl) + ..write(frame.value); expect(encoded, [0x90, 0xA9, ...writer.toBytes()]); }); }); @@ -179,8 +183,11 @@ void main() { var db = await _getDbWith({'key1': 1, 'key2': null, 'key3': 3}); var backend = _getBackend(db: db); - var keystore = Keystore(null, ChangeNotifier(), null); - expect(await backend.initialize(null, keystore, false), 0); + var keystore = Keystore.debug(notifier: ChangeNotifier()); + expect( + await backend.initialize( + TypeRegistryImpl.nullImpl, keystore, false), + 0); expect(keystore.frames, [ Frame('key1', 1), Frame('key2', null), @@ -192,8 +199,10 @@ void main() { var db = await _getDbWith({'key1': 1, 'key2': null, 'key3': 3}); var backend = _getBackend(db: db); - var keystore = Keystore(null, ChangeNotifier(), null); - expect(await backend.initialize(null, keystore, true), 0); + var keystore = Keystore.debug(notifier: ChangeNotifier()); + expect( + await backend.initialize(TypeRegistryImpl.nullImpl, keystore, true), + 0); expect(keystore.frames, [ Frame.lazy('key1'), Frame.lazy('key2'), diff --git a/hive/test/tests/backend/storage_backend_memory_test.dart b/hive/test/tests/backend/storage_backend_memory_test.dart index 0a846d3cc..db89cb88b 100644 --- a/hive/test/tests/backend/storage_backend_memory_test.dart +++ b/hive/test/tests/backend/storage_backend_memory_test.dart @@ -2,6 +2,7 @@ import 'dart:typed_data'; import 'package:hive/src/backend/storage_backend_memory.dart'; import 'package:hive/src/binary/frame.dart'; +import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:test/test.dart'; import '../common.dart'; @@ -23,7 +24,7 @@ void main() { var bytes = Uint8List.fromList([1, 2, 3, 4]); var backend = StorageBackendMemory(bytes, null); expect( - () => backend.initialize(null, null, false), + () => backend.initialize(TypeRegistryImpl.nullImpl, null, false), throwsHiveError('Wrong checksum'), ); }); diff --git a/hive/test/tests/backend/vm/read_write_sync_test.dart b/hive/test/tests/backend/vm/read_write_sync_test.dart index 8b9a4a801..7b45a68da 100644 --- a/hive/test/tests/backend/vm/read_write_sync_test.dart +++ b/hive/test/tests/backend/vm/read_write_sync_test.dart @@ -2,11 +2,11 @@ import 'package:hive/src/backend/vm/read_write_sync.dart'; import 'package:test/test.dart'; Future _asyncRead(ReadWriteSync rw, int id, List history, - {bool throwError = false}) { + {bool? throwError = false}) { return rw.syncRead(() async { history.add('startread$id'); await Future.delayed(Duration(milliseconds: 10)); - if (throwError) { + if (throwError!) { throw 'error$id'; // ignore: only_throw_errors } history.add('stopread$id'); @@ -14,11 +14,11 @@ Future _asyncRead(ReadWriteSync rw, int id, List history, } Future _asyncWrite(ReadWriteSync rw, int id, List history, - {bool throwError = false}) { + {bool? throwError = false}) { return rw.syncWrite(() async { history.add('startwrite$id'); await Future.delayed(Duration(milliseconds: 10)); - if (throwError) { + if (throwError!) { throw 'error$id'; // ignore: only_throw_errors } history.add('stopwrite$id'); @@ -26,19 +26,23 @@ Future _asyncWrite(ReadWriteSync rw, int id, List history, } Future _asyncReadWrite(ReadWriteSync rw, int id, List history, - {bool throwError = false}) { + {bool? throwError = false}) { return rw.syncReadWrite(() async { history.add('startreadwrite$id'); await Future.delayed(Duration(milliseconds: 10)); - if (throwError) { + if (throwError!) { throw 'error$id'; // ignore: only_throw_errors } history.add('stopreadwrite$id'); }); } -typedef _Operation = Future - Function(ReadWriteSync rw, int id, List history, {bool throwError}); +typedef _Operation = Future Function( + ReadWriteSync rw, + int id, + List history, { + bool? throwError, +}); Future _asyncOperation( ReadWriteSync rw, _Operation operation, int id, List history, diff --git a/hive/test/tests/backend/vm/storage_backend_vm_test.dart b/hive/test/tests/backend/vm/storage_backend_vm_test.dart index bba5f879b..d0061c751 100644 --- a/hive/test/tests/backend/vm/storage_backend_vm_test.dart +++ b/hive/test/tests/backend/vm/storage_backend_vm_test.dart @@ -9,14 +9,14 @@ import 'package:hive/src/backend/vm/storage_backend_vm.dart'; import 'package:hive/src/binary/binary_writer_impl.dart'; import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/io/frame_io_helper.dart'; +import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import '../../common.dart'; import '../../frames.dart'; -import '../../mocks.dart'; -class FrameIoHelperMock extends Mock implements FrameIoHelper {} +import '../../mocks.dart'; const testMap = { 'SomeKey': 123, @@ -36,26 +36,30 @@ Uint8List getFrameBytes(Iterable frames) { } StorageBackendVm _getBackend({ - File file, - File lockFile, + File? file, + File? lockFile, bool crashRecovery = false, - HiveCipher cipher, - FrameIoHelper ioHelper, - TypeRegistry registry, - ReadWriteSync sync, - RandomAccessFile readRaf, - RandomAccessFile writeRaf, + HiveCipher? cipher, + FrameIoHelper? ioHelper, + ReadWriteSync? sync, + RandomAccessFile? readRaf, + RandomAccessFile? writeRaf, }) { - return StorageBackendVm.debug( - file ?? FileMock(), - lockFile ?? FileMock(), + final backend = StorageBackendVm.debug( + file ?? MockFile(), + lockFile ?? MockFile(), crashRecovery, cipher, - ioHelper ?? FrameIoHelperMock(), + ioHelper ?? MockFrameIoHelper(), sync ?? ReadWriteSync(), - ) - ..readRaf = readRaf - ..writeRaf = writeRaf; + ); + if (readRaf != null) { + backend.readRaf = readRaf; + } + if (writeRaf != null) { + backend.writeRaf = writeRaf; + } + return backend; } void main() { @@ -73,12 +77,13 @@ void main() { group('.open()', () { test('readFile & writeFile', () async { - var file = FileMock(); - var readRaf = RAFMock(); - var writeRaf = RAFMock(); + var file = MockFile(); + var readRaf = MockRandomAccessFile(); + var writeRaf = MockRandomAccessFile(); when(file.open()).thenAnswer((i) => Future.value(readRaf)); when(file.open(mode: FileMode.writeOnlyAppend)) .thenAnswer((i) => Future.value(writeRaf)); + when(writeRaf.length()).thenAnswer((_) => Future.value(0)); var backend = _getBackend(file: file); await backend.open(); @@ -87,10 +92,12 @@ void main() { }); test('writeOffset', () async { - var file = FileMock(); - var writeFile = RAFMock(); + var file = MockFile(); + var writeFile = MockRandomAccessFile(); + var readRaf = MockRandomAccessFile(); when(file.open(mode: FileMode.writeOnlyAppend)) .thenAnswer((i) => Future.value(writeFile)); + when(file.open()).thenAnswer((i) => Future.value(readRaf)); when(writeFile.length()).thenAnswer((i) => Future.value(123)); var backend = _getBackend(file: file); @@ -101,14 +108,14 @@ void main() { group('.initialize()', () { File getLockFile() { - var lockFileMock = FileMock(); - when(lockFileMock.open(mode: FileMode.write)) - .thenAnswer((i) => Future.value(RAFMock())); - return lockFileMock; + var lockMockFile = MockFile(); + when(lockMockFile.open(mode: FileMode.write)) + .thenAnswer((i) => Future.value(MockRandomAccessFile())); + return lockMockFile; } FrameIoHelper getFrameIoHelper(int recoveryOffset) { - var helper = FrameIoHelperMock(); + var helper = MockFrameIoHelper(); when(helper.framesFromFile(any, any, any, any)).thenAnswer((i) { return Future.value(recoveryOffset); }); @@ -120,42 +127,62 @@ void main() { void runTests(bool lazy) { test('opens lock file and acquires lock', () async { - var lockFile = FileMock(); - var lockRaf = RAFMock(); + var lockFile = MockFile(); + var lockRaf = MockRandomAccessFile(); when(lockFile.open(mode: FileMode.write)) .thenAnswer((i) => Future.value(lockRaf)); + when(lockRaf.lock()).thenAnswer((i) => Future.value(lockRaf)); var backend = _getBackend( lockFile: lockFile, ioHelper: getFrameIoHelper(-1), ); + when(backend.path).thenReturn('nullPath'); - await backend.initialize(null, KeystoreMock(), lazy); + await backend.initialize( + TypeRegistryImpl.nullImpl, MockKeystore(), lazy); verify(lockRaf.lock()); }); test('recoveryOffset with crash recovery', () async { - var writeRaf = RAFMock(); + var writeRaf = MockRandomAccessFile(); + var lockFile = getLockFile(); + var lockRaf = MockRandomAccessFile(); + var backend = _getBackend( - lockFile: getLockFile(), + lockFile: lockFile, ioHelper: getFrameIoHelper(20), crashRecovery: true, writeRaf: writeRaf, ); + when(backend.path).thenReturn('nullPath'); + when(lockFile.open(mode: FileMode.write)) + .thenAnswer((i) => Future.value(lockRaf)); + when(lockRaf.lock()).thenAnswer((i) => Future.value(lockRaf)); + when(writeRaf.truncate(20)).thenAnswer((i) => Future.value(writeRaf)); - await backend.initialize(null, KeystoreMock(), lazy); + await backend.initialize( + TypeRegistryImpl.nullImpl, MockKeystore(), lazy); verify(writeRaf.truncate(20)); }); test('recoveryOffset without crash recovery', () async { + var lockFile = getLockFile(); + var lockRaf = MockRandomAccessFile(); + var backend = _getBackend( - lockFile: getLockFile(), + lockFile: lockFile, ioHelper: getFrameIoHelper(20), crashRecovery: false, ); + when(backend.path).thenReturn('nullPath'); + when(lockFile.open(mode: FileMode.write)) + .thenAnswer((i) => Future.value(lockRaf)); + when(lockRaf.lock()).thenAnswer((i) => Future.value(lockRaf)); await expectLater( - () => backend.initialize(null, KeystoreMock(), lazy), + () => backend.initialize( + TypeRegistryImpl.nullImpl, MockKeystore(), lazy), throwsHiveError('corrupted')); }); } @@ -174,7 +201,11 @@ void main() { var frameBytes = getFrameBytes([Frame('test', 123)]); var readRaf = await getTempRaf([1, 2, 3, 4, 5, ...frameBytes]); - var backend = _getBackend(readRaf: readRaf); + var backend = _getBackend(readRaf: readRaf) + // The registry needs to be initialized before reading values, and + // because we do not call StorageBackendVM.initialize(), we set it + // manually. + ..registry = TypeRegistryImpl.nullImpl; var value = await backend.readValue( Frame('test', 123, length: frameBytes.length, offset: 5), ); @@ -185,7 +216,11 @@ void main() { test('throws exception when frame cannot be read', () async { var readRaf = await getTempRaf([1, 2, 3, 4, 5]); - var backend = _getBackend(readRaf: readRaf); + var backend = _getBackend(readRaf: readRaf) + // The registry needs to be initialized before reading values, and + // because we do not call StorageBackendVM.initialize(), we set it + // manually. + ..registry = TypeRegistryImpl.nullImpl; var frame = Frame('test', 123, length: frameBytes.length, offset: 0); await expectLater( @@ -200,8 +235,16 @@ void main() { var frames = [Frame('key1', 'value'), Frame('key2', null)]; var bytes = getFrameBytes(frames); - var writeRaf = RAFMock(); - var backend = _getBackend(writeRaf: writeRaf); + var writeRaf = MockRandomAccessFile(); + when(writeRaf.setPosition(0)).thenAnswer((i) => Future.value(writeRaf)); + when(writeRaf.writeFrom(bytes)) + .thenAnswer((i) => Future.value(writeRaf)); + + var backend = _getBackend(writeRaf: writeRaf) + // The registry needs to be initialized before writing values, and + // because we do not call StorageBackendVM.initialize(), we set it + // manually. + ..registry = TypeRegistryImpl.nullImpl; await backend.writeFrames(frames); verify(writeRaf.writeFrom(bytes)); @@ -210,8 +253,15 @@ void main() { test('updates offsets', () async { var frames = [Frame('key1', 'value'), Frame('key2', null)]; - var writeRaf = RAFMock(); - var backend = _getBackend(writeRaf: writeRaf); + var writeRaf = MockRandomAccessFile(); + when(writeRaf.setPosition(5)).thenAnswer((i) => Future.value(writeRaf)); + when(writeRaf.writeFrom(any)).thenAnswer((i) => Future.value(writeRaf)); + + var backend = _getBackend(writeRaf: writeRaf) + // The registry needs to be initialized before writing values, and + // because we do not call StorageBackendVM.initialize(), we set it + // manually. + ..registry = TypeRegistryImpl.nullImpl; backend.writeOffset = 5; await backend.writeFrames(frames); @@ -223,9 +273,13 @@ void main() { }); test('resets writeOffset on error', () async { - var writeRaf = RAFMock(); + var writeRaf = MockRandomAccessFile(); when(writeRaf.writeFrom(any)).thenThrow('error'); - var backend = _getBackend(writeRaf: writeRaf); + var backend = _getBackend(writeRaf: writeRaf) + // The registry needs to be initialized before writing values, and + // because we do not call StorageBackendVM.initialize(), we set it + // manually. + ..registry = TypeRegistryImpl.nullImpl; backend.writeOffset = 123; await expectLater(() => backend.writeFrames([Frame('key1', 'value')]), @@ -302,7 +356,9 @@ void main() { });*/ test('.clear()', () async { - var writeRaf = RAFMock(); + var writeRaf = MockRandomAccessFile(); + when(writeRaf.truncate(0)).thenAnswer((i) => Future.value(writeRaf)); + when(writeRaf.setPosition(0)).thenAnswer((i) => Future.value(writeRaf)); var backend = _getBackend(writeRaf: writeRaf); backend.writeOffset = 111; @@ -313,10 +369,15 @@ void main() { }); test('.close()', () async { - var readRaf = RAFMock(); - var writeRaf = RAFMock(); - var lockRaf = RAFMock(); - var lockFile = FileMock(); + var readRaf = MockRandomAccessFile(); + var writeRaf = MockRandomAccessFile(); + var lockRaf = MockRandomAccessFile(); + var lockFile = MockFile(); + + returnFutureVoid(when(readRaf.close())); + returnFutureVoid(when(writeRaf.close())); + returnFutureVoid(when(lockRaf.close())); + when(lockFile.delete()).thenAnswer((i) => Future.value(lockFile)); var backend = _getBackend( lockFile: lockFile, @@ -335,11 +396,17 @@ void main() { }); test('.deleteFromDisk()', () async { - var readRaf = RAFMock(); - var writeRaf = RAFMock(); - var lockRaf = RAFMock(); - var lockFile = FileMock(); - var file = FileMock(); + var readRaf = MockRandomAccessFile(); + var writeRaf = MockRandomAccessFile(); + var lockRaf = MockRandomAccessFile(); + var lockFile = MockFile(); + var file = MockFile(); + + returnFutureVoid(when(readRaf.close())); + returnFutureVoid(when(writeRaf.close())); + returnFutureVoid(when(lockRaf.close())); + when(lockFile.delete()).thenAnswer((i) => Future.value(lockFile)); + when(file.delete()).thenAnswer((i) => Future.value(file)); var backend = _getBackend( file: file, diff --git a/hive/test/tests/binary/binary_reader_test.dart b/hive/test/tests/binary/binary_reader_test.dart index 0a18fe2ec..6f0b1aa09 100644 --- a/hive/test/tests/binary/binary_reader_test.dart +++ b/hive/test/tests/binary/binary_reader_test.dart @@ -6,7 +6,6 @@ import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/object/hive_list_impl.dart'; import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:test/test.dart'; -import 'package:dartx/dartx.dart'; import '../common.dart'; import '../frames.dart'; @@ -355,61 +354,65 @@ void main() { test('normal', () { var frames = framesSetLengthOffset(testFrames, frameBytes); var offset = 0; - frames.forEachIndexed((frame, i) { + for (var i = 0; i < frames.length; i++) { + final frame = frames[i]; var reader = BinaryReaderImpl(frameBytes[i], testRegistry); expectFrame( - reader.readFrame(lazy: false, frameOffset: offset), + reader.readFrame(lazy: false, frameOffset: offset)!, frame, ); offset += frameBytes[i].length; - }); + } }); test('lazy', () { var frames = framesSetLengthOffset(testFrames, frameBytes); var offset = 0; - frames.forEachIndexed((frame, i) { + for (var i = 0; i < frames.length; i++) { + final frame = frames[i]; var reader = BinaryReaderImpl(frameBytes[i], testRegistry); expectFrame( - reader.readFrame(lazy: true, frameOffset: offset), + reader.readFrame(lazy: true, frameOffset: offset)!, frame.toLazy(), ); offset += frameBytes[i].length; - }); + } }); test('encrypted', () { var frames = framesSetLengthOffset(testFrames, frameBytesEncrypted); var offset = 0; - frames.forEachIndexed((frame, i) { + for (var i = 0; i < frames.length; i++) { + final frame = frames[i]; var reader = BinaryReaderImpl(frameBytesEncrypted[i], testRegistry); expectFrame( reader.readFrame( lazy: false, frameOffset: offset, cipher: testCipher, - ), + )!, frame, ); offset += frameBytesEncrypted[i].length; - }); + } }); test('lazy', () { var frames = framesSetLengthOffset(testFrames, frameBytesEncrypted); var offset = 0; - frames.forEachIndexed((frame, i) { + for (var i = 0; i < frames.length; i++) { + final frame = frames[i]; var reader = BinaryReaderImpl(frameBytesEncrypted[i], testRegistry); expectFrame( reader.readFrame( lazy: true, frameOffset: offset, cipher: testCipher, - ), + )!, frame.toLazy(), ); offset += frameBytesEncrypted[i].length; - }); + } }); }); diff --git a/hive/test/tests/binary/binary_writer_test.dart b/hive/test/tests/binary/binary_writer_test.dart index 879108a52..3e5e4c1b1 100644 --- a/hive/test/tests/binary/binary_writer_test.dart +++ b/hive/test/tests/binary/binary_writer_test.dart @@ -7,7 +7,6 @@ import 'package:hive/src/object/hive_object.dart'; import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import 'package:dartx/dartx.dart'; import '../frames.dart'; import '../mocks.dart'; @@ -15,7 +14,6 @@ import '../mocks.dart'; List bytes(ByteData byteData) => byteData.buffer.asUint8List(); BinaryWriterImpl getWriter() => BinaryWriterImpl(TypeRegistryImpl()); - void main() { group('BinaryWriter', () { test('.writeByte()', () { @@ -34,8 +32,6 @@ void main() { bw = getWriter(); bw.writeByte(257); expect(bw.toBytes(), [1]); - - expect(() => bw.writeByte(null), throwsA(anything)); }); test('.writeWord()', () { @@ -54,8 +50,6 @@ void main() { bw = getWriter(); bw.writeWord(65536); expect(bw.toBytes(), [0, 0]); - - expect(() => bw.writeWord(null), throwsA(anything)); }); test('.writeInt32()', () { @@ -95,8 +89,6 @@ void main() { bw.writeInt32(-65537); bd.setInt32(0, -65537, Endian.little); expect(bw.toBytes(), bytes(bd)); - - expect(() => bw.writeInt32(null), throwsA(anything)); }); test('.writeUint32()', () { @@ -121,8 +113,6 @@ void main() { bw.writeUint32(-2147483648); bd.setUint32(0, -2147483648, Endian.little); expect(bw.toBytes(), bytes(bd)); - - expect(() => bw.writeUint32(null), throwsA(anything)); }); test('.writeInt()', () { @@ -152,8 +142,6 @@ void main() { bw.writeInt(-2 ^ 53); bd.setFloat64(0, (-2 ^ 53).toDouble(), Endian.little); expect(bw.toBytes(), bytes(bd)); - - expect(() => bw.writeInt(null), throwsA(anything)); }); test('.writeDouble()', () { @@ -193,8 +181,6 @@ void main() { bw.writeDouble(double.minPositive); bd.setFloat64(0, double.minPositive, Endian.little); expect(bw.toBytes(), bytes(bd)); - - expect(() => bw.writeDouble(null), throwsA(anything)); }); test('.writeBool()', () { @@ -205,8 +191,6 @@ void main() { bw = getWriter(); bw.writeBool(false); expect(bw.toBytes(), [0]); - - expect(() => bw.writeBool(null), throwsA(anything)); }); test('.writeString()', () { @@ -232,8 +216,6 @@ void main() { 0xe2, 0x80, 0x8d, 0xf0, 0x9f, 0x91, 0xa7, 0xe2, 0x80, 0x8d, 0xf0, // 0x9f, 0x91, 0xa6 // ]); - - expect(() => bw.writeString(null), throwsA(anything)); }); test('.writeByteList()', () { @@ -252,8 +234,6 @@ void main() { bw = getWriter(); bw.writeByteList([1, 2, 3, 4], writeLength: false); expect(bw.toBytes(), [1, 2, 3, 4]); - - expect(() => bw.writeByteList(null), throwsA(anything)); }); test('.writeIntList()', () { @@ -274,8 +254,6 @@ void main() { bw.writeIntList([1, 2], writeLength: false); expect( bw.toBytes(), [0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 64]); - - expect(() => bw.writeIntList(null), throwsA(anything)); }); test('.writeDoubleList()', () { @@ -294,8 +272,6 @@ void main() { bw = getWriter(); bw.writeDoubleList([1.0], writeLength: false); expect(bw.toBytes(), [0, 0, 0, 0, 0, 0, 240, 63]); - - expect(() => bw.writeDoubleList(null), throwsA(anything)); }); test('.writeBoolList()', () { @@ -314,8 +290,6 @@ void main() { bw = getWriter(); bw.writeBoolList([true, false, true], writeLength: false); expect(bw.toBytes(), [1, 0, 1]); - - expect(() => bw.writeBoolList(null), throwsA(anything)); }); test('.writeStringList()', () { @@ -337,8 +311,6 @@ void main() { bw = getWriter(); bw.writeStringList(['a', 'ab'], writeLength: false); expect(bw.toBytes(), [1, 0, 0, 0, 97, 2, 0, 0, 0, 97, 98]); - - expect(() => bw.writeBoolList(null), throwsA(anything)); }); test('.writeList()', () { @@ -380,7 +352,7 @@ void main() { }); group('.writeHiveList()', () { - var box = BoxMock(); + var box = MockBox(); when(box.name).thenReturn('Box'); var obj = TestHiveObject()..init('key', box); @@ -410,20 +382,22 @@ void main() { group('.writeFrame()', () { test('normal', () { - testFrames.forEachIndexed((frame, i) { + for (var i = 0; i < testFrames.length; i++) { + final frame = testFrames[i]; var writer = BinaryWriterImpl(testRegistry); expect(writer.writeFrame(frame), frameBytes[i].length); expect(writer.toBytes(), frameBytes[i]); - }); + } }); test('encrypted', () { - testFrames.forEachIndexed((frame, i) { + for (var i = 0; i < testFrames.length; i++) { + final frame = testFrames[i]; var writer = BinaryWriterImpl(testRegistry); expect(writer.writeFrame(frame, cipher: testCipher), frameBytesEncrypted[i].length); expect(writer.toBytes(), frameBytesEncrypted[i]); - }); + } }); }); @@ -483,7 +457,7 @@ void main() { }); test('HiveList', () { - var box = BoxMock(); + var box = MockBox(); when(box.name).thenReturn('Box'); var obj = TestHiveObject()..init('key', box); diff --git a/hive/test/tests/box/box_base_test.dart b/hive/test/tests/box/box_base_test.dart index 4484b9b6f..e67b2fd54 100644 --- a/hive/test/tests/box/box_base_test.dart +++ b/hive/test/tests/box/box_base_test.dart @@ -8,33 +8,57 @@ import 'package:hive/src/box/keystore.dart'; import 'package:hive/src/hive_impl.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; - import '../common.dart'; + import '../mocks.dart'; -class _BoxBaseMock extends BoxBaseImpl with Mock { +class _FakeStorageBackend extends Fake implements StorageBackend {} + +class _FakeHiveImpl extends Fake implements HiveImpl {} + +class _FakeKeystore extends Fake implements HiveImpl {} + +class _BoxBaseMock extends BoxBaseImpl with Mock { _BoxBaseMock( HiveImpl hive, String name, - CompactionStrategy cStrategy, + KeyComparator? keyComparator, + CompactionStrategy compactionStrategy, StorageBackend backend, ) : super( - hive ?? HiveImpl(), - name ?? 'testBox', - null, - cStrategy ?? (total, deleted) => false, - backend ?? BackendMock(), + hive, + name, + keyComparator, + compactionStrategy, + backend, ); + Future putAll(Map entries) => + (super.noSuchMethod(Invocation.method(#putAll, [entries]), Future.value()) + as Future); + Future deleteAll(Iterable keys) => + (super.noSuchMethod(Invocation.method(#deleteAll, [keys]), Future.value()) + as Future); + bool get lazy => + (super.noSuchMethod(Invocation.getter(#lazy), false) as bool); } _BoxBaseMock _openBoxBaseMock({ - HiveImpl hive, - String name, - Keystore keystore, - CompactionStrategy cStrategy, - StorageBackend backend, + HiveImpl? hive, + String? name, + Keystore? keystore, + CompactionStrategy? cStrategy, + StorageBackend? backend, }) { - var mock = _BoxBaseMock(hive, name, cStrategy, backend); + hive ??= HiveImpl(); + name ??= 'testBox'; + backend ??= MockStorageBackend(); + var mock = _BoxBaseMock( + hive, + name, + null, + cStrategy ?? (_, __) => false, + backend, + ); mock.keystore = keystore ?? Keystore(mock, ChangeNotifier(), null); return mock; } @@ -47,7 +71,7 @@ void main() { }); test('.path', () { - var backend = BackendMock(); + var backend = MockStorageBackend(); when(backend.path).thenReturn('some/path'); var box = _openBoxBaseMock(backend: backend); @@ -65,7 +89,10 @@ void main() { }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.keys, throwsHiveError('closed')); }); @@ -91,7 +118,10 @@ void main() { }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.length, throwsHiveError('closed')); expect(() => box.isEmpty, throwsHiveError('closed')); @@ -101,15 +131,19 @@ void main() { group('.watch()', () { test('calls keystore.watch()', () { - var keystore = KeystoreMock(); + var keystore = MockKeystore(); var box = _openBoxBaseMock(keystore: keystore); + when(keystore.watch(key: 123)).thenAnswer((_) => Stream.empty()); box.watch(key: 123); verify(keystore.watch(key: 123)); }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.watch(), throwsHiveError('closed')); }); @@ -123,15 +157,19 @@ void main() { }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.keyAt(0), throwsHiveError('closed')); }); }); test('.initialize()', () async { - var backend = BackendMock(); + var backend = MockStorageBackend(); var box = _openBoxBaseMock(backend: backend); + when(box.lazy).thenReturn(false); when(backend.initialize(any, any, any)).thenAnswer((i) async { i.positionalArguments[1].insert(Frame('key1', 1)); @@ -155,7 +193,7 @@ void main() { }); test('does not use backend', () { - var backend = BackendMock(); + var backend = MockStorageBackend(); var box = _openBoxBaseMock(backend: backend); box.keystore.insert(Frame.lazy('existingKey')); @@ -165,7 +203,10 @@ void main() { }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.containsKey(0), throwsHiveError('closed')); }); @@ -174,12 +215,16 @@ void main() { group('.add()', () { test('calls put()', () async { var box = _openBoxBaseMock(); + when(box.put(0, 123)).thenAnswer((i) => Future.value(0)); + expect(await box.add(123), 0); verify(box.put(0, 123)); }); test('updates auto increment', () async { var box = _openBoxBaseMock(); + returnFutureVoid(when(box.putAll({5: 123}))); + box.keystore.updateAutoIncrement(4); expect(await box.add(123), 5); }); @@ -188,15 +233,19 @@ void main() { test('.addAll()', () async { var box = _openBoxBaseMock(); box.keystore.updateAutoIncrement(4); + final vals = {5: 1, 6: 2, 7: 3}; + returnFutureVoid(when(box.putAll(vals))); expect(await box.addAll([1, 2, 3]), [5, 6, 7]); expect(box.keystore.autoIncrement(), 8); - verify(box.putAll({5: 1, 6: 2, 7: 3})); + verify(box.putAll(vals)); }); group('.putAt()', () { test('override existing', () async { var box = _openBoxBaseMock(); + returnFutureVoid(when(box.putAll({'b': 'test'}))); + box.keystore.insert(Frame.lazy('a')); box.keystore.insert(Frame.lazy('b')); @@ -224,6 +273,8 @@ void main() { group('.deleteAt()', () { test('delete frame', () async { var box = _openBoxBaseMock(); + returnFutureVoid(when(box.deleteAll(['b']))); + box.keystore.insert(Frame.lazy('a')); box.keystore.insert(Frame.lazy('b')); @@ -248,9 +299,12 @@ void main() { group('.clear()', () { test('clears keystore and backend', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); + + returnFutureVoid(when(backend.clear())); when(keystore.clear()).thenReturn(2); + var box = _openBoxBaseMock(backend: backend, keystore: keystore); expect(await box.clear(), 2); @@ -261,7 +315,10 @@ void main() { }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.clear(), throwsHiveError('closed')); }); @@ -269,7 +326,7 @@ void main() { group('.compact()', () { test('does nothing if backend does not support compaction', () async { - var backend = BackendMock(); + var backend = MockStorageBackend(); when(backend.supportsCompaction).thenReturn(false); var box = _openBoxBaseMock(backend: backend); @@ -279,7 +336,7 @@ void main() { }); test('does nothing if there are no deleted entries', () async { - var backend = BackendMock(); + var backend = MockStorageBackend(); when(backend.supportsCompaction).thenReturn(true); var box = _openBoxBaseMock(backend: backend); box.keystore.insert(Frame.lazy('key1')); @@ -290,12 +347,17 @@ void main() { }); test('compact', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(keystore.frames) .thenReturn([Frame('key', 1, length: 22, offset: 33)]); when(backend.supportsCompaction).thenReturn(true); + // In case it is 0, we will bail out before compaction + when(keystore.deletedEntries).thenReturn(1); + returnFutureVoid( + when(backend.compact([Frame('key', 1, length: 22, offset: 33)])), + ); var box = _openBoxBaseMock(backend: backend, keystore: keystore); @@ -305,22 +367,27 @@ void main() { }); test('throws if box is closed', () async { - var box = _openBoxBaseMock(); + var backend = MockStorageBackend(); + returnFutureVoid(when(backend.close())); + + var box = _openBoxBaseMock(backend: backend); await box.close(); expect(() => box.compact(), throwsHiveError('closed')); }); }); test('.close()', () async { - var hive = HiveMock(); - var keystore = KeystoreMock(); - var backend = BackendMock(); + var hive = MockHiveImpl(); + var keystore = MockKeystore(); + var backend = MockStorageBackend(); var box = _openBoxBaseMock( name: 'myBox', hive: hive, keystore: keystore, backend: backend, ); + returnFutureVoid(when(keystore.close())); + returnFutureVoid(when(backend.close())); await box.close(); verifyInOrder([ @@ -333,8 +400,13 @@ void main() { group('.deleteFromDisk()', () { test('only deleted file if box is closed', () async { - var backend = BackendMock(); - var box = _openBoxBaseMock(backend: backend); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); + var box = _openBoxBaseMock(backend: backend, keystore: keystore); + returnFutureVoid(when(keystore.close())); + returnFutureVoid(when(backend.close())); + returnFutureVoid(when(backend.deleteFromDisk())); + await box.close(); await box.deleteFromDisk(); @@ -342,15 +414,18 @@ void main() { }); test('closes and deletes box', () async { - var hive = HiveMock(); - var keystore = KeystoreMock(); - var backend = BackendMock(); + var hive = MockHiveImpl(); + var keystore = MockKeystore(); + var backend = MockStorageBackend(); var box = _openBoxBaseMock( name: 'myBox', hive: hive, keystore: keystore, backend: backend, ); + returnFutureVoid(when(keystore.close())); + returnFutureVoid(when(backend.close())); + returnFutureVoid(when(backend.deleteFromDisk())); await box.deleteFromDisk(); verifyInOrder([ diff --git a/hive/test/tests/box/box_impl_test.dart b/hive/test/tests/box/box_impl_test.dart index d5c4abcc6..0ad8fcab6 100644 --- a/hive/test/tests/box/box_impl_test.dart +++ b/hive/test/tests/box/box_impl_test.dart @@ -7,22 +7,22 @@ import 'package:hive/src/box/keystore.dart'; import 'package:hive/src/hive_impl.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; - +import '../common.dart'; import '../mocks.dart'; BoxImpl _getBox({ - String name, - HiveImpl hive, - Keystore keystore, - CompactionStrategy cStrategy, - StorageBackend backend, + String? name, + HiveImpl? hive, + Keystore? keystore, + CompactionStrategy? cStrategy, + StorageBackend? backend, }) { var box = BoxImpl( hive ?? HiveImpl(), name ?? 'testBox', null, cStrategy ?? (total, deleted) => false, - backend ?? BackendMock(), + backend ?? MockStorageBackend(), ); box.keystore = keystore ?? Keystore(box, ChangeNotifier(), null); return box; @@ -55,7 +55,7 @@ void main() { group('.get()', () { test('returns defaultValue if key does not exist', () { - var backend = BackendMock(); + var backend = MockStorageBackend(); var box = _getBox(backend: backend); expect(box.get('someKey'), null); @@ -64,7 +64,7 @@ void main() { }); test('returns cached value if it exists', () { - var backend = BackendMock(); + var backend = MockStorageBackend(); var box = _getBox( backend: backend, keystore: Keystore.debug(frames: [ @@ -90,11 +90,18 @@ void main() { group('.putAll()', () { test('values', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); - when(keystore.frames).thenReturn([Frame('keystoreFrames', 123)]); + var frames = [Frame('key1', 'value1'), Frame('key2', 'value2')]; + var keystoreFrames = [Frame('keystoreFrames', 123)]; + + var backend = MockStorageBackend(); + var keystore = MockKeystore(); + when(keystore.frames).thenReturn(keystoreFrames); when(keystore.beginTransaction(any)).thenReturn(true); + returnFutureVoid(when(backend.writeFrames(frames))); + returnFutureVoid(when(backend.compact(keystoreFrames))); when(backend.supportsCompaction).thenReturn(true); + when(keystore.length).thenReturn(-1); + when(keystore.deletedEntries).thenReturn(-1); var box = _getBox( keystore: keystore, @@ -103,7 +110,6 @@ void main() { ); await box.putAll({'key1': 'value1', 'key2': 'value2'}); - var frames = [Frame('key1', 'value1'), Frame('key2', 'value2')]; verifyInOrder([ keystore.beginTransaction(frames), backend.writeFrames(frames), @@ -113,8 +119,8 @@ void main() { }); test('does nothing if no frames are provided', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(keystore.beginTransaction([])).thenReturn(false); var box = _getBox(backend: backend, keystore: keystore); @@ -125,8 +131,8 @@ void main() { }); test('handles exceptions', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(backend.writeFrames(any)).thenThrow('Some error'); when(keystore.beginTransaction(any)).thenReturn(true); @@ -148,19 +154,33 @@ void main() { group('.deleteAll()', () { test('do nothing when deleting non existing keys', () async { - var backend = BackendMock(); - var box = _getBox(backend: backend); + var frames = []; + + var backend = MockStorageBackend(); + var keystore = MockKeystore(); + var box = _getBox(backend: backend, keystore: keystore); + when(keystore.frames).thenReturn(frames); + when(keystore.containsKey(any)).thenReturn(false); + returnFutureVoid(when(backend.compact(frames))); + when(keystore.beginTransaction(frames)).thenReturn(false); await box.deleteAll(['key1', 'key2', 'key3']); verifyZeroInteractions(backend); }); test('delete keys', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var frames = [Frame.deleted('key1'), Frame.deleted('key2')]; + + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(backend.supportsCompaction).thenReturn(true); when(keystore.beginTransaction(any)).thenReturn(true); + returnFutureVoid(when(backend.writeFrames(frames))); when(keystore.containsKey(any)).thenReturn(true); + when(keystore.length).thenReturn(-1); + when(keystore.deletedEntries).thenReturn(-1); + when(keystore.frames).thenReturn(frames); + returnFutureVoid(when(backend.compact(frames))); var box = _getBox( backend: backend, @@ -169,7 +189,6 @@ void main() { ); await box.deleteAll(['key1', 'key2']); - var frames = [Frame.deleted('key1'), Frame.deleted('key2')]; verifyInOrder([ keystore.containsKey('key1'), keystore.containsKey('key2'), diff --git a/hive/test/tests/box/change_notifier_test.dart b/hive/test/tests/box/change_notifier_test.dart index 25930fad1..faa138800 100644 --- a/hive/test/tests/box/change_notifier_test.dart +++ b/hive/test/tests/box/change_notifier_test.dart @@ -3,10 +3,17 @@ import 'dart:async'; import 'package:hive/hive.dart'; import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/box/change_notifier.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -class StreamControllerMock extends Mock implements StreamController {} +import '../common.dart'; + +class StreamControllerMock extends Mock implements StreamController { + Future close() => + (super.noSuchMethod(Invocation.method(#close, []), Future.value()) + as Future); +} void main() { group('ChangeNotifier', () { @@ -43,7 +50,7 @@ void main() { test('close', () async { var controller = StreamControllerMock(); - when(controller.close()).thenAnswer((i) => Future.value()); + returnFutureVoid(when(controller.close())); var notifier = ChangeNotifier.debug(controller); await notifier.close(); diff --git a/hive/test/tests/box/keystore_test.dart b/hive/test/tests/box/keystore_test.dart index 4af2106ba..c3adec2f2 100644 --- a/hive/test/tests/box/keystore_test.dart +++ b/hive/test/tests/box/keystore_test.dart @@ -1,5 +1,9 @@ +import 'package:hive/hive.dart'; import 'package:hive/src/binary/frame.dart'; +import 'package:hive/src/box/change_notifier.dart'; import 'package:hive/src/box/keystore.dart'; +import 'package:hive/src/object/hive_object.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; @@ -185,7 +189,7 @@ void main() { }); test('initializes HiveObject', () { - var box = BoxMock(); + var box = MockBox(); var keystore = Keystore.debug(box: box); var hiveObject = TestHiveObject(); @@ -213,7 +217,7 @@ void main() { }); test('unloads previous HiveObject', () { - var box = BoxMock(); + var box = MockBox(); var keystore = Keystore.debug(box: box); var hiveObject = TestHiveObject(); @@ -225,7 +229,7 @@ void main() { }); test('does not unload HiveObject if it is the same instance', () { - var box = BoxMock(); + var box = MockBox(); var keystore = Keystore.debug(box: box); var hiveObject = TestHiveObject(); @@ -248,7 +252,7 @@ void main() { }); test('broadcasts change event', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug(notifier: notifier); keystore.insert(Frame('key1', 'val1')); @@ -279,7 +283,7 @@ void main() { }); test('unloads deleted HiveObject', () { - var box = BoxMock(); + var box = MockBox(); var hiveObject = TestHiveObject(); var keystore = Keystore.debug(frames: [Frame('key', hiveObject)], box: box); @@ -298,7 +302,7 @@ void main() { }); test('broadcasts change event', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key1', 'val1')], notifier: notifier, @@ -317,7 +321,7 @@ void main() { group('.beginTransaction()', () { test('adding new frames', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug(notifier: notifier); var created = keystore.beginTransaction([ @@ -333,7 +337,7 @@ void main() { }); test('overriding existing keys', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key1', 'val1')], notifier: notifier, @@ -355,7 +359,7 @@ void main() { }); test('empty transaction', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key1', 'val1')], notifier: notifier, @@ -370,7 +374,7 @@ void main() { }); test('deleting frames', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [ Frame('key1', 'val1'), @@ -417,7 +421,7 @@ void main() { group('.cancelTransaction()', () { test('add', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug(notifier: notifier); keystore.beginTransaction([Frame('key', 'val1')]); keystore.beginTransaction([Frame('otherKey', 'otherVal')]); @@ -433,7 +437,7 @@ void main() { }); test('add then override', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug(notifier: notifier); keystore.beginTransaction([Frame('key', 'val1')]); keystore.beginTransaction([Frame('key', 'val2')]); @@ -446,7 +450,7 @@ void main() { }); test('add then delete', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug(notifier: notifier); keystore.beginTransaction([Frame('key', 'val1')]); keystore.beginTransaction([ @@ -471,7 +475,7 @@ void main() { }); test('override', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key', 'val1')], notifier: notifier, @@ -486,7 +490,7 @@ void main() { }); test('override then add', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key', 'val1')], notifier: notifier, @@ -506,7 +510,7 @@ void main() { }); test('override then delete', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key', 'val1')], notifier: notifier, @@ -524,7 +528,7 @@ void main() { }); test('delete', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key', 'val1')], notifier: notifier, @@ -539,7 +543,7 @@ void main() { }); test('delete then add', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug(frames: [Frame('key', 'val1')]); keystore.beginTransaction([Frame.deleted('key')]); keystore.beginTransaction([Frame('key', 'val2')]); @@ -568,7 +572,7 @@ void main() { test('unloads HiveObjects', () { var hiveObject = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); var keystore = Keystore.debug(frames: [ Frame('key1', 'val1'), Frame('key2', hiveObject), @@ -604,7 +608,7 @@ void main() { }); test('broadcasts change event', () { - var notifier = ChangeNotifierMock(); + var notifier = MockChangeNotifier(); var keystore = Keystore.debug( frames: [Frame('key1', 'val1'), Frame('key2', 'val2')], notifier: notifier, diff --git a/hive/test/tests/box/lazy_box_impl_test.dart b/hive/test/tests/box/lazy_box_impl_test.dart index 47377932c..4fc174c3d 100644 --- a/hive/test/tests/box/lazy_box_impl_test.dart +++ b/hive/test/tests/box/lazy_box_impl_test.dart @@ -8,21 +8,22 @@ import 'package:hive/src/hive_impl.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; +import '../common.dart'; import '../mocks.dart'; LazyBoxImpl _getBox({ - String name, - HiveImpl hive, - Keystore keystore, - CompactionStrategy cStrategy, - StorageBackend backend, + String? name, + HiveImpl? hive, + Keystore? keystore, + CompactionStrategy? cStrategy, + StorageBackend? backend, }) { var box = LazyBoxImpl( hive ?? HiveImpl(), name ?? 'testBox', null, cStrategy ?? (total, deleted) => false, - backend ?? BackendMock(), + backend ?? MockStorageBackend(), ); box.keystore = keystore ?? Keystore(box, ChangeNotifier(), null); return box; @@ -32,7 +33,7 @@ void main() { group('LazyBoxImpl', () { group('.get()', () { test('returns defaultValue if key does not exist', () async { - var backend = BackendMock(); + var backend = MockStorageBackend(); var box = _getBox(backend: backend); expect(await box.get('someKey'), null); @@ -41,7 +42,7 @@ void main() { }); test('reads value from backend', () async { - var backend = BackendMock(); + var backend = MockStorageBackend(); when(backend.readValue(any)).thenAnswer((i) async => 'testVal'); var box = _getBox(backend: backend); @@ -58,7 +59,7 @@ void main() { Frame.lazy(0), Frame.lazy('a'), ]); - var backend = BackendMock(); + var backend = MockStorageBackend(); when(backend.readValue(any)).thenAnswer((i) { return Future.value('A'); }); @@ -69,9 +70,12 @@ void main() { group('.putAll()', () { test('values', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(keystore.containsKey(any)).thenReturn(false); + returnFutureVoid(when(backend.writeFrames(any))); + when(keystore.length).thenReturn(-1); + when(keystore.deletedEntries).thenReturn(-1); var box = _getBox( backend: backend, @@ -90,10 +94,11 @@ void main() { }); test('handles exceptions', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); + final theError = 'Some error'; - when(backend.writeFrames(any)).thenThrow('Some error'); + when(backend.writeFrames(any)).thenThrow(theError); when(keystore.containsKey(any)).thenReturn(true); var box = _getBox( @@ -105,7 +110,7 @@ void main() { () async => await box.putAll( {'key1': 'value1', 'key2': 'value2'}, ), - throwsA(anything), + throwsA(theError), ); verifyInOrder([ backend.writeFrames([ @@ -119,8 +124,8 @@ void main() { group('.deleteAll()', () { test('does nothing when deleting non existing keys', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(keystore.containsKey(any)).thenReturn(false); var box = _getBox( backend: backend, @@ -132,9 +137,12 @@ void main() { }); test('delete keys', () async { - var backend = BackendMock(); - var keystore = KeystoreMock(); + var backend = MockStorageBackend(); + var keystore = MockKeystore(); when(keystore.containsKey(any)).thenReturn(true); + returnFutureVoid(when(backend.writeFrames(any))); + when(keystore.length).thenReturn(-1); + when(keystore.deletedEntries).thenReturn(-1); var box = _getBox( backend: backend, diff --git a/hive/test/tests/common.dart b/hive/test/tests/common.dart index 3cf1967eb..b6dfccfdd 100644 --- a/hive/test/tests/common.dart +++ b/hive/test/tests/common.dart @@ -2,10 +2,11 @@ import 'dart:io'; import 'dart:math'; import 'package:hive/hive.dart'; +import 'package:mockito/mockito.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; -Matcher isAHiveError([String contains]) { +Matcher isAHiveError([String? contains]) { return allOf( isA(), predicate((HiveError e) => @@ -13,7 +14,7 @@ Matcher isAHiveError([String contains]) { e.toString().toLowerCase().contains(contains.toLowerCase()))); } -Matcher throwsHiveError([String contains]) { +Matcher throwsHiveError([String? contains]) { return throwsA(isAHiveError(contains)); } @@ -22,7 +23,7 @@ String tempPath = path.join(Directory.current.path, '.dart_tool', 'test', 'tmp'); String assetsPath = path.join(Directory.current.path, 'test', 'assets'); -Future getTempFile([List bytes]) async { +Future getTempFile([List? bytes]) async { var name = random.nextInt(pow(2, 32) as int); var file = File(path.join(tempPath, '$name.tmp')); await file.create(recursive: true); @@ -50,12 +51,12 @@ Future getTempDir() async { return dir; } -File getAssetFile(String part1, [String part2, String part3, String part4]) { +File getAssetFile(String part1, [String? part2, String? part3, String? part4]) { return File(path.join(assetsPath, part1, part2, part3, part4)); } Future getTempAssetFile(String part1, - [String part2, String part3, String part4]) async { + [String? part2, String? part3, String? part4]) async { var assetFile = getAssetFile(part1, part2, part3, part4); var tempFile = await getTempFile(); @@ -63,7 +64,7 @@ Future getTempAssetFile(String part1, } Future getAssetDir(String part1, - [String part2, String part3, String part4]) async { + [String? part2, String? part3, String? part4]) async { var assetDir = Directory(path.join(assetsPath, part1, part2, part3, part4)); var tempDir = await getTempDir(); @@ -106,7 +107,19 @@ Future _expectDirsEqual( } Future expectDirEqualsAssetDir(Directory dir1, String part1, - [String part2, String part3, String part4]) { + [String? part2, String? part3, String? part4]) { var assetDir = Directory(path.join(assetsPath, part1, part2, part3, part4)); return expectDirsEqual(dir1, assetDir); } + +void returnFutureVoid(PostExpectation> v) => + v.thenAnswer((i) => Future.value(null)); + +final bool soundNullSafety = (() { + try { + null as Object; + return false; + } on TypeError { + return true; + } +})(); diff --git a/hive/test/tests/crypto/aes_cbc_pkcs7_test.dart b/hive/test/tests/crypto/aes_cbc_pkcs7_test.dart index 15d57c5ee..1a8c8fe2b 100644 --- a/hive/test/tests/crypto/aes_cbc_pkcs7_test.dart +++ b/hive/test/tests/crypto/aes_cbc_pkcs7_test.dart @@ -1,3 +1,4 @@ +@Skip('Cannot run with sound null safety') import 'dart:typed_data'; import 'package:hive/src/crypto/aes_cbc_pkcs7.dart'; diff --git a/hive/test/tests/crypto/aes_engine_test.dart b/hive/test/tests/crypto/aes_engine_test.dart index bdbaaf913..f5a683ade 100644 --- a/hive/test/tests/crypto/aes_engine_test.dart +++ b/hive/test/tests/crypto/aes_engine_test.dart @@ -1,3 +1,4 @@ +@Skip('Cannot run with sound null safety') import 'dart:typed_data'; import 'package:hive/src/crypto/aes_engine.dart'; diff --git a/hive/test/tests/hive_impl_test.dart b/hive/test/tests/hive_impl_test.dart index eb4395585..abf177eab 100644 --- a/hive/test/tests/hive_impl_test.dart +++ b/hive/test/tests/hive_impl_test.dart @@ -21,17 +21,19 @@ void main() { test('.init()', () { var hive = HiveImpl(); - hive.init('MYPATH'); + expect(() => hive.init('MYPATH'), returnsNormally); expect(hive.homePath, 'MYPATH'); - hive.init('OTHERPATH'); - expect(hive.homePath, 'OTHERPATH'); + expect( + () => hive.init('OTHERPATH'), + throwsHiveError('Instance has already been initialized.'), + ); expect( - hive.findAdapterForValue(DateTime.now()).adapter, + hive.findAdapterForValue(DateTime.now())!.adapter, isA(), ); - expect(hive.findAdapterForTypeId(16).adapter, isA()); + expect(hive.findAdapterForTypeId(16)!.adapter, isA()); }); group('.openBox()', () { @@ -71,8 +73,8 @@ void main() { test('same box returned if it is already opening', () async { var hive = await initHive(); - Box box1; - Box box2; + Box? box1; + Box? box2; await Future.wait([ hive.openBox('TESTBOX').then((value) => box1 = value), hive.openBox('testbox').then((value) => box2 = value) @@ -96,8 +98,8 @@ void main() { }); test('same box returned if it is already opening', () async { - LazyBox box1; - LazyBox box2; + LazyBox? box1; + LazyBox? box2; var hive = await initHive(); await Future.wait([ @@ -245,7 +247,7 @@ void main() { var box1 = await hive.openBox('testBox1'); await box1.put('key', 'value'); - var box1File = File(box1.path); + var box1File = File(box1.path!); await hive.deleteBoxFromDisk('testBox1'); expect(await box1File.exists(), false); @@ -259,7 +261,7 @@ void main() { var box1 = await hive.openBox('testBox1'); await box1.put('key', 'value'); - var path = box1.path; + var path = box1.path!; await box1.close(); var box1File = File(path); @@ -282,11 +284,11 @@ void main() { var box1 = await hive.openBox('testBox1'); await box1.put('key', 'value'); - var box1File = File(box1.path); + var box1File = File(box1.path!); var box2 = await hive.openBox('testBox2'); await box2.put('key', 'value'); - var box2File = File(box1.path); + var box2File = File(box1.path!); await hive.deleteFromDisk(); expect(await box1File.exists(), false); diff --git a/hive/test/tests/io/buffered_file_reader_test.dart b/hive/test/tests/io/buffered_file_reader_test.dart index c310b083e..36bae0fa7 100644 --- a/hive/test/tests/io/buffered_file_reader_test.dart +++ b/hive/test/tests/io/buffered_file_reader_test.dart @@ -36,7 +36,7 @@ void main() { expect(reader.remainingInBuffer, 0); expect(reader.offset, 5); - await reader.file.close(); + await reader.file!.close(); }); test('fails if not enough bytes available', () async { @@ -47,7 +47,7 @@ void main() { expect(() => reader.skip(4), throwsA(anything)); - await reader.file.close(); + await reader.file!.close(); }); }); @@ -63,7 +63,7 @@ void main() { expect(reader.viewBytes(3), [3, 4, 5]); expect(reader.offset, 5); - await reader.file.close(); + await reader.file!.close(); }); test('fails if not enough bytes available', () async { @@ -72,7 +72,7 @@ void main() { expect(() => reader.viewBytes(6), throwsA(anything)); - await reader.file.close(); + await reader.file!.close(); }); }); @@ -85,7 +85,7 @@ void main() { expect(reader.viewBytes(2), [1, 2]); expect(reader.viewBytes(1), [3]); - await reader.file.close(); + await reader.file!.close(); }); test('increases the buffer if it is too small', () async { @@ -96,7 +96,7 @@ void main() { expect(await reader.loadBytes(3), 3); expect(reader.viewBytes(3), [3, 4, 5]); - await reader.file.close(); + await reader.file!.close(); }); test('copies unused bytes', () async { @@ -110,7 +110,7 @@ void main() { expect(await reader.loadBytes(5), 4); expect(reader.viewBytes(3), [4, 5, 6]); - await reader.file.close(); + await reader.file!.close(); }); }); }); diff --git a/hive/test/tests/io/buffered_file_writer_test.dart b/hive/test/tests/io/buffered_file_writer_test.dart index cd49e739c..405c7afe4 100644 --- a/hive/test/tests/io/buffered_file_writer_test.dart +++ b/hive/test/tests/io/buffered_file_writer_test.dart @@ -1,3 +1,4 @@ +@TestOn('vm') import 'package:hive/src/io/buffered_file_writer.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; @@ -7,13 +8,14 @@ import '../mocks.dart'; void main() { group('BufferedFileWriter', () { test('.write()', () async { - var file = RAFMock(); + var file = MockRandomAccessFile(); var writer = BufferedFileWriter(file, 10); await writer.write([1, 2, 3, 4, 5, 6]); await writer.write([7, 8, 9]); verifyZeroInteractions(file); + when(file.writeFrom(any)).thenAnswer((i) => Future.value(file)); await writer.write([10]); verify(file.writeFrom([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); @@ -21,12 +23,14 @@ void main() { await writer.flush(); verifyZeroInteractions(file); + when(file.writeFrom(any)).thenAnswer((i) => Future.value(file)); await writer.write([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]); verify(file.writeFrom([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])); }); test('flush()', () async { - var file = RAFMock(); + var file = MockRandomAccessFile(); + when(file.writeFrom(any)).thenAnswer((i) => Future.value(file)); var writer = BufferedFileWriter(file, 10); await writer.flush(); diff --git a/hive/test/tests/io/frame_io_helper_test.dart b/hive/test/tests/io/frame_io_helper_test.dart index 5c019b5da..1aae25884 100644 --- a/hive/test/tests/io/frame_io_helper_test.dart +++ b/hive/test/tests/io/frame_io_helper_test.dart @@ -1,5 +1,4 @@ @TestOn('vm') - import 'dart:io'; import 'dart:typed_data'; @@ -40,7 +39,8 @@ void main() { test('frame', () async { var keystore = Keystore.debug(); var ioHelper = _FrameIoHelperTest(_getBytes(frameBytes)); - var recoveryOffset = await ioHelper.keysFromFile(null, keystore, null); + var recoveryOffset = + await ioHelper.keysFromFile('null', keystore, null); expect(recoveryOffset, -1); var testKeystore = Keystore.debug( @@ -54,7 +54,7 @@ void main() { var keystore = Keystore.debug(); var ioHelper = _FrameIoHelperTest(_getBytes(frameBytesEncrypted)); var recoveryOffset = - await ioHelper.keysFromFile(null, keystore, testCipher); + await ioHelper.keysFromFile('null', keystore, testCipher); expect(recoveryOffset, -1); var testKeystore = Keystore.debug( @@ -74,7 +74,7 @@ void main() { var keystore = Keystore.debug(); var ioHelper = _FrameIoHelperTest(_getBytes(frameBytes)); var recoveryOffset = - await ioHelper.framesFromFile(null, keystore, testRegistry, null); + await ioHelper.framesFromFile('null', keystore, testRegistry, null); expect(recoveryOffset, -1); var testKeystore = Keystore.debug( @@ -88,7 +88,7 @@ void main() { var keystore = Keystore.debug(); var ioHelper = _FrameIoHelperTest(_getBytes(frameBytesEncrypted)); var recoveryOffset = await ioHelper.framesFromFile( - null, keystore, testRegistry, testCipher); + 'null', keystore, testRegistry, testCipher); expect(recoveryOffset, -1); var testKeystore = Keystore.debug( diff --git a/hive/test/tests/mocks.dart b/hive/test/tests/mocks.dart index d7d7d380a..b5c32933a 100644 --- a/hive/test/tests/mocks.dart +++ b/hive/test/tests/mocks.dart @@ -1,38 +1,34 @@ +library hive.test.mocks; + import 'dart:io'; import 'package:hive/hive.dart'; import 'package:hive/src/backend/storage_backend.dart'; import 'package:hive/src/box/change_notifier.dart'; import 'package:hive/src/box/keystore.dart'; -import 'package:hive/src/object/hive_list_impl.dart'; import 'package:hive/src/hive_impl.dart'; -import 'package:mockito/mockito.dart'; -import 'package:pointycastle/api.dart'; - -class HiveMock extends Mock implements HiveImpl {} - -class RAFMock extends Mock implements RandomAccessFile {} - -class BinaryReaderMock extends Mock implements BinaryReader {} - -class BinaryWriterMock extends Mock implements BinaryWriter {} - -class BackendMock extends Mock implements StorageBackend {} - -class ChangeNotifierMock extends Mock implements ChangeNotifier {} - -class SecureRandomMock extends Mock implements SecureRandom {} - -class BoxMock extends Mock implements Box {} - -class LazyBoxMock extends Mock implements LazyBox {} - -class KeystoreMock extends Mock implements Keystore {} - -class FileMock extends Mock implements File {} - -class HiveObjectMock extends Mock implements HiveObject {} - -class HiveListMock extends Mock implements HiveListImpl {} +import 'package:hive/src/io/frame_io_helper.dart'; +import 'package:hive/src/object/hive_list_impl.dart'; +import 'package:hive/src/object/hive_object.dart'; +import 'package:mockito/annotations.dart'; + +export 'mocks.mocks.dart'; + +@GenerateMocks([], customMocks: [ + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), +]) +// ignore: prefer_typing_uninitialized_variables, unused_element +var _mocks; class TestHiveObject extends HiveObject {} diff --git a/hive/test/tests/mocks.mocks.dart b/hive/test/tests/mocks.mocks.dart new file mode 100644 index 000000000..b81c339fa --- /dev/null +++ b/hive/test/tests/mocks.mocks.dart @@ -0,0 +1,821 @@ +import 'package:hive/src/box/default_compaction_strategy.dart'; +import 'package:hive/src/box/default_key_comparator.dart'; +import 'package:mockito/mockito.dart' as _i1; +import 'dart:collection' as _i2; +import 'package:hive/hive.dart' as _i3; +import 'package:hive/src/object/hive_object.dart' as _i4; +import 'dart:typed_data' as _i5; +import 'dart:io' as _i6; +import 'dart:async' as _i7; +import 'package:hive/src/box/change_notifier.dart' as _i8; +import 'package:hive/src/binary/frame.dart' as _i9; +import 'package:hive/src/backend/storage_backend.dart' as _i10; +import 'package:hive/src/box/keystore.dart' as _i11; +import 'package:hive/src/hive_impl.dart' as _i12; +import 'package:hive/src/registry/type_registry_impl.dart' as _i13; +import 'package:hive/src/object/hive_list_impl.dart' as _i14; +import 'dart:convert' as _i15; +import 'package:hive/src/io/frame_io_helper.dart' as _i16; + +class _FakeType extends _i1.Fake implements Type {} + +class _FakeListQueue extends _i1.Fake implements _i2.ListQueue {} + +class _FakeBox extends _i1.Fake implements _i3.Box {} + +class _FakeLazyBox extends _i1.Fake implements _i3.LazyBox {} + +class _FakeBoxBase extends _i1.Fake implements _i3.BoxBase {} + +class _FakeHiveList extends _i1.Fake + implements _i3.HiveList {} + +class _FakeIterator extends _i1.Fake implements Iterator {} + +class _FakeHiveObject extends _i1.Fake implements _i4.HiveObject {} + +class _FakeUint8List extends _i1.Fake implements _i5.Uint8List {} + +class _FakeRandomAccessFile extends _i1.Fake implements _i6.RandomAccessFile {} + +class _FakeFile extends _i1.Fake implements _i6.File {} + +class _FakeDateTime extends _i1.Fake implements DateTime {} + +class _FakeIOSink extends _i1.Fake implements _i6.IOSink {} + +/// A class which mocks [Box]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBox extends _i1.Mock implements _i3.Box { + Iterable get values => + (super.noSuchMethod(Invocation.getter(#values), []) as Iterable); + Iterable valuesBetween({dynamic startKey, dynamic endKey}) => + (super.noSuchMethod( + Invocation.method( + #valuesBetween, [], {#startKey: startKey, #endKey: endKey}), + []) as Iterable); + E? getAt(int? index) => + (super.noSuchMethod(Invocation.method(#getAt, [index])) as E?); + Map toMap() => + (super.noSuchMethod(Invocation.method(#toMap, []), {}) + as Map); + String get name => + (super.noSuchMethod(Invocation.getter(#name), '') as String); + bool get lazy => + (super.noSuchMethod(Invocation.getter(#lazy), false) as bool); + Future put(dynamic key, E value) => + (super.noSuchMethod(Invocation.method(#put, [key, value]), Future.value()) + as Future); + _i7.Future delete(key) => + (super.noSuchMethod(Invocation.method(#delete, [key]), Future.value()) + as Future); + _i7.Future deleteAll(Iterable keys) => + (super.noSuchMethod(Invocation.method(#deleteAll, [keys]), Future.value()) + as Future); + bool containsKey(key) => + (super.noSuchMethod(Invocation.method(#containsKey, [key]), false) + as bool); +} + +/// A class which mocks [ChangeNotifier]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockChangeNotifier extends _i1.Mock implements _i8.ChangeNotifier { + void notify(_i9.Frame? frame) => + super.noSuchMethod(Invocation.method(#notify, [frame])); + _i7.Stream<_i3.BoxEvent> watch({dynamic key}) => (super.noSuchMethod( + Invocation.method(#watch, [], {#key: key}), + Stream<_i3.BoxEvent>.empty()) as _i7.Stream<_i3.BoxEvent>); + _i7.Future close() => + (super.noSuchMethod(Invocation.method(#close, []), Future.value(null)) + as _i7.Future); +} + +/// A class which mocks [StorageBackend]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockStorageBackend extends _i1.Mock implements _i10.StorageBackend { + bool get supportsCompaction => + (super.noSuchMethod(Invocation.getter(#supportsCompaction), false) + as bool); + _i7.Future initialize(_i3.TypeRegistry? registry, + _i11.Keystore? keystore, bool? lazy) => + (super.noSuchMethod( + Invocation.method(#initialize, [registry, keystore, lazy]), + Future.value(null)) as _i7.Future); + _i7.Future readValue(_i9.Frame? frame) => (super.noSuchMethod( + Invocation.method(#readValue, [frame]), Future.value(null)) + as _i7.Future); + _i7.Future writeFrames(List<_i9.Frame>? frames) => (super.noSuchMethod( + Invocation.method(#writeFrames, [frames]), Future.value(null)) + as _i7.Future); + _i7.Future compact(Iterable<_i9.Frame>? frames) => (super.noSuchMethod( + Invocation.method(#compact, [frames]), Future.value(null)) + as _i7.Future); + _i7.Future clear() => + (super.noSuchMethod(Invocation.method(#clear, []), Future.value(null)) + as _i7.Future); + _i7.Future close() => + (super.noSuchMethod(Invocation.method(#close, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteFromDisk() => (super.noSuchMethod( + Invocation.method(#deleteFromDisk, []), Future.value(null)) + as _i7.Future); +} + +/// A class which mocks [Keystore]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockKeystore extends _i1.Mock implements _i11.Keystore { + _i2.ListQueue<_i11.KeyTransaction> get transactions => (super.noSuchMethod( + Invocation.getter(#transactions), + _FakeListQueue<_i11.KeyTransaction>()) + as _i2.ListQueue<_i11.KeyTransaction>); + int get deletedEntries => + (super.noSuchMethod(Invocation.getter(#deletedEntries), 0) as int); + int get length => (super.noSuchMethod(Invocation.getter(#length), 0) as int); + Iterable<_i9.Frame> get frames => + (super.noSuchMethod(Invocation.getter(#frames), <_i9.Frame>[]) + as Iterable<_i9.Frame>); + int autoIncrement() => + (super.noSuchMethod(Invocation.method(#autoIncrement, []), 0) as int); + void updateAutoIncrement(int? key) => + super.noSuchMethod(Invocation.method(#updateAutoIncrement, [key])); + bool containsKey(dynamic key) => + (super.noSuchMethod(Invocation.method(#containsKey, [key]), false) + as bool); + dynamic keyAt(int? index) => + (super.noSuchMethod(Invocation.method(#keyAt, [index])) as dynamic); + _i9.Frame? getAt(int? index) => + (super.noSuchMethod(Invocation.method(#getAt, [index])) as _i9.Frame?); + Iterable getKeys() => + (super.noSuchMethod(Invocation.method(#getKeys, []), []) + as Iterable); + Iterable getValues() => + (super.noSuchMethod(Invocation.method(#getValues, []), []) + as Iterable); + Iterable getValuesBetween([dynamic startKey, dynamic endKey]) => + (super.noSuchMethod( + Invocation.method(#getValuesBetween, [startKey, endKey]), []) + as Iterable); + _i7.Stream<_i3.BoxEvent> watch({dynamic key}) => (super.noSuchMethod( + Invocation.method(#watch, [], {#key: key}), + Stream<_i3.BoxEvent>.empty()) as _i7.Stream<_i3.BoxEvent>); + _i9.Frame? insert(_i9.Frame? frame, {bool? notify = true}) => (super + .noSuchMethod(Invocation.method(#insert, [frame], {#notify: notify})) + as _i9.Frame?); + bool beginTransaction(List<_i9.Frame>? newFrames) => (super.noSuchMethod( + Invocation.method(#beginTransaction, [newFrames]), false) as bool); + int clear() => (super.noSuchMethod(Invocation.method(#clear, []), 0) as int); + _i7.Future close() => + (super.noSuchMethod(Invocation.method(#close, []), Future.value(null)) + as _i7.Future); +} + +/// A class which mocks [HiveImpl]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockHiveImpl extends _i1.Mock implements _i12.HiveImpl { + void init(String? path) => + super.noSuchMethod(Invocation.method(#init, [path])); + _i7.Future<_i3.Box> openBox(String? name, + {_i3.HiveCipher? encryptionCipher, + _i3.KeyComparator? keyComparator = defaultKeyComparator, + _i3.CompactionStrategy? compactionStrategy = + defaultCompactionStrategy, + bool? crashRecovery = true, + String? path, + _i5.Uint8List? bytes, + List? encryptionKey}) => + (super.noSuchMethod( + Invocation.method(#openBox, [ + name + ], { + #encryptionCipher: encryptionCipher, + #keyComparator: keyComparator, + #compactionStrategy: compactionStrategy, + #crashRecovery: crashRecovery, + #path: path, + #bytes: bytes, + #encryptionKey: encryptionKey + }), + Future.value(_FakeBox())) as _i7.Future<_i3.Box>); + _i7.Future<_i3.LazyBox> openLazyBox(String? name, + {_i3.HiveCipher? encryptionCipher, + _i3.KeyComparator? keyComparator = defaultKeyComparator, + _i3.CompactionStrategy? compactionStrategy = + defaultCompactionStrategy, + bool? crashRecovery = true, + String? path, + List? encryptionKey}) => + (super.noSuchMethod( + Invocation.method(#openLazyBox, [ + name + ], { + #encryptionCipher: encryptionCipher, + #keyComparator: keyComparator, + #compactionStrategy: compactionStrategy, + #crashRecovery: crashRecovery, + #path: path, + #encryptionKey: encryptionKey + }), + Future.value(_FakeLazyBox())) as _i7.Future<_i3.LazyBox>); + _i3.BoxBase? getBoxWithoutCheckInternal(String? name) => (super + .noSuchMethod(Invocation.method(#getBoxWithoutCheckInternal, [name])) + as _i3.BoxBase?); + _i3.Box box(String? name) => + (super.noSuchMethod(Invocation.method(#box, [name]), _FakeBox()) + as _i3.Box); + _i3.LazyBox lazyBox(String? name) => (super + .noSuchMethod(Invocation.method(#lazyBox, [name]), _FakeLazyBox()) + as _i3.LazyBox); + bool isBoxOpen(String? name) => + (super.noSuchMethod(Invocation.method(#isBoxOpen, [name]), false) + as bool); + _i7.Future close() => + (super.noSuchMethod(Invocation.method(#close, []), Future.value(null)) + as _i7.Future); + void unregisterBox(String? name) => + super.noSuchMethod(Invocation.method(#unregisterBox, [name])); + _i7.Future deleteBoxFromDisk(String? name, {String? path}) => + (super.noSuchMethod( + Invocation.method(#deleteBoxFromDisk, [name], {#path: path}), + Future.value(null)) as _i7.Future); + _i7.Future deleteFromDisk() => (super.noSuchMethod( + Invocation.method(#deleteFromDisk, []), Future.value(null)) + as _i7.Future); + List generateSecureKey() => + (super.noSuchMethod(Invocation.method(#generateSecureKey, []), []) + as List); + _i7.Future boxExists(String? name, {String? path}) => + (super.noSuchMethod(Invocation.method(#boxExists, [name], {#path: path}), + Future.value(false)) as _i7.Future); + _i13.ResolvedAdapter? findAdapterForTypeId(int? typeId) => + (super.noSuchMethod(Invocation.method(#findAdapterForTypeId, [typeId])) + as _i13.ResolvedAdapter?); + void registerAdapter(_i3.TypeAdapter? adapter, + {bool? internal = false, bool? override = false}) => + super.noSuchMethod(Invocation.method(#registerAdapter, [adapter], + {#internal: internal, #override: override})); + bool isAdapterRegistered(int? typeId, {bool? internal = false}) => + (super.noSuchMethod( + Invocation.method( + #isAdapterRegistered, [typeId], {#internal: internal}), + false) as bool); + void ignoreTypeId(int? typeId) => + super.noSuchMethod(Invocation.method(#ignoreTypeId, [typeId])); +} + +/// A class which mocks [HiveList]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockHiveList extends _i1.Mock + implements _i3.HiveList { + _i3.BoxBase get box => + (super.noSuchMethod(Invocation.getter(#box), _FakeBoxBase()) + as _i3.BoxBase); + Iterable get keys => + (super.noSuchMethod(Invocation.getter(#keys), []) as Iterable); + _i3.HiveList castHiveList() => + (super.noSuchMethod( + Invocation.method(#castHiveList, []), _FakeHiveList()) + as _i3.HiveList); + _i7.Future deleteAllFromHive() => (super.noSuchMethod( + Invocation.method(#deleteAllFromHive, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteFirstFromHive() => (super.noSuchMethod( + Invocation.method(#deleteFirstFromHive, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteLastFromHive() => (super.noSuchMethod( + Invocation.method(#deleteLastFromHive, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteFromHive(int? index) => (super.noSuchMethod( + Invocation.method(#deleteFromHive, [index]), Future.value(null)) + as _i7.Future); + Map toMap() => + (super.noSuchMethod(Invocation.method(#toMap, []), {}) + as Map); +} + +/// A class which mocks [HiveListImpl]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockHiveListImpl extends _i1.Mock + implements _i14.HiveListImpl { + String get boxName => + (super.noSuchMethod(Invocation.getter(#boxName), '') as String); + Iterable get keys => + (super.noSuchMethod(Invocation.getter(#keys), []) as Iterable); + _i3.Box get box => + (super.noSuchMethod(Invocation.getter(#box), _FakeBox()) + as _i3.Box); + List get delegate => + (super.noSuchMethod(Invocation.getter(#delegate), []) as List); + set length(int? newLength) => + super.noSuchMethod(Invocation.setter(#length, [newLength])); + set debugHive(_i3.HiveInterface? hive) => + super.noSuchMethod(Invocation.setter(#debugHive, [hive])); + Iterator get iterator => + (super.noSuchMethod(Invocation.getter(#iterator), _FakeIterator()) + as Iterator); + bool get isEmpty => + (super.noSuchMethod(Invocation.getter(#isEmpty), false) as bool); + bool get isNotEmpty => + (super.noSuchMethod(Invocation.getter(#isNotEmpty), false) as bool); + E get first => (super.noSuchMethod(Invocation.getter(#first), null) as E); + set first(E? value) => super.noSuchMethod(Invocation.setter(#first, [value])); + E get last => (super.noSuchMethod(Invocation.getter(#last), null) as E); + set last(E? value) => super.noSuchMethod(Invocation.setter(#last, [value])); + E get single => (super.noSuchMethod(Invocation.getter(#single), null) as E); + Iterable get reversed => + (super.noSuchMethod(Invocation.getter(#reversed), []) as Iterable); + void operator []=(int? index, E? value) => + super.noSuchMethod(Invocation.method(#[]=, [index, value])); + void add(E? element) => + super.noSuchMethod(Invocation.method(#add, [element])); + void addAll(Iterable? iterable) => + super.noSuchMethod(Invocation.method(#addAll, [iterable])); + _i3.HiveList castHiveList() => + (super.noSuchMethod( + Invocation.method(#castHiveList, []), _FakeHiveList()) + as _i3.HiveList); + _i7.Future deleteAllFromHive() => (super.noSuchMethod( + Invocation.method(#deleteAllFromHive, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteFirstFromHive() => (super.noSuchMethod( + Invocation.method(#deleteFirstFromHive, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteLastFromHive() => (super.noSuchMethod( + Invocation.method(#deleteLastFromHive, []), Future.value(null)) + as _i7.Future); + _i7.Future deleteFromHive(int? index) => (super.noSuchMethod( + Invocation.method(#deleteFromHive, [index]), Future.value(null)) + as _i7.Future); + Map toMap() => + (super.noSuchMethod(Invocation.method(#toMap, []), {}) + as Map); + E elementAt(int? index) => (super.noSuchMethod( + Invocation.method(#elementAt, [index]), _FakeHiveObject()) as E); + Iterable followedBy(Iterable? other) => + (super.noSuchMethod(Invocation.method(#followedBy, [other]), []) + as Iterable); + void forEach(void Function(E)? action) => + super.noSuchMethod(Invocation.method(#forEach, [action])); + bool contains(Object? element) => + (super.noSuchMethod(Invocation.method(#contains, [element]), false) + as bool); + bool every(bool Function(E)? test) => + (super.noSuchMethod(Invocation.method(#every, [test]), false) as bool); + bool any(bool Function(E)? test) => + (super.noSuchMethod(Invocation.method(#any, [test]), false) as bool); + E firstWhere(bool Function(E)? test, {E Function()? orElse}) => + (super.noSuchMethod( + Invocation.method(#firstWhere, [test], {#orElse: orElse}), + _FakeHiveObject()) as E); + E lastWhere(bool Function(E)? test, {E Function()? orElse}) => + (super.noSuchMethod( + Invocation.method(#lastWhere, [test], {#orElse: orElse}), + _FakeHiveObject()) as E); + E singleWhere(bool Function(E)? test, {E Function()? orElse}) => + (super.noSuchMethod( + Invocation.method(#singleWhere, [test], {#orElse: orElse}), + _FakeHiveObject()) as E); + String join([String? separator]) => + (super.noSuchMethod(Invocation.method(#join, [separator]), '') as String); + Iterable where(bool Function(E)? test) => + (super.noSuchMethod(Invocation.method(#where, [test]), []) + as Iterable); + Iterable whereType() => + (super.noSuchMethod(Invocation.method(#whereType, []), []) + as Iterable); + Iterable map(T Function(E)? f) => + (super.noSuchMethod(Invocation.method(#map, [f]), []) as Iterable); + Iterable expand(Iterable Function(E)? f) => + (super.noSuchMethod(Invocation.method(#expand, [f]), []) as Iterable); + E reduce(E Function(E, E)? combine) => (super.noSuchMethod( + Invocation.method(#reduce, [combine]), _FakeHiveObject()) as E); + T fold(T? initialValue, T Function(T, E)? combine) => (super.noSuchMethod( + Invocation.method(#fold, [initialValue, combine]), null) as T); + Iterable skip(int? count) => + (super.noSuchMethod(Invocation.method(#skip, [count]), []) + as Iterable); + Iterable skipWhile(bool Function(E)? test) => + (super.noSuchMethod(Invocation.method(#skipWhile, [test]), []) + as Iterable); + Iterable take(int? count) => + (super.noSuchMethod(Invocation.method(#take, [count]), []) + as Iterable); + Iterable takeWhile(bool Function(E)? test) => + (super.noSuchMethod(Invocation.method(#takeWhile, [test]), []) + as Iterable); + List toList({bool? growable}) => (super.noSuchMethod( + Invocation.method(#toList, [], {#growable: growable}), []) as List); + Set toSet() => + (super.noSuchMethod(Invocation.method(#toSet, []), {}) as Set); + bool remove(Object? element) => + (super.noSuchMethod(Invocation.method(#remove, [element]), false) + as bool); + void removeWhere(bool Function(E)? test) => + super.noSuchMethod(Invocation.method(#removeWhere, [test])); + void retainWhere(bool Function(E)? test) => + super.noSuchMethod(Invocation.method(#retainWhere, [test])); + List cast() => + (super.noSuchMethod(Invocation.method(#cast, []), []) as List); + E removeLast() => + (super.noSuchMethod(Invocation.method(#removeLast, []), _FakeHiveObject()) + as E); + Map asMap() => + (super.noSuchMethod(Invocation.method(#asMap, []), {}) + as Map); + List operator +(List? other) => + (super.noSuchMethod(Invocation.method(#+, [other]), []) as List); + List sublist(int? start, [int? end]) => + (super.noSuchMethod(Invocation.method(#sublist, [start, end]), []) + as List); + Iterable getRange(int? start, int? end) => + (super.noSuchMethod(Invocation.method(#getRange, [start, end]), []) + as Iterable); + void removeRange(int? start, int? end) => + super.noSuchMethod(Invocation.method(#removeRange, [start, end])); + void fillRange(int? start, int? end, [E? fill]) => + super.noSuchMethod(Invocation.method(#fillRange, [start, end, fill])); + void setRange(int? start, int? end, Iterable? iterable, + [int? skipCount]) => + super.noSuchMethod( + Invocation.method(#setRange, [start, end, iterable, skipCount])); + void replaceRange(int? start, int? end, Iterable? newContents) => + super.noSuchMethod( + Invocation.method(#replaceRange, [start, end, newContents])); + int indexOf(Object? element, [int? start]) => + (super.noSuchMethod(Invocation.method(#indexOf, [element, start]), 0) + as int); + int indexWhere(bool Function(E)? test, [int? start]) => + (super.noSuchMethod(Invocation.method(#indexWhere, [test, start]), 0) + as int); + int lastIndexOf(Object? element, [int? start]) => + (super.noSuchMethod(Invocation.method(#lastIndexOf, [element, start]), 0) + as int); + int lastIndexWhere(bool Function(E)? test, [int? start]) => + (super.noSuchMethod(Invocation.method(#lastIndexWhere, [test, start]), 0) + as int); + void insert(int? index, E? element) => + super.noSuchMethod(Invocation.method(#insert, [index, element])); + E removeAt(int? index) => (super.noSuchMethod( + Invocation.method(#removeAt, [index]), _FakeHiveObject()) as E); + void insertAll(int? index, Iterable? iterable) => + super.noSuchMethod(Invocation.method(#insertAll, [index, iterable])); + void setAll(int? index, Iterable? iterable) => + super.noSuchMethod(Invocation.method(#setAll, [index, iterable])); +} + +/// A class which mocks [RandomAccessFile]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockRandomAccessFile extends _i1.Mock implements _i6.RandomAccessFile { + String get path => + (super.noSuchMethod(Invocation.getter(#path), '') as String); + _i7.Future close() => + (super.noSuchMethod(Invocation.method(#close, []), Future.value(null)) + as _i7.Future); + _i7.Future readByte() => + (super.noSuchMethod(Invocation.method(#readByte, []), Future.value(0)) + as _i7.Future); + int readByteSync() => + (super.noSuchMethod(Invocation.method(#readByteSync, []), 0) as int); + _i7.Future<_i5.Uint8List> read(int? bytes) => (super.noSuchMethod( + Invocation.method(#read, [bytes]), Future.value(_FakeUint8List())) + as _i7.Future<_i5.Uint8List>); + _i5.Uint8List readSync(int? bytes) => (super + .noSuchMethod(Invocation.method(#readSync, [bytes]), _FakeUint8List()) + as _i5.Uint8List); + _i7.Future readInto(List? buffer, [int? start, int? end]) => + (super.noSuchMethod(Invocation.method(#readInto, [buffer, start, end]), + Future.value(0)) as _i7.Future); + int readIntoSync(List? buffer, [int? start, int? end]) => + (super.noSuchMethod( + Invocation.method(#readIntoSync, [buffer, start, end]), 0) as int); + _i7.Future<_i6.RandomAccessFile> writeByte(int? value) => (super.noSuchMethod( + Invocation.method(#writeByte, [value]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + int writeByteSync(int? value) => + (super.noSuchMethod(Invocation.method(#writeByteSync, [value]), 0) + as int); + _i7.Future<_i6.RandomAccessFile> writeFrom(List? buffer, + [int? start, int? end]) => + (super.noSuchMethod(Invocation.method(#writeFrom, [buffer, start, end]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + void writeFromSync(List? buffer, [int? start, int? end]) => super + .noSuchMethod(Invocation.method(#writeFromSync, [buffer, start, end])); + _i7.Future<_i6.RandomAccessFile> writeString(String? string, + {_i15.Encoding? encoding}) => + (super.noSuchMethod( + Invocation.method(#writeString, [string], {#encoding: encoding}), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + void writeStringSync(String? string, {_i15.Encoding? encoding}) => + super.noSuchMethod( + Invocation.method(#writeStringSync, [string], {#encoding: encoding})); + _i7.Future position() => + (super.noSuchMethod(Invocation.method(#position, []), Future.value(0)) + as _i7.Future); + int positionSync() => + (super.noSuchMethod(Invocation.method(#positionSync, []), 0) as int); + _i7.Future<_i6.RandomAccessFile> setPosition(int? position) => + (super.noSuchMethod(Invocation.method(#setPosition, [position]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + void setPositionSync(int? position) => + super.noSuchMethod(Invocation.method(#setPositionSync, [position])); + _i7.Future<_i6.RandomAccessFile> truncate(int? length) => (super.noSuchMethod( + Invocation.method(#truncate, [length]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + void truncateSync(int? length) => + super.noSuchMethod(Invocation.method(#truncateSync, [length])); + _i7.Future length() => + (super.noSuchMethod(Invocation.method(#length, []), Future.value(0)) + as _i7.Future); + int lengthSync() => + (super.noSuchMethod(Invocation.method(#lengthSync, []), 0) as int); + _i7.Future<_i6.RandomAccessFile> flush() => (super.noSuchMethod( + Invocation.method(#flush, []), Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + _i7.Future<_i6.RandomAccessFile> lock( + [_i6.FileLock? mode, int? start, int? end]) => + (super.noSuchMethod(Invocation.method(#lock, [mode, start, end]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + void lockSync([_i6.FileLock? mode, int? start, int? end]) => + super.noSuchMethod(Invocation.method(#lockSync, [mode, start, end])); + _i7.Future<_i6.RandomAccessFile> unlock([int? start, int? end]) => + (super.noSuchMethod(Invocation.method(#unlock, [start, end]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + void unlockSync([int? start, int? end]) => + super.noSuchMethod(Invocation.method(#unlockSync, [start, end])); +} + +/// A class which mocks [BinaryReader]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBinaryReader extends _i1.Mock implements _i3.BinaryReader { + int get availableBytes => + (super.noSuchMethod(Invocation.getter(#availableBytes), 0) as int); + int get usedBytes => + (super.noSuchMethod(Invocation.getter(#usedBytes), 0) as int); + void skip(int? bytes) => + super.noSuchMethod(Invocation.method(#skip, [bytes])); + int readByte() => + (super.noSuchMethod(Invocation.method(#readByte, []), 0) as int); + _i5.Uint8List viewBytes(int? bytes) => (super.noSuchMethod( + Invocation.method(#viewBytes, [bytes]), _FakeUint8List()) + as _i5.Uint8List); + _i5.Uint8List peekBytes(int? bytes) => (super.noSuchMethod( + Invocation.method(#peekBytes, [bytes]), _FakeUint8List()) + as _i5.Uint8List); + int readWord() => + (super.noSuchMethod(Invocation.method(#readWord, []), 0) as int); + int readInt32() => + (super.noSuchMethod(Invocation.method(#readInt32, []), 0) as int); + int readUint32() => + (super.noSuchMethod(Invocation.method(#readUint32, []), 0) as int); + int readInt() => + (super.noSuchMethod(Invocation.method(#readInt, []), 0) as int); + double readDouble() => + (super.noSuchMethod(Invocation.method(#readDouble, []), 0.0) as double); + bool readBool() => + (super.noSuchMethod(Invocation.method(#readBool, []), false) as bool); + String readString( + [int? byteCount, + _i15.Converter, String>? decoder = + const _i15.Utf8Decoder()]) => + (super.noSuchMethod( + Invocation.method(#readString, [byteCount, decoder]), '') as String); + _i5.Uint8List readByteList([int? length]) => (super.noSuchMethod( + Invocation.method(#readByteList, [length]), _FakeUint8List()) + as _i5.Uint8List); + List readIntList([int? length]) => + (super.noSuchMethod(Invocation.method(#readIntList, [length]), []) + as List); + List readDoubleList([int? length]) => (super.noSuchMethod( + Invocation.method(#readDoubleList, [length]), []) + as List); + List readBoolList([int? length]) => + (super.noSuchMethod(Invocation.method(#readBoolList, [length]), []) + as List); + List readStringList( + [int? length, + _i15.Converter, String>? decoder = + const _i15.Utf8Decoder()]) => + (super.noSuchMethod( + Invocation.method(#readStringList, [length, decoder]), []) + as List); + List readList([int? length]) => + (super.noSuchMethod(Invocation.method(#readList, [length]), []) + as List); + Map readMap([int? length]) => (super.noSuchMethod( + Invocation.method(#readMap, [length]), {}) + as Map); + _i3.HiveList<_i4.HiveObject> readHiveList([int? length]) => + (super.noSuchMethod(Invocation.method(#readHiveList, [length]), + _FakeHiveList<_i4.HiveObject>()) as _i3.HiveList<_i4.HiveObject>); +} + +/// A class which mocks [BinaryWriter]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBinaryWriter extends _i1.Mock implements _i3.BinaryWriter { + void writeByte(int? byte) => + super.noSuchMethod(Invocation.method(#writeByte, [byte])); + void writeWord(int? value) => + super.noSuchMethod(Invocation.method(#writeWord, [value])); + void writeInt32(int? value) => + super.noSuchMethod(Invocation.method(#writeInt32, [value])); + void writeUint32(int? value) => + super.noSuchMethod(Invocation.method(#writeUint32, [value])); + void writeInt(int? value) => + super.noSuchMethod(Invocation.method(#writeInt, [value])); + void writeDouble(double? value) => + super.noSuchMethod(Invocation.method(#writeDouble, [value])); + void writeBool(bool? value) => + super.noSuchMethod(Invocation.method(#writeBool, [value])); + void writeString(String? value, + {bool? writeByteCount = true, + _i15.Converter>? encoder = + const _i15.Utf8Encoder()}) => + super.noSuchMethod(Invocation.method(#writeString, [value], + {#writeByteCount: writeByteCount, #encoder: encoder})); + void writeByteList(List? bytes, {bool? writeLength = true}) => + super.noSuchMethod(Invocation.method( + #writeByteList, [bytes], {#writeLength: writeLength})); + void writeIntList(List? list, {bool? writeLength = true}) => + super.noSuchMethod(Invocation.method( + #writeIntList, [list], {#writeLength: writeLength})); + void writeDoubleList(List? list, {bool? writeLength = true}) => + super.noSuchMethod(Invocation.method( + #writeDoubleList, [list], {#writeLength: writeLength})); + void writeBoolList(List? list, {bool? writeLength = true}) => + super.noSuchMethod(Invocation.method( + #writeBoolList, [list], {#writeLength: writeLength})); + void writeStringList(List? list, + {bool? writeLength = true, + _i15.Converter>? encoder = + const _i15.Utf8Encoder()}) => + super.noSuchMethod(Invocation.method(#writeStringList, [list], + {#writeLength: writeLength, #encoder: encoder})); + void writeList(List? list, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method(#writeList, [list], {#writeLength: writeLength})); + void writeMap(Map? map, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method(#writeMap, [map], {#writeLength: writeLength})); + void writeHiveList(_i3.HiveList<_i4.HiveObject>? list, + {bool? writeLength = true}) => + super.noSuchMethod(Invocation.method( + #writeHiveList, [list], {#writeLength: writeLength})); + void write(T? value, {bool? writeTypeId = true}) => super.noSuchMethod( + Invocation.method(#write, [value], {#writeTypeId: writeTypeId})); +} + +/// A class which mocks [File]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFile extends _i1.Mock implements _i6.File { + _i6.File get absolute => + (super.noSuchMethod(Invocation.getter(#absolute), _FakeFile()) + as _i6.File); + String get path => + (super.noSuchMethod(Invocation.getter(#path), '') as String); + _i7.Future<_i6.File> create({bool? recursive}) => (super.noSuchMethod( + Invocation.method(#create, [], {#recursive: recursive}), + Future.value(_FakeFile())) as _i7.Future<_i6.File>); + void createSync({bool? recursive}) => super.noSuchMethod( + Invocation.method(#createSync, [], {#recursive: recursive})); + _i7.Future<_i6.File> rename(String? newPath) => (super.noSuchMethod( + Invocation.method(#rename, [newPath]), Future.value(_FakeFile())) + as _i7.Future<_i6.File>); + _i6.File renameSync(String? newPath) => (super.noSuchMethod( + Invocation.method(#renameSync, [newPath]), _FakeFile()) as _i6.File); + _i7.Future<_i6.File> copy(String? newPath) => (super.noSuchMethod( + Invocation.method(#copy, [newPath]), Future.value(_FakeFile())) + as _i7.Future<_i6.File>); + _i6.File copySync(String? newPath) => + (super.noSuchMethod(Invocation.method(#copySync, [newPath]), _FakeFile()) + as _i6.File); + _i7.Future length() => + (super.noSuchMethod(Invocation.method(#length, []), Future.value(0)) + as _i7.Future); + int lengthSync() => + (super.noSuchMethod(Invocation.method(#lengthSync, []), 0) as int); + _i7.Future lastAccessed() => (super.noSuchMethod( + Invocation.method(#lastAccessed, []), Future.value(_FakeDateTime())) + as _i7.Future); + DateTime lastAccessedSync() => (super.noSuchMethod( + Invocation.method(#lastAccessedSync, []), _FakeDateTime()) as DateTime); + _i7.Future setLastAccessed(DateTime? time) => (super.noSuchMethod( + Invocation.method(#setLastAccessed, [time]), Future.value(null)) + as _i7.Future); + void setLastAccessedSync(DateTime? time) => + super.noSuchMethod(Invocation.method(#setLastAccessedSync, [time])); + _i7.Future lastModified() => (super.noSuchMethod( + Invocation.method(#lastModified, []), Future.value(_FakeDateTime())) + as _i7.Future); + DateTime lastModifiedSync() => (super.noSuchMethod( + Invocation.method(#lastModifiedSync, []), _FakeDateTime()) as DateTime); + _i7.Future setLastModified(DateTime? time) => (super.noSuchMethod( + Invocation.method(#setLastModified, [time]), Future.value(null)) + as _i7.Future); + void setLastModifiedSync(DateTime? time) => + super.noSuchMethod(Invocation.method(#setLastModifiedSync, [time])); + _i7.Future<_i6.RandomAccessFile> open({_i6.FileMode? mode}) => + (super.noSuchMethod(Invocation.method(#open, [], {#mode: mode}), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + _i6.RandomAccessFile openSync({_i6.FileMode? mode}) => (super.noSuchMethod( + Invocation.method(#openSync, [], {#mode: mode}), + _FakeRandomAccessFile()) as _i6.RandomAccessFile); + _i7.Stream> openRead([int? start, int? end]) => (super.noSuchMethod( + Invocation.method(#openRead, [start, end]), Stream>.empty()) + as _i7.Stream>); + _i6.IOSink openWrite({_i6.FileMode? mode, _i15.Encoding? encoding}) => + (super.noSuchMethod( + Invocation.method(#openWrite, [], {#mode: mode, #encoding: encoding}), + _FakeIOSink()) as _i6.IOSink); + _i7.Future<_i5.Uint8List> readAsBytes() => (super.noSuchMethod( + Invocation.method(#readAsBytes, []), Future.value(_FakeUint8List())) + as _i7.Future<_i5.Uint8List>); + _i5.Uint8List readAsBytesSync() => (super.noSuchMethod( + Invocation.method(#readAsBytesSync, []), _FakeUint8List()) + as _i5.Uint8List); + _i7.Future readAsString({_i15.Encoding? encoding}) => + (super.noSuchMethod( + Invocation.method(#readAsString, [], {#encoding: encoding}), + Future.value('')) as _i7.Future); + String readAsStringSync({_i15.Encoding? encoding}) => (super.noSuchMethod( + Invocation.method(#readAsStringSync, [], {#encoding: encoding}), '') + as String); + _i7.Future> readAsLines({_i15.Encoding? encoding}) => + (super.noSuchMethod( + Invocation.method(#readAsLines, [], {#encoding: encoding}), + Future.value([])) as _i7.Future>); + List readAsLinesSync({_i15.Encoding? encoding}) => + (super.noSuchMethod( + Invocation.method(#readAsLinesSync, [], {#encoding: encoding}), + []) as List); + _i7.Future<_i6.File> writeAsBytes(List? bytes, + {_i6.FileMode? mode, bool? flush}) => + (super.noSuchMethod( + Invocation.method( + #writeAsBytes, [bytes], {#mode: mode, #flush: flush}), + Future.value(_FakeFile())) as _i7.Future<_i6.File>); + void writeAsBytesSync(List? bytes, {_i6.FileMode? mode, bool? flush}) => + super.noSuchMethod(Invocation.method( + #writeAsBytesSync, [bytes], {#mode: mode, #flush: flush})); + _i7.Future<_i6.File> writeAsString(String? contents, + {_i6.FileMode? mode, _i15.Encoding? encoding, bool? flush}) => + (super.noSuchMethod( + Invocation.method(#writeAsString, [contents], + {#mode: mode, #encoding: encoding, #flush: flush}), + Future.value(_FakeFile())) as _i7.Future<_i6.File>); + void writeAsStringSync(String? contents, + {_i6.FileMode? mode, _i15.Encoding? encoding, bool? flush}) => + super.noSuchMethod(Invocation.method(#writeAsStringSync, [contents], + {#mode: mode, #encoding: encoding, #flush: flush})); + _i7.Future<_i6.FileSystemEntity> delete({bool recursive = false}) => + (super.noSuchMethod( + Invocation.method(#delete, [], {#recursive: recursive}), + Future.value(_FakeFile())) as _i7.Future<_i6.FileSystemEntity>); +} + +/// A class which mocks [FrameIoHelper]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFrameIoHelper extends _i1.Mock implements _i16.FrameIoHelper { + _i7.Future<_i6.RandomAccessFile> openFile(String? path) => + (super.noSuchMethod(Invocation.method(#openFile, [path]), + Future.value(_FakeRandomAccessFile())) + as _i7.Future<_i6.RandomAccessFile>); + _i7.Future> readFile(String? path) => (super.noSuchMethod( + Invocation.method(#readFile, [path]), Future.value([])) + as _i7.Future>); + _i7.Future keysFromFile(String? path, _i11.Keystore? keystore, + _i3.HiveCipher? cipher) => + (super.noSuchMethod( + Invocation.method(#keysFromFile, [path, keystore, cipher]), + Future.value(0)) as _i7.Future); + _i7.Future framesFromFile(String? path, _i11.Keystore? keystore, + _i3.TypeRegistry? registry, _i3.HiveCipher? cipher) => + (super.noSuchMethod( + Invocation.method( + #framesFromFile, [path, keystore, registry, cipher]), + Future.value(0)) as _i7.Future); + int framesFromBytes(_i5.Uint8List? bytes, _i11.Keystore? keystore, + _i3.TypeRegistry? registry, _i3.HiveCipher? cipher) => + (super.noSuchMethod( + Invocation.method( + #framesFromBytes, [bytes, keystore, registry, cipher]), + 0) as int); +} diff --git a/hive/test/tests/object/hive_collection_mixin_test.dart b/hive/test/tests/object/hive_collection_mixin_test.dart index f87452671..54cb8645f 100644 --- a/hive/test/tests/object/hive_collection_mixin_test.dart +++ b/hive/test/tests/object/hive_collection_mixin_test.dart @@ -2,10 +2,11 @@ import 'package:hive/hive.dart'; import 'package:hive/src/object/hive_object.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; - +import '../common.dart'; import '../mocks.dart'; -HiveList _getTestList(Box box) { +HiveList _getTestList(MockBox box) { + when(box.name).thenReturn('testBox'); var obj1 = TestHiveObject(); obj1.init('key1', box); var obj2 = TestHiveObject(); @@ -19,46 +20,54 @@ HiveList _getTestList(Box box) { void main() { group('HiveCollectionMixin', () { test('.keys', () { - var box = BoxMock(); + var box = MockBox(); var hiveList = _getTestList(box); expect(hiveList.keys, ['key1', 'key2', 'key3']); }); test('.deleteAllFromHive()', () { - var box = BoxMock(); + final keys = ['key1', 'key2', 'key3']; + var box = MockBox(); var hiveList = _getTestList(box); + returnFutureVoid(when(box.deleteAll( + keys.map((e) => e), // Turn the List into an regular Iterable + ))); hiveList.deleteAllFromHive(); - verify(box.deleteAll(['key1', 'key2', 'key3'])); + verify(box.deleteAll(keys)); }); test('.deleteFirstFromHive()', () { - var box = BoxMock(); + var box = MockBox(); var hiveList = _getTestList(box); + returnFutureVoid(when(box.delete('key1'))); hiveList.deleteFirstFromHive(); verify(box.delete('key1')); }); test('.deleteLastFromHive()', () { - var box = BoxMock(); + var box = MockBox(); var hiveList = _getTestList(box); + returnFutureVoid(when(box.delete('key3'))); hiveList.deleteLastFromHive(); verify(box.delete('key3')); }); - test('.deleteFromFromHive()', () { - var box = BoxMock(); + test('.deleteFromHive()', () { + var box = MockBox(); var hiveList = _getTestList(box); + returnFutureVoid(when(box.delete('key2'))); hiveList.deleteFromHive(1); verify(box.delete('key2')); }); test('.toMap()', () { - var box = BoxMock(); + var box = MockBox(); + when(box.name).thenReturn('testBox'); var obj1 = TestHiveObject(); obj1.init('key1', box); var obj2 = TestHiveObject(); diff --git a/hive/test/tests/object/hive_list_impl_test.dart b/hive/test/tests/object/hive_list_impl_test.dart index 285f239e7..b27fea22f 100644 --- a/hive/test/tests/object/hive_list_impl_test.dart +++ b/hive/test/tests/object/hive_list_impl_test.dart @@ -10,7 +10,7 @@ import 'package:test/test.dart'; import '../common.dart'; import '../mocks.dart'; -HiveObject _getHiveObject(String key, BoxMock box) { +HiveObject _getHiveObject(String key, MockBox box) { var hiveObject = TestHiveObject(); hiveObject.init(key, box); when(box.get(key, defaultValue: argThat(isNotNull, named: 'defaultValue'))) @@ -19,10 +19,18 @@ HiveObject _getHiveObject(String key, BoxMock box) { return hiveObject; } +MockBox _mockBox() { + var box = MockBox(); + // The HiveListImpl constructor sets the boxName property to box.name, + // therefore we need to return an valid String on sound null safety. + when(box.name).thenReturn('testBox'); + return box; +} + void main() { group('HiveListImpl', () { test('HiveListImpl()', () { - var box = BoxMock(); + var box = _mockBox(); var item1 = _getHiveObject('item1', box); var item2 = _getHiveObject('item2', box); @@ -61,7 +69,7 @@ void main() { }); test('removes correct elements if invalidated', () { - var box = BoxMock(); + var box = _mockBox(); var item1 = _getHiveObject('item1', box); var item2 = _getHiveObject('item2', box); var list = HiveListImpl(box, objects: [item1, item2, item1]); @@ -73,11 +81,11 @@ void main() { }); test('creates delegate and links HiveList if delegate == null', () { - var hive = HiveMock(); - var box = BoxMock(); - when(box.containsKey(any)).thenReturn(false); + var hive = MockHiveImpl(); + var box = _mockBox(); when(box.containsKey('item1')).thenReturn(true); when(box.containsKey('item2')).thenReturn(true); + when(box.containsKey('none')).thenReturn(false); when(hive.getBoxWithoutCheckInternal('box')).thenReturn(box); var item1 = _getHiveObject('item1', box); @@ -93,7 +101,7 @@ void main() { group('.dispose()', () { test('unlinks remote HiveObjects if delegate exists', () { - var box = BoxMock(); + var box = _mockBox(); var item1 = _getHiveObject('item1', box); var item2 = _getHiveObject('item2', box); @@ -106,7 +114,7 @@ void main() { }); test('set length', () { - var box = BoxMock(); + var box = _mockBox(); var item1 = _getHiveObject('item1', box); var item2 = _getHiveObject('item2', box); @@ -119,7 +127,7 @@ void main() { group('operator []=', () { test('sets key at index', () { - var box = BoxMock(); + var box = _mockBox(); var oldItem = _getHiveObject('old', box); var newItem = _getHiveObject('new', box); @@ -132,9 +140,9 @@ void main() { }); test('throws HiveError if HiveObject is not valid', () { - var box = BoxMock(); + var box = _mockBox(); var oldItem = _getHiveObject('old', box); - var newItem = _getHiveObject('new', BoxMock()); + var newItem = _getHiveObject('new', MockBox()); var list = HiveListImpl(box, objects: [oldItem]); expect(() => list[0] = newItem, throwsHiveError()); @@ -143,7 +151,7 @@ void main() { group('.add()', () { test('adds key', () { - var box = BoxMock(); + var box = _mockBox(); var item1 = _getHiveObject('item1', box); var item2 = _getHiveObject('item2', box); @@ -155,8 +163,8 @@ void main() { }); test('throws HiveError if HiveObject is not valid', () { - var box = BoxMock(); - var item = _getHiveObject('item', BoxMock()); + var box = _mockBox(); + var item = _getHiveObject('item', MockBox()); var list = HiveListImpl(box); expect(() => list.add(item), throwsHiveError('needs to be in the box')); }); @@ -164,7 +172,7 @@ void main() { group('.addAll()', () { test('adds keys', () { - var box = BoxMock(); + var box = _mockBox(); var item1 = _getHiveObject('item1', box); var item2 = _getHiveObject('item2', box); @@ -176,8 +184,8 @@ void main() { }); test('throws HiveError if HiveObject is not valid', () { - var box = BoxMock(); - var item = _getHiveObject('item', BoxMock()); + var box = _mockBox(); + var item = _getHiveObject('item', MockBox()); var list = HiveListImpl(box); expect(() => list.addAll([item]), diff --git a/hive/test/tests/object/hive_object_test.dart b/hive/test/tests/object/hive_object_test.dart index c89af8416..560b95cc5 100644 --- a/hive/test/tests/object/hive_object_test.dart +++ b/hive/test/tests/object/hive_object_test.dart @@ -10,7 +10,7 @@ void main() { group('.init()', () { test('adds key and box to HiveObject', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); obj.init('someKey', box); @@ -20,7 +20,7 @@ void main() { test('does nothing if old key and box are equal to new key and box', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); obj.init('someKey', box); obj.init('someKey', box); @@ -31,8 +31,8 @@ void main() { test('throws exception if object is already in a different box', () { var obj = TestHiveObject(); - var box1 = BoxMock(); - var box2 = BoxMock(); + var box1 = MockBox(); + var box2 = MockBox(); obj.init('someKey', box1); expect(() => obj.init('someKey', box2), @@ -41,7 +41,7 @@ void main() { test('throws exception if object has already different key', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); obj.init('key1', box); expect( @@ -52,7 +52,7 @@ void main() { group('.dispose()', () { test('removes key and box', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); obj.init('key', box); obj.dispose(); @@ -63,10 +63,10 @@ void main() { test('notifies remote HiveLists', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); obj.init('key', box); - var list = HiveListMock(); + var list = MockHiveListImpl(); obj.linkHiveList(list); obj.dispose(); @@ -75,10 +75,10 @@ void main() { }); test('.linkHiveList()', () { - var box = BoxMock(); + var box = MockBox(); var obj = TestHiveObject(); obj.init('key', box); - var hiveList = HiveListMock(); + var hiveList = MockHiveListImpl(); obj.linkHiveList(hiveList); expect(obj.debugHiveLists, {hiveList: 1}); @@ -87,10 +87,10 @@ void main() { }); test('.unlinkHiveList()', () { - var box = BoxMock(); + var box = MockBox(); var obj = TestHiveObject(); obj.init('key', box); - var hiveList = HiveListMock(); + var hiveList = MockHiveListImpl(); obj.linkHiveList(hiveList); obj.linkHiveList(hiveList); @@ -105,7 +105,9 @@ void main() { group('.save()', () { test('updates object in box', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); + returnFutureVoid(when(box.put('key', obj))); + obj.init('key', box); verifyZeroInteractions(box); @@ -122,7 +124,9 @@ void main() { group('.delete()', () { test('removes object from box', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); + returnFutureVoid(when(box.delete('key'))); + obj.init('key', box); verifyZeroInteractions(box); @@ -144,7 +148,7 @@ void main() { test('returns true if object is in normal box', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); when(box.lazy).thenReturn(false); obj.init('key', box); @@ -154,7 +158,7 @@ void main() { test('returns the result ob box.containsKey() if object is in lazy box', () { var obj = TestHiveObject(); - var box = BoxMock(); + var box = MockBox(); when(box.lazy).thenReturn(true); obj.init('key', box); diff --git a/hive/test/tests/registry/type_registry_impl_test.dart b/hive/test/tests/registry/type_registry_impl_test.dart index 8fa3f7681..0f1dafad4 100644 --- a/hive/test/tests/registry/type_registry_impl_test.dart +++ b/hive/test/tests/registry/type_registry_impl_test.dart @@ -41,7 +41,7 @@ void main() { var adapter = TestAdapter(); registry.registerAdapter(adapter); - var resolved = registry.findAdapterForValue(123); + var resolved = registry.findAdapterForValue(123)!; expect(resolved.typeId, 32); expect(resolved.adapter, adapter); }); @@ -67,7 +67,7 @@ void main() { var adapter = TestAdapter(); registry.registerAdapter(adapter); - var resolvedAdapter = registry.findAdapterForTypeId(32); + var resolvedAdapter = registry.findAdapterForTypeId(32)!; expect(resolvedAdapter.typeId, 32); expect(resolvedAdapter.adapter, adapter); }); @@ -78,7 +78,7 @@ void main() { var adapter = TestAdapter(); registry.registerAdapter(adapter); - var resolvedAdapter = registry.findAdapterForValue(123); + var resolvedAdapter = registry.findAdapterForValue(123)!; expect(resolvedAdapter.typeId, 32); expect(resolvedAdapter.adapter, adapter); }); @@ -90,7 +90,7 @@ void main() { registry.registerAdapter(adapter1); registry.registerAdapter(adapter2); - var resolvedAdapter = registry.findAdapterForValue(123); + var resolvedAdapter = registry.findAdapterForValue(123)!; expect(resolvedAdapter.typeId, 32); expect(resolvedAdapter.adapter, adapter1); }); @@ -133,7 +133,7 @@ void main() { test('registers IgnoredTypeAdapter', () { var registry = TypeRegistryImpl(); registry.ignoreTypeId(0); - var resolved = registry.findAdapterForTypeId(32); + var resolved = registry.findAdapterForTypeId(32)!; expect(resolved.adapter is IgnoredTypeAdapter, true); }); diff --git a/hive/test/tests/util/delegating_list_view_mixin_test.dart b/hive/test/tests/util/delegating_list_view_mixin_test.dart index 87fc06635..953f42291 100644 --- a/hive/test/tests/util/delegating_list_view_mixin_test.dart +++ b/hive/test/tests/util/delegating_list_view_mixin_test.dart @@ -3,9 +3,11 @@ import 'dart:math'; import 'package:hive/src/util/delegating_list_view_mixin.dart'; import 'package:test/test.dart'; +import '../common.dart'; + void main() { group('DelegatingIterable', () { - _TestList testList; + late _TestList testList; setUp(() { testList = _TestList(['a', 'b', 'cc']); @@ -57,7 +59,7 @@ void main() { }); test('.fold()', () { - expect(testList.fold('z', (p, e) => p + e), 'zabcc'); + expect(testList.fold('z', (dynamic p, e) => p + e), 'zabcc'); }); test('.forEach()', () { @@ -97,7 +99,11 @@ void main() { test('.forEach()', () { final it = testList.iterator; - expect(it.current, isNull); + if (soundNullSafety) { + expect(() => it.current, throwsA(anything)); + } else { + expect(it.current, null); + } expect(it.moveNext(), isTrue); expect(it.current, 'a'); expect(it.moveNext(), isTrue); @@ -105,7 +111,11 @@ void main() { expect(it.moveNext(), isTrue); expect(it.current, 'cc'); expect(it.moveNext(), isFalse); - expect(it.current, isNull); + if (soundNullSafety) { + expect(() => it.current, throwsA(anything)); + } else { + expect(it.current, null); + } }); test('.join()', () { @@ -218,7 +228,7 @@ class _TestList with DelegatingListViewMixin { void clear() => throw UnimplementedError(); @override - void fillRange(int start, int end, [T fillValue]) => + void fillRange(int start, int end, [T? fillValue]) => throw UnimplementedError(); @override @@ -237,7 +247,7 @@ class _TestList with DelegatingListViewMixin { set length(int newLength) => throw UnimplementedError(); @override - bool remove(Object value) => throw UnimplementedError(); + bool remove(Object? value) => throw UnimplementedError(); @override T removeAt(int index) => throw UnimplementedError(); @@ -267,8 +277,8 @@ class _TestList with DelegatingListViewMixin { throw UnimplementedError(); @override - void shuffle([Random random]) => throw UnimplementedError(); + void shuffle([Random? random]) => throw UnimplementedError(); @override - void sort([int Function(T a, T b) compare]) => throw UnimplementedError(); + void sort([int Function(T a, T b)? compare]) => throw UnimplementedError(); } diff --git a/hive_flutter/CHANGELOG.md b/hive_flutter/CHANGELOG.md index 6cb59fe14..5641235a7 100644 --- a/hive_flutter/CHANGELOG.md +++ b/hive_flutter/CHANGELOG.md @@ -1,20 +1,34 @@ +## 1.0.0 + +- Stable null-safety version + +## 0.1.0-nullsafety.0 + +- Null safety support + ## 0.3.1 + - Added Time and Color adapters ## 0.3.0+2 + - Fixed GitHub homepage path ## 0.3.0+1 + - Added `box.listenable()` which returns a `ValueListenable` - Added `Hive.initFlutter()` - **Breaking** Deprecated `WatchBoxBuilder` in favor of `box.listenable()`. Will be removed in a future version ## 0.2.1 + - Bump Hive version -- Changed WatchBoxBuilderState to _WatchBoxBuilderState +- Changed WatchBoxBuilderState to \_WatchBoxBuilderState ## 0.2.0 + - Breaking API change, renamed `HiveBuilder` to `BoxWidgetBuilder`. ## 0.1.0 + - First version diff --git a/hive_flutter/example/pubspec.yaml b/hive_flutter/example/pubspec.yaml index 66147a50a..db449f083 100644 --- a/hive_flutter/example/pubspec.yaml +++ b/hive_flutter/example/pubspec.yaml @@ -1 +1,3 @@ -name: example \ No newline at end of file +name: example +environment: + sdk: '>=2.10.0 <3.0.0' \ No newline at end of file diff --git a/hive_flutter/lib/src/box_extensions.dart b/hive_flutter/lib/src/box_extensions.dart index 7569d9d20..269e8d19d 100644 --- a/hive_flutter/lib/src/box_extensions.dart +++ b/hive_flutter/lib/src/box_extensions.dart @@ -7,7 +7,7 @@ extension BoxX on Box { /// /// If [keys] filter is provided, only changes to entries with the /// specified keys notify the listeners. - ValueListenable> listenable({List keys}) => + ValueListenable> listenable({List? keys}) => _BoxListenable(this, keys?.toSet()); } @@ -18,18 +18,18 @@ extension LazyBoxX on LazyBox { /// /// If [keys] filter is provided, only changes to entries with the /// specified keys notify the listeners. - ValueListenable> listenable({List keys}) => + ValueListenable> listenable({List? keys}) => _BoxListenable(this, keys?.toSet()); } class _BoxListenable> extends ValueListenable { final B box; - final Set keys; + final Set? keys; final List _listeners = []; - StreamSubscription _subscription; + StreamSubscription? _subscription; _BoxListenable(this.box, this.keys); @@ -38,7 +38,7 @@ class _BoxListenable> extends ValueListenable { if (_listeners.isEmpty) { if (keys != null) { _subscription = box.watch().listen((event) { - if (keys.contains(event.key)) { + if (keys!.contains(event.key)) { for (var listener in _listeners) { listener(); } diff --git a/hive_flutter/lib/src/hive_extensions.dart b/hive_flutter/lib/src/hive_extensions.dart index 7a2cc61e5..26cc660a4 100644 --- a/hive_flutter/lib/src/hive_extensions.dart +++ b/hive_flutter/lib/src/hive_extensions.dart @@ -5,15 +5,15 @@ extension HiveX on HiveInterface { /// Initializes Hive with the path from [getApplicationDocumentsDirectory]. /// /// You can provide a [subDir] where the boxes should be stored. - Future initFlutter([String subDir]) async { + Future initFlutter([String? subDir]) async { WidgetsFlutterBinding.ensureInitialized(); if (!kIsWeb) { var appDir = await getApplicationDocumentsDirectory(); - var path = appDir.path; - if (subDir != null) { - path = path_helper.join(path, subDir); + if (appDir != null) { + init(path_helper.join(appDir.path, subDir)); + } else { + NullThrownError(); } - init(path); } } } diff --git a/hive_flutter/lib/src/watch_box_builder.dart b/hive_flutter/lib/src/watch_box_builder.dart index 8a9258f11..0c1ec09c1 100644 --- a/hive_flutter/lib/src/watch_box_builder.dart +++ b/hive_flutter/lib/src/watch_box_builder.dart @@ -15,13 +15,11 @@ class WatchBoxBuilder extends StatefulWidget { /// If you specify [watchKeys], the widget only refreshes when a value /// associated to a key in [watchKeys] changes. WatchBoxBuilder({ - Key key, - @required this.box, - @required this.builder, + Key? key, + required this.box, + required this.builder, this.watchKeys, - }) : assert(box != null), - assert(builder != null), - super(key: key); + }) : super(key: key); /// The box which should be watched. final Box box; @@ -30,7 +28,7 @@ class WatchBoxBuilder extends StatefulWidget { final BoxWidgetBuilder builder; /// Specifies which keys should be watched. - final List watchKeys; + final List? watchKeys; @override _WatchBoxBuilderState createState() => _WatchBoxBuilderState(); @@ -39,7 +37,7 @@ class WatchBoxBuilder extends StatefulWidget { // ignore: deprecated_member_use_from_same_package class _WatchBoxBuilderState extends State { @visibleForTesting - StreamSubscription subscription; + StreamSubscription? subscription; @override void initState() { @@ -61,7 +59,7 @@ class _WatchBoxBuilderState extends State { void _subscribe() { subscription = widget.box.watch().listen((event) { - if (widget.watchKeys != null && !widget.watchKeys.contains(event.key)) { + if (widget.watchKeys != null && !widget.watchKeys!.contains(event.key)) { return; } diff --git a/hive_flutter/pubspec.yaml b/hive_flutter/pubspec.yaml index 9134545f5..737d4a7d2 100644 --- a/hive_flutter/pubspec.yaml +++ b/hive_flutter/pubspec.yaml @@ -1,22 +1,23 @@ name: hive_flutter description: Extension for Hive. Makes it easier to use Hive in Flutter apps. -version: 0.3.1 +version: 1.0.0 homepage: https://github.com/hivedb/hive/tree/master/hive_flutter documentation: https://docs.hivedb.dev/ environment: - sdk: ">=2.6.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: sdk: flutter - hive: ^1.0.0 - path_provider: ^1.0.0 - path: ^1.6.0 + hive: ^2.0.0 + path_provider: ^2.0.0 + path: ^1.8.0 dev_dependencies: flutter_test: sdk: flutter - pedantic: ">=1.8.0 <2.0.0" - mockito: ^4.1.1 + pedantic: ^1.8.0 + mockito: ^5.0.0-nullsafety.5 + build_runner: ^1.10.0 diff --git a/hive_flutter/test/adapters/color_adapter_test.dart b/hive_flutter/test/adapters/color_adapter_test.dart index e9dccafd8..ef78b691a 100644 --- a/hive_flutter/test/adapters/color_adapter_test.dart +++ b/hive_flutter/test/adapters/color_adapter_test.dart @@ -10,7 +10,7 @@ void main() { group('ColorAdapter', () { test('.read()', () { const color = Color(0xFF000000); - final BinaryReader binaryReader = BinaryReaderMock(); + final BinaryReader binaryReader = MockBinaryReader(); when(binaryReader.readInt()).thenReturn(color.value); final readColor = ColorAdapter().read(binaryReader); @@ -20,7 +20,7 @@ void main() { test('.write()', () { const color = Color(0xFF000000); - final BinaryWriter binaryWriter = BinaryWriterMock(); + final BinaryWriter binaryWriter = MockBinaryWriter(); ColorAdapter().write(binaryWriter, color); verify(binaryWriter.writeInt(color.value)); diff --git a/hive_flutter/test/adapters/time_adapter_test.dart b/hive_flutter/test/adapters/time_adapter_test.dart index 6d6fcae9b..f06fe1d6d 100644 --- a/hive_flutter/test/adapters/time_adapter_test.dart +++ b/hive_flutter/test/adapters/time_adapter_test.dart @@ -10,7 +10,7 @@ void main() { group('TimeOfDayAdapter', () { test('.read()', () { final time = TimeOfDay(hour: 8, minute: 0); - final BinaryReader binaryReader = BinaryReaderMock(); + final BinaryReader binaryReader = MockBinaryReader(); when(binaryReader.read()).thenReturn(time); final readTime = TimeAdapter().read(binaryReader); @@ -20,10 +20,10 @@ void main() { test('.write()', () { final time = TimeOfDay(hour: 8, minute: 0); - final BinaryWriter binaryWriter = BinaryWriterMock(); + final BinaryWriter binaryWriter = MockBinaryWriter(); TimeAdapter().write(binaryWriter, time); verify(binaryWriter.write(time)); }); }); -} \ No newline at end of file +} diff --git a/hive_flutter/test/mocks.dart b/hive_flutter/test/mocks.dart index 97b7e7d60..0eb720890 100644 --- a/hive_flutter/test/mocks.dart +++ b/hive_flutter/test/mocks.dart @@ -1,6 +1,13 @@ +library hive_flutter.test.mocks; + import 'package:hive/hive.dart'; -import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; -class BinaryReaderMock extends Mock implements BinaryReader {} +export 'mocks.mocks.dart'; -class BinaryWriterMock extends Mock implements BinaryWriter {} \ No newline at end of file +@GenerateMocks([], customMocks: [ + MockSpec(returnNullOnMissingStub: true), + MockSpec(returnNullOnMissingStub: true), +]) +// ignore: prefer_typing_uninitialized_variables, unused_element +var _mocks; diff --git a/hive_flutter/test/mocks.mocks.dart b/hive_flutter/test/mocks.mocks.dart new file mode 100644 index 000000000..73efe5dd4 --- /dev/null +++ b/hive_flutter/test/mocks.mocks.dart @@ -0,0 +1,210 @@ +// Mocks generated by Mockito 5.0.0-nullsafety.7 from annotations +// in hive_flutter/test/mocks.dart. +// Do not manually edit this file. + +import 'dart:convert' as _i5; +import 'dart:typed_data' as _i2; + +import 'package:hive/hive.dart' as _i4; +import 'package:hive/src/object/hive_object.dart' as _i3; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis + +class _FakeUint8List extends _i1.Fake implements _i2.Uint8List {} + +class _FakeHiveList extends _i1.Fake + implements _i4.HiveList {} + +/// A class which mocks [BinaryReader]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBinaryReader extends _i1.Mock implements _i4.BinaryReader { + @override + int get availableBytes => + (super.noSuchMethod(Invocation.getter(#availableBytes), returnValue: 0) + as int); + @override + int get usedBytes => + (super.noSuchMethod(Invocation.getter(#usedBytes), returnValue: 0) + as int); + @override + void skip(int? bytes) => super.noSuchMethod(Invocation.method(#skip, [bytes]), + returnValueForMissingStub: null); + @override + int readByte() => + (super.noSuchMethod(Invocation.method(#readByte, []), returnValue: 0) + as int); + @override + _i2.Uint8List viewBytes(int? bytes) => + (super.noSuchMethod(Invocation.method(#viewBytes, [bytes]), + returnValue: _FakeUint8List()) as _i2.Uint8List); + @override + _i2.Uint8List peekBytes(int? bytes) => + (super.noSuchMethod(Invocation.method(#peekBytes, [bytes]), + returnValue: _FakeUint8List()) as _i2.Uint8List); + @override + int readWord() => + (super.noSuchMethod(Invocation.method(#readWord, []), returnValue: 0) + as int); + @override + int readInt32() => + (super.noSuchMethod(Invocation.method(#readInt32, []), returnValue: 0) + as int); + @override + int readUint32() => + (super.noSuchMethod(Invocation.method(#readUint32, []), returnValue: 0) + as int); + @override + int readInt() => + (super.noSuchMethod(Invocation.method(#readInt, []), returnValue: 0) + as int); + @override + double readDouble() => + (super.noSuchMethod(Invocation.method(#readDouble, []), returnValue: 0.0) + as double); + @override + bool readBool() => + (super.noSuchMethod(Invocation.method(#readBool, []), returnValue: false) + as bool); + @override + String readString( + [int? byteCount, + _i5.Converter, String>? decoder = + const _i5.Utf8Decoder()]) => + (super.noSuchMethod(Invocation.method(#readString, [byteCount, decoder]), + returnValue: '') as String); + @override + _i2.Uint8List readByteList([int? length]) => + (super.noSuchMethod(Invocation.method(#readByteList, [length]), + returnValue: _FakeUint8List()) as _i2.Uint8List); + @override + List readIntList([int? length]) => + (super.noSuchMethod(Invocation.method(#readIntList, [length]), + returnValue: []) as List); + @override + List readDoubleList([int? length]) => + (super.noSuchMethod(Invocation.method(#readDoubleList, [length]), + returnValue: []) as List); + @override + List readBoolList([int? length]) => + (super.noSuchMethod(Invocation.method(#readBoolList, [length]), + returnValue: []) as List); + @override + List readStringList( + [int? length, + _i5.Converter, String>? decoder = + const _i5.Utf8Decoder()]) => + (super.noSuchMethod(Invocation.method(#readStringList, [length, decoder]), + returnValue: []) as List); + @override + List readList([int? length]) => + (super.noSuchMethod(Invocation.method(#readList, [length]), + returnValue: []) as List); + @override + Map readMap([int? length]) => + (super.noSuchMethod(Invocation.method(#readMap, [length]), + returnValue: {}) as Map); + @override + _i4.HiveList<_i3.HiveObject> readHiveList([int? length]) => + (super.noSuchMethod(Invocation.method(#readHiveList, [length]), + returnValue: _FakeHiveList<_i3.HiveObject>()) + as _i4.HiveList<_i3.HiveObject>); +} + +/// A class which mocks [BinaryWriter]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBinaryWriter extends _i1.Mock implements _i4.BinaryWriter { + @override + void writeByte(int? byte) => + super.noSuchMethod(Invocation.method(#writeByte, [byte]), + returnValueForMissingStub: null); + @override + void writeWord(int? value) => + super.noSuchMethod(Invocation.method(#writeWord, [value]), + returnValueForMissingStub: null); + @override + void writeInt32(int? value) => + super.noSuchMethod(Invocation.method(#writeInt32, [value]), + returnValueForMissingStub: null); + @override + void writeUint32(int? value) => + super.noSuchMethod(Invocation.method(#writeUint32, [value]), + returnValueForMissingStub: null); + @override + void writeInt(int? value) => + super.noSuchMethod(Invocation.method(#writeInt, [value]), + returnValueForMissingStub: null); + @override + void writeDouble(double? value) => + super.noSuchMethod(Invocation.method(#writeDouble, [value]), + returnValueForMissingStub: null); + @override + void writeBool(bool? value) => + super.noSuchMethod(Invocation.method(#writeBool, [value]), + returnValueForMissingStub: null); + @override + void writeString(String? value, + {bool? writeByteCount = true, + _i5.Converter>? encoder = + const _i5.Utf8Encoder()}) => + super.noSuchMethod( + Invocation.method(#writeString, [value], + {#writeByteCount: writeByteCount, #encoder: encoder}), + returnValueForMissingStub: null); + @override + void writeByteList(List? bytes, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method( + #writeByteList, [bytes], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void writeIntList(List? list, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method(#writeIntList, [list], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void writeDoubleList(List? list, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method( + #writeDoubleList, [list], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void writeBoolList(List? list, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method( + #writeBoolList, [list], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void writeStringList(List? list, + {bool? writeLength = true, + _i5.Converter>? encoder = + const _i5.Utf8Encoder()}) => + super.noSuchMethod( + Invocation.method(#writeStringList, [list], + {#writeLength: writeLength, #encoder: encoder}), + returnValueForMissingStub: null); + @override + void writeList(List? list, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method(#writeList, [list], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void writeMap(Map? map, {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method(#writeMap, [map], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void writeHiveList(_i4.HiveList<_i3.HiveObject>? list, + {bool? writeLength = true}) => + super.noSuchMethod( + Invocation.method( + #writeHiveList, [list], {#writeLength: writeLength}), + returnValueForMissingStub: null); + @override + void write(T? value, {bool? writeTypeId = true}) => super.noSuchMethod( + Invocation.method(#write, [value], {#writeTypeId: writeTypeId}), + returnValueForMissingStub: null); +} diff --git a/hive_generator/CHANGELOG.md b/hive_generator/CHANGELOG.md index 609d38ed3..cf5f83842 100644 --- a/hive_generator/CHANGELOG.md +++ b/hive_generator/CHANGELOG.md @@ -1,62 +1,93 @@ +## 1.0.0 + +- Stable null-safety version + +## 0.9.0-nullsafety.1 + +- Enum nullsafety support - [#555](https://github.com/hivedb/hive/issues/555) + +## 0.9.0-nullsafety.0 + +- Support generating null-safe code for libraries using Dart >= 2.12.0 +- Does not generate incompatible code for legacy libraries, so this is **NOT** a breaking change. + ## 0.8.2 + - Inheritance support. Fixes [#442](https://github.com/hivedb/hive/issues/442) - Support for both older and newer analyzer versions ## 0.8.1 + - Fixes [#455](https://github.com/hivedb/hive/issues/455) ## 0.8.0 + - `analyzer: ^0.40.0` version support - [#455](https://github.com/hivedb/hive/issues/455) ## 0.7.2+1 + - Fixed [#225] ## 0.7.2 + - Fixed [#225](https://github.com/hivedb/hive/issues/225) ## 0.7.1 + - Fixed dependency issues ## 0.7.0+2 + - Fixed Changelog ## 0.7.0+2 + - Fixed GitHub homepage path ## 0.7.0 + - Fixed final fields in constructor - Support for `typeId` parameter ## 0.6.0 + - Support for HiveLists - Support for getters & setters - Support for inheritance ## 0.5.2 + - Fix bug with Uint8Lists ## 0.5.1 + - Bump Hive version ## 0.5.0 + - Support final members ## 0.4.0+2 + - Support for Lists and Maps in strong mode ## 0.4.0+1 + - Support for enums - Sanity checks - Bugfixes ## 0.3.0 + - Support for typed lists - Bugfixes - **Breaking:** Not compatible to previous adapters ## 0.2.0 + - Improve performance of adapers - Cast lists to the correct type ## 0.1.0+1 -- First release \ No newline at end of file + +- First release diff --git a/hive_generator/example/lib/cat.dart b/hive_generator/example/lib/cat.dart index 10260881f..bed68e3ae 100644 --- a/hive_generator/example/lib/cat.dart +++ b/hive_generator/example/lib/cat.dart @@ -4,7 +4,7 @@ part 'cat.g.dart'; @HiveType(typeId: 3) class Animal { - Animal({this.field1, this.field0}); + Animal({required this.field1, required this.field0}); @HiveField(0) final String field0; @@ -15,8 +15,12 @@ class Animal { @HiveType(typeId: 5) class Cat extends Animal { - Cat({this.field2, String field0, int field1, String foo}) - : super(field1: field1, field0: field0); + Cat({ + required this.field2, + required String field0, + required int field1, + String? foo, + }) : super(field1: field1, field0: field0); @HiveField(2) final String field2; @@ -24,8 +28,13 @@ class Cat extends Animal { @HiveType(typeId: 6) class Tiger extends Cat { - Tiger(this.field3, {String field2, String field0, int field1, String foo}) - : super(field0: field0, field1: field1, field2: field2); + Tiger( + this.field3, { + required String field2, + required String field0, + required int field1, + String? foo, + }) : super(field0: field0, field1: field1, field2: field2); @HiveField(3) final int field3; diff --git a/hive_generator/example/lib/person.dart b/hive_generator/example/lib/person.dart index 46748a152..4ed900ada 100644 --- a/hive_generator/example/lib/person.dart +++ b/hive_generator/example/lib/person.dart @@ -5,19 +5,19 @@ part 'person.g.dart'; @HiveType(typeId: 1) class Person extends HiveObject { @HiveField(0) - String firstName; + String? firstName; @HiveField(1) - String lastName; + String? lastName; @HiveField(2) - DateTime birthday; + DateTime? birthday; @HiveField(3) - List roles; + List? roles; @HiveField(4) - HiveList friends; + HiveList? friends; } @HiveType(typeId: 2) @@ -25,7 +25,7 @@ enum UserRole { @HiveField(0) customer, - @HiveField(1) + @HiveField(1, defaultValue: true) contentEditor, @HiveField(2) diff --git a/hive_generator/example/lib/person.g.dart b/hive_generator/example/lib/person.g.dart index 8a98f69e7..f83b0078a 100644 --- a/hive_generator/example/lib/person.g.dart +++ b/hive_generator/example/lib/person.g.dart @@ -20,7 +20,7 @@ class UserRoleAdapter extends TypeAdapter { case 2: return UserRole.admin; default: - return null; + return UserRole.customer; } } @@ -61,11 +61,11 @@ class PersonAdapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return Person() - ..firstName = fields[0] as String - ..lastName = fields[1] as String - ..birthday = fields[2] as DateTime - ..roles = (fields[3] as List)?.cast() - ..friends = (fields[4] as HiveList)?.castHiveList(); + ..firstName = fields[0] as String? + ..lastName = fields[1] as String? + ..birthday = fields[2] as DateTime? + ..roles = (fields[3] as List?)?.cast() + ..friends = (fields[4] as HiveList?)?.castHiveList(); } @override diff --git a/hive_generator/example/pubspec.yaml b/hive_generator/example/pubspec.yaml index 73a9b73a0..3727b308a 100644 --- a/hive_generator/example/pubspec.yaml +++ b/hive_generator/example/pubspec.yaml @@ -3,5 +3,12 @@ dependencies: hive: any dev_dependencies: build_runner: any + hive_generator: + path: .. +environment: + sdk: '>=2.12.0-0 <3.0.0' +dependency_overrides: + hive: + path: ../../hive hive_generator: path: .. \ No newline at end of file diff --git a/hive_generator/lib/src/builder.dart b/hive_generator/lib/src/builder.dart index 7284a7289..707e4fe83 100644 --- a/hive_generator/lib/src/builder.dart +++ b/hive_generator/lib/src/builder.dart @@ -5,8 +5,9 @@ class AdapterField { final int index; final String name; final DartType type; + final bool defaultValue; - AdapterField(this.index, this.name, this.type); + AdapterField(this.index, this.name, this.type, this.defaultValue); } abstract class Builder { diff --git a/hive_generator/lib/src/class_builder.dart b/hive_generator/lib/src/class_builder.dart index 812702305..c2e3a7e80 100644 --- a/hive_generator/lib/src/class_builder.dart +++ b/hive_generator/lib/src/class_builder.dart @@ -1,12 +1,12 @@ import 'dart:typed_data'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:hive/hive.dart'; import 'package:hive_generator/src/builder.dart'; import 'package:hive_generator/src/helper.dart'; import 'package:source_gen/source_gen.dart'; -import 'package:dartx/dartx.dart'; class ClassBuilder extends Builder { var hiveListChecker = const TypeChecker.fromRuntime(HiveList); @@ -66,23 +66,22 @@ class ClassBuilder extends Builder { } String _cast(DartType type, String variable) { - if (hiveListChecker.isExactlyType(type)) { - return '($variable as HiveList)?.castHiveList()'; + var suffix = _suffixFromType(type); + if (hiveListChecker.isAssignableFromType(type)) { + return '($variable as HiveList$suffix)?.castHiveList()'; } else if (iterableChecker.isAssignableFromType(type) && !isUint8List(type)) { - return '($variable as List)${_castIterable(type)}'; - } else if (mapChecker.isExactlyType(type)) { - return '($variable as Map)${_castMap(type)}'; + return '($variable as List$suffix)${_castIterable(type)}'; + } else if (mapChecker.isAssignableFromType(type)) { + return '($variable as Map$suffix)${_castMap(type)}'; } else { return '$variable as ${_displayString(type)}'; } } bool isMapOrIterable(DartType type) { - return listChecker.isExactlyType(type) || - setChecker.isExactlyType(type) || - iterableChecker.isExactlyType(type) || - mapChecker.isExactlyType(type); + return iterableChecker.isAssignableFromType(type) || + mapChecker.isAssignableFromType(type); } bool isUint8List(DartType type) { @@ -92,16 +91,22 @@ class ClassBuilder extends Builder { String _castIterable(DartType type) { var paramType = type as ParameterizedType; var arg = paramType.typeArguments.first; + var suffix = _accessorSuffixFromType(type); if (isMapOrIterable(arg) && !isUint8List(arg)) { var cast = ''; - if (listChecker.isExactlyType(type)) { - cast = '?.toList()'; - } else if (setChecker.isExactlyType(type)) { - cast = '?.toSet()'; + // Using assignable because List? is not exactly List + if (listChecker.isAssignableFromType(type)) { + cast = '.toList()'; + // Using assignable because Set? is not exactly Set + } else if (setChecker.isAssignableFromType(type)) { + cast = '.toSet()'; } - return '?.map((dynamic e)=> ${_cast(arg, 'e')})$cast'; + // The suffix is not needed with nnbd on $cast becauuse it short circuits, + // otherwise it is needed. + var castWithSuffix = isLibraryNNBD(cls) ? '$cast' : '$suffix$cast'; + return '$suffix.map((dynamic e)=> ${_cast(arg, 'e')})$castWithSuffix'; } else { - return '?.cast<${_displayString(arg)}>()'; + return '$suffix.cast<${_displayString(arg)}>()'; } } @@ -109,11 +114,12 @@ class ClassBuilder extends Builder { var paramType = type as ParameterizedType; var arg1 = paramType.typeArguments[0]; var arg2 = paramType.typeArguments[1]; + var suffix = _accessorSuffixFromType(type); if (isMapOrIterable(arg1) || isMapOrIterable(arg2)) { - return '?.map((dynamic k, dynamic v)=>' + return '$suffix.map((dynamic k, dynamic v)=>' 'MapEntry(${_cast(arg1, 'k')},${_cast(arg2, 'v')}))'; } else { - return '?.cast<${_displayString(arg1)}, ' + return '$suffix.cast<${_displayString(arg1)}, ' '${_displayString(arg2)}>()'; } } @@ -135,20 +141,58 @@ class ClassBuilder extends Builder { } String _convertIterable(DartType type, String accessor) { - if (setChecker.isExactlyType(type) || iterableChecker.isExactlyType(type)) { - return '$accessor?.toList()'; + if (listChecker.isAssignableFromType(type)) { + return accessor; + } else + // Using assignable because Set? and Iterable? are not exactly Set and + // Iterable + if (setChecker.isAssignableFromType(type) || + iterableChecker.isAssignableFromType(type)) { + var suffix = _accessorSuffixFromType(type); + return '$accessor$suffix.toList()'; } else { return accessor; } } } -String _displayString(dynamic e) { +extension _FirstOrNullWhere on Iterable { + T /*?*/ firstOrNullWhere(bool Function(T) predicate) => + firstWhere(predicate, orElse: () => null); +} + +/// Suffix to use when accessing a field in [type]. +/// $variable$suffix.field +String _accessorSuffixFromType(DartType type) { + if (type.nullabilitySuffix == NullabilitySuffix.star) { + return '?'; + } + if (type.nullabilitySuffix == NullabilitySuffix.question) { + return '?'; + } + return ''; +} + +/// Suffix to use when casting a value to [type]. +/// $variable as $type$suffix +String _suffixFromType(DartType type) { + if (type.nullabilitySuffix == NullabilitySuffix.star) { + return ''; + } + if (type.nullabilitySuffix == NullabilitySuffix.question) { + return '?'; + } + return ''; +} + +String _displayString(DartType e) { try { - return e.getDisplayString(withNullability: false) as String; + var suffix = _suffixFromType(e); + return '${e.getDisplayString(withNullability: false) as String}$suffix'; } catch (error) { if (error is TypeError) { - return e.getDisplayString() as String; + var suffix = _suffixFromType(e); + return '${e.getDisplayString() as String}$suffix'; } else { rethrow; } diff --git a/hive_generator/lib/src/enum_builder.dart b/hive_generator/lib/src/enum_builder.dart index 857e6d06a..54904f205 100644 --- a/hive_generator/lib/src/enum_builder.dart +++ b/hive_generator/lib/src/enum_builder.dart @@ -1,5 +1,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:hive_generator/src/builder.dart'; +import 'package:hive_generator/src/helper.dart'; class EnumBuilder extends Builder { EnumBuilder(ClassElement cls, List getters) @@ -7,6 +8,8 @@ class EnumBuilder extends Builder { @override String buildRead() { + check(getters.isNotEmpty, '${cls.name} does not have any enum value.'); + var code = StringBuffer(); code.writeln('switch (reader.readByte()) {'); @@ -16,9 +19,11 @@ class EnumBuilder extends Builder { return ${cls.name}.${field.name};'''); } + var defaultField = getters.firstWhere((el) => el.defaultValue == true, + orElse: () => getters.first); code.writeln(''' default: - return null; + return ${cls.name}.${defaultField.name}; }'''); return code.toString(); diff --git a/hive_generator/lib/src/helper.dart b/hive_generator/lib/src/helper.dart index 933783876..d99a73e05 100644 --- a/hive_generator/lib/src/helper.dart +++ b/hive_generator/lib/src/helper.dart @@ -12,6 +12,16 @@ HiveField getHiveFieldAnn(Element element) { ); } +bool isLibraryNNBD(Element element) { + final dartVersion = element.library.languageVersion.effective; + // Libraries with the dart version >= 2.12 are nnbd + if (dartVersion.major >= 2 && dartVersion.minor >= 12) { + return true; + } else { + return false; + } +} + Iterable getTypeAndAllSupertypes(ClassElement cls) { var types = {}; types.add(cls); diff --git a/hive_generator/lib/src/type_adapter_generator.dart b/hive_generator/lib/src/type_adapter_generator.dart index 9df457059..704128ad8 100644 --- a/hive_generator/lib/src/type_adapter_generator.dart +++ b/hive_generator/lib/src/type_adapter_generator.dart @@ -106,7 +106,12 @@ class TypeAdapterGenerator extends GeneratorForAnnotation { getHiveFieldAnn(getter.variable) ?? getHiveFieldAnn(getter); if (getterAnn != null) { var field = getter.variable; - getters.add(AdapterField(getterAnn.index, field.name, field.type)); + getters.add(AdapterField( + getterAnn.index, + field.name, + field.type, + getterAnn.defaultValue, + )); } } @@ -116,7 +121,12 @@ class TypeAdapterGenerator extends GeneratorForAnnotation { getHiveFieldAnn(setter.variable) ?? getHiveFieldAnn(setter); if (setterAnn != null) { var field = setter.variable; - setters.add(AdapterField(setterAnn.index, field.name, field.type)); + setters.add(AdapterField( + setterAnn.index, + field.name, + field.type, + setterAnn.defaultValue, + )); } } } diff --git a/hive_generator/pubspec.yaml b/hive_generator/pubspec.yaml index 6e440e27e..8bddfca4e 100644 --- a/hive_generator/pubspec.yaml +++ b/hive_generator/pubspec.yaml @@ -1,21 +1,21 @@ name: hive_generator description: Extension for Hive. Automatically generates TypeAdapters to store any class. -version: 0.8.2 +version: 1.0.0 homepage: https://github.com/hivedb/hive/tree/master/hive_generator documentation: https://docs.hivedb.dev/ -environment: - sdk: ">=2.6.0 <3.0.0" +environment: + sdk: '>=2.10.0 <3.0.0' dependencies: - build: ^1.1.6 - source_gen: ">=0.9.4+4 <2.0.0" - hive: ">=1.3.0 <2.0.0" - analyzer: ">=0.36.0 <2.0.0" - dartx: ">=0.2.0 <1.0.0" + build: ^1.5.2 + source_gen: ">=0.9.10+1 <2.0.0" + hive: ^2.0.0 + analyzer: ">=0.40.0 <2.0.0" dev_dependencies: - test: ^1.6.4 + test: ^1.16.0 build_test: any build_runner: any - pedantic: "1.7.0" + pedantic: ^1.10.0 + \ No newline at end of file