js-only: Separate error from out args
Change-Id: I1446168173e3fa4394356cc34527750f3e8f886e
MultiPart: 1/4
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index a472e68..65b9d0a 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -67,7 +67,7 @@
errArgEncoding = verror.Register(pkgPath+".argEncoding", verror.NoRetry, "failed to encode arg #{3}{:4:}")
- errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "expected {3} results, but got {4}")
+ errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "got {3} results, but want {4}")
errResultDecoding = verror.Register(pkgPath+".resultDecoding", verror.NoRetry, "failed to decode result #{3}{:4}")
diff --git a/runtimes/google/testing/mocks/ipc/simple_client.go b/runtimes/google/testing/mocks/ipc/simple_client.go
index 23a6b89..d90ccd7 100644
--- a/runtimes/google/testing/mocks/ipc/simple_client.go
+++ b/runtimes/google/testing/mocks/ipc/simple_client.go
@@ -3,13 +3,14 @@
import (
"errors"
"fmt"
- "reflect"
"sync"
"v.io/core/veyron2/context"
"v.io/core/veyron2/ipc"
"v.io/core/veyron2/security"
+ "v.io/core/veyron2/vdl/valconv"
"v.io/core/veyron2/vlog"
+ "v.io/core/veyron2/vom2"
)
// NewSimpleClient creates a new mocked ipc client where the given map of method name
@@ -51,8 +52,21 @@
return nil, errors.New(fmt.Sprintf("method %s not found", method))
}
+ // Copy the results so that they can be modified without effecting the original.
+ // This must be done via vom encode and decode rather than a direct deep copy because (among other reasons)
+ // reflect-based deep copy on vdl.Type objects will fail because of their private fields. This is not a problem with vom
+ // as it manually creates the type objects. It is also more realistic to use the same mechanism as the ultimate calls.
+ vomBytes, err := vom2.Encode(results)
+ if err != nil {
+ panic(fmt.Sprintf("Error copying value with vom (failed on encode): %v", err))
+ }
+ var copiedResults []interface{}
+ if err := vom2.Decode(vomBytes, &copiedResults); err != nil {
+ panic(fmt.Sprintf("Error copying value with vom (failed on decode): %v", err))
+ }
+
clientCall := mockCall{
- results: results,
+ results: copiedResults,
}
c.Lock()
@@ -92,10 +106,11 @@
}
for ax, res := range resultptrs {
if mc.results[ax] != nil {
- reflect.ValueOf(res).Elem().Set(reflect.ValueOf(mc.results[ax]))
+ if err := valconv.Convert(res, mc.results[ax]); err != nil {
+ panic(fmt.Sprintf("Error converting out argument %#v: %v", mc.results[ax], err))
+ }
}
}
-
return nil
}
diff --git a/runtimes/google/testing/mocks/ipc/simple_client_test.go b/runtimes/google/testing/mocks/ipc/simple_client_test.go
index 0cf23e6..a4bd4f0 100644
--- a/runtimes/google/testing/mocks/ipc/simple_client_test.go
+++ b/runtimes/google/testing/mocks/ipc/simple_client_test.go
@@ -35,7 +35,7 @@
return
}
var resultOne string
- var resultTwo int
+ var resultTwo int64
method1Call.Finish(&resultOne, &resultTwo)
if resultOne != "one" {
t.Errorf(`FinishCall: first result was "%v", want "one"`, resultOne)
@@ -73,21 +73,21 @@
}
type sampleStruct struct {
- name string
+ Name string
}
func TestStructResult(t *testing.T) {
client := NewSimpleClient(map[string][]interface{}{
"foo": []interface{}{
- sampleStruct{name: "bar"},
+ sampleStruct{Name: "bar"},
},
})
ctx := testContext()
call, _ := client.StartCall(ctx, "name/obj", "foo", []interface{}{})
var result sampleStruct
call.Finish(&result)
- if result.name != "bar" {
- t.Errorf(`FinishCall: second result was "%v", want "bar"`, result.name)
+ if result.Name != "bar" {
+ t.Errorf(`FinishCall: second result was "%v", want "bar"`, result.Name)
return
}
}