Skip to content

Commit

Permalink
refactor(js): more elegant JS options marshalling implementation
Browse files Browse the repository at this point in the history
Thanks to @na--'s comments in PR grafana#1151.
  • Loading branch information
Ivan Mirić committed Sep 26, 2019
1 parent 1f5689c commit a3876bc
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 16 deletions.
13 changes: 0 additions & 13 deletions js/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"runtime"

"github.com/loadimpact/k6/lib/consts"
"gopkg.in/guregu/null.v3"

"github.com/dop251/goja"
"github.com/loadimpact/k6/js/common"
Expand Down Expand Up @@ -218,18 +217,6 @@ func (b *Bundle) Instantiate() (bi *BundleInstance, instErr error) {
jsOptionsObj = jsOptions.ToObject(rt)
}
b.Options.ForEachSpecified("json", func(key string, val interface{}) {
switch v := val.(type) {
case null.Bool:
val = v.ValueOrZero()
case null.Float:
val = v.ValueOrZero()
case null.Int:
val = v.ValueOrZero()
case null.String:
val = v.ValueOrZero()
case null.Time:
val = v.ValueOrZero()
}
if err := jsOptionsObj.Set(key, val); err != nil {
instErr = err
}
Expand Down
17 changes: 15 additions & 2 deletions js/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ func TestBundleInstantiate(t *testing.T) {
b, err := getSimpleBundle("/script.js", `
export let options = {
vus: 5,
teardownTimeout: '1s',
};
let val = true;
export default function() { return val; }
Expand Down Expand Up @@ -621,8 +622,20 @@ func TestBundleInstantiate(t *testing.T) {
t.Run("Options", func(t *testing.T) {
// Ensure `options` properties are correctly marshalled
jsOptions := bi.Runtime.Get("options").ToObject(bi.Runtime)
val := jsOptions.Get("vus").Export()
assert.Equal(t, int64(5), val)
vus := jsOptions.Get("vus").Export()
assert.Equal(t, int64(5), vus)
tdt := jsOptions.Get("teardownTimeout").Export()
assert.Equal(t, "1s", tdt)

// Ensure options propagate correctly from outside to the script
optOrig := b.Options.VUs
b.Options.VUs = null.IntFrom(10)
bi2, err := b.Instantiate()
assert.NoError(t, err)
jsOptions = bi2.Runtime.Get("options").ToObject(bi2.Runtime)
vus = jsOptions.Get("vus").Export()
assert.Equal(t, int64(10), vus)
b.Options.VUs = optOrig
})
}

Expand Down
11 changes: 10 additions & 1 deletion lib/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,20 @@ func (o Options) ForEachSpecified(structTag string, callback func(key string, va
for i := 0; i < structType.NumField(); i++ {
fieldType := structType.Field(i)
fieldVal := structVal.Field(i)
value := fieldVal.Interface()

shouldCall := false
switch fieldType.Type.Kind() {
case reflect.Struct:
// Unpack any guregu/null values
shouldCall = fieldVal.FieldByName("Valid").Bool()
valOrZero := fieldVal.MethodByName("ValueOrZero")
if shouldCall && valOrZero.IsValid() {
value = valOrZero.Call([]reflect.Value{})[0].Interface()
if v, ok := value.(types.Duration); ok {
value = v.String()
}
}
case reflect.Slice:
shouldCall = fieldVal.Len() > 0
case reflect.Map:
Expand All @@ -521,7 +530,7 @@ func (o Options) ForEachSpecified(structTag string, callback func(key string, va
key = fieldType.Name
}

callback(key, fieldVal.Interface())
callback(key, value)
}
}
}
10 changes: 10 additions & 0 deletions lib/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,13 @@ func (d NullDuration) MarshalJSON() ([]byte, error) {
}
return d.Duration.MarshalJSON()
}

// ValueOrZero returns the underlying Duration value of d if valid or
// its zero equivalent otherwise. It matches the existing guregu/null API.
func (d NullDuration) ValueOrZero() Duration {
if !d.Valid {
return Duration(0)
}

return d.Duration
}

0 comments on commit a3876bc

Please sign in to comment.