[sledge] Refactor integration test
This CL adds `LedgerTestInstanceProvider` which is used to return
multiple connections to the same Ledger, and the `newSledgeForTesting`
helper.
This CL also tests that connecting to two different Sledge backed by the same
Ledger works.
TEST=fx run-test sledge_integration_tests
Change-Id: Ic05ccb85c23fc7ced874565904ff321231b03f9f
diff --git a/public/dart/sledge/README.md b/public/dart/sledge/README.md
index 003121c..b637a01 100644
--- a/public/dart/sledge/README.md
+++ b/public/dart/sledge/README.md
@@ -124,7 +124,7 @@
```
fx set x64 --product ermine --monolith topaz/packages/all --monolith topaz/packages/tests/all
fx build
-fx shell "run fuchsia-pkg://fuchsia.com/sledge_integration_tests#meta/sledge_integration_tests.cmx"
+fx run-test sledge_integration_tests
```
The results of the tests are visible in the logs:
diff --git a/public/dart/sledge/lib/src/sledge.dart b/public/dart/sledge/lib/src/sledge.dart
index 0d188af..4c76f51 100644
--- a/public/dart/sledge/lib/src/sledge.dart
+++ b/public/dart/sledge/lib/src/sledge.dart
@@ -126,11 +126,9 @@
}
/// Convenience constructor for integration tests.
- factory Sledge.fromLedgerHandle(
- fidl.InterfaceHandle<ledger.Ledger> ledgerHandle,
- [SledgePageId pageId]) {
- return new Sledge._(ledgerHandle, pageId);
- }
+ Sledge.fromLedgerHandle(fidl.InterfaceHandle<ledger.Ledger> ledgerHandle,
+ [SledgePageId pageId])
+ : this._(ledgerHandle, pageId);
/// Closes connection to ledger.
void close() {
diff --git a/public/dart/sledge/test/integration_tests/helpers.dart b/public/dart/sledge/test/integration_tests/helpers.dart
new file mode 100644
index 0000000..507c7dc
--- /dev/null
+++ b/public/dart/sledge/test/integration_tests/helpers.dart
@@ -0,0 +1,65 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:fidl/fidl.dart' as fidl;
+import 'package:fidl_fuchsia_ledger/fidl.dart' as ledger;
+import 'package:fidl_fuchsia_sys/fidl_async.dart'
+ show LaunchInfo, ComponentControllerProxy;
+import 'package:lib.app.dart/app_async.dart' show Services, StartupContext;
+import 'package:sledge/sledge.dart';
+
+/// References a service that provides channels to a unique Ledger instance.
+class LedgerTestInstanceProvider {
+ /// Default constructor.
+ LedgerTestInstanceProvider(this.services, this._controller);
+
+ /// The service providing channels to Ledger.
+ Services services;
+ // Prevents the controller from being GCed, which would result in the service
+ // being closed.
+ // ignore: unused_field
+ ComponentControllerProxy _controller;
+}
+
+/// Returns a new LedgerTestInstanceProvider that creates connections to a
+/// in-memory Ledger.
+Future<LedgerTestInstanceProvider> newLedgerTestInstanceProvider() async {
+ String server =
+ 'fuchsia-pkg://fuchsia.com/ledger_test_instance_provider#meta/ledger_test_instance_provider.cmx';
+ final Services services = new Services();
+ final LaunchInfo launchInfo =
+ new LaunchInfo(url: server, directoryRequest: services.request());
+ final context = new StartupContext.fromStartupInfo();
+ final ComponentControllerProxy controller = new ComponentControllerProxy();
+ await context.launcher.createComponent(launchInfo, controller.ctrl.request());
+ return new LedgerTestInstanceProvider(services, controller);
+}
+
+/// Sledge subclass that makes sure the ComponentControllerProxy does not get GCed.
+class _SledgeForTesting extends Sledge {
+ _SledgeForTesting(fidl.InterfaceHandle<ledger.Ledger> ledgerHandle,
+ SledgePageId pageId, this._controller)
+ : super.fromLedgerHandle(ledgerHandle, pageId);
+ // Prevents the connection to Ledger from being closed.
+ // ignore: unused_field
+ ComponentControllerProxy _controller;
+}
+
+/// Creates a new test Sledge instance backed by an in-memory Ledger provided
+/// by [ledgerInstanceProvider].
+/// If no [ledgerInstanceProvider] is provided, a new provider is created.
+Future<Sledge> newSledgeForTesting(
+ {SledgePageId pageId,
+ LedgerTestInstanceProvider ledgerInstanceProvider}) async {
+ pageId ??= new SledgePageId('');
+ ledgerInstanceProvider ??= await newLedgerTestInstanceProvider();
+ fidl.InterfaceHandle<ledger.Ledger> ledgerHandle =
+ await ledgerInstanceProvider.services
+ .connectToServiceByName<ledger.Ledger>(ledger.Ledger.$serviceName);
+ final sledge = new _SledgeForTesting(
+ ledgerHandle, pageId, ledgerInstanceProvider._controller);
+ return sledge;
+}
diff --git a/public/dart/sledge/test/integration_tests/sledge_integration_test.dart b/public/dart/sledge/test/integration_tests/sledge_integration_test.dart
index 87e97b0..955cfd5 100644
--- a/public/dart/sledge/test/integration_tests/sledge_integration_test.dart
+++ b/public/dart/sledge/test/integration_tests/sledge_integration_test.dart
@@ -2,57 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:async';
-
-import 'package:fidl/fidl.dart';
-import 'package:fidl_fuchsia_ledger/fidl.dart' as ledger;
-import 'package:fidl_fuchsia_sys/fidl_async.dart' show LaunchInfo, ComponentControllerProxy;
-import 'package:lib.app.dart/app_async.dart' show Services, StartupContext;
import 'package:sledge/sledge.dart';
import 'package:test/test.dart';
-class _LedgerTestInstance {
- _LedgerTestInstance(this._componentControllerProxy);
- InterfaceHandle<ledger.Ledger> ledgerHandle;
- // ignore: unused_field
- ComponentControllerProxy _componentControllerProxy;
-}
-
-/// Returns a new in-memory Ledger handle.
-Future<_LedgerTestInstance> getInMemoryLedgerTestInstance() async {
- String server =
- 'fuchsia-pkg://fuchsia.com/ledger_test_instance_provider#meta/ledger_test_instance_provider.cmx';
- final Services services = new Services();
- final LaunchInfo launchInfo =
- new LaunchInfo(url: server, directoryRequest: services.request());
- final context = new StartupContext.fromStartupInfo();
- final ComponentControllerProxy controller = new ComponentControllerProxy();
- await context.launcher.createComponent(launchInfo, controller.ctrl.request());
-
- final ledgerTestInstance = new _LedgerTestInstance(controller)
- ..ledgerHandle = await services.connectToServiceByName<ledger.Ledger>(ledger.Ledger.$serviceName);
- return ledgerTestInstance;
-}
-
-Completer<_LedgerTestInstance> _ledgerTestInstance;
-
-/// Creates a new test Sledge instance backed by an in-memory Ledger.
-Future<Sledge> getTestSledge() async {
- if (_ledgerTestInstance == null) {
- // If the completer has never been created, create it and start the process
- // of obtaining a LedgerTestInstance.
- _ledgerTestInstance = new Completer();
- final futureLedgerTestInstance = getInMemoryLedgerTestInstance();
- _ledgerTestInstance.complete(await futureLedgerTestInstance);
- }
- final ledgerTestInstance = await _ledgerTestInstance.future;
- final sledge = new Sledge.fromLedgerHandle(ledgerTestInstance.ledgerHandle);
- return sledge;
-}
+import 'helpers.dart';
void main() {
test('Save a document', () async {
- final sledge = await getTestSledge();
+ final pageId = new SledgePageId('some page');
+ final ledgerInstanceProvider = await newLedgerTestInstanceProvider();
+ final activeSledge = await newSledgeForTesting(
+ ledgerInstanceProvider: ledgerInstanceProvider, pageId: pageId);
Map<String, BaseType> schemaDescription = <String, BaseType>{
'someInteger': new Integer()
};
@@ -60,16 +20,58 @@
DocumentId id = new DocumentId(schema);
// Store a document in Sledge.
- await sledge.runInTransaction(() async {
+ await activeSledge.runInTransaction(() async {
final List<Document> documents =
- await sledge.getDocuments(new Query(schema));
+ await activeSledge.getDocuments(new Query(schema));
assert(documents.isEmpty);
- assert(await sledge.documentExists(id) == false);
+ assert(await activeSledge.documentExists(id) == false);
- Document doc = await sledge.getDocument(id);
+ Document doc = await activeSledge.getDocument(id);
assert(doc['someInteger'].value == 0);
+
doc['someInteger'].value = 42;
assert(doc['someInteger'].value == 42);
});
+
+ // Verify that the document is present when reading using a separate
+ // Sledge instance.
+ final passiveSledge = await newSledgeForTesting(
+ ledgerInstanceProvider: ledgerInstanceProvider, pageId: pageId);
+ await passiveSledge.runInTransaction(() async {
+ final List<Document> documents =
+ await passiveSledge.getDocuments(new Query(schema));
+ assert(documents.isNotEmpty);
+ assert(await passiveSledge.documentExists(id) == true);
+ Document doc = await passiveSledge.getDocument(id);
+ assert(doc['someInteger'].value == 42);
+ });
+
+ // Verify that the document is not present in a Sledge instance
+ // created with a different page.
+ final unrelatedPageId = new SledgePageId('some other page');
+ final unrelatedSledge = await newSledgeForTesting(
+ ledgerInstanceProvider: ledgerInstanceProvider,
+ pageId: unrelatedPageId);
+ await unrelatedSledge.runInTransaction(() async {
+ final List<Document> documents =
+ await unrelatedSledge.getDocuments(new Query(schema));
+ assert(documents.isEmpty);
+ });
+
+ // Change a document in [activeSledge] and wait until [passiveSledge] gets
+ // the updates.
+ // This tests that Ledger changes are properly propagated by Sledge.
+ await activeSledge.runInTransaction(() async {
+ Document doc = await activeSledge.getDocument(id);
+ doc['someInteger'].value = 43;
+ });
+
+ int someInteger;
+ while (someInteger != 43) {
+ await passiveSledge.runInTransaction(() async {
+ Document doc = await passiveSledge.getDocument(id);
+ someInteger = doc['someInteger'].value;
+ });
+ }
});
}