使用 Dart::ffi 使用原生函数测试颤振包中的库函数

问题描述

我正在编写一个 Dart 库来使用 Flutter 访问 C 共享对象。

到目前为止,我创建的示例应用程序按预期工作(在某种程度上),但我想包括单元测试,以保持库的稳定性。

详情:

  • 共享对象位于 APP/android/src/main/jniLibs/{abi}/liboqs.so
  • example/lib/main.dart 中的示例应用程序并按预期工作
  • 库在 APP/lib/liboqs_Flutter.dart

图书馆使用

  static final ffi.DynamicLibrary _liboqs = Platform.isAndroid
      ? ffi.DynamicLibrary.open("liboqs.so")
      : ffi.DynamicLibrary.process();

设置库。

但是当我尝试使用 Flutter_test 访问这个库时(例如运行运行静态最终 C 本机函数 OQS_init 的初始化函数 LiboqsFlutter.init(),我得到:

Failed to load "/{HOME DIRECTOR}/liboqs_Flutter/test/liboqs_Flutter_test.dart": Invalid argument(s): Failed to lookup symbol (dlsym(RTLD_DEFAULT,OQS_init): symbol not found)

我知道 Flutter 测试无法访问“主要”资产,但我如何强制通过它,以便正确测试我的代码

这个issue offers two solutions

但我并不完全明白如何让这些对我有用。颤振驱动程序如何帮助我? #2 代码应该添加到测试中还是原始库中并在测试中调用?如果我已经在 main/jniLibs 文件夹中预先构建了共享对象,那么在测试时是否真的需要重建项目?这似乎浪费了很多时间来测试应用程序。

解决方法

在 Android Studio 中进行测试可以通过以下两种方式之一进行。 1) 在手机或模拟器环境中或 2) 在桌面上。我正在构建一个 Flutter 包,所以我有一个在手机上测试的示例,以及一个在我的开发环境(桌面)上测试的 Dart 库。

我正在寻找的配置在桌面上。因此,我需要为我的 (Mac) 环境编译共享对象 (.dylib),将其包含在构建/测试文件夹中,并像这样调用它:

static ffi.DynamicLibrary _open() {
    if (Platform.environment.containsKey('FLUTTER_TEST')) {
      return ffi.DynamicLibrary.open('build/test/{clibrary}.dylib');
    } else {
      return Platform.isAndroid
          ? ffi.DynamicLibrary.open("liboqs.so")
          : ffi.DynamicLibrary.process();
    }
  }

为了完整起见,首先检测操作系统然后提供适当的共享对象文件是有意义的。

这将确保您拥有可用于单元测试的共享对象。

flutter drive 选项出于相同目的使用集成测试。我认为添加一些 hacky 代码比添加另一个仅用于测试的依赖项更好。