243 lines
6.3 KiB
Go
243 lines
6.3 KiB
Go
|
package jail_test
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/status-im/status-go/geth"
|
||
|
"github.com/status-im/status-go/jail"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
TEST_ADDRESS = "0x89b50b2b26947ccad43accaef76c21d175ad85f4"
|
||
|
CHAT_ID_INIT = "CHAT_ID_INIT_TEST"
|
||
|
CHAT_ID_CALL = "CHAT_ID_CALL_TEST"
|
||
|
CHAT_ID_NON_EXISTENT = "CHAT_IDNON_EXISTENT"
|
||
|
|
||
|
TESTDATA_STATUS_JS = "testdata/status.js"
|
||
|
)
|
||
|
|
||
|
func TestJailUnInited(t *testing.T) {
|
||
|
errorWrapper := func(err error) string {
|
||
|
return `{"error":"` + err.Error() + `"}`
|
||
|
}
|
||
|
|
||
|
expectedError := errorWrapper(jail.ErrInvalidJail)
|
||
|
|
||
|
var jailInstance *jail.Jail
|
||
|
response := jailInstance.Parse(CHAT_ID_CALL, ``)
|
||
|
if response != expectedError {
|
||
|
t.Errorf("error expected, but got: %v", response)
|
||
|
}
|
||
|
|
||
|
response = jailInstance.Call(CHAT_ID_CALL, `["commands", "testCommand"]`, `{"val": 12}`)
|
||
|
if response != expectedError {
|
||
|
t.Errorf("error expected, but got: %v", response)
|
||
|
}
|
||
|
|
||
|
_, err := jailInstance.GetVM(CHAT_ID_CALL)
|
||
|
if err != jail.ErrInvalidJail {
|
||
|
t.Errorf("error expected, but got: %v", err)
|
||
|
}
|
||
|
|
||
|
_, err = jailInstance.ClientRestartWrapper()
|
||
|
if err != jail.ErrInvalidJail {
|
||
|
t.Errorf("error expected, but got: %v", err)
|
||
|
}
|
||
|
|
||
|
// now make sure that if Init is called, then Parse doesn't produce any error
|
||
|
jailInstance = jail.Init(``)
|
||
|
if jailInstance == nil {
|
||
|
t.Error("jail instance shouldn't be nil at this point")
|
||
|
return
|
||
|
}
|
||
|
statusJS := geth.LoadFromFile(TESTDATA_STATUS_JS) + `;
|
||
|
_status_catalog.commands["testCommand"] = function (params) {
|
||
|
return params.val * params.val;
|
||
|
};`
|
||
|
response = jailInstance.Parse(CHAT_ID_CALL, statusJS)
|
||
|
expectedResponse := `{"result": {"commands":{},"responses":{}}}`
|
||
|
if response != expectedResponse {
|
||
|
t.Errorf("unexpected response received: %v", response)
|
||
|
}
|
||
|
|
||
|
// however, we still expect issue voiced if somebody tries to execute code with Call
|
||
|
response = jailInstance.Call(CHAT_ID_CALL, `["commands", "testCommand"]`, `{"val": 12}`)
|
||
|
if response != errorWrapper(geth.ErrInvalidGethNode) {
|
||
|
t.Errorf("error expected, but got: %v", response)
|
||
|
}
|
||
|
|
||
|
// make sure that Call() succeeds when node is started
|
||
|
err = geth.PrepareTestNode()
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
return
|
||
|
}
|
||
|
response = jailInstance.Call(CHAT_ID_CALL, `["commands", "testCommand"]`, `{"val": 12}`)
|
||
|
expectedResponse = `{"result": 144}`
|
||
|
if response != expectedResponse {
|
||
|
t.Errorf("expected response is not returned: expected %s, got %s", expectedResponse, response)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestJailInit(t *testing.T) {
|
||
|
err := geth.PrepareTestNode()
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
initCode := `
|
||
|
var _status_catalog = {
|
||
|
foo: 'bar'
|
||
|
};
|
||
|
`
|
||
|
jailInstance := jail.Init(initCode)
|
||
|
|
||
|
extraCode := `
|
||
|
var extraFunc = function (x) {
|
||
|
return x * x;
|
||
|
};
|
||
|
`
|
||
|
response := jailInstance.Parse(CHAT_ID_INIT, extraCode)
|
||
|
|
||
|
expectedResponse := `{"result": {"foo":"bar"}}`
|
||
|
|
||
|
if !reflect.DeepEqual(expectedResponse, response) {
|
||
|
t.Error("Expected output not returned from jail.Parse()")
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestJailFunctionCall(t *testing.T) {
|
||
|
err := geth.PrepareTestNode()
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
jailInstance := jail.Init("")
|
||
|
|
||
|
// load Status JS and add test command to it
|
||
|
statusJS := geth.LoadFromFile(TESTDATA_STATUS_JS) + `;
|
||
|
_status_catalog.commands["testCommand"] = function (params) {
|
||
|
return params.val * params.val;
|
||
|
};`
|
||
|
jailInstance.Parse(CHAT_ID_CALL, statusJS)
|
||
|
|
||
|
// call with wrong chat id
|
||
|
response := jailInstance.Call(CHAT_ID_NON_EXISTENT, "", "")
|
||
|
expectedError := `{"error":"VM[CHAT_IDNON_EXISTENT] doesn't exist."}`
|
||
|
if response != expectedError {
|
||
|
t.Errorf("expected error is not returned: expected %s, got %s", expectedError, response)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// call extraFunc()
|
||
|
response = jailInstance.Call(CHAT_ID_CALL, `["commands", "testCommand"]`, `{"val": 12}`)
|
||
|
expectedResponse := `{"result": 144}`
|
||
|
if response != expectedResponse {
|
||
|
t.Errorf("expected response is not returned: expected %s, got %s", expectedResponse, response)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestJailRPCSend(t *testing.T) {
|
||
|
err := geth.PrepareTestNode()
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
jailInstance := jail.Init("")
|
||
|
|
||
|
// load Status JS and add test command to it
|
||
|
statusJS := geth.LoadFromFile(TESTDATA_STATUS_JS)
|
||
|
jailInstance.Parse(CHAT_ID_CALL, statusJS)
|
||
|
|
||
|
// obtain VM for a given chat (to send custom JS to jailed version of Send())
|
||
|
vm, err := jailInstance.GetVM(CHAT_ID_CALL)
|
||
|
if err != nil {
|
||
|
t.Errorf("cannot get VM: %v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
_, err = vm.Run(`
|
||
|
var data = {"jsonrpc":"2.0","method":"eth_getBalance","params":["` + TEST_ADDRESS + `", "latest"],"id":1};
|
||
|
var sendResult = web3.currentProvider.send(data)
|
||
|
console.log(JSON.stringify(sendResult))
|
||
|
var sendResult = web3.fromWei(sendResult.result, "ether")
|
||
|
`)
|
||
|
if err != nil {
|
||
|
t.Errorf("cannot run custom code on VM: %v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
value, err := vm.Get("sendResult")
|
||
|
if err != nil {
|
||
|
t.Errorf("cannot obtain result of balance check operation: %v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
balance, err := value.ToFloat()
|
||
|
if err != nil {
|
||
|
t.Errorf("cannot obtain result of balance check operation: %v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if balance < 90 || balance > 100 {
|
||
|
t.Error("wrong balance (there should be lots of test Ether on that account)")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
t.Logf("Balance of %.2f ETH found on '%s' account", balance, TEST_ADDRESS)
|
||
|
}
|
||
|
|
||
|
func TestJailMultipleInitSingletonJail(t *testing.T) {
|
||
|
err := geth.PrepareTestNode()
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
jailInstance1 := jail.Init("")
|
||
|
jailInstance2 := jail.Init("")
|
||
|
jailInstance3 := jail.New()
|
||
|
jailInstance4 := jail.GetInstance()
|
||
|
|
||
|
if !reflect.DeepEqual(jailInstance1, jailInstance2) {
|
||
|
t.Error("singleton property of jail instance is violated")
|
||
|
}
|
||
|
if !reflect.DeepEqual(jailInstance2, jailInstance3) {
|
||
|
t.Error("singleton property of jail instance is violated")
|
||
|
}
|
||
|
if !reflect.DeepEqual(jailInstance3, jailInstance4) {
|
||
|
t.Error("singleton property of jail instance is violated")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestJailGetVM(t *testing.T) {
|
||
|
err := geth.PrepareTestNode()
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
jailInstance := jail.Init("")
|
||
|
|
||
|
expectedError := `VM[` + CHAT_ID_NON_EXISTENT + `] doesn't exist.`
|
||
|
_, err = jailInstance.GetVM(CHAT_ID_NON_EXISTENT)
|
||
|
if err == nil || err.Error() != expectedError {
|
||
|
t.Error("expected error, but call succeeded")
|
||
|
}
|
||
|
|
||
|
// now let's create VM..
|
||
|
jailInstance.Parse(CHAT_ID_CALL, ``)
|
||
|
// ..and see if VM becomes available
|
||
|
_, err = jailInstance.GetVM(CHAT_ID_CALL)
|
||
|
if err != nil {
|
||
|
t.Errorf("unexpected error: %v", err)
|
||
|
}
|
||
|
}
|