veyron/examples/{mdb,todos}: attempt #2 to fix test.sh's

Specific changes:
- Use npm binary from ${VEYRON_ROOT}/environment/cout/node/bin
- Use findunusedport to pick ports
- Use mktemp to generate all file/dir paths

As a side effect, this change addresses most of Asim's remaining comments from https://veyron-review.googlesource.com/3690.

Change-Id: I3a2f2370552282a387c9098d7ad2367b03f501d0
diff --git a/examples/mdb/Makefile b/examples/mdb/Makefile
index d453a6a..c215080 100644
--- a/examples/mdb/Makefile
+++ b/examples/mdb/Makefile
@@ -1,5 +1,5 @@
 build:
-	${VEYRON_ROOT}/veyron/scripts/build/go install veyron/examples/mdb/... veyron/services/mounttable/mounttabled veyron/services/store/stored veyron/tools/identity
+	${VEYRON_ROOT}/veyron/scripts/build/go install veyron/examples/mdb/... veyron/services/mounttable/mounttabled veyron/services/store/stored veyron/tools/findunusedport veyron/tools/identity
 
 run: build
 	./run.sh
diff --git a/examples/mdb/run.sh b/examples/mdb/run.sh
index 7ead48a..295341f 100755
--- a/examples/mdb/run.sh
+++ b/examples/mdb/run.sh
@@ -3,32 +3,43 @@
 set -e
 set -u
 
+# Used by test.sh to get the store viewer port.
+VIEWER_PORT_FILE=""
+if [ $# -eq 1 ]; then
+  VIEWER_PORT_FILE="$1"
+fi
+readonly VIEWER_PORT_FILE
+
 readonly VEYRON_BIN=${VEYRON_ROOT}/veyron/go/bin
-readonly ID_FILE=/var/tmp/id
+
+readonly repo_root=$(git rev-parse --show-toplevel)
+readonly id_file=$(mktemp "${repo_root}/go/tmp.XXXXXXXXXXX")
+readonly db_dir=$(mktemp -d "${repo_root}/go/tmp.XXXXXXXXXXX")
 
 trap onexit INT TERM EXIT
 
 onexit() {
   exec 2>/dev/null
   kill $(jobs -p)
-  rm -rf "${ID_FILE}"
+  rm -rf "${id_file}" "${db_dir}"
 }
 
 # Generate a self-signed identity.
-${VEYRON_BIN}/identity generate > ${ID_FILE}
+${VEYRON_BIN}/identity generate > ${id_file}
 
 # Start the mounttable daemon.
-${VEYRON_BIN}/mounttabled --address=':8100' &
+readonly mt_port=$(${VEYRON_BIN}/findunusedport)
+${VEYRON_BIN}/mounttabled --address=":${mt_port}" &
 
 # Wait for mounttabled to start up.
 sleep 1
 
-export VEYRON_IDENTITY=${ID_FILE}
-export NAMESPACE_ROOT='/127.0.0.1:8100'
+export VEYRON_IDENTITY=${id_file}
+export NAMESPACE_ROOT="/127.0.0.1:${mt_port}"
 
 # Start the store daemon.
-rm -rf /var/tmp/veyron_store.db
-${VEYRON_BIN}/stored &
+readonly viewer_port=$(${VEYRON_BIN}/findunusedport)
+${VEYRON_BIN}/stored --db="${db_dir}" --viewerPort="${viewer_port}" &
 
 # Wait for stored to start up.
 sleep 1
@@ -36,7 +47,11 @@
 # Initialize the store with data and templates.
 ${VEYRON_BIN}/mdb_init --load-all
 
+if [ -n "${VIEWER_PORT_FILE}" ]; then
+  echo "${viewer_port}" > "${VIEWER_PORT_FILE}"
+fi
+
 echo
-echo 'Visit http://localhost:5000 to browse the store.'
-echo 'Hit Ctrl-C to kill all running services.'
+echo "Visit http://localhost:${viewer_port} to browse the store."
+echo "Hit Ctrl-C to kill all running services."
 wait
diff --git a/examples/mdb/test.sh b/examples/mdb/test.sh
index 99a9504..938e260 100755
--- a/examples/mdb/test.sh
+++ b/examples/mdb/test.sh
@@ -34,19 +34,25 @@
 main() {
   cd "${repo_root}/go/src/veyron/examples/mdb"
   make build || fail "line ${LINENO}: failed to build"
-  ./run.sh >/dev/null 2>&1 &
+
+  local -r VIEWER_PORT_FILE="${workdir}/viewer_port.txt"
+  ./run.sh "${VIEWER_PORT_FILE}" >/dev/null 2>&1 &
 
   sleep 5  # Wait for services to warm up.
 
-  local -r URL="http://localhost:5000"
-  local -r FILE="${workdir}/index.html"
+  if [ ! -f "${VIEWER_PORT_FILE}" ]; then
+    fail "line ${LINENO}: failed to get viewer url"
+  fi
+  local VIEWER_PORT
+  VIEWER_PORT=$(cat "${VIEWER_PORT_FILE}")
 
-  curl 2>/dev/null "${URL}" -o "${FILE}" || fail "line ${LINENO}: failed to fetch ${URL}"
+  local -r HTML_FILE="${workdir}/index.html"
+  curl 2>/dev/null "http://localhost:${VIEWER_PORT}" -o "${HTML_FILE}" || fail "line ${LINENO}: failed to fetch ${URL}"
 
-  if grep -q "moviesbox" "${FILE}"; then
+  if grep -q "moviesbox" "${HTML_FILE}"; then
     pass
   else
-    cat ${FILE}
+    cat "${HTML_FILE}"
     fail "line ${LINENO}: fetched page does not meet expectations"
   fi
 }
diff --git a/examples/todos/Makefile b/examples/todos/Makefile
index 95fd02b..cece7f9 100644
--- a/examples/todos/Makefile
+++ b/examples/todos/Makefile
@@ -1,7 +1,7 @@
 # TODO(sadovsky): Eliminate separate {build,run,watch}app rules once everything
 # is wired together.
 
-export PATH := node_modules/.bin:${PATH}
+export PATH := node_modules/.bin:${VEYRON_ROOT}/environment/cout/node/bin:${PATH}
 
 VEYRON_JS_API := ${VEYRON_ROOT}/veyron/javascript/api
 BUNDLE_JS := todos_appd/public/bundle.js
@@ -11,7 +11,7 @@
 	(cd todos_appd && npm install)
 
 buildgo:
-	${VEYRON_ROOT}/veyron/scripts/build/go install veyron/examples/todos/... veyron/services/mounttable/mounttabled veyron/services/store/stored veyron/tools/identity
+	${VEYRON_ROOT}/veyron/scripts/build/go install veyron/examples/todos/... veyron/services/mounttable/mounttabled veyron/services/store/stored veyron/tools/findunusedport veyron/tools/identity
 
 buildapp: node_modules
 	browserify -d todos_appd/browser/*.js -p [minifyify --map bundle.js.map --output ${BUNDLE_JS}.map] -o ${BUNDLE_JS}
diff --git a/examples/todos/run.sh b/examples/todos/run.sh
index a145ff0..f636c38 100755
--- a/examples/todos/run.sh
+++ b/examples/todos/run.sh
@@ -3,32 +3,43 @@
 set -e
 set -u
 
+# Used by test.sh to get the store viewer port.
+VIEWER_PORT_FILE=""
+if [ $# -eq 1 ]; then
+  VIEWER_PORT_FILE="$1"
+fi
+readonly VIEWER_PORT_FILE
+
 readonly VEYRON_BIN=${VEYRON_ROOT}/veyron/go/bin
-readonly ID_FILE=/var/tmp/id
+
+readonly repo_root=$(git rev-parse --show-toplevel)
+readonly id_file=$(mktemp "${repo_root}/go/tmp.XXXXXXXXXXX")
+readonly db_dir=$(mktemp -d "${repo_root}/go/tmp.XXXXXXXXXXX")
 
 trap onexit INT TERM EXIT
 
 onexit() {
   exec 2>/dev/null
   kill $(jobs -p)
-  rm -rf "${ID_FILE}"
+  rm -rf "${id_file}" "${db_dir}"
 }
 
 # Generate a self-signed identity.
-${VEYRON_BIN}/identity generate > ${ID_FILE}
+${VEYRON_BIN}/identity generate > ${id_file}
 
 # Start the mounttable daemon.
-${VEYRON_BIN}/mounttabled --address=':8100' &
+readonly mt_port=$(${VEYRON_BIN}/findunusedport)
+${VEYRON_BIN}/mounttabled --address=":${mt_port}" &
 
 # Wait for mounttabled to start up.
 sleep 1
 
-export VEYRON_IDENTITY=${ID_FILE}
-export NAMESPACE_ROOT='/127.0.0.1:8100'
+export VEYRON_IDENTITY=${id_file}
+export NAMESPACE_ROOT="/127.0.0.1:${mt_port}"
 
 # Start the store daemon.
-rm -rf /var/tmp/veyron_store.db
-${VEYRON_BIN}/stored &
+readonly viewer_port=$(${VEYRON_BIN}/findunusedport)
+${VEYRON_BIN}/stored --db="${db_dir}" --viewerPort="${viewer_port}" &
 
 # Wait for stored to start up.
 sleep 1
@@ -36,7 +47,11 @@
 # Initialize the store with data and templates.
 ${VEYRON_BIN}/todos_init --data-path=todos_init/data.json
 
+if [ -n "${VIEWER_PORT_FILE}" ]; then
+  echo "${viewer_port}" > "${VIEWER_PORT_FILE}"
+fi
+
 echo
-echo 'Visit http://localhost:5000 to browse the store.'
-echo 'Hit Ctrl-C to kill all running services.'
+echo "Visit http://localhost:${viewer_port} to browse the store."
+echo "Hit Ctrl-C to kill all running services."
 wait
diff --git a/examples/todos/test.sh b/examples/todos/test.sh
index 0d6f2f5..d49f52d 100755
--- a/examples/todos/test.sh
+++ b/examples/todos/test.sh
@@ -34,19 +34,25 @@
 main() {
   cd "${repo_root}/go/src/veyron/examples/todos"
   make build || fail "line ${LINENO}: failed to build"
-  ./run.sh >/dev/null 2>&1 &
+
+  local -r VIEWER_PORT_FILE="${workdir}/viewer_port.txt"
+  ./run.sh "${VIEWER_PORT_FILE}" >/dev/null 2>&1 &
 
   sleep 5  # Wait for services to warm up.
 
-  local -r URL="http://localhost:5000"
-  local -r FILE="${workdir}/index.html"
+  if [ ! -f "${VIEWER_PORT_FILE}" ]; then
+    fail "line ${LINENO}: failed to get viewer url"
+  fi
+  local VIEWER_PORT
+  VIEWER_PORT=$(cat "${VIEWER_PORT_FILE}")
 
-  curl 2>/dev/null "${URL}" -o "${FILE}" || fail "line ${LINENO}: failed to fetch ${URL}"
+  local -r HTML_FILE="${workdir}/index.html"
+  curl 2>/dev/null "http://localhost:${VIEWER_PORT}" -o "${HTML_FILE}" || fail "line ${LINENO}: failed to fetch ${URL}"
 
-  if grep -q "/lists" "${FILE}"; then
+  if grep -q "/lists" "${HTML_FILE}"; then
     pass
   else
-    cat ${FILE}
+    cat "${HTML_FILE}"
     fail "line ${LINENO}: fetched page does not meet expectations"
   fi
 }