Do not mutate original object even temporarily to avoid data races

pull/6/head
Mikhail Mazurskiy 2017-09-01 20:42:43 +10:00
parent 6a845c67f0
commit 483ee1853b
No known key found for this signature in database
GPG Key ID: 93551ECC96E2F568
3 changed files with 32 additions and 4 deletions

View File

@ -10,6 +10,7 @@ go_test(
name = "go_default_test", name = "go_default_test",
srcs = ["unstructured_test.go"], srcs = ["unstructured_test.go"],
library = ":go_default_library", library = ":go_default_library",
deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
) )
go_library( go_library(

View File

@ -702,9 +702,12 @@ func (unstructuredJSONScheme) Encode(obj runtime.Object, w io.Writer) error {
for _, i := range t.Items { for _, i := range t.Items {
items = append(items, i.Object) items = append(items, i.Object)
} }
t.Object["items"] = items listObj := make(map[string]interface{}, len(t.Object)+1)
defer func() { delete(t.Object, "items") }() for k, v := range t.Object { // Make a shallow copy
return json.NewEncoder(w).Encode(t.Object) listObj[k] = v
}
listObj["items"] = items
return json.NewEncoder(w).Encode(listObj)
case *runtime.Unknown: case *runtime.Unknown:
// TODO: Unstructured needs to deal with ContentType. // TODO: Unstructured needs to deal with ContentType.
_, err := w.Write(t.Raw) _, err := w.Write(t.Raw)

View File

@ -16,7 +16,31 @@ limitations under the License.
package unstructured package unstructured
import "testing" import (
"io/ioutil"
"sync"
"testing"
"github.com/stretchr/testify/assert"
)
// TestCodecOfUnstructuredList tests that there are no data races in Encode().
// i.e. that it does not mutate the object being encoded.
func TestCodecOfUnstructuredList(t *testing.T) {
var wg sync.WaitGroup
concurrency := 10
list := UnstructuredList{
Object: map[string]interface{}{},
}
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
defer wg.Done()
assert.NoError(t, UnstructuredJSONScheme.Encode(&list, ioutil.Discard))
}()
}
wg.Wait()
}
func TestUnstructuredList(t *testing.T) { func TestUnstructuredList(t *testing.T) {
list := &UnstructuredList{ list := &UnstructuredList{