Unverified Commit 876a76b2 authored by 33cn's avatar 33cn Committed by GitHub

Merge pull request #194 from vipwzw/js

support big number
parents 86fae6a8 3fb4cb6d
...@@ -109,4 +109,6 @@ function callcode(context, f, args, loglist) { ...@@ -109,4 +109,6 @@ function callcode(context, f, args, loglist) {
} }
return runobj[funcname](arg) return runobj[funcname](arg)
} }
//Long
!function(t,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define([],i):"object"==typeof exports?exports.Long=i():t.Long=i()}("undefined"!=typeof self?self:this,function(){return function(t){function i(h){if(n[h])return n[h].exports;var e=n[h]={i:h,l:!1,exports:{}};return t[h].call(e.exports,e,e.exports,i),e.l=!0,e.exports}var n={};return i.m=t,i.c=n,i.d=function(t,n,h){i.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:h})},i.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(n,"a",n),n},i.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},i.p="",i(i.s=0)}([function(t,i){function n(t,i,n){this.low=0|t,this.high=0|i,this.unsigned=!!n}function h(t){return!0===(t&&t.__isLong__)}function e(t,i){var n,h,e;return i?(t>>>=0,(e=0<=t&&t<256)&&(h=l[t])?h:(n=r(t,(0|t)<0?-1:0,!0),e&&(l[t]=n),n)):(t|=0,(e=-128<=t&&t<128)&&(h=f[t])?h:(n=r(t,t<0?-1:0,!1),e&&(f[t]=n),n))}function s(t,i){if(isNaN(t))return i?p:m;if(i){if(t<0)return p;if(t>=c)return q}else{if(t<=-w)return _;if(t+1>=w)return E}return t<0?s(-t,i).neg():r(t%d|0,t/d|0,i)}function r(t,i,h){return new n(t,i,h)}function o(t,i,n){if(0===t.length)throw Error("empty string");if("NaN"===t||"Infinity"===t||"+Infinity"===t||"-Infinity"===t)return m;if("number"==typeof i?(n=i,i=!1):i=!!i,(n=n||10)<2||36<n)throw RangeError("radix");var h;if((h=t.indexOf("-"))>0)throw Error("interior hyphen");if(0===h)return o(t.substring(1),i,n).neg();for(var e=s(a(n,8)),r=m,u=0;u<t.length;u+=8){var g=Math.min(8,t.length-u),f=parseInt(t.substring(u,u+g),n);if(g<8){var l=s(a(n,g));r=r.mul(l).add(s(f))}else r=r.mul(e),r=r.add(s(f))}return r.unsigned=i,r}function u(t,i){return"number"==typeof t?s(t,i):"string"==typeof t?o(t,i):r(t.low,t.high,"boolean"==typeof i?i:t.unsigned)}t.exports=n;var g=null;try{g=new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0,97,115,109,1,0,0,0,1,13,2,96,0,1,127,96,4,127,127,127,127,1,127,3,7,6,0,1,1,1,1,1,6,6,1,127,1,65,0,11,7,50,6,3,109,117,108,0,1,5,100,105,118,95,115,0,2,5,100,105,118,95,117,0,3,5,114,101,109,95,115,0,4,5,114,101,109,95,117,0,5,8,103,101,116,95,104,105,103,104,0,0,10,191,1,6,4,0,35,0,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,126,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,127,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,128,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,129,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,130,34,4,66,32,135,167,36,0,32,4,167,11])),{}).exports}catch(t){}n.prototype.__isLong__,Object.defineProperty(n.prototype,"__isLong__",{value:!0}),n.isLong=h;var f={},l={};n.fromInt=e,n.fromNumber=s,n.fromBits=r;var a=Math.pow;n.fromString=o,n.fromValue=u;var d=4294967296,c=d*d,w=c/2,v=e(1<<24),m=e(0);n.ZERO=m;var p=e(0,!0);n.UZERO=p;var y=e(1);n.ONE=y;var b=e(1,!0);n.UONE=b;var N=e(-1);n.NEG_ONE=N;var E=r(-1,2147483647,!1);n.MAX_VALUE=E;var q=r(-1,-1,!0);n.MAX_UNSIGNED_VALUE=q;var _=r(0,-2147483648,!1);n.MIN_VALUE=_;var B=n.prototype;B.toInt=function(){return this.unsigned?this.low>>>0:this.low},B.toNumber=function(){return this.unsigned?(this.high>>>0)*d+(this.low>>>0):this.high*d+(this.low>>>0)},B.toString=function(t){if((t=t||10)<2||36<t)throw RangeError("radix");if(this.isZero())return"0";if(this.isNegative()){if(this.eq(_)){var i=s(t),n=this.div(i),h=n.mul(i).sub(this);return n.toString(t)+h.toInt().toString(t)}return"-"+this.neg().toString(t)}for(var e=s(a(t,6),this.unsigned),r=this,o="";;){var u=r.div(e),g=r.sub(u.mul(e)).toInt()>>>0,f=g.toString(t);if(r=u,r.isZero())return f+o;for(;f.length<6;)f="0"+f;o=""+f+o}},B.getHighBits=function(){return this.high},B.getHighBitsUnsigned=function(){return this.high>>>0},B.getLowBits=function(){return this.low},B.getLowBitsUnsigned=function(){return this.low>>>0},B.getNumBitsAbs=function(){if(this.isNegative())return this.eq(_)?64:this.neg().getNumBitsAbs();for(var t=0!=this.high?this.high:this.low,i=31;i>0&&0==(t&1<<i);i--);return 0!=this.high?i+33:i+1},B.isZero=function(){return 0===this.high&&0===this.low},B.eqz=B.isZero,B.isNegative=function(){return!this.unsigned&&this.high<0},B.isPositive=function(){return this.unsigned||this.high>=0},B.isOdd=function(){return 1==(1&this.low)},B.isEven=function(){return 0==(1&this.low)},B.equals=function(t){return h(t)||(t=u(t)),(this.unsigned===t.unsigned||this.high>>>31!=1||t.high>>>31!=1)&&(this.high===t.high&&this.low===t.low)},B.eq=B.equals,B.notEquals=function(t){return!this.eq(t)},B.neq=B.notEquals,B.ne=B.notEquals,B.lessThan=function(t){return this.comp(t)<0},B.lt=B.lessThan,B.lessThanOrEqual=function(t){return this.comp(t)<=0},B.lte=B.lessThanOrEqual,B.le=B.lessThanOrEqual,B.greaterThan=function(t){return this.comp(t)>0},B.gt=B.greaterThan,B.greaterThanOrEqual=function(t){return this.comp(t)>=0},B.gte=B.greaterThanOrEqual,B.ge=B.greaterThanOrEqual,B.compare=function(t){if(h(t)||(t=u(t)),this.eq(t))return 0;var i=this.isNegative(),n=t.isNegative();return i&&!n?-1:!i&&n?1:this.unsigned?t.high>>>0>this.high>>>0||t.high===this.high&&t.low>>>0>this.low>>>0?-1:1:this.sub(t).isNegative()?-1:1},B.comp=B.compare,B.negate=function(){return!this.unsigned&&this.eq(_)?_:this.not().add(y)},B.neg=B.negate,B.add=function(t){h(t)||(t=u(t));var i=this.high>>>16,n=65535&this.high,e=this.low>>>16,s=65535&this.low,o=t.high>>>16,g=65535&t.high,f=t.low>>>16,l=65535&t.low,a=0,d=0,c=0,w=0;return w+=s+l,c+=w>>>16,w&=65535,c+=e+f,d+=c>>>16,c&=65535,d+=n+g,a+=d>>>16,d&=65535,a+=i+o,a&=65535,r(c<<16|w,a<<16|d,this.unsigned)},B.subtract=function(t){return h(t)||(t=u(t)),this.add(t.neg())},B.sub=B.subtract,B.multiply=function(t){if(this.isZero())return m;if(h(t)||(t=u(t)),g){return r(g.mul(this.low,this.high,t.low,t.high),g.get_high(),this.unsigned)}if(t.isZero())return m;if(this.eq(_))return t.isOdd()?_:m;if(t.eq(_))return this.isOdd()?_:m;if(this.isNegative())return t.isNegative()?this.neg().mul(t.neg()):this.neg().mul(t).neg();if(t.isNegative())return this.mul(t.neg()).neg();if(this.lt(v)&&t.lt(v))return s(this.toNumber()*t.toNumber(),this.unsigned);var i=this.high>>>16,n=65535&this.high,e=this.low>>>16,o=65535&this.low,f=t.high>>>16,l=65535&t.high,a=t.low>>>16,d=65535&t.low,c=0,w=0,p=0,y=0;return y+=o*d,p+=y>>>16,y&=65535,p+=e*d,w+=p>>>16,p&=65535,p+=o*a,w+=p>>>16,p&=65535,w+=n*d,c+=w>>>16,w&=65535,w+=e*a,c+=w>>>16,w&=65535,w+=o*l,c+=w>>>16,w&=65535,c+=i*d+n*a+e*l+o*f,c&=65535,r(p<<16|y,c<<16|w,this.unsigned)},B.mul=B.multiply,B.divide=function(t){if(h(t)||(t=u(t)),t.isZero())throw Error("division by zero");if(g){if(!this.unsigned&&-2147483648===this.high&&-1===t.low&&-1===t.high)return this;return r((this.unsigned?g.div_u:g.div_s)(this.low,this.high,t.low,t.high),g.get_high(),this.unsigned)}if(this.isZero())return this.unsigned?p:m;var i,n,e;if(this.unsigned){if(t.unsigned||(t=t.toUnsigned()),t.gt(this))return p;if(t.gt(this.shru(1)))return b;e=p}else{if(this.eq(_)){if(t.eq(y)||t.eq(N))return _;if(t.eq(_))return y;return i=this.shr(1).div(t).shl(1),i.eq(m)?t.isNegative()?y:N:(n=this.sub(t.mul(i)),e=i.add(n.div(t)))}if(t.eq(_))return this.unsigned?p:m;if(this.isNegative())return t.isNegative()?this.neg().div(t.neg()):this.neg().div(t).neg();if(t.isNegative())return this.div(t.neg()).neg();e=m}for(n=this;n.gte(t);){i=Math.max(1,Math.floor(n.toNumber()/t.toNumber()));for(var o=Math.ceil(Math.log(i)/Math.LN2),f=o<=48?1:a(2,o-48),l=s(i),d=l.mul(t);d.isNegative()||d.gt(n);)i-=f,l=s(i,this.unsigned),d=l.mul(t);l.isZero()&&(l=y),e=e.add(l),n=n.sub(d)}return e},B.div=B.divide,B.modulo=function(t){if(h(t)||(t=u(t)),g){return r((this.unsigned?g.rem_u:g.rem_s)(this.low,this.high,t.low,t.high),g.get_high(),this.unsigned)}return this.sub(this.div(t).mul(t))},B.mod=B.modulo,B.rem=B.modulo,B.not=function(){return r(~this.low,~this.high,this.unsigned)},B.and=function(t){return h(t)||(t=u(t)),r(this.low&t.low,this.high&t.high,this.unsigned)},B.or=function(t){return h(t)||(t=u(t)),r(this.low|t.low,this.high|t.high,this.unsigned)},B.xor=function(t){return h(t)||(t=u(t)),r(this.low^t.low,this.high^t.high,this.unsigned)},B.shiftLeft=function(t){return h(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?r(this.low<<t,this.high<<t|this.low>>>32-t,this.unsigned):r(0,this.low<<t-32,this.unsigned)},B.shl=B.shiftLeft,B.shiftRight=function(t){return h(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?r(this.low>>>t|this.high<<32-t,this.high>>t,this.unsigned):r(this.high>>t-32,this.high>=0?0:-1,this.unsigned)},B.shr=B.shiftRight,B.shiftRightUnsigned=function(t){return h(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?r(this.low>>>t|this.high<<32-t,this.high>>>t,this.unsigned):32===t?r(this.high,0,this.unsigned):r(this.high>>>t-32,0,this.unsigned)},B.shru=B.shiftRightUnsigned,B.shr_u=B.shiftRightUnsigned,B.rotateLeft=function(t){var i;return h(t)&&(t=t.toInt()),0==(t&=63)?this:32===t?r(this.high,this.low,this.unsigned):t<32?(i=32-t,r(this.low<<t|this.high>>>i,this.high<<t|this.low>>>i,this.unsigned)):(t-=32,i=32-t,r(this.high<<t|this.low>>>i,this.low<<t|this.high>>>i,this.unsigned))},B.rotl=B.rotateLeft,B.rotateRight=function(t){var i;return h(t)&&(t=t.toInt()),0==(t&=63)?this:32===t?r(this.high,this.low,this.unsigned):t<32?(i=32-t,r(this.high<<i|this.low>>>t,this.low<<i|this.high>>>t,this.unsigned)):(t-=32,i=32-t,r(this.low<<i|this.high>>>t,this.high<<i|this.low>>>t,this.unsigned))},B.rotr=B.rotateRight,B.toSigned=function(){return this.unsigned?r(this.low,this.high,!1):this},B.toUnsigned=function(){return this.unsigned?this:r(this.low,this.high,!0)},B.toBytes=function(t){return t?this.toBytesLE():this.toBytesBE()},B.toBytesLE=function(){var t=this.high,i=this.low;return[255&i,i>>>8&255,i>>>16&255,i>>>24,255&t,t>>>8&255,t>>>16&255,t>>>24]},B.toBytesBE=function(){var t=this.high,i=this.low;return[t>>>24,t>>>16&255,t>>>8&255,255&t,i>>>24,i>>>16&255,i>>>8&255,255&i]},n.fromBytes=function(t,i,h){return h?n.fromBytesLE(t,i):n.fromBytesBE(t,i)},n.fromBytesLE=function(t,i){return new n(t[0]|t[1]<<8|t[2]<<16|t[3]<<24,t[4]|t[5]<<8|t[6]<<16|t[7]<<24,i)},n.fromBytesBE=function(t,i){return new n(t[4]<<24|t[5]<<16|t[6]<<8|t[7],t[0]<<24|t[1]<<16|t[2]<<8|t[3],i)}}])});
` `
...@@ -8,18 +8,32 @@ import ( ...@@ -8,18 +8,32 @@ import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ptypes "github.com/33cn/plugin/plugin/dapp/js/types" ptypes "github.com/33cn/plugin/plugin/dapp/js/types"
"github.com/33cn/plugin/plugin/dapp/js/types/jsproto" "github.com/33cn/plugin/plugin/dapp/js/types/jsproto"
lru "github.com/hashicorp/golang-lru"
"github.com/robertkrimen/otto" "github.com/robertkrimen/otto"
) )
var driverName = ptypes.JsX var driverName = ptypes.JsX
var basevm *otto.Otto
var codecache *lru.Cache
func init() { func init() {
ety := types.LoadExecutorType(driverName) ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&js{})) ety.InitFuncList(types.ListMethod(&js{}))
basevm = otto.New()
_, err := basevm.Run(callcode)
if err != nil {
panic(err)
}
} }
//Init 插件初始化 //Init 插件初始化
func Init(name string, sub []byte) { func Init(name string, sub []byte) {
//最新的64个code做cache
var err error
codecache, err = lru.New(512)
if err != nil {
panic(err)
}
drivers.Register(GetName(), newjs, 0) drivers.Register(GetName(), newjs, 0)
} }
...@@ -47,21 +61,24 @@ func (u *js) GetDriverName() string { ...@@ -47,21 +61,24 @@ func (u *js) GetDriverName() string {
func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction, func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction,
index int, receiptData *types.ReceiptData) (*otto.Object, error) { index int, receiptData *types.ReceiptData) (*otto.Object, error) {
vm, err := u.createVM(payload.Name, tx, index) if payload.Args != "" {
if err != nil { newjson, err := rewriteJSON([]byte(payload.Args))
return nil, err if err != nil {
return nil, err
}
payload.Args = string(newjson)
} else {
payload.Args = "{}"
} }
db := u.GetStateDB() loglist, err := jslogs(receiptData)
code, err := db.Get(calcCodeKey(payload.Name))
if err != nil { if err != nil {
return nil, err return nil, err
} }
loglist, err := jslogs(receiptData) vm, err := u.createVM(payload.Name, tx, index)
if err != nil { if err != nil {
return nil, err return nil, err
} }
vm.Set("loglist", loglist) vm.Set("loglist", loglist)
vm.Set("code", code)
if prefix == "init" { if prefix == "init" {
vm.Set("f", "init") vm.Set("f", "init")
} else { } else {
...@@ -69,7 +86,7 @@ func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction, ...@@ -69,7 +86,7 @@ func (u *js) callVM(prefix string, payload *jsproto.Call, tx *types.Transaction,
} }
vm.Set("args", payload.Args) vm.Set("args", payload.Args)
callfunc := "callcode(context, f, args, loglist)" callfunc := "callcode(context, f, args, loglist)"
jsvalue, err := vm.Run(callcode + string(code) + "\n" + callfunc) jsvalue, err := vm.Run(callfunc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -186,7 +203,20 @@ func (u *js) createVM(name string, tx *types.Transaction, index int) (*otto.Otto ...@@ -186,7 +203,20 @@ func (u *js) createVM(name string, tx *types.Transaction, index int) (*otto.Otto
if err != nil { if err != nil {
return nil, err return nil, err
} }
vm := otto.New() var vm *otto.Otto
if vmitem, ok := codecache.Get(name); ok {
vm = vmitem.(*otto.Otto).Copy()
} else {
code, err := u.GetStateDB().Get(calcCodeKey(name))
if err != nil {
return nil, err
}
//cache 合约代码部分,不会cache 具体执行
cachevm := basevm.Copy()
cachevm.Run(code)
codecache.Add(name, cachevm)
vm = cachevm.Copy()
}
vm.Set("context", string(data)) vm.Set("context", string(data))
u.getstatedbFunc(vm, name) u.getstatedbFunc(vm, name)
u.getlocaldbFunc(vm, name) u.getlocaldbFunc(vm, name)
......
package executor package executor
import ( import (
"bytes"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"strings"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ptypes "github.com/33cn/plugin/plugin/dapp/js/types" ptypes "github.com/33cn/plugin/plugin/dapp/js/types"
...@@ -107,3 +110,50 @@ func parseKV(data *otto.Object) (kv *types.KeyValue, err error) { ...@@ -107,3 +110,50 @@ func parseKV(data *otto.Object) (kv *types.KeyValue, err error) {
} }
return &types.KeyValue{Key: []byte(key), Value: []byte(value)}, nil return &types.KeyValue{Key: []byte(key), Value: []byte(value)}, nil
} }
func rewriteJSON(data []byte) ([]byte, error) {
dat := make(map[string]interface{})
d := json.NewDecoder(bytes.NewBuffer(data))
d.UseNumber()
if err := d.Decode(&dat); err != nil {
return nil, err
}
dat = rewriteString(dat)
return json.Marshal(dat)
}
func rewriteString(dat map[string]interface{}) map[string]interface{} {
for k, v := range dat {
if n, ok := v.(json.Number); ok {
dat[k] = jssafe(n)
} else if arr, ok := v.([]interface{}); ok {
for i := 0; i < len(arr); i++ {
v := arr[i]
if n, ok := v.(json.Number); ok {
arr[i] = jssafe(n)
}
}
dat[k] = arr
} else if d, ok := v.(map[string]interface{}); ok {
dat[k] = rewriteString(d)
} else {
dat[k] = v
}
}
return dat
}
func jssafe(n json.Number) interface{} {
if strings.Contains(string(n), ".") { //float
return n
}
i, err := n.Int64()
if err != nil {
return n
}
//javascript can not parse
if i >= 9007199254740991 || i <= -9007199254740991 {
return string(n)
}
return n
}
...@@ -2,6 +2,9 @@ package executor ...@@ -2,6 +2,9 @@ package executor
import ( import (
"encoding/json" "encoding/json"
"fmt"
"math"
"runtime"
"strings" "strings"
"testing" "testing"
"time" "time"
...@@ -67,12 +70,15 @@ Query.prototype.hello = function(args) { ...@@ -67,12 +70,15 @@ Query.prototype.hello = function(args) {
} }
` `
func initExec(ldb db.DB, kvdb db.KVDB, t *testing.T) *js { func init() {
Init("js", nil)
}
func initExec(ldb db.DB, kvdb db.KVDB, t assert.TestingT) *js {
e := newjs().(*js) e := newjs().(*js)
e.SetEnv(1, time.Now().Unix(), 1) e.SetEnv(1, time.Now().Unix(), 1)
e.SetLocalDB(kvdb) e.SetLocalDB(kvdb)
e.SetStateDB(kvdb) e.SetStateDB(kvdb)
c, tx := createCodeTx("test", jscode) c, tx := createCodeTx("test", jscode)
receipt, err := e.Exec_Create(c, tx, 0) receipt, err := e.Exec_Create(c, tx, 0)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -158,8 +164,8 @@ func TestCallError(t *testing.T) { ...@@ -158,8 +164,8 @@ func TestCallError(t *testing.T) {
call, tx := callCodeTx("test", "hello", `{hello":"world"}`) call, tx := callCodeTx("test", "hello", `{hello":"world"}`)
_, err := e.callVM("exec", call, tx, 0, nil) _, err := e.callVM("exec", call, tx, 0, nil)
_, ok := err.(*otto.Error) _, ok := err.(*otto.Error)
assert.Equal(t, true, ok) assert.Equal(t, false, ok)
assert.Equal(t, true, strings.Contains(err.Error(), "SyntaxError")) assert.Equal(t, true, strings.Contains(err.Error(), "invalid character 'h'"))
call, tx = callCodeTx("test", "hello", `{"hello":"world"}`) call, tx = callCodeTx("test", "hello", `{"hello":"world"}`)
_, err = e.callVM("hello", call, tx, 0, nil) _, err = e.callVM("hello", call, tx, 0, nil)
...@@ -174,9 +180,81 @@ func TestCallError(t *testing.T) { ...@@ -174,9 +180,81 @@ func TestCallError(t *testing.T) {
assert.Equal(t, true, strings.Contains(err.Error(), ptypes.ErrFuncNotFound.Error())) assert.Equal(t, true, strings.Contains(err.Error(), ptypes.ErrFuncNotFound.Error()))
} }
//数字非常大的数字的处理
func TestBigInt(t *testing.T) {
dir, ldb, kvdb := util.CreateTestDB()
defer util.CloseTestDB(dir, ldb)
e := initExec(ldb, kvdb, t)
//test call error(invalid json input)
s := fmt.Sprintf(`{"balance":%d,"balance1":%d,"balance2":%d,"balance3":%d}`, math.MaxInt64, math.MinInt64, 9007199254740990, -9007199254740990)
call, tx := callCodeTx("test", "hello", s)
data, err := e.callVM("exec", call, tx, 0, nil)
assert.Nil(t, err)
kvs, _, err := parseJsReturn(data)
assert.Nil(t, err)
assert.Equal(t, `{"balance":"9223372036854775807","balance1":"-9223372036854775808","balance2":9007199254740990,"balance3":-9007199254740990}`, string(kvs[0].Value))
}
func BenchmarkBigInt(b *testing.B) {
dir, ldb, kvdb := util.CreateTestDB()
defer util.CloseTestDB(dir, ldb)
e := initExec(ldb, kvdb, b)
//test call error(invalid json input)
s := fmt.Sprintf(`{"balance":%d,"balance1":%d,"balance2":%d,"balance3":%d}`, math.MaxInt64, math.MinInt64, 9007199254740990, -9007199254740990)
call, tx := callCodeTx("test", "hello", s)
b.StartTimer()
for i := 0; i < b.N; i++ {
_, err := e.callVM("exec", call, tx, 0, nil)
assert.Nil(b, err)
}
}
func TestRewriteJSON(t *testing.T) {
s := fmt.Sprintf(`{"balance":%d,"balance1":%d,"balance2":%d,"balance3":%d}`, math.MaxInt64, math.MinInt64, 9007199254740990, -9007199254740990)
quota := fmt.Sprintf(`{"balance":"%d","balance1":"%d","balance2":%d,"balance3":%d}`, math.MaxInt64, math.MinInt64, 9007199254740990, -9007199254740990)
data, err := rewriteJSON([]byte(s))
assert.Nil(t, err)
assert.Equal(t, quota, string(data))
data2 := make(map[string]interface{})
data2["ints"] = []int64{math.MaxInt64, math.MinInt64, 9007199254740990, -9007199254740990, 1, 0}
data2["float"] = []float64{1.1, 1000000000000000000000000000, 10000000000000000}
json1, err := json.Marshal(data2)
assert.Nil(t, err)
//assert.Equal(t, `{"float":[1.1,1100000000000000000000,-1100000000000000000000],"ints":[9223372036854775807,-9223372036854775808,9007199254740990,-9007199254740990,1,0]}`, string(json1))
json2, err := rewriteJSON(json1)
assert.Nil(t, err)
assert.Equal(t, string(json2), `{"float":[1.1,1e+27,"10000000000000000"],"ints":["9223372036854775807","-9223372036854775808",9007199254740990,-9007199254740990,1,0]}`)
}
func TestCalcLocalPrefix(t *testing.T) { func TestCalcLocalPrefix(t *testing.T) {
assert.Equal(t, calcLocalPrefix([]byte("a")), []byte("LODB-a-")) assert.Equal(t, calcLocalPrefix([]byte("a")), []byte("LODB-a-"))
assert.Equal(t, calcStatePrefix([]byte("a")), []byte("mavl-a-")) assert.Equal(t, calcStatePrefix([]byte("a")), []byte("mavl-a-"))
assert.Equal(t, calcCodeKey("a"), []byte("mavl-js-code-a")) assert.Equal(t, calcCodeKey("a"), []byte("mavl-js-code-a"))
assert.Equal(t, calcRollbackKey([]byte("a")), []byte("LODB-js-rollback-a")) assert.Equal(t, calcRollbackKey([]byte("a")), []byte("LODB-js-rollback-a"))
} }
func TestCacheMemUsage(t *testing.T) {
dir, ldb, kvdb := util.CreateTestDB()
defer util.CloseTestDB(dir, ldb)
e := initExec(ldb, kvdb, t)
vm, err := e.createVM("test", nil, 0)
assert.Nil(t, err)
vms := make([]*otto.Otto, 1024)
for i := 0; i < 1024; i++ {
vms[i] = vm.Copy()
}
printMemUsage()
}
func printMemUsage() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
fmt.Printf("\tNumGC = %v\n", m.NumGC)
}
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment