Syncbase: Tests run (and pass*) on Android.

* Caveat 1: The test runner only notices that they pass if the phone is
rooted.  See https://github.com/domokit/mojo/issues/385

* Caveat 2: The tests are currently flakey because of
https://github.com/domokit/mojo/issues/387.  If you see errors about
"!consumer_in_two_phase_read()", ignore and re-run the tests.

This CL also consolodates environment-checks in a single task, and split
"clean" task into "clean" and "veryclean", the later deletes build
artifacts that are unlikely to change often.

Change-Id: I4d9805ac2becd924f7bf98f8cfb62620bc132191
diff --git a/Makefile b/Makefile
index 7937733..f40569e 100644
--- a/Makefile
+++ b/Makefile
@@ -8,31 +8,15 @@
 # Flags for Syncbase service running as Mojo service.
 # See v.io/x/ref/runtime/internal/mojo_util.go for the wonderful magic that
 # makes this work.
-# NOTE(nlacasse): Switch to --alsologtostderr=true to see syncbased logs in
-# mojo_shell stderr.
-# TODO(nlacasse): Passing these values in an environment variable won't work on
-# Android.  Consider passing these values as url params when loading the
-# service.  (Does that work?  Follow up with Mojons.)  Another possilibity is
-# to load the values from a configuration file.
 SYNCBASED_ADDR := 127.0.0.1:4002
-V23_MOJO_FLAGS := --v=5 --alsologtostderr=false --root-dir=/tmp/syncbase_mojo --v23.tcp.address=$(SYNCBASED_ADDR) --v23.permissions.literal={"Admin":{"In":["..."]},"Write":{"In":["..."]},"Read":{"In":["..."]},"Resolve":{"In":["..."]},"Debug":{"In":["..."]}} --v23.credentials=$(V23_ROOT)/experimental/projects/ether/creds
+V23_MOJO_FLAGS := --v=5 --root-dir=/tmp/syncbase_mojo --v23.tcp.address=$(SYNCBASED_ADDR) --v23.permissions.literal={\"Admin\":{\"In\":[\"...\"]},\"Write\":{\"In\":[\"...\"]},\"Read\":{\"In\":[\"...\"]},\"Resolve\":{\"In\":[\"...\"]},\"Debug\":{\"In\":[\"...\"]}}
 
 #MOUNTTABLE_ADDR := 127.0.0.1:4001
 ifdef MOUNTTABLE_ADDR
 	V23_MOJO_FLAGS += --name=syncbase_mojo --v23.namespace.root=/$(MOUNTTABLE_ADDR)
 endif
 
-# Wrap the env var value in single quotes. Note, shell parsing works correctly
-# because the value itself does not contain single quotes.
-V23_MOJO_FLAGS := '$(V23_MOJO_FLAGS)'
-
-ifndef MOJO_DIR
-	$(error MOJO_DIR is not set)
-endif
-
-ifndef V23_ROOT
-	$(error V23_ROOT is not set)
-endif
+GO_BUILD_TAGS := mojo
 
 ifdef ANDROID
 	# Configure compiler and linker for Android.
@@ -41,38 +25,48 @@
 	export GOOS := android
 	export GOARCH := arm
 	export GOARM := 7
+	GO_BUILD_TAGS += android
 
 	ANDROID_NDK := $(V23_ROOT)/third_party/android/ndk-toolchain
 
-	ifeq ($(wildcard $(ANDROID_NDK)),)
-		$(error ERROR: $(ANDROID_NDK) does not exist.  Please install android profile with "v23 profile install android")
-	endif
-
 	export CC := $(ANDROID_NDK)/bin/arm-linux-androideabi-gcc
 	export CXX := $(ANDROID_NDK)/bin/arm-linux-androideabi-g++
 
 	MOJO_ANDROID_FLAGS := --android
 	MOJO_BUILD_DIR := $(MOJO_DIR)/src/out/android_Debug
 	MOJO_SHARED_LIB := $(PWD)/gen/lib/android/libsystem_thunk.a
+	MOJO_SHELL_PATH := $(MOJO_BUILD_DIR)/apks/MojoShell.apk
 
 	ETHER_BUILD_DIR := $(PWD)/gen/mojo/android
 
 	LEVELDB_OUT_DIR := $(PWD)/gen/lib/android/leveldb
 	SNAPPY_OUT_DIR := $(PWD)/gen/lib/android/snappy
+
+	# NOTE(nlacasse): Trying to write to a directory that the app does not have
+	# permission to causes a crash with no stack trace.  Because of this, we
+	# set logtostderr=true to prevent vlog from writing logs to directories we
+	# don't have permissions on.  (Alternatively, we could set --log_dir to a
+	# directory inside APP_HOME_DIR.)  We set syncbase root-dir inside
+	# APP_HOME_DIR for the same reason.
+	APP_HOME_DIR = /data/data/org.chromium.mojo.shell/app_home
+	V23_MOJO_FLAGS += --logtostderr=true --root-dir=$(APP_HOME_DIR)/syncbase_data
 else
 	# Configure compiler and linker for Linux.
 	export GOROOT := $(MOJO_DIR)/src/third_party/go/tool/linux_amd64
 
 	MOJO_BUILD_DIR := $(MOJO_DIR)/src/out/Debug
 	MOJO_SHARED_LIB := $(PWD)/gen/lib/linux_amd64/libsystem_thunk.a
+	MOJO_SHELL_PATH := $(MOJO_BUILD_DIR)/mojo_shell
 
 	ETHER_BUILD_DIR := $(PWD)/gen/mojo/linux_amd64
 
 	LEVELDB_OUT_DIR := $(V23_ROOT)/third_party/cout/linux_amd64/leveldb
 	SNAPPY_OUT_DIR := $(V23_ROOT)/third_party/cout/linux_amd64/snappy
+
+	V23_MOJO_FLAGS += --root-dir=/tmp/syncbase_data
 endif
 
-GOPATH := $(V23_GOPATH):$(MOJO_DIR):$(MOJO_DIR)/third_party/go:$(MOJO_BUILD_DIR)/gen/go:$(PWD)/gen/go
+GOPATH := $(V23_GOPATH):$(MOJO_DIR):$(MOJO_DIR)/third_party/go:$(MOJO_BUILD_DIR)/gen/go:$(PWD)/go:$(PWD)/gen/go
 CGO_CFLAGS := -I$(MOJO_DIR)/src
 CGO_CXXFLAGS := -I$(MOJO_DIR)/src
 CGO_LDFLAGS := -L$(dir $(MOJO_SHARED_LIB)) -lsystem_thunk
@@ -86,19 +80,10 @@
 	--config-alias ETHER_DIR=$(PWD) \
 	--config-alias ETHER_BUILD_DIR=$(ETHER_BUILD_DIR)
 
-ifeq ($(wildcard $(MOJO_BUILD_DIR)),)
-	$(error ERROR: $(MOJO_BUILD_DIR) does not exist.  Please see README.md for instructions on compiling Mojo resources.)
-endif
-
 LEVELDB_SRC_DIR := $(V23_ROOT)/third_party/csrc/leveldb
-ifeq ($(wildcard $(LEVELDB_SRC_DIR)),)
-	$(error ERROR: $(LEVELDB_SRC_DIR) does not exist.  Please install syncbase profile with "v23 profile install syncbase")
-endif
-
 SNAPPY_SRC_DIR := $(V23_ROOT)/third_party/csrc/snappy-1.1.2
-ifeq ($(wildcard $(SNAPPY_SRC_DIR)),)
-	$(error ERROR: $(SNAPPY_SRC_DIR) does not exist.  Please install syncbase profile with "v23 profile install syncbase")
-endif
+
+LDFLAGS := -shared
 
 # Compiles a Go program and links against the Mojo C library.
 # $1 is input filename.
@@ -109,8 +94,8 @@
 	CGO_CFLAGS="$(CGO_CFLAGS)" \
 	CGO_CXXFLAGS="$(CGO_CXXFLAGS)" \
 	CGO_LDFLAGS="$(CGO_LDFLAGS)" \
-	$(GOROOT)/bin/go build -o $2 -tags=mojo -ldflags=-shared -buildmode=c-shared $1
-	rm $(basename $2).h
+	$(GOROOT)/bin/go build -o $2 -tags="$(GO_BUILD_TAGS)" -ldflags="$(LDFLAGS)" -buildmode=c-shared $1
+	rm -f $(basename $2).h
 endef
 
 # Generates go bindings from .mojom file.
@@ -127,7 +112,7 @@
 all: test
 
 # Builds mounttabled, principal, and syncbased.
-bin: $(V23_GO_FILES)
+bin: $(V23_GO_FILES) | env-check
 	v23 go build -a -o $@/mounttabled v.io/x/ref/services/mounttable/mounttabled
 	v23 go build -a -o $@/principal v.io/x/ref/cmd/principal
 	v23 go build -a -o $@/syncbased v.io/syncbase/x/ref/services/syncbase/syncbased
@@ -139,7 +124,7 @@
 	touch $@
 
 # Builds the library that Mojo services must be linked with.
-$(MOJO_SHARED_LIB):
+$(MOJO_SHARED_LIB): | env-check
 	mkdir -p $(dir $@)
 	ar rcs $@ $(MOJO_BUILD_DIR)/obj/mojo/public/platform/native/system.system_thunks.o
 
@@ -147,7 +132,7 @@
 # Builds leveldb library for Android.
 $(LEVELDB_OUT_DIR)/lib/libleveldb.a: export TARGET_OS := OS_ANDROID_CROSSCOMPILE
 $(LEVELDB_OUT_DIR)/lib/libleveldb.a: export PREFIX := $(LEVELDB_OUT_DIR)/lib
-$(LEVELDB_OUT_DIR)/lib/libleveldb.a:
+$(LEVELDB_OUT_DIR)/lib/libleveldb.a: | env-check
 	mkdir -p $(dir $@)
 	cd $(LEVELDB_SRC_DIR) && make clean && make all
 	# Delete the dynamic libraries, to prevent ld from linking leveldb
@@ -155,7 +140,7 @@
 	rm $(LEVELDB_OUT_DIR)/lib/*.so*
 
 # Builds snappy library for Android.
-$(SNAPPY_OUT_DIR)/lib/libsnappy.a:
+$(SNAPPY_OUT_DIR)/lib/libsnappy.a: | env-check
 	mkdir -p $(dir $@)
 	cd $(SNAPPY_SRC_DIR) && make clean && ./configure --prefix=$(SNAPPY_OUT_DIR) --build=x86_64-unknown-linux-gnu --host=arm-linux-androideabi --target=arm-linux-androideabi && make install
 	# Delete the dynamic libraries, to prevent ld from linking snappy
@@ -172,7 +157,7 @@
 
 dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart: mojom/echo.mojom
 dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart: mojom/syncbase.mojom
-dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart:
+dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart: | env-check
 	$(call MOJOM_GEN,$<,dart/lib/gen,dart)
 	# TODO(nlacasse): Figure out why mojom_bindings_generator creates these bad
 	# symlinks on dart files.
@@ -180,17 +165,23 @@
 
 gen/go/src/mojom/echo/echo.mojom.go: mojom/echo.mojom
 gen/go/src/mojom/syncbase/syncbase.mojom.go: mojom/syncbase.mojom
-gen/go/src/mojom/echo/echo.mojom.go gen/go/src/mojom/syncbase/syncbase.mojom.go:
+gen/go/src/mojom/echo/echo.mojom.go gen/go/src/mojom/syncbase/syncbase.mojom.go: | env-check
 	$(call MOJOM_GEN,$<,gen,go)
 	gofmt -w $@
 
-$(ETHER_BUILD_DIR)/echo_server.mojo: $(GO_FILES) $(MOJO_SHARED_LIB) gen/go/src/mojom/echo/echo.mojom.go
+$(ETHER_BUILD_DIR)/echo_server.mojo: $(GO_FILES) $(MOJO_SHARED_LIB) gen/go/src/mojom/echo/echo.mojom.go | env-check
 	$(call MOGO_BUILD,$(PWD)/go/src/echo_server.go,$@)
 
+# TODO(nlacasse): These target-specific variables will affect this task and all
+# pre-requisite tasks.  Luckily none of the prerequisites require that these
+# variables have their original value, so everything works.  Once we have a
+# prereq that requires the original value, we will need to re-work these
+# variables.
 $(ETHER_BUILD_DIR)/syncbase_server.mojo: CGO_CFLAGS += -I$(LEVELDB_SRC_DIR)/include -I$(SNAPPY_SRC_DIR)/include
 $(ETHER_BUILD_DIR)/syncbase_server.mojo: CGO_CXXFLAGS += -I$(LEVELDB_SRC_DIR)/include -I$(SNAPPY_SRC_DIR)/include
 $(ETHER_BUILD_DIR)/syncbase_server.mojo: CGO_LDFLAGS += -lsystem_thunk -L$(LEVELDB_OUT_DIR)/lib -lleveldb -L$(SNAPPY_OUT_DIR)/lib -lsnappy
-$(ETHER_BUILD_DIR)/syncbase_server.mojo: $(GO_FILES) $(V23_GO_FILES) $(MOJO_SHARED_LIB) $(LEVELDB_OUT_DIR)/lib/libleveldb.a $(SNAPPY_OUT_DIR)/lib/libsnappy.a gen/go/src/mojom/syncbase/syncbase.mojom.go
+$(ETHER_BUILD_DIR)/syncbase_server.mojo: LDFLAGS += -X v.io/x/ref/runtime/internal.commandLineFlags '$(V23_MOJO_FLAGS)'
+$(ETHER_BUILD_DIR)/syncbase_server.mojo: $(GO_FILES) $(V23_GO_FILES) $(MOJO_SHARED_LIB) $(LEVELDB_OUT_DIR)/lib/libleveldb.a $(SNAPPY_OUT_DIR)/lib/libsnappy.a gen/go/src/mojom/syncbase/syncbase.mojom.go | env-check
 	$(call MOGO_BUILD,v.io/syncbase/x/ref/services/syncbase/syncbased,$@)
 
 # Formats dart files to follow dart style conventions.
@@ -211,18 +202,51 @@
 	cd dart && pub get
 
 .PHONY: run-syncbase-example
-run-syncbase-example: $(ETHER_BUILD_DIR)/syncbase_server.mojo dart/packages dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart
-	V23_MOJO_FLAGS=$(V23_MOJO_FLAGS) $(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) https://mojo.v.io/syncbase_example.dart
+run-syncbase-example: $(ETHER_BUILD_DIR)/syncbase_server.mojo dart/packages dart/lib/gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart | env-check
+	$(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) https://mojo.v.io/syncbase_example.dart
 
 .PHONY: run-echo-example
-run-echo-example: $(ETHER_BUILD_DIR)/echo_server.mojo dart/packages dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart
+run-echo-example: $(ETHER_BUILD_DIR)/echo_server.mojo dart/packages dart/lib/gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart | env-check
 	$(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) https://mojo.v.io/echo_example.dart
 
+# TODO(nlacasse): The tests are currently flaky due to
+# https://github.com/domokit/mojo/issues/387.  If you see errors about
+# "!consumer_in_two_phase_read()", ignore and re-run the tests.
 .PHONY: test
-test: dart/packages $(ETHER_BUILD_DIR)/echo_server.mojo $(ETHER_BUILD_DIR)/syncbase_server.mojo gen-mojom
-	V23_MOJO_FLAGS=$(V23_MOJO_FLAGS) $(MOJO_DIR)/src/mojo/devtools/common/mojo_test $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) --shell-path $(MOJO_DIR)/src/out/Debug/mojo_shell tests
+test: dart/packages $(ETHER_BUILD_DIR)/echo_server.mojo $(ETHER_BUILD_DIR)/syncbase_server.mojo gen-mojom | env-check
+ifdef ANDROID
+	@echo "NOTE: Running the tests with ANDROID=1 requires a *rooted* Android phone with developer mode enabled connected via USB.  See https://github.com/domokit/mojo/issues/385"
+endif
+	$(MOJO_DIR)/src/mojo/devtools/common/mojo_test $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) --shell-path $(MOJO_SHELL_PATH) tests
+
+.PHONY: env-check
+env-check:
+ifndef MOJO_DIR
+	$(error MOJO_DIR is not set)
+endif
+ifndef V23_ROOT
+	$(error V23_ROOT is not set)
+endif
+ifeq ($(wildcard $(MOJO_BUILD_DIR)),)
+	$(error ERROR: $(MOJO_BUILD_DIR) does not exist.  Please see README.md for instructions on compiling Mojo resources.)
+endif
+ifdef ANDROID
+ifeq ($(wildcard $(ANDROID_NDK)),)
+	$(error ERROR: $(ANDROID_NDK) does not exist.  Please install android profile with "v23 profile install android")
+endif
+ifeq ($(wildcard $(LEVELDB_SRC_DIR)),)
+	$(error ERROR: $(LEVELDB_SRC_DIR) does not exist.  Please install syncbase profile with "v23 profile install syncbase")
+endif
+ifeq ($(wildcard $(SNAPPY_SRC_DIR)),)
+	$(error ERROR: $(SNAPPY_SRC_DIR) does not exist.  Please install syncbase profile with "v23 profile install syncbase")
+endif
+endif
 
 .PHONY: clean
 clean:
+	rm -rf gen/mojo gen/go
+
+.PHONY: veryclean
+veryclean:
 	rm -rf gen
 	rm -rf dart/{lib/gen,packages,.packages,pubspec.lock}
diff --git a/mojoconfig b/mojoconfig
index e8232da..4830855 100644
--- a/mojoconfig
+++ b/mojoconfig
@@ -41,5 +41,11 @@
         ('', ['@{ETHER_BUILD_DIR}', '@{ETHER_DIR}/dart/bin']),
       ],
     },
+    {
+      'host': 'https://test.mojo.v.io',
+      'mappings': [
+        ('', ['@{ETHER_DIR}/dart/test']),
+      ],
+    },
   ],
 }
diff --git a/tests b/tests
index 861c96d..03a494f 100644
--- a/tests
+++ b/tests
@@ -2,12 +2,12 @@
 
 tests = [
 	{
-		"test": "dart/test/echo_test.dart",
+		"test": "https://test.mojo.v.io/echo_test.dart",
 		"type": "dart",
 		"timeout": 10
 	},
 	{
-		"test": "dart/test/syncbase_test.dart",
+		"test": "https://test.mojo.v.io/syncbase_test.dart",
 		"type": "dart",
 		"timeout": 30
 	}