playground: Fix Javascript tests to use VDL generation.
Added support for Javascript VDL to builder.
Added VDL to pingpong test and fortune example.
Reduced test output verbosity.
Change-Id: If27176d891f478324011bcfba349e316cf2a756c
diff --git a/client/bundles/fortune/ex0_js/server.js b/client/bundles/fortune/ex0_js/server.js
deleted file mode 100644
index 32d9ee9..0000000
--- a/client/bundles/fortune/ex0_js/server.js
+++ /dev/null
@@ -1,90 +0,0 @@
-// index=1
-var veyron = require('veyron');
-var vom = veyron.vom;
-
-/**
- * 1) Implement a simple fortune service
- */
-
-var fortuneService = {
- // List of fortunes
- fortunes: [],
-
- numFortunesServed: 0,
-
- // Gets a random fortune
- getRandomFortune: function(ctx) {
- var numExistingfortunes = this.fortunes.length;
- if(numExistingfortunes === 0) {
- throw new Error('Sorry! No fortune available :(');
- }
- var randomIndex = Math.floor(Math.random() * numExistingfortunes);
- var fortune = this.fortunes[randomIndex];
- this.numFortunesServed++;
- console.info('Serving:', fortune);
- return fortune;
- },
-
- // Adds a new fortune
- addNewFortune: function(ctx, fortune) {
- if(!fortune || fortune.trim() === '') {
- throw new Error('Sorry! Can\'t add empty or null fortune!');
- }
- console.info('Adding:', fortune);
- this.fortunes.push(fortune);
- },
-
- // Describes the fortune service.
- // TODO(alexfandrianto): The correct way to do this is to generate the JS code
- // from the VDL file and inherit from the generated service stub.
- _serviceDescription: {
- methods: [
- {
- name: 'GetRandomFortune',
- outArgs: [
- {
- type: vom.Types.STRING
- }
- ]
- },
- {
- name: 'AddNewFortune',
- inArgs: [
- {
- name: 'fortune',
- type: vom.Types.STRING
- }
- ],
- outArgs: []
- }
- ]
- }
-};
-
-/**
- * 2) Publish the fortune service
- */
-
-// Create a Vanadium runtime using the configuration
-veyron.init().then(function(rt) {
- var server = rt.newServer();
- // Serve the fortune server under a name. Serve returns a Promise object
- server.serve('bakery/cookie/fortune', fortuneService).then(function() {
- console.log('Fortune server serving under: bakery/cookie/fortune');
- }).catch(function(err) {
- console.error('Failed to serve the fortune server because:\n', err);
- process.exit(1);
- });
-}).catch(function(err) {
- console.error('Failed to start the fortune server because:\n', err);
- process.exit(1);
-});
-
-// Let's add a few fortunes to start with
-[
- 'The fortune you seek is in another cookie.',
- 'Everything will now come your way.',
- 'Conquer your fears or they will conquer you.'
-].forEach(function(fortune) {
- fortuneService.addNewFortune(null, fortune);
-});
diff --git a/client/bundles/fortune/ex0_js/client.js b/client/bundles/fortune/ex0_js/src/client/client.js
similarity index 100%
rename from client/bundles/fortune/ex0_js/client.js
rename to client/bundles/fortune/ex0_js/src/client/client.js
diff --git a/client/bundles/fortune/ex0_js/src/fortune/fortune.vdl b/client/bundles/fortune/ex0_js/src/fortune/fortune.vdl
new file mode 100644
index 0000000..e3c3ea8
--- /dev/null
+++ b/client/bundles/fortune/ex0_js/src/fortune/fortune.vdl
@@ -0,0 +1,10 @@
+// index=3
+package fortune
+
+type Fortune interface {
+ // Returns a random fortune.
+ GetRandomFortune() (Fortune string | error)
+
+ // Adds a fortune to the set used by GetRandomFortune().
+ AddNewFortune(Fortune string) error
+}
diff --git a/client/bundles/fortune/ex0_js/src/server/server.js b/client/bundles/fortune/ex0_js/src/server/server.js
new file mode 100644
index 0000000..79822b2
--- /dev/null
+++ b/client/bundles/fortune/ex0_js/src/server/server.js
@@ -0,0 +1,67 @@
+// index=1
+var inherits = require('util').inherits;
+var veyron = require('veyron');
+
+var fortune = require('../fortune/fortune');
+
+/**
+ * 1) Implement a simple fortune service
+ */
+
+function FortuneService() {
+ // List of fortunes
+ this.fortunes = [];
+}
+
+inherits(FortuneService, fortune.Fortune);
+
+// Gets a random fortune
+FortuneService.prototype.GetRandomFortune = function(ctx) {
+ var numExistingfortunes = this.fortunes.length;
+ if(numExistingfortunes === 0) {
+ throw new Error('Sorry! No fortune available :(');
+ }
+ var randomIndex = Math.floor(Math.random() * numExistingfortunes);
+ var fortune = this.fortunes[randomIndex];
+ console.info('Serving:', fortune);
+ return fortune;
+};
+
+// Adds a new fortune
+FortuneService.prototype.AddNewFortune = function(ctx, fortune) {
+ if(!fortune || fortune.trim() === '') {
+ throw new Error('Sorry! Can\'t add empty or null fortune!');
+ }
+ console.info('Adding:', fortune);
+ this.fortunes.push(fortune);
+};
+
+/**
+ * 2) Publish the fortune service
+ */
+
+var fortuneService = new FortuneService();
+
+// Create a Vanadium runtime using the configuration
+veyron.init().then(function(rt) {
+ var server = rt.newServer();
+ // Serve the fortune server under a name. Serve returns a Promise object
+ server.serve('bakery/cookie/fortune', fortuneService).then(function() {
+ console.log('Fortune server serving under: bakery/cookie/fortune');
+ }).catch(function(err) {
+ console.error('Failed to serve the fortune server because:\n', err);
+ process.exit(1);
+ });
+}).catch(function(err) {
+ console.error('Failed to start the fortune server because:\n', err);
+ process.exit(1);
+});
+
+// Let's add a few fortunes to start with
+[
+ 'The fortune you seek is in another cookie.',
+ 'Everything will now come your way.',
+ 'Conquer your fears or they will conquer you.'
+].forEach(function(fortune) {
+ fortuneService.AddNewFortune(null, fortune);
+});
diff --git a/client/test.sh b/client/test.sh
index 3423138..21968c7 100755
--- a/client/test.sh
+++ b/client/test.sh
@@ -27,7 +27,7 @@
for e in $EXAMPLES; do
local d="${PG_BUNDLES_DIR}/${e}"
echo -e "\n\n>>>>> Test ${d}\n\n"
- test_pg_example "${d}" "-v=true --includeServiceOutput=true --runTimeout=5000" || shell_test::fail "${d}: failed to run"
+ test_pg_example "${d}" "-v=true --runTimeout=5000" || shell_test::fail "${d}: failed to run"
# TODO(sadovsky): Make this "clean exit" check more robust.
grep -q "\"Exited cleanly.\"" builder.out || shell_test::fail "${d}: did not exit cleanly"
rm -f builder.out
diff --git a/go/src/playground/builder/main.go b/go/src/playground/builder/main.go
index 12f02bd..8d74d78 100644
--- a/go/src/playground/builder/main.go
+++ b/go/src/playground/builder/main.go
@@ -115,6 +115,8 @@
return nil
}
+// All .go and .vdl files must have paths at least two directories deep,
+// beginning with "src/".
func parseRequest(in io.Reader) (r request, err error) {
debug("Parsing input")
data, err := ioutil.ReadAll(in)
@@ -189,36 +191,58 @@
}
// If compilation failed due to user error (bad input), returns badInput=true
-// and err=nil. Only internal errors return non-nil err.
-func compileFiles(files []*codeFile) (badInput bool, err error) {
- needToCompile := false
+// and cerr=nil. Only internal errors return non-nil cerr.
+func compileFiles(files []*codeFile) (badInput bool, cerr error) {
+ found := make(map[string]bool)
for _, f := range files {
- if f.lang == "vdl" || f.lang == "go" {
- needToCompile = true
- break
- }
+ found[f.lang] = true
}
- if !needToCompile {
- return
+ if !found["go"] && !found["vdl"] {
+ // No need to compile.
+ return false, nil
}
debug("Compiling files")
pwd, err := os.Getwd()
if err != nil {
- return
+ return false, fmt.Errorf("Error getting current directory: %v", err)
+ }
+ srcd := filepath.Join(pwd, "src")
+ if err = os.Chdir(srcd); err != nil {
+ panicOnError(out.Write(event.New("", "stderr", ".go or .vdl files outside src/ directory.")))
+ return true, nil
}
os.Setenv("GOPATH", pwd+":"+os.Getenv("GOPATH"))
os.Setenv("VDLPATH", pwd+":"+os.Getenv("VDLPATH"))
// We set isService=false for compilation because "go install" only produces
// output on error, and we always want clients to see such errors.
- err = makeCmd("<compile>", false, "v23", "go", "install", "./...").Run()
// TODO(ivanpi): We assume *exec.ExitError results from uncompilable input
// files; other cases can result from bugs in playground backend or compiler
// itself.
- if _, ok := err.(*exec.ExitError); ok {
- badInput, err = true, nil
+ if found["js"] && found["vdl"] {
+ debug("Generating VDL for Javascript")
+ err = makeCmd("<compile>", false,
+ "vdl", "generate", "-lang=Javascript", "-js_out_dir="+srcd, "./...").Run()
+ if _, ok := err.(*exec.ExitError); ok {
+ return true, nil
+ } else if err != nil {
+ return false, err
+ }
}
- return
+ if found["go"] {
+ debug("Generating VDL for Go and compiling Go")
+ err = makeCmd("<compile>", false,
+ "v23", "go", "install", "./...").Run()
+ if _, ok := err.(*exec.ExitError); ok {
+ return true, nil
+ } else if err != nil {
+ return false, err
+ }
+ }
+ if err = os.Chdir(pwd); err != nil {
+ return false, fmt.Errorf("Error returning to parent directory: %v", err)
+ }
+ return false, nil
}
func runFiles(files []*codeFile) {
diff --git a/go/src/playground/test.sh b/go/src/playground/test.sh
index 33dc5fe..1e9f197 100755
--- a/go/src/playground/test.sh
+++ b/go/src/playground/test.sh
@@ -18,7 +18,7 @@
cp "${TESTDATA_DIR}/${f}" "${fdir}/"
done
- test_pg_example "${PGBUNDLE_DIR}" "-v=true --includeServiceOutput=true --includeV23Env=true --runTimeout=5000"
+ test_pg_example "${PGBUNDLE_DIR}" "-v=true --includeV23Env=true --runTimeout=5000"
}
main() {
@@ -32,11 +32,11 @@
echo -e "\n\n>>>>> Test as the same principal\n\n"
- test_with_files "src/pingpong/wire.vdl" "src/pong/pong.go" "src/ping/ping.go" || shell_test::fail "line ${LINENO}: basic ping (go -> go)"
+ test_with_files "src/pong/pong.go" "src/ping/ping.go" "src/pingpong/wire.vdl" || shell_test::fail "line ${LINENO}: basic ping (go -> go)"
grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
- test_with_files "src/pong/pong.js" "src/ping/ping.js" || shell_test::fail "line ${LINENO}: basic ping (js -> js)"
+ test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/pingpong/wire.vdl" || shell_test::fail "line ${LINENO}: basic ping (js -> js)"
grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
@@ -54,7 +54,7 @@
grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
- test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/ids/authorized.id" || shell_test::fail "line ${LINENO}: authorized id (js -> js)"
+ test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/pingpong/wire.vdl" "src/ids/authorized.id" || shell_test::fail "line ${LINENO}: authorized id (js -> js)"
grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
@@ -63,7 +63,7 @@
test_with_files "src/pong/pong.go" "src/ping/ping.go" "src/pingpong/wire.vdl" "src/ids/expired.id" || shell_test::fail "line ${LINENO}: expired id (go -> go)"
grep -q "not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded (go -> go)"
- test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/ids/expired.id" || shell_test::fail "line ${LINENO}: expired id (js -> js)"
+ test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/pingpong/wire.vdl" "src/ids/expired.id" || shell_test::fail "line ${LINENO}: expired id (js -> js)"
grep -q "not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded (js -> js)"
echo -e "\n\n>>>>> Test with unauthorized blessings\n\n"
@@ -71,7 +71,7 @@
test_with_files "src/pong/pong.go" "src/ping/ping.go" "src/pingpong/wire.vdl" "src/ids/unauthorized.id" || shell_test::fail "line ${LINENO}: unauthorized id (go -> go)"
grep -q "not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with unauthorized id succeeded (go -> go)"
- test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/ids/unauthorized.id" || shell_test::fail "line ${LINENO}: unauthorized id (js -> js)"
+ test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/pingpong/wire.vdl" "src/ids/unauthorized.id" || shell_test::fail "line ${LINENO}: unauthorized id (js -> js)"
grep -q "not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with unauthorized id succeeded (js -> js)"
shell_test::pass
diff --git a/go/src/playground/testdata/src/pong/pong.js b/go/src/playground/testdata/src/pong/pong.js
index 466423f..5edda64 100644
--- a/go/src/playground/testdata/src/pong/pong.js
+++ b/go/src/playground/testdata/src/pong/pong.js
@@ -1,33 +1,19 @@
+var inherits = require('util').inherits;
var veyron = require('veyron');
-var vom = veyron.vom;
-var pingPongService = {
- ping: function(ctx, msg) {
- console.log('[' + ctx.remoteBlessingStrings + '] ' + msg);
- return 'PONG';
- },
- // TODO(alexfandrianto): The correct way to do this is to generate the JS code
- // from the VDL file and inherit from the generated service stub.
- _serviceDescription: {
- methods: [
- {
- name: 'Ping',
- inArgs: [
- {
- name: 'msg',
- type: vom.Types.STRING
- }
- ],
- outArgs: [
- {
- type: vom.Types.STRING
- }
- ]
- }
- ]
- }
+var pingpong = require('../pingpong/pingpong');
+
+function PingPongService() {}
+
+inherits(PingPongService, pingpong.PingPong);
+
+PingPongService.prototype.Ping = function(ctx, message) {
+ console.log('[' + ctx.remoteBlessingStrings + '] ' + message);
+ return 'PONG';
};
+var pingPongService = new PingPongService();
+
veyron.init(function(err, rt) {
if (err) throw err;