TBR: website: Automated tests for DataFlow and DataModel
code snippets.

Change-Id: Ib528bf1f6d5d21f19f9f9feeec86effda7fe5b57
diff --git a/Makefile b/Makefile
index 1cfaceb..9a28af5 100644
--- a/Makefile
+++ b/Makefile
@@ -104,7 +104,9 @@
 tutJavaFortune = tutorials/java/fortune
 
 syncbaseAndroidQuickstart = syncbase/quickstart
-syncbaseAndroidFirstApp = syncbase/first-app
+syncbaseAndroidFirstApp   = syncbase/first-app
+syncbaseAndroidDataModel  = syncbase/guides/data-model
+syncbaseAndroidDataFlow   = syncbase/guides/data-flow
 
 # Scripts that 'complete' the named tutorials, creating all relevant files
 # (code, credentials, etc.) but skipping ephemeral steps like starting servers,
@@ -384,7 +386,9 @@
 
 depsOneBigSyncbaseAndroidTest = \
 	content/$(syncbaseAndroidQuickstart).md \
-	content/$(syncbaseAndroidFirstApp).md
+	content/$(syncbaseAndroidFirstApp).md \
+	content/$(syncbaseAndroidDataModel).md \
+	content/$(syncbaseAndroidDataFlow).md
 
 .PHONY: test
 test: test-site test-tutorials-core test-tutorials-java test-syncbase-android
diff --git a/content/syncbase/guides/data-flow.md b/content/syncbase/guides/data-flow.md
index 92715ed..0851d6e 100644
--- a/content/syncbase/guides/data-flow.md
+++ b/content/syncbase/guides/data-flow.md
@@ -5,6 +5,30 @@
 toc: true
 = yaml =
 
+{{# helpers.hidden }}
+<!-- @setupEnvironment @test -->
+```
+export PROJECT_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")
+cp -r $JIRI_ROOT/website/tools/android_project_stubs/example/* $PROJECT_DIR
+cat - <<EOF >> $PROJECT_DIR/app/build.gradle
+dependencies {
+  compile 'io.v:syncbase:0.1.4'
+}
+EOF
+cat - <<EOF > $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataFlow.java
+package io.v.syncbase.example;
+import io.v.syncbase.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+public class DataFlow {
+  Database db;
+  class Task {}
+  void main() {
+EOF
+```
+{{/ helpers.hidden }}
+
 # Introduction
 
 Syncbase API is designed to encourage writing reactive applications where the app
@@ -34,38 +58,53 @@
 from. UI actions such as adding new task or deleting one simply do a `put` or
 `delete` on the corresponding collection.
 
-```Java
+<!-- @addWatchHandler @test -->
+```
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataFlow.java
 db.addWatchChangeHandler(new Database.WatchChangeHandler() {
 
-    @Override
-    public void onInitialState(Iterator<WatchChange> values) {
+  @Override
+  public void onInitialState(Iterator<WatchChange> values) {
 
-        // onInitialState is called with all of existing data in Syncbase.
-        // Although the value type is WatchChange, since this is existing
-        // data, there will not be any values with ChangeType == DELETE_CHANGE
-        while(values.hasNext()) {
-            updateState(values.next());
-        }
-
-        // Trigger UI update
+    // onInitialState is called with all of existing data in Syncbase.
+    // Although the value type is WatchChange, since this is existing
+    // data, there will not be any values with ChangeType == DELETE_CHANGE
+    while (values.hasNext()) {
+      updateState(values.next());
     }
 
-    @Override
-    public void onChangeBatch(Iterator<WatchChange> changes) {
+    // Trigger UI update
+  }
 
-        // onChangeBatch is called whenever changes are made to the data.
-        // Changes that are part of the same batch are presented together,
-        // otherwise changes iterator may only contain a single change.
-        while(changes.hasNext()) {
-            updateState(changes.next());
-        }
+  @Override
+  public void onChangeBatch(Iterator<WatchChange> changes) {
 
-        // Trigger UI update
+    // onChangeBatch is called whenever changes are made to the data.
+    // Changes that are part of the same batch are presented together,
+    // otherwise changes iterator may only contain a single change.
+    while (changes.hasNext()) {
+      updateState(changes.next());
     }
-});
 
+    // Trigger UI update
+  }
+}, new Database.AddWatchChangeHandlerOptions());
+EOF
+```
 
-// Modeling our in-memory state as a map of Todolist-Id to a map of (Task-Id, Task)
+{{# helpers.hidden }}
+<!-- @closeMainFunction @test -->
+```
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataFlow.java
+  }
+EOF
+```
+{{/ helpers.hidden }}
+
+Modeling our in-memory state as a map of Todolist-Id to a map of (Task-Id, Task)
+<!-- @updateState @test -->
+```
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataFlow.java
 HashMap<String, Map<String, Task>> state = new HashMap<String, Map<String, Task>>();
 
 // Update the state based on the changes.
@@ -74,21 +113,21 @@
     String collectionId = change.getCollectionId().encode();
     String rowKey = change.getRowKey();
 
-    switch (change.getChangeType()) {
-        case ChangeType.PUT_CHANGE:
-            if(!state.containsKey(collectionId)) {
-                state.put(collectionId, new HashMap<String, Task>());
-            }
-            Task rowValue = change.getValue(Task.class);
-            state.get(collectionId).put(rowKey, rowValue);
-            break;
+    if(change.getChangeType() == WatchChange.ChangeType.PUT) {
 
-        case ChangeType.DELETE_CHANGE:
-            state.get(collectionId).remove(rowKey);
-            break;
+      if(!state.containsKey(collectionId)) {
+        state.put(collectionId, new HashMap<String, Task>());
+      }
+      Task rowValue = (Task)change.getValue();
+      state.get(collectionId).put(rowKey, rowValue);
+
+    } else if(change.getChangeType() == WatchChange.ChangeType.DELETE) {
+
+      state.get(collectionId).remove(rowKey);
+
     }
 }
-
+EOF
 ```
 
 {{# helpers.info }}
@@ -105,4 +144,14 @@
 * Syncbase's Watch method is designed to help build reactive applications.
 * Watch surfaces both local and synced data changes.
 * We recommend using the Watch method to keep an up-to-date in-memory state that
-the UI renders from.
\ No newline at end of file
+the UI renders from.
+
+{{# helpers.hidden }}
+<!-- @compileSnippets_mayTakeMinues @test -->
+```
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataFlow.java
+}
+EOF
+cd $PROJECT_DIR && ./gradlew assembleRelease
+```
+{{/ helpers.hidden }}
\ No newline at end of file
diff --git a/content/syncbase/guides/data-model.md b/content/syncbase/guides/data-model.md
index 5287909..a2aad2a 100644
--- a/content/syncbase/guides/data-model.md
+++ b/content/syncbase/guides/data-model.md
@@ -5,6 +5,29 @@
 toc: true
 = yaml =
 
+{{# helpers.hidden }}
+<!-- @setupEnvironment @test -->
+```
+export PROJECT_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")
+cp -r $JIRI_ROOT/website/tools/android_project_stubs/example/* $PROJECT_DIR
+cat - <<EOF >> $PROJECT_DIR/app/build.gradle
+dependencies {
+  compile 'io.v:syncbase:0.1.4'
+}
+EOF
+cat - <<EOF > $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataModel.java
+package io.v.syncbase.example;
+import io.v.syncbase.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+public class DataModel {
+  Database db;
+  void main() {
+EOF
+```
+{{/ helpers.hidden }}
+
 # Introduction
 Syncbase is a key-value storage system that handles both structured data and
 blobs. The data is organized by the following hierarchy:
@@ -25,13 +48,20 @@
 There is a pre-configured database for each app. `Syncbase.getDatabase()` is
 used to initialize Syncbase and get a reference to the app's database.
 
+<!-- @createDatabase @test -->
 ```
-DatabaseOptions dbOpt = new DatabaseOptions();
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataModel.java
+Syncbase.DatabaseOptions options = new Syncbase.DatabaseOptions();
+// dbOpt.cloudSyncbaseAddress = "<Your Cloud Syncbase Address>";
+// dbOpt.cloudSyncbaseBlessing = "<Your Cloud Syncbase Blessing>";
 
-dbOpt.cloudSyncbaseAddress = "<Your Cloud Syncbase Address>";
-dbOpt.cloudSyncbaseBlessing = "<Your Cloud Syncbase Blessing>";
-
-Database db = Syncbase.getDatabase();
+Syncbase.database(new Syncbase.DatabaseCallback() {
+  @Override
+  public void onSuccess(final Database db) {
+    // Use database to interact with Syncbase.
+  }
+}, options);
+EOF
 ```
 
 Other database options include ability to set the directory where data files
@@ -66,16 +96,19 @@
 restricted to alphanumeric characters plus underscore and can have a maximum
 length of 64 bytes.
 
+<!-- @createCollection @test -->
 ```
-UUID collectionName = Syncbase.getUUID();
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataModel.java
+String collectionName = UUID.randomUUID().toString();
 Collection collection = db.collection(collectionName);
 
-UUID rowKey = Syncbase.getUUID();
+String rowKey = UUID.randomUUID().toString();
 collection.put(rowKey, "myValue");
 
 String myValue = collection.get(rowKey, String.class);
 
 collection.delete(rowKey);
+EOF
 ```
 
 As mentioned earlier, collections are synced across user's devices by default
@@ -113,22 +146,25 @@
 as values and takes case of serialization. POJO classes must have an empty
 constructor.
 
+<!-- @addPojoToCollection @test -->
 ```
-public class MyPojo {
-    String foo;
-    Integer bar;
-    List<MyPojo> baz;
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataModel.java
+class MyPojo {
+  String foo;
+  Integer bar;
+  List<MyPojo> baz;
 
-    public MyPojo() {
-        foo = null;
-        bar = null;
-        baz = Lists.newArrayList();
-    }
+  public MyPojo() {
+    foo = null;
+    bar = null;
+    baz = new ArrayList<MyPojo>();
+  }
 }
 
 MyPojo pojoIn = new MyPojo();
-collection.put('myKey', pojo);
-MyPojo pojoOut = collection.get('myKey', MyPojo.class);
+collection.put("myKey", pojoIn);
+MyPojo pojoOut = collection.get("myKey", MyPojo.class);
+EOF
 ```
 
 {{# helpers.info }}
@@ -209,4 +245,15 @@
 (e.g., stock watchlist) may be shared in read-only mode with other apps.
 There is no sharing between user accounts.
 
-[Design Doc](/syncbase/designdocs/brokerage.html)
\ No newline at end of file
+[Design Doc](/syncbase/designdocs/brokerage.html)
+
+{{# helpers.hidden }}
+<!-- @compileSnippets_mayTakeMinutes @test -->
+```
+cat - <<EOF >> $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/DataModel.java
+  }
+}
+EOF
+cd $PROJECT_DIR && ./gradlew assembleRelease
+```
+{{/ helpers.hidden }}
\ No newline at end of file