Start of actual Syncbase client library.
Dart has restrictions on where imports for a library package can come
from. I had to move the generated dart mojom bindings inside the
dart/lib directory to make it happy.
I got rid of the dart/bin scripts, since they don't make sense for this
repo, and were redundant with the tests in dart/test.
Currently we have two libraries: echo_client and syncbase_client. I did
some refactoring to pull out the common parts of the two. Once we get
rid of echo_client, things will get simpler again.
The only syncbase method I actually implemented is "appExists", and I
wrote a tests that "appExist(foo) == false". This test is currently commented out
(see "tests" file) because we don't have syncbase running in a mojo
service quite yet.
Change-Id: I3b5d04325c2b514b9e55140901094000202fa348
diff --git a/.gitignore b/.gitignore
index cacfb4f..82e486e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,6 @@
# Dart dependencies
/dart/.packages
/dart/.pub
+/dart/lib/gen
/dart/pubspec.lock
/dart/**/packages
diff --git a/Makefile b/Makefile
index f4868f4..bb385e0 100644
--- a/Makefile
+++ b/Makefile
@@ -62,7 +62,7 @@
$(MOJOM_BIN) $1 -d . -o $2 -g $3
endef
-all: run-echo-app
+all: test
# Builds the shared library that Mojo services must be linked with.
$(MOJO_SHARED_LIB):
@@ -76,14 +76,20 @@
# TODO(nlacasse): The echo_client and echo_server are currently used to test
# compilation and mojom binding generation. We should remove them once they
# are no longer needed.
-gen-mojom: gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart gen/go/src/mojom/echo/echo.mojom.go
-gen-mojom: gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart gen/go/src/mojom/syncbase/syncbase.mojom.go
+gen-mojom: dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart gen/go/src/mojom/echo/echo.mojom.go
+gen-mojom: dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart gen/go/src/mojom/syncbase/syncbase.mojom.go
-gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart: mojom/echo.mojom
- $(call MOJOM_GEN,$<,gen,dart)
+dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart: mojom/echo.mojom
+ $(call MOJOM_GEN,$<,dart/lib/gen,dart)
+ # TODO(nlacasse): Figure out why mojom_bindings_generator creates these bad
+ # symlinks on dart files.
+ rm -f dart/lib/gen/mojom/echo.mojom.dart
-gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart: mojom/syncbase.mojom
- $(call MOJOM_GEN,$<,gen,dart)
+dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart: mojom/syncbase.mojom
+ $(call MOJOM_GEN,$<,dart/lib/gen,dart)
+ # TODO(nlacasse): Figure out why mojom_bindings_generator creates these bad
+ # symlinks on dart files.
+ rm -f dart/lib/gen/mojom/syncbase.mojom.dart
gen/go/src/mojom/echo/echo.mojom.go: mojom/echo.mojom
$(call MOJOM_GEN,$<,gen,go)
@@ -108,22 +114,25 @@
# Lint src and test files with dartanalyzer. This takes a few seconds.
.PHONY: dartanalyzer
dartanalyzer: dart/packages gen-mojom
- cd dart && dartanalyzer $(DART_FILES)
+ # TODO(nlacasse): Fix dart mojom binding generator so it does not produce
+ # files that violate dartanalyzer. For now, we use "grep -v" to hide all
+ # warnings from *.mojom.dart files.
+ cd dart && dartanalyzer bin/*.dart lib/*.dart test/*.dart | grep -v '\.mojom\.dart'
# Installs dart dependencies.
dart/packages: dart/pubspec.yaml
cd dart && pub get
-.PHONY: run-echo-app
-run-echo-app: gen/mojo/echo_server.mojo gen-mojom dart/packages
- $(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_FLAGS) -v --enable-multiprocess $(PWD)/dart/bin/echo_client.dart
-
+# TODO(nlacasse): Remove this task and dart/bin/syncbase.dart when the tests
+# are stable enough to reliably test syncbase.
.PHONY: run-syncbase-app
run-syncbase-app: gen/mojo/syncbase_server.mojo gen-mojom dart/packages
- $(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_FLAGS) -v --enable-multiprocess $(PWD)/dart/bin/syncbase_client.dart
+ $(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_FLAGS) -v --enable-multiprocess $(PWD)/dart/bin/syncbase.dart
.PHONY: test
-test: dartanalyzer gen-mojom gen/mojo/echo_server.mojo
+test: dart/packages gen-mojom gen/mojo/echo_server.mojo
+ # TODO(nlacasse): These tests sometimes hang. I suspect some connection is
+ # not getting closed properly. More debugging is necessary.
# TODO(nlacasse): We should be passing "--enable-multiprocess" here, since
# that is usually needed for Go Mojo services. However, using that flag
# causes the test runner to crash on exit with "Connection error to the
@@ -134,4 +143,4 @@
.PHONY: clean
clean:
rm -rf gen
- rm -rf dart/{packages,.packages,pubspec.lock}
+ rm -rf dart/{lib/gen,packages,.packages,pubspec.lock}
diff --git a/README.md b/README.md
index a92cc72..6cf1514 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,11 @@
This will run all tests listed in the `tests` file in the root directory of
this repo.
+The following command will run a single test file. This is useful when the
+full test suite hangs with no output.
+
+ $(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_FLAGS) -v --shell-path $(MOJO_DIR)/src/out/Debug/mojo_shell dart/test/<filename>
+
[architecture proposal]: https://docs.google.com/document/d/1TyxPYIhj9VBCtY7eAXu_MEV9y0dtRx7n7UY4jm76Qq4/edit
[depot tools]: http://www.chromium.org/developers/how-tos/install-depot-tools
[goma]: https://sites.google.com/a/google.com/goma/how-to-use-goma/how-to-use-goma-for-chrome-team
diff --git a/dart/bin/echo_client.dart b/dart/bin/echo_client.dart
deleted file mode 100644
index bb8aa73..0000000
--- a/dart/bin/echo_client.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-#!mojo mojo:dart_content_handler
-
-import 'dart:async';
-
-// TODO(nlacasse): Use 'show' or 'as' in non-stdlib import statements, per
-// Vanadium Dart convention.
-import 'package:mojo/application.dart';
-import 'package:mojo/core.dart';
-
-import '../../gen/dart-gen/mojom/lib/mojo/echo.mojom.dart' show EchoEchoStringResponseParams, EchoProxy;
-
-class Client extends Application {
- Client.fromHandle(MojoHandle handle) : super.fromHandle(handle);
-
- void initialize(List<String> args, String url) {
- // TODO(nlacasse): This is pretty gross, but there's no good way to get the
- // current directory from within a Mojo app. Dart's Directory.current() is
- // either broken or unsupported. In any case, this will never work on
- // Android, so we should switch to serving these files over http rather
- // than directly from the filesystem.
- String serviceUrl = url.replaceFirst('dart/bin/echo_client.dart', 'gen/mojo/echo_server.mojo');
-
- print('connecting to $serviceUrl');
-
- EchoProxy p = new EchoProxy.unbound();
- connectToService(serviceUrl, p);
-
- print('connected');
-
- String input = 'foobee';
-
- print('calling echoString($input)');
- p.ptr.echoString(input).then((EchoEchoStringResponseParams v) {
- String output = v.value;
- print('got echo result: $output');
-
- assert(input == output);
- print('SUCCESS');
-
- closeApplication();
- });
-
- print('done calling echoString');
- }
-
- Future closeApplication() async {
- await close();
- assert(MojoHandle.reportLeakedHandles());
- }
-}
-
-main(List args) {
- MojoHandle appHandle = new MojoHandle(args[0]);
- new Client.fromHandle(appHandle);
-}
diff --git a/dart/bin/syncbase.dart b/dart/bin/syncbase.dart
new file mode 100644
index 0000000..011997e
--- /dev/null
+++ b/dart/bin/syncbase.dart
@@ -0,0 +1,21 @@
+#!mojo mojo:dart_content_handler
+
+// TODO(nlacasse): Remove this file once the tests are sufficiently reliable to
+// test syncbase connectivity.
+
+import 'package:mojo/core.dart' show MojoHandle;
+
+import '../lib/syncbase_client.dart' show SyncbaseClient;
+
+main(List args) async {
+ MojoHandle handle = new MojoHandle(args[0]);
+
+ // TODO(nlacasse): Switch to serving these files over http rather than
+ // directly from the filesystem, so they can be accessed by Android.
+ String url = args[1].replaceFirst('dart/bin/syncbase.dart', 'gen/mojo/syncbase_server.mojo');
+
+ SyncbaseClient c = new SyncbaseClient(handle, url);
+ await c.connect();
+ bool exists = await c.appExists('foo');
+ print('appExists(foo): $exists');
+}
diff --git a/dart/bin/syncbase_client.dart b/dart/bin/syncbase_client.dart
deleted file mode 100644
index 536c6df..0000000
--- a/dart/bin/syncbase_client.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-#!mojo mojo:dart_content_handler
-
-import 'dart:async';
-
-// TODO(nlacasse): Use 'show' or 'as' in non-stdlib import statements, per
-// Vanadium Dart convention.
-import 'package:mojo/application.dart';
-import 'package:mojo/core.dart';
-
-import '../../gen/dart-gen/mojom/lib/mojo/syncbase.mojom.dart' show SyncbaseProxy;
-
-class Client extends Application {
- Client.fromHandle(MojoHandle handle) : super.fromHandle(handle);
-
- void initialize(List<String> args, String url) {
- // TODO(nlacasse): This is pretty gross, but there's no good way to get the
- // current directory from within a Mojo app. Dart's Directory.current() is
- // either broken or unsupported. In any case, this will never work on
- // Android, so we should switch to serving these files over http rather
- // than directly from the filesystem.
- String serviceUrl = url.replaceFirst('dart/bin/syncbase_client.dart', 'gen/mojo/syncbase_server.mojo');
-
- print('connecting to $serviceUrl');
-
- SyncbaseProxy p = new SyncbaseProxy.unbound();
- connectToService(serviceUrl, p);
-
- print('connected');
-
- closeApplication();
- }
-
- Future closeApplication() async {
- await close();
- assert(MojoHandle.reportLeakedHandles());
- }
-}
-
-main(List args) {
- MojoHandle appHandle = new MojoHandle(args[0]);
- new Client.fromHandle(appHandle);
-}
diff --git a/dart/lib/echo_client.dart b/dart/lib/echo_client.dart
new file mode 100644
index 0000000..df38894
--- /dev/null
+++ b/dart/lib/echo_client.dart
@@ -0,0 +1,29 @@
+library echo_client;
+
+import 'dart:async';
+
+import 'package:mojo/core.dart' show MojoHandle;
+
+import 'gen/dart-gen/mojom/lib/mojo/echo.mojom.dart' as mojom;
+import 'src/client_base.dart' show ClientBase;
+
+class EchoClient extends ClientBase {
+ final mojom.EchoProxy _proxy;
+
+ EchoClient(MojoHandle handle, String url) :
+ _proxy = new mojom.EchoProxy.unbound(),
+ super(handle, url);
+
+ Future connect() {
+ return connectWithProxy(_proxy);
+ }
+
+ Future<String> echo(String s) async {
+ print('calling echoString($s)');
+ mojom.EchoEchoStringResponseParams v = await _proxy.ptr.echoString(s);
+
+ String output = v.value;
+ print('got echo result: $output');
+ return output;
+ }
+}
diff --git a/dart/lib/src/apptest/apptest.dart b/dart/lib/src/apptest/apptest.dart
deleted file mode 100644
index 83303ea..0000000
--- a/dart/lib/src/apptest/apptest.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(nlacasse): This file was copied from
-// $MOJO_DIR/src/mojo/dart/apptest/lib/apptest.dart.
-// The Mojo team has plans to make this library available in Pub. Once they
-// do, we should delete this file, and use the one in Pub.
-
-library apptest;
-
-import 'package:mojo/application.dart';
-import 'package:mojo/core.dart';
-
-// Import and reexport the test package. We are a *.dartzip file designed to
-// be linked into your_apptest.mojo file and are your main entrypoint.
-import 'package:test/test.dart';
-export 'package:test/test.dart';
-
-typedef AppTestFunction(Application app, String url);
-
-// This class is an application that does nothing but tears down the connections
-// between each test.
-class _ConnectionToShellApplication extends Application {
- final List<AppTestFunction> _testFunctions;
-
- _ConnectionToShellApplication.fromHandle(
- MojoHandle handle, this._testFunctions)
- : super.fromHandle(handle);
-
- // Only run the test suite passed in once we have received an initialize()
- // call from the shell. We need to first have a valid connection to the shell
- // so that apptests can connect to other applications.
- void initialize(List<String> args, String url) {
- group('dart_apptests', () {
- setUp(testSetUp);
- tearDown(testTearDown);
- for (var testFunction in _testFunctions) {
- testFunction(this, url);
- }
- });
- // Append a final test to terminate shell connection.
- // TODO(johnmccutchan): Remove this once package 'test' supports a global
- // tearDown callback.
- test('TERMINATE SHELL CONNECTION', () async {
- await close();
- assert(MojoHandle.reportLeakedHandles());
- });
- }
-
- void testSetUp() {
- }
-
- void testTearDown() {
- // Reset any connections between tests.
- resetConnections();
- }
-}
-
-/// The public interface to apptests.
-///
-/// In a dart mojo application, [incomingHandle] is `args[0]`. [testFunctions]
-/// is list of [AppTestFunction]. Each function will be passed the application
-/// and url.
-runAppTests(var incomingHandle, List<AppTestFunction> testFunctions) {
- var appHandle = new MojoHandle(incomingHandle);
- var application =
- new _ConnectionToShellApplication.fromHandle(appHandle, testFunctions);
- /// [Application]'s [initialize] will be called.
-}
diff --git a/dart/lib/src/client_base.dart b/dart/lib/src/client_base.dart
new file mode 100644
index 0000000..3c94c40
--- /dev/null
+++ b/dart/lib/src/client_base.dart
@@ -0,0 +1,47 @@
+import 'dart:async';
+
+// TODO(nlacasse): Once echo_client is gone, make this file (and any other
+// shared dependencies) a "part of" syncbase library so we can use private
+// methods and variables.
+
+import 'package:mojo/application.dart' show Application;
+import 'package:mojo/bindings.dart' show ProxyBase;
+import 'package:mojo/core.dart' show MojoHandle;
+
+// InitializedApplication is an Application with a future 'initialized' that is
+// resolved after the 'initialize' method finishes.
+class InitializedApplication extends Application {
+ final _initializeCompleter = new Completer();
+ Future get initialized => _initializeCompleter.future;
+
+ InitializedApplication.fromHandle(MojoHandle handle) :
+ super.fromHandle(handle);
+
+ void initialize(List<String> args, String url) {
+ _initializeCompleter.complete();
+ }
+}
+
+// ClientBase is the base class for a client that needs to connect to a mojo
+// service.
+// TODO(nlacasse): This class is useful for holding the common parts of
+// echo_client and syncbase_client during this time of rapid change. Once we
+// get rid of echo_client, reconsider if this base class makes sense.
+abstract class ClientBase {
+ final String url;
+ final InitializedApplication _app;
+
+ ClientBase(MojoHandle handle, this.url) :
+ this._app = new InitializedApplication.fromHandle(handle);
+
+ Future connectWithProxy(ProxyBase p) async {
+ await _app.initialized;
+ print('connecting to $url');
+ _app.connectToService(url, p);
+ print('connected');
+ }
+
+ Future close() {
+ return _app.close();
+ }
+}
diff --git a/dart/lib/syncbase_client.dart b/dart/lib/syncbase_client.dart
new file mode 100644
index 0000000..112b708
--- /dev/null
+++ b/dart/lib/syncbase_client.dart
@@ -0,0 +1,31 @@
+library syncbase_client;
+
+import 'dart:async';
+
+import 'package:mojo/core.dart' show MojoHandle;
+
+import 'gen/dart-gen/mojom/lib/mojo/syncbase.mojom.dart' as mojom;
+import 'src/client_base.dart' show ClientBase;
+
+class SyncbaseClient extends ClientBase {
+ final mojom.SyncbaseProxy _proxy;
+
+ SyncbaseClient(MojoHandle handle, String url) :
+ _proxy = new mojom.SyncbaseProxy.unbound(),
+ super(handle, url);
+
+ Future connect() async {
+ return connectWithProxy(_proxy);
+ }
+
+ // TODO(nlacasse): Test this function with working syncbase mojo service.
+ Future<bool> appExists(String name) async {
+ mojom.SyncbaseAppExistsResponseParams v = await _proxy.ptr.appExists(name);
+ if (v.err != null) {
+ throw v.err;
+ }
+ return v.exists;
+ }
+
+ // TODO(nlacasse): Implement more methods here.
+}
diff --git a/dart/test/echo_test.dart b/dart/test/echo_test.dart
index ef6b69b..56be100 100644
--- a/dart/test/echo_test.dart
+++ b/dart/test/echo_test.dart
@@ -2,35 +2,39 @@
import 'dart:async';
-import 'package:mojo/application.dart' show Application;
+import 'package:mojo/core.dart' show MojoHandle;
+import 'package:test/test.dart';
-// TODO(nlacasse): Get this library from Pub once it is available there.
-import '../lib/src/apptest/apptest.dart';
+import '../lib/echo_client.dart' show EchoClient;
-import '../../gen/dart-gen/mojom/lib/mojo/echo.mojom.dart' show EchoEchoStringResponseParams, EchoProxy;
+main(List args) async {
+ // args[0] is the mojo handle.
+ MojoHandle handle = new MojoHandle(args[0]);
-echoTests(Application app, String url) {
- // TODO(nlacasse): This is pretty gross, but there's no good way to get the
- // current directory from within a Mojo app. Dart's Directory.current() is
- // either broken or unsupported. In any case, this will never work on
- // Android, so we should switch to serving these files over http rather
- // than directly from the filesystem.
- String echoServerUrl = url.replaceFirst('dart/test/echo_test.dart', 'gen/mojo/echo_server.mojo');
+ // TODO(nlacasse): Switch to serving these files over http rather than
+ // directly from the filesystem, so they can be accessed by Android.
+ String serviceUrl = 'file://' + args[1].replaceFirst('dart/test/echo_test.dart', 'gen/mojo/echo_server.mojo');
- test('echo returns correct response', () async {
- EchoProxy ep = new EchoProxy.unbound();
- app.connectToService(echoServerUrl, ep);
+ EchoClient c = new EchoClient(handle, serviceUrl);
+ c.connect();
+ test('echo string returns correct response', () {
String input = 'foobee';
- var v = await ep.ptr.echoString(input);
- expect(v.value, equals(input));
-
- await ep.ptr.quit();
- await ep.close();
+ Future<String> got = c.echo(input);
+ expect(got, completion(equals(input)));
});
-}
-Future<int> main(List args) async {
- var exitCode = await runAppTests(args[0], [echoTests]);
- return exitCode;
+ test('echo empty string returns correct response', () {
+ String input = '';
+ Future<String> got = c.echo(input);
+ expect(got, completion(equals(input)));
+ });
+
+ // Append a final test to terminate shell connection.
+ // TODO(nlacasse): Remove this once package 'test' supports a global tearDown
+ // callback. See https://github.com/dart-lang/test/issues/18.
+ test('terminate shell connection', () async {
+ await c.close();
+ expect(MojoHandle.reportLeakedHandles(), isTrue);
+ });
}
diff --git a/dart/test/syncbase_test.dart b/dart/test/syncbase_test.dart
new file mode 100755
index 0000000..3958eac
--- /dev/null
+++ b/dart/test/syncbase_test.dart
@@ -0,0 +1,30 @@
+#!mojo mojo:dart_content_handler
+
+import 'package:mojo/core.dart' show MojoHandle;
+import 'package:test/test.dart';
+
+import '../lib/syncbase_client.dart' show SyncbaseClient;
+
+main(List args) async {
+ // args[0] is the mojo handle.
+ MojoHandle handle = new MojoHandle(args[0]);
+
+ // TODO(nlacasse): Switch to serving these files over http rather than
+ // directly from the filesystem, so they can be accessed by Android.
+ String serviceUrl = 'file://' + args[1].replaceFirst('dart/test/syncbase_test.dart', 'gen/mojo/synbase_server.mojo');
+
+ SyncbaseClient c = new SyncbaseClient(handle, serviceUrl);
+ c.connect();
+
+ test('appExists(foo) should be false', () {
+ expect(c.appExists, completion(isFalse));
+ });
+
+ // Append a final test to terminate shell connection.
+ // TODO(nlacasse): Remove this once package 'test' supports a global tearDown
+ // callback. See https://github.com/dart-lang/test/issues/18.
+ test('terminate shell connection', () async {
+ await c.close();
+ expect(MojoHandle.reportLeakedHandles(), isTrue);
+ });
+}
diff --git a/tests b/tests
index 0f43ea4..5f56e37 100644
--- a/tests
+++ b/tests
@@ -4,5 +4,11 @@
{
"test": "dart/test/echo_test.dart",
"type": "dart"
- }
+ },
+# TODO(nlacasse,sadovsky): Enable these tests once syncbase runs in a mojo
+# service.
+# {
+# "test": "dart/test/syncbase_test.dart",
+# "type": "dart"
+# }
]