From b627585f2826938f964cbb5a44b5f710d08bdeee Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 23 Oct 2018 09:47:51 -0700 Subject: [PATCH 1/3] go-ipfs-config: add a Clone function The user must call this before modifying the config. Given that the config contains slices/maps modifications can modified *shared* state, even after dereferencing. --- config/config.go | 16 ++++++++++++++++ config/config_test.go | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 config/config_test.go diff --git a/config/config.go b/config/config.go index 44b700f1141..dc987547951 100644 --- a/config/config.go +++ b/config/config.go @@ -110,3 +110,19 @@ func ToMap(conf *Config) (map[string]interface{}, error) { } return m, nil } + +// Clone copies the config. Use when updating. +func (c *Config) Clone() (*Config, error) { + var newConfig Config + var buf bytes.Buffer + + if err := json.NewEncoder(&buf).Encode(c); err != nil { + return nil, fmt.Errorf("failure to encode config: %s", err) + } + + if err := json.NewDecoder(&buf).Decode(&newConfig); err != nil { + return nil, fmt.Errorf("failure to decode config: %s", err) + } + + return &newConfig, nil +} diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 00000000000..9c82bb2ff1a --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,23 @@ +package config + +import ( + "testing" +) + +func TestClone(t *testing.T) { + c := new(Config) + c.Identity.PeerID = "faketest" + c.API.HTTPHeaders = map[string][]string{"foo": []string{"bar"}} + + newCfg, err := c.Clone() + if err != nil { + t.Fatal(err) + } + if newCfg.Identity.PeerID != c.Identity.PeerID { + t.Fatal("peer ID not preserved") + } + delete(c.API.HTTPHeaders, "foo") + if newCfg.API.HTTPHeaders["foo"][0] != "bar" { + t.Fatal("HTTP headers not preserved") + } +} From 3cd45d889ab0326cbafd6b36c17aa9d81991cea7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 23 Oct 2018 09:49:35 -0700 Subject: [PATCH 2/3] go-ipfs-config: add tests for the "Strings" type (missed in my previous PR) --- config/types_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 config/types_test.go diff --git a/config/types_test.go b/config/types_test.go new file mode 100644 index 00000000000..7523962ae83 --- /dev/null +++ b/config/types_test.go @@ -0,0 +1,53 @@ +package config + +import ( + "encoding/json" + "testing" +) + +func TestOneStrings(t *testing.T) { + out, err := json.Marshal(Strings{"one"}) + if err != nil { + t.Fatal(err) + + } + expected := "\"one\"" + if string(out) != expected { + t.Fatalf("expected %s, got %s", expected, string(out)) + } +} + +func TestNoStrings(t *testing.T) { + out, err := json.Marshal(Strings{}) + if err != nil { + t.Fatal(err) + + } + expected := "null" + if string(out) != expected { + t.Fatalf("expected %s, got %s", expected, string(out)) + } +} + +func TestManyStrings(t *testing.T) { + out, err := json.Marshal(Strings{"one", "two"}) + if err != nil { + t.Fatal(err) + + } + expected := "[\"one\",\"two\"]" + if string(out) != expected { + t.Fatalf("expected %s, got %s", expected, string(out)) + } +} + +func TestFunkyStrings(t *testing.T) { + toParse := " [ \"one\", \"two\" ] " + var s Strings + if err := json.Unmarshal([]byte(toParse), &s); err != nil { + t.Fatal(err) + } + if len(s) != 2 || s[0] != "one" && s[1] != "two" { + t.Fatalf("unexpected result: %v", s) + } +} From e4282bdb7ab3f69d892b1d4e0798b3823e181555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 6 Nov 2018 15:39:53 +0100 Subject: [PATCH 3/3] go-ipfs-config: Add one more test for config.Clone --- config/config_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config/config_test.go b/config/config_test.go index 9c82bb2ff1a..dead06f8a23 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -7,7 +7,7 @@ import ( func TestClone(t *testing.T) { c := new(Config) c.Identity.PeerID = "faketest" - c.API.HTTPHeaders = map[string][]string{"foo": []string{"bar"}} + c.API.HTTPHeaders = map[string][]string{"foo": {"bar"}} newCfg, err := c.Clone() if err != nil { @@ -16,6 +16,12 @@ func TestClone(t *testing.T) { if newCfg.Identity.PeerID != c.Identity.PeerID { t.Fatal("peer ID not preserved") } + + c.API.HTTPHeaders["foo"] = []string{"baz"} + if newCfg.API.HTTPHeaders["foo"][0] != "bar" { + t.Fatal("HTTP headers not preserved") + } + delete(c.API.HTTPHeaders, "foo") if newCfg.API.HTTPHeaders["foo"][0] != "bar" { t.Fatal("HTTP headers not preserved")