Skip to content

Commit

Permalink
pkg/pillar: make ioBundleError deepcopy-able
Browse files Browse the repository at this point in the history
error types very often have private members that cannot be marshalled
with `json.Marshal`

we fix this by only storing the error type and the error string
(err.Error()) as values in uppercase members of our own ioBundleError type

log output:
```
json Unmarshal in deepCopy: json: cannot unmarshal object into Go struct field IoBundleError.IoBundleList.Error.Errors of type error
```

introduced by d1e13b8

Signed-off-by: Christoph Ostarek <christoph@zededa.com>
(cherry picked from commit 9cc6ca8)
  • Loading branch information
christoph-zededa committed Sep 27, 2024
1 parent 9914b62 commit 505022f
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 61 deletions.
6 changes: 3 additions & 3 deletions pkg/pillar/pubsub/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (pub *PublicationImpl) Publish(key string, item interface{}) error {
pub.log.Fatalf("Publish got a pointer for %s", name)
}
// Perform a deepCopy in case the caller might change a map etc
newItem := deepCopy(pub.log, item)
newItem := DeepCopy(pub.log, item)
if m, ok := pub.km.key.Load(key); ok {
if cmp.Equal(m, newItem) {
pub.log.Tracef("Publish(%s/%s) unchanged\n", name, key)
Expand Down Expand Up @@ -190,7 +190,7 @@ func (pub *PublicationImpl) ClearRestarted() error {
func (pub *PublicationImpl) Get(key string) (interface{}, error) {
m, ok := pub.km.key.Load(key)
if ok {
newIntf := deepCopy(pub.log, m)
newIntf := DeepCopy(pub.log, m)
return newIntf, nil
} else {
name := pub.nameString()
Expand All @@ -203,7 +203,7 @@ func (pub *PublicationImpl) Get(key string) (interface{}, error) {
func (pub *PublicationImpl) GetAll() map[string]interface{} {
result := make(map[string]interface{})
assigner := func(key string, val interface{}) bool {
newVal := deepCopy(pub.log, val)
newVal := DeepCopy(pub.log, val)
result[key] = newVal
return true
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/pillar/pubsub/subscribe.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ func handleModify(ctxArg interface{}, key string, itemcb []byte) {
sub.dump("after handleModify")
}
// Need a copy in case the caller will modify e.g., embedded maps
newItem := deepCopy(sub.log, item)
newItem := DeepCopy(sub.log, item)
if created {
if sub.CreateHandler != nil {
(sub.CreateHandler)(sub.userCtx, key, newItem)
Expand Down
4 changes: 2 additions & 2 deletions pkg/pillar/pubsub/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/lf-edge/eve/pkg/pillar/base"
)

// deepCopy returns the same type as what is passed as input
// DeepCopy returns the same type as what is passed as input
// Warning: only public fields will be exported
// Note why json marshalling is used:
// Type casting and associated type assertions in golang are only
Expand All @@ -24,7 +24,7 @@ import (
// Golang doesn't have support for a deep copy. Once can build it
// oneself using reflect package, but it ends up doing the same thing
// as json encode+decode apart from the exported fields check.
func deepCopy(log *base.LogObject, in interface{}) interface{} {
func DeepCopy(log *base.LogObject, in interface{}) interface{} {
b, err := json.Marshal(in)
if err != nil {
log.Fatal("json Marshal in deepCopy", err)
Expand Down
61 changes: 61 additions & 0 deletions pkg/pillar/pubsub/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2024 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0

package pubsub_test

import (
"fmt"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/lf-edge/eve/pkg/pillar/base"
"github.com/lf-edge/eve/pkg/pillar/pubsub"
"github.com/lf-edge/eve/pkg/pillar/types"
"github.com/sirupsen/logrus"
)

func TestDeepCopyIoBundlError(t *testing.T) {

Check failure on line 18 in pkg/pillar/pubsub/util_test.go

View workflow job for this annotation

GitHub Actions / yetus

golangcilint: Function TestDeepCopyIoBundlError missing the call to method parallel (paralleltest)
logger := logrus.StandardLogger()
log := base.NewSourceLogObject(logger, "test", 1234)

errs := []error{
fmt.Errorf("some error"),
types.ErrOwnParent{},
types.ErrParentAssigngrpMismatch{},
types.ErrEmptyAssigngrpWithParent{},
types.ErrCycleDetected{},
types.ErrIOBundleCollision{
Collisions: []types.IOBundleCollision{{
Phylabel: "phy1",
USBAddr: "usb1",
USBProduct: "usbprod1",
PCILong: "pcilong",
Assigngrp: "assigngrp",
},
},
},
}
iob := types.IoBundle{
Error: types.IOBundleError{
TimeOfError: time.Time{},
},
}

for _, err := range errs {
iob.Error.Append(err)
}
output := pubsub.DeepCopy(log, iob)

t.Logf("copy: %v", output)

for _, err := range errs {
if !iob.Error.HasErrorByType(err) {
t.Fatalf("error %v missing", err)
}
}

if !cmp.Equal(output, iob) {
t.Fatalf("not equal: %s", cmp.Diff(output, iob))
}
}
Loading

0 comments on commit 505022f

Please sign in to comment.