isar-community / isar

Extremely fast, easy to use, and fully async NoSQL database for Flutter
https://isar-community.dev
Apache License 2.0
131 stars 15 forks source link

[Unit Testing] initializeCoreBinary - download option #30

Closed geoffwc closed 4 months ago

geoffwc commented 5 months ago

Nice job on updating this library!

I have a pretty large app I'm migrating from Xamarin which has a lot of local storage for offline support. I updated to 3.1.4 a couple of days ago and everything seems to working fine. I make a lot of use of composite indexes, nested entities and extensive filtering, querying. Only problem I've found is in a few unit tests where I'm checking data storage in a few tests. The Isar db is setup using:

Isar.initializeIsarCore(download: true)

example:

setUp(() async {
    final dir = await Directory.systemTemp.createTemp('test_isar');
    await Isar.initializeIsarCore(download: true);
    isar = await Isar.open([PlantEntitySchema], directory: dir.path);

    log = MockLog();
  }); 

The download option should download the correct dart libs for the current Abi for the test, however the binaries aren't in the correct place in the community version.

If we look in: https://github.com/isar-community/isar/blob/b75f93d88ea28b6277445722b3a336559a196ef6/packages/isar/lib/src/native/isar_core.dart#L113

We can see the URL is defined here:

const String _githubUrl = 'https://github.com/isar-community/isar/releases/download';

...but /releases/download does not exist and the binaries are at /releases

As a workaround I've downloaded the Mac lib and initialised like this instead:

const macIsarPath = 'test/lib/libisar_macos.dylib';

extension IsarExtensions on Isar {
  static Future initializeIsarLibraries() =>
      Isar.initializeIsarCore(libraries: {Abi.macosArm64: macIsarPath});
}

so example becomes:

setUp(() async {
    final dir = await Directory.systemTemp.createTemp('test_isar');
    await IsarExtensions.initializeIsarLibraries();
    isar = await Isar.open([PlantEntitySchema], directory: dir.path);

    log = MockLog();
  }); 

I'm assuming if the /download part of the path is removed, then the initialiser will work, but not sure on the intentions regarding short-term / long-term releases?

mrclauss commented 5 months ago

If you look at the releases page from github you'll see that there should be a version number somewhere inbetween: https://github.com/isar-community/isar/releases/ In release 3.1.4 libisar_macos.dylib is linked to: https://github.com/isar-community/isar/releases/download/3.1.4/libisar_macos.dylib

The corresponding line where the version is inserted into the download URL is here (same for v4 and v3 as far as I see): https://github.com/isar-community/isar/blob/b75f93d88ea28b6277445722b3a336559a196ef6/packages/isar/lib/src/native/isar_core.dart#L138

For some reason this does not seem to work. Do you use the hosted package from isar-community.dev or build it yourself from git? (Aka what does your pubspec.yaml look like regarding isar?)

mrclauss commented 5 months ago

Any feedback on that? Did you use the package from git or from hosted?

geoffwc commented 5 months ago

Sorry for slow response. This is my pubspec.yaml:

  # isar: ^3.1.0+1
  # isar_flutter_libs: ^3.1.0+1
  isar: 
    version: ^3.1.4
    hosted: https://isar-community.dev/
  isar_flutter_libs: # contains Isar Core
    version: ^3.1.4
    hosted: https://isar-community.dev/
mrclauss commented 5 months ago

Could you try if it works of you replace the github url with this one: https://isar-community.dev/releases/3.1.4/

geoffwc commented 5 months ago

Yeah I’ll give it a try and report back…

mrclauss commented 5 months ago

I reproduced the issue here. Interestingly sometimes the download from github works, sometimes it doesn't (maybe depending on load). Downloading from isar-community.dev seems to work reliably.

geoffwc commented 5 months ago

Ah ok, I made a fork today and was going to look tomorrow morning, have you merged a fix?

mrclauss commented 5 months ago

Yes, it's merged an v3.1.5 is created. Please give that one a try

geoffwc commented 5 months ago

Still not working unfortunately. I'll take a look at creating a test my fork

vicenterusso commented 5 months ago

Still not working unfortunately. I'll take a look at creating a test my fork

please create a repository to reproduce this

geoffwc commented 5 months ago

Ok I've created a test on my fork and it's working fine even if I commend out the local cache:

https://github.com/geoffwc/isar_test_init_core https://github.com/geoffwc/isar_test_init_core/commit/7cdd3d35dc4b6379a2d7892aac4252fc9f7ae746

I'll keep working on this as it's still failing in my tests. Might take a few days as I'm doing a few different things. Will keep you guys posted

FritzMatthaeus commented 5 months ago

I had add also issues with Isar.initializeCore(download:true) running unit tests on MacOS. I ran into a notice saying:

Bad state: There is no current invoker. Please make sure that you are making the call inside a test zone.

calling Isar.initializeCore(download: true) fails but does not throw any exception and the following unit test failed as the Isar Instance has not been opened.

I could fix it by manually downloading the "Isar MacOs.dylib" file, renaming it into "libisar.dylib".

geoffwc commented 5 months ago

Might be getting somewhere. When the binaries are downloaded they are saved in this path:

var scriptDir = Platform.script.pathSegments
          .sublist(0, Platform.script.pathSegments.length - 1)
          .join(Platform.pathSeparator);
      print(scriptDir);

I added the above to my test and I get this path Users/geoff/Projects/projName ...looked in finder and there's the .dylib file causing the problems...don't know how I never noticed it. Delete the file and the test downloads the file again and passes.

This works fine if you know to delete the file but if you don't it will cause problems again when the version changes. So this probably is an existing issue I would say.

...further exploration...

I noticed when I look at that path in the test I created in the Isar fork, I get this path var/folders/db/wrfmj23d0k56wbtd8982vdmm0000gn/T/dart_test.kernel.jd0yD0

and the path changes every run, so it looks like the binaries would be copied to a clean test area each run which would mean we get a clean binary each time...it's running a bit like a build server.

...I've trawled through the project and can't find anything which configures the tests in a certain way or any special test packages. Anybody any idea how this is done?

FritzMatthaeus commented 5 months ago

I had to switch back to the original Isar 3.1.0 as in the community-version all of my unit tests were broken due to mdbx corruption issues. I could not get them working on 3.1.5, but they run fine in the 3.1.0 version. Maybe it's the dylib file or whatever. I don't understand anything of Rust, etc., so unfortunately i cannot give you further insights.

FritzMatthaeus commented 5 months ago

If you want to digg deeper, please tell me and i will try to setup an example to reproduce the error.

geoffwc commented 5 months ago

I had to switch back to the original Isar 3.1.0 as in the community-version all of my unit tests were broken due to mdbx corruption issues. I could not get them working on 3.1.5, but they run fine in the 3.1.0 version. Maybe it's the dylib file or whatever. I don't understand anything of Rust, etc., so unfortunately i cannot give you further insights.

What OS are you running tests on? Mine ran ok on macOS once I finally figured out the 3.1.0 version wasn’t getting overwritten. Have you tried the workaround I mentioned in the start of the thread?

FritzMatthaeus commented 5 months ago

I am running the Tests on MacOs. I downloaded the macOs dylib file for Version 3.1.5, renamed it to isarlib.dylib and just called Isar.initializeCore(download: true). As the file was there, it worked out of the box. But i got those nasty Corruption Errors as soon as the unit tests tried to perform multiple read & write operations. To be precise, the write operations are taking place in isolates, which could be the reason for crashing. They run fine in 3.1.0.

mrclauss commented 5 months ago

Could you please retest with 3.1.6?

FritzMatthaeus commented 5 months ago

Could you please retest with 3.1.6?

I will try and give you feedback. Unfortunately i won't be able to test in the next days, sorry.

Thank you for adressing this issue. Your work is highly appreciated.

geoffwc commented 5 months ago

Could you please retest with 3.1.6?

yeah sure, will be next week though...trying to get a release out...

FritzMatthaeus commented 5 months ago

Here my feedback on unit testing with 3.1.6.

Test Setup

Platform: MacOS (2019), Sonoma 14.4, Intel-Processors Flutter: 3.16.8

Test Run 1

I tried to just call await Isar.initializeCore(download: true) without any manual downloading of libs. I got the following error:


error in test setup: Bad state: There is no current invoker. Please make sure that you are making the call inside a test zone., #0      _currentInvoker (package:test_api/src/scaffolding/utils.dart:49:6)
#1      printOnFailure (package:test_api/src/scaffolding/utils.dart:37:3)
#2      _MockHttpOverrides.createHttpClient (package:flutter_test/src/_binding_io.dart:76:20)
#3      new HttpClient (dart:_http:1288:22)
#4      _downloadIsarCore (package:isar/src/native/isar_core.dart:141:25)
<asynchronous suspension>
#5      initializeCoreBinary.<anonymous closure> (package:isar/src/native/isar_core.dart:70:53)
<asynchronous suspension>
#6      Isar.initializeIsarCore (package:isar/src/isar.dart:309:5)
<asynchronous suspension>

Test Run 2

I download the macOS dylib file from Release 3.1.6, saved it to the root folder of my project and renamed it to libisar.dylib .

In the unit test i was still running ``await Isar.initializeCore(download: true). All test were running fine!

Test Run 3

I removed the previous libisar.dylib file and and downloaded the Isar MacOS.dylib from Release Version 3.1.6.

In the unit test i was running

 await Isar.initializeIsarCore(download: true, libraries: {
        Abi.macosX64: "Isar MacOS.dylib",
      });

All tests were running fine!

Test Run 3

The same as Run 3, but without download: true Option set.

In the unit test i was running

 await Isar.initializeIsarCore(libraries: {
        Abi.macosX64: "Isar MacOS.dylib",
      });

All tests were running fine!

Conclusion

In my unit tests i am opening the Isar instance in Isolates, which broke on the previous version 3.1.5 with different corruption errors. The Tests with Version 3.1.6 were successful as long as i manually downloaded the dylib file. The automatic download did not work.

Thanks for your great work and support!

xVemu commented 5 months ago

Isar core v3.1.6 isn't available to download through link provided in isar_core.dart. However, version 3.1.5 works perfectly. You can see that 3.1.6 download link returns 404, while 3.1.5 download link returns correct file.

FritzMatthaeus commented 5 months ago

Isar core v3.1.6 isn't available to download through link provided in isar_core.dart. However, version 3.1.5 works perfectly. You can see that 3.1.6 download link returns 404, while 3.1.5 download link returns correct file.

It did not work for me, the last time i tested with v3.1.5. It worked, if i already had the correct dylib file, correctly named, in my root folder. But it did not download it. And i had those corruption errors when running tests with database operations in isolates. These errors are fixed in 3.1.6.

vicenterusso commented 5 months ago

We have 2 problems here

1) From this issue ( https://github.com/isar/isar/issues/1168#issuecomment-1661813440 ), core downloading in tests are broken in v3 since before the fork

2) The download path is pointing to a URL that for some reason did not contains 3.1.6. Maybe @mrclauss could take a look. By the way we are moving the docs site to Github Pages and from next releases, the download path will be moved to another subdomain

mrclauss commented 5 months ago

Yeah, I missed to put the release binaries for 3.1.6 to the new URL. That should work now. (And as @vicenterusso mentioned, the URL will change to github pages in the future)

geoffwc commented 4 months ago

Just updated to 3.1.6 and tests are running fine now. Just need to delete the libisar.dylib after version changes as it doesn't overwrite - probably because there's already a file there. Can't think of a simple way to fix this, if we delete the lib during test setup/teardown it'll cause issues with tests running in parallel. Might need some mechanism for doing a version check of the lib and overwriting if it doesn't match. Anyway this isn't causing me much of an issue

mrclauss commented 4 months ago

Nice to read that it works now. I also saw this when reviewing the source code, that it just checks the presence, not the version, but this might not be trivial to improve...

mrclauss commented 4 months ago

So I'm closing this based on your feedback as fixed in 3.1.6