Repository: seqsense/aws-iot-device-sdk-go (go)

Issue:
shadow: panic occurs when updating state after get
### Steps to Reproduce
```go
data := map[string]interface{}{
	"foo": "var",
}
err := s.Delete(ctx)
doc, err := s.Report(ctx, data)
doc, err = s.Get(ctx)
doc, err = s.Desire(ctx, data)
```
then panic occurs with the following stack trace.

```
panic: assignment to entry in nil map

goroutine 16 [running]:
github.com/seqsense/aws-iot-device-sdk-go/v5/shadow.updateState(0x0, 0xc00046eae0, 0x10, 0x1ada660)
        /Users/shinichi/workspace/aws-iot-device-sdk-go/shadow/state.go:195 +0x26c
github.com/seqsense/aws-iot-device-sdk-go/v5/shadow.updateStateRaw(0x0, 0xc0000c2040, 0xd, 0x10, 0x0, 0xc00071a000)
        /Users/shinichi/workspace/aws-iot-device-sdk-go/shadow/state.go:159 +0x113
github.com/seqsense/aws-iot-device-sdk-go/v5/shadow.(*ThingDocument).update(0xc0005320a0, 0xc0003fc750, 0xa0, 0x1a644e0)
        /Users/shinichi/workspace/aws-iot-device-sdk-go/shadow/state.go:111 +0x71
github.com/seqsense/aws-iot-device-sdk-go/v5/shadow.(*shadow).updateAccepted(0xc000148af0, 0xc00046ea80)
        /Users/shinichi/workspace/aws-iot-device-sdk-go/shadow/shadow.go:134 +0xc5
github.com/at-wat/mqtt-go.HandlerFunc.Serve(0xc0006987a0, 0xc00046ea80)
        /Users/shinichi/go/pkg/mod/github.com/at-wat/mqtt-go@v0.12.1/mqtt.go:68 +0x30
github.com/at-wat/mqtt-go.(*ServeMux).Serve(0xc000148af0, 0xc00046e9c0)
        /Users/shinichi/go/pkg/mod/github.com/at-wat/mqtt-go@v0.12.1/servemux.go:50 +0x267
github.com/at-wat/mqtt-go.(*ServeMux).Serve(0xc00049c0d0, 0xc00046e870)
        /Users/shinichi/go/pkg/mod/github.com/at-wat/mqtt-go@v0.12.1/servemux.go:50 +0x267
github.com/at-wat/mqtt-go.(*BaseClient).serve(0xc0001c9d90, 0x0, 0xc00051e000)
        /Users/shinichi/go/pkg/mod/github.com/at-wat/mqtt-go@v0.12.1/serve.go:85 +0xbf9
github.com/at-wat/mqtt-go.(*BaseClient).Connect.func1(0xc0001c9d90)
        /Users/shinichi/go/pkg/mod/github.com/at-wat/mqtt-go@v0.12.1/connect.go:121 +0x2f
created by github.com/at-wat/mqtt-go.(*BaseClient).Connect
        /Users/shinichi/go/pkg/mod/github.com/at-wat/mqtt-go@v0.12.1/connect.go:120 +0x193
```

### Your Environment
- v5.0.0-rc2
- macOS 10.15.7
- Go 1.16


Pull request:
shadow: Avoid panic on updateAccepted
Fixes #235 
Currently getAccepted updates Reported, Accepted or Delta to nil when they are empty on Shadow, so that panic due to nil pointer reference occurs [here](https://github.com/seqsense/aws-iot-device-sdk-go/blob/407d38db980ed84290bda35c60e52df3f5e98c0a/shadow/shadow.go#L133) on updateAccepted.

Patch:
diff --git a/shadow/shadow.go b/shadow/shadow.go
index 4c2727a..7dd3c5c 100644
--- a/shadow/shadow.go
+++ b/shadow/shadow.go
@@ -99,7 +99,7 @@ func (s *shadow) handleResponse(r interface{}) {
 }
 
 func (s *shadow) getAccepted(msg *mqtt.Message) {
-	doc := &ThingDocument{}
+	doc := newThingDocument()
 	if err := json.Unmarshal(msg.Payload, doc); err != nil {
 		s.handleError(ioterr.New(err, "unmarshaling thing document"))
 		return
@@ -178,18 +178,7 @@ func New(ctx context.Context, cli awsiotdev.Device, opt ...Option) (Shadow, erro
 		cli:       cli,
 		thingName: cli.ThingName(),
 		opts:      &opts,
-		doc: &ThingDocument{
-			State: ThingState{
-				Desired:  NestedState{},
-				Reported: NestedState{},
-				Delta:    NestedState{},
-			},
-			Metadata: ThingStateMetadata{
-				Desired:  NestedMetadata{},
-				Reported: NestedMetadata{},
-				Delta:    NestedMetadata{},
-			},
-		},
+		doc:       newThingDocument(),
 
 		chResps: make(map[string]chan interface{}),
 	}
diff --git a/shadow/state.go b/shadow/state.go
index 2b31433..1fff495 100644
--- a/shadow/state.go
+++ b/shadow/state.go
@@ -86,6 +86,21 @@ type thingDelta struct {
 	Timestamp int            `json:"timestamp,omitempty"`
 }
 
+func newThingDocument() *ThingDocument {
+	return &ThingDocument{
+		State: ThingState{
+			Desired:  NestedState{},
+			Reported: NestedState{},
+			Delta:    NestedState{},
+		},
+		Metadata: ThingStateMetadata{
+			Desired:  NestedMetadata{},
+			Reported: NestedMetadata{},
+			Delta:    NestedMetadata{},
+		},
+	}
+}
+
 func (s *ThingDocument) update(state *thingDocumentRaw) error {
 	if s.Version > state.Version {
 		// Received an old version; just ignore it.


Test patch:
diff --git a/shadow/shadow_test.go b/shadow/shadow_test.go
index 9aae7a9..0ebefe2 100644
--- a/shadow/shadow_test.go
+++ b/shadow/shadow_test.go
@@ -147,6 +147,9 @@ func TestHandlers(t *testing.T) {
 					State: ThingState{
 						Desired: NestedState{"key": "value_init"},
 					},
+					Metadata: ThingStateMetadata{
+						Delta: NestedMetadata{},
+					},
 					Version:   2,
 					Timestamp: 12345,
 				},
@@ -159,8 +162,14 @@ func TestHandlers(t *testing.T) {
 			}
 			expectedDoc := &ThingDocument{
 				State: ThingState{
-					Desired: NestedState{"key2": "value2"},
-					Delta:   NestedState{"key2": "value2"},
+					Desired:  NestedState{"key2": "value2"},
+					Reported: NestedState{},
+					Delta:    NestedState{"key2": "value2"},
+				},
+				Metadata: ThingStateMetadata{
+					Desired:  NestedMetadata{},
+					Reported: NestedMetadata{},
+					Delta:    NestedMetadata{},
 				},
 				Version:   3,
 				Timestamp: 12346,