diff --git a/engine/env.go b/engine/env.go index f63f29e10f..3e292107a7 100644 --- a/engine/env.go +++ b/engine/env.go @@ -199,6 +199,22 @@ func (env *Env) SetAuto(k string, v interface{}) { } } +func changeFloats(v interface{}) interface{} { + switch v := v.(type) { + case float64: + return int(v) + case map[string]interface{}: + for key, val := range v { + v[key] = changeFloats(val) + } + case []interface{}: + for idx, val := range v { + v[idx] = changeFloats(val) + } + } + return v +} + func (env *Env) Encode(dst io.Writer) error { m := make(map[string]interface{}) for k, v := range env.Map() { @@ -207,10 +223,7 @@ func (env *Env) Encode(dst io.Writer) error { // FIXME: we fix-convert float values to int, because // encoding/json decodes integers to float64, but cannot encode them back. // (See http://golang.org/src/pkg/encoding/json/decode.go#L46) - if fval, isFloat := val.(float64); isFloat { - val = int(fval) - } - m[k] = val + m[k] = changeFloats(val) } else { m[k] = v } diff --git a/engine/env_test.go b/engine/env_test.go index 104b0db5bf..f76d879114 100644 --- a/engine/env_test.go +++ b/engine/env_test.go @@ -2,6 +2,7 @@ package engine import ( "bytes" + "encoding/json" "testing" "github.com/dotcloud/docker/pkg/testutils" @@ -269,3 +270,43 @@ func BenchmarkDecode(b *testing.B) { reader.Seek(0, 0) } } + +func TestLongNumbers(t *testing.T) { + type T struct { + TestNum int64 + } + v := T{67108864} + var buf bytes.Buffer + e := &Env{} + e.SetJson("Test", v) + if err := e.Encode(&buf); err != nil { + t.Fatal(err) + } + res := make(map[string]T) + if err := json.Unmarshal(buf.Bytes(), &res); err != nil { + t.Fatal(err) + } + if res["Test"].TestNum != v.TestNum { + t.Fatalf("TestNum %d, expected %d", res["Test"].TestNum, v.TestNum) + } +} + +func TestLongNumbersArray(t *testing.T) { + type T struct { + TestNum []int64 + } + v := T{[]int64{67108864}} + var buf bytes.Buffer + e := &Env{} + e.SetJson("Test", v) + if err := e.Encode(&buf); err != nil { + t.Fatal(err) + } + res := make(map[string]T) + if err := json.Unmarshal(buf.Bytes(), &res); err != nil { + t.Fatal(err) + } + if res["Test"].TestNum[0] != v.TestNum[0] { + t.Fatalf("TestNum %d, expected %d", res["Test"].TestNum, v.TestNum) + } +}