Repository: seqsense/aws-iot-device-sdk-go
Pull request #240 (2021-03-19 15:08:32)

fix(deps): update module github.com/aws/aws-sdk-go to v1.38.1
[![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/aws/aws-sdk-go](https://togithub.com/aws/aws-sdk-go) | require | minor | `v1.37.33` -> `v1.38.1` |

---

### Release Notes

<details>
<summary>aws/aws-sdk-go</summary>

### [`v1.38.1`](https://togithub.com/aws/aws-sdk-go/blob/master/CHANGELOG.md#Release-v1381-2021-03-19)

[Compare Source](https://togithub.com/aws/aws-sdk-go/compare/v1.38.0...v1.38.1)

===

##### Service Client Updates

-   `service/ec2`: Updates service API
    -   X2gd instances are the next generation of memory-optimized instances powered by AWS-designed, Arm-based AWS Graviton2 processors.
-   `service/sagemaker`: Updates service API and documentation
    -   Adding authentication support for pulling images stored in private Docker registries to build containers for real-time inference.

### [`v1.38.0`](https://togithub.com/aws/aws-sdk-go/blob/master/CHANGELOG.md#Release-v1380-2021-03-18)

[Compare Source](https://togithub.com/aws/aws-sdk-go/compare/v1.37.33...v1.38.0)

===

##### Service Client Updates

-   `service/autoscaling`: Updates service API and documentation
    -   Amazon EC2 Auto Scaling Instance Refresh now supports phased deployments.
-   `service/redshift`: Updates service API and documentation
    -   Add new fields for additional information about VPC endpoint for clusters with reallocation enabled, and a new field for total storage capacity for all clusters.
-   `service/securityhub`: Updates service API and documentation

##### SDK Features

-   `service/s3`: S3 Object Lambda is a new S3 feature that enables users to apply their own custom code to process the output of a standard S3 GET request by automatically invoking a Lambda function with a GET request
-   `service/s3control`: S3 Object Lambda is a new S3 feature that enables users to apply their own custom code to process the output of a standard S3 GET request by automatically invoking a Lambda function with a GET request.

</details>

---

### Renovate configuration

:date: **Schedule**: "every weekend" in timezone Asia/Tokyo.

:vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

:recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/seqsense/aws-iot-device-sdk-go).

codecov[bot]: # [Codecov](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240?src=pr&el=h1) Report
> Merging [#240](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240?src=pr&el=desc) (6aa4ad9) into [master](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/commit/39e80816fd9e0e54396de06f727afa9387ed1ddb?el=desc) (39e8081) will **not change** coverage.
> The diff coverage is `n/a`.

> :exclamation: Current head 6aa4ad9 differs from pull request most recent head bd57df6. Consider uploading reports for the commit bd57df6 to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240/graphs/tree.svg?width=650&height=150&src=pr&token=St5U6jzMqv)](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master     #240   +/-   ##
=======================================
  Coverage   60.41%   60.41%           
=======================================
  Files          29       29           
  Lines        1483     1483           
=======================================
  Hits          896      896           
  Misses        505      505           
  Partials       82       82           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240?src=pr&el=footer). Last update [39e8081...bd57df6](https://codecov.io/gh/seqsense/aws-iot-device-sdk-go/pull/240?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/examples/go.sum b/examples/go.sum
index ed352ef..e92d04b 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/at-wat/mqtt-go v0.12.1 h1:bO211unVuC9EN6BdkyKVislVSoIhVsXC0c57RUQlMJk=
 github.com/at-wat/mqtt-go v0.12.1/go.mod h1:b4QTk+HgoReGBw9R652AH0Kqc2OvkLSD7lOgyxWgeQE=
-github.com/aws/aws-sdk-go v1.37.33 h1:bAzhEFOh/UKC2e1QwlUA4klDc6EdV0j0AcnzgeGzifU=
-github.com/aws/aws-sdk-go v1.37.33/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
+github.com/aws/aws-sdk-go v1.38.1 h1:dVtNY7+5CtiRfAbEVxm5NgL5Xol8AMNoAf6TkyhDq1I=
+github.com/aws/aws-sdk-go v1.38.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/go.mod b/go.mod
index 9e7db75..13196dc 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,7 @@ module github.com/seqsense/aws-iot-device-sdk-go/v5
 
 require (
 	github.com/at-wat/mqtt-go v0.12.1
-	github.com/aws/aws-sdk-go v1.37.33
+	github.com/aws/aws-sdk-go v1.38.1
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/golang/protobuf v1.4.3
 	github.com/google/uuid v1.2.0
diff --git a/go.sum b/go.sum
index 537a90b..873ba45 100644
--- a/go.sum
+++ b/go.sum
@@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/at-wat/mqtt-go v0.12.1 h1:bO211unVuC9EN6BdkyKVislVSoIhVsXC0c57RUQlMJk=
 github.com/at-wat/mqtt-go v0.12.1/go.mod h1:b4QTk+HgoReGBw9R652AH0Kqc2OvkLSD7lOgyxWgeQE=
-github.com/aws/aws-sdk-go v1.37.33 h1:bAzhEFOh/UKC2e1QwlUA4klDc6EdV0j0AcnzgeGzifU=
-github.com/aws/aws-sdk-go v1.37.33/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
+github.com/aws/aws-sdk-go v1.38.1 h1:dVtNY7+5CtiRfAbEVxm5NgL5Xol8AMNoAf6TkyhDq1I=
+github.com/aws/aws-sdk-go v1.38.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/shadow/state.go b/shadow/state.go
index 1fff495..6effaf3 100644
--- a/shadow/state.go
+++ b/shadow/state.go
@@ -62,6 +62,8 @@ type ThingDocument struct {
 	Version     int                `json:"version,omitempty"`
 	Timestamp   int                `json:"timestamp,omitempty"`
 	ClientToken string             `json:"clientToken,omitempty"`
+
+	MaybeIncomplete bool `json:"-"`
 }
 
 type thingStateRaw struct {
@@ -128,10 +130,20 @@ func (s *ThingDocument) updateDelta(state *thingDelta) bool {
 		// Received an old version; just ignore it.
 		return false
 	}
+
+	if s.Version+1 != state.Version {
+		// Versions were dropped.
+		s.MaybeIncomplete = true
+	}
+
 	s.Version = state.Version
 	s.Timestamp = state.Timestamp
 	s.State.Delta = state.State
 	s.Metadata.Delta = state.Metadata
+
+	updateState(s.State.Desired, state.State)
+	updateState(s.Metadata.Desired, state.Metadata)
+
 	return true
 }
 
@@ -156,7 +168,8 @@ func updateStateRaw(state NestedState, update json.RawMessage) error {
 	if err := json.Unmarshal([]byte(update), &u); err != nil {
 		return ioterr.New(err, "unmarshaling update")
 	}
-	return updateState(state, u)
+	updateState(state, u)
+	return nil
 }
 
 func updateStateMetadataRaw(state NestedMetadata, update json.RawMessage) error {
@@ -167,23 +180,23 @@ func updateStateMetadataRaw(state NestedMetadata, update json.RawMessage) error
 	if err := json.Unmarshal([]byte(update), &u); err != nil {
 		return ioterr.New(err, "unmarshaling update")
 	}
-	return updateState(state, u)
+	updateState(state, u)
+	return nil
 }
 
-func updateState(state map[string]interface{}, update map[string]interface{}) error {
+func updateState(state map[string]interface{}, update map[string]interface{}) {
 	if len(update) == 0 {
 		for k := range state {
 			delete(state, k)
 		}
-		return nil
+		return
 	}
 	for key, val := range update {
 		switch v := val.(type) {
 		case NestedState:
 			if s, ok := state[key].(NestedState); ok {
-				if err := updateState(s, v); err != nil {
-					return ioterr.New(err, "updating state")
-				}
+				updateState(s, v)
+				return
 			} else {
 				state[key] = v
 			}
@@ -195,7 +208,7 @@ func updateState(state map[string]interface{}, update map[string]interface{}) er
 			state[key] = v
 		}
 	}
-	return nil
+	return
 }
 
 func hasUpdate(s json.RawMessage) bool {


Test patch:
diff --git a/shadow/shadow_test.go b/shadow/shadow_test.go
index 0ebefe2..8ecbcd6 100644
--- a/shadow/shadow_test.go
+++ b/shadow/shadow_test.go
@@ -18,6 +18,7 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
+	"fmt"
 	"reflect"
 	"testing"
 	"time"
@@ -436,39 +437,158 @@ func TestOnDelta(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
+	s.(*shadow).doc.Version = 9
 	cli.Handle(s)
 
-	expected := NestedState{
-		"key": "value",
+	testSeq := []struct {
+		expectedDelta NestedState
+		req           *thingDelta
+		expectedDoc   *ThingDocument
+	}{
+		{
+			expectedDelta: NestedState{
+				"key": "value",
+			},
+			req: &thingDelta{
+				State: NestedState{
+					"key": "value",
+				},
+				Metadata: NestedMetadata{
+					"key": Metadata{Timestamp: 1},
+				},
+				Version:   10,
+				Timestamp: 1,
+			},
+			expectedDoc: &ThingDocument{
+				State: ThingState{
+					Desired:  NestedState{"key": "value"},
+					Delta:    NestedState{"key": "value"},
+					Reported: NestedState{},
+				},
+				Metadata: ThingStateMetadata{
+					Desired:  NestedMetadata{"key": Metadata{Timestamp: 1}},
+					Delta:    NestedMetadata{"key": Metadata{Timestamp: 1}},
+					Reported: NestedMetadata{},
+				},
+				Version:   10,
+				Timestamp: 1,
+			},
+		},
+		{
+			expectedDelta: NestedState{
+				"key2": "value2",
+			},
+			req: &thingDelta{
+				State: NestedState{
+					"key2": "value2",
+				},
+				Metadata: NestedMetadata{
+					"key2": Metadata{Timestamp: 2},
+				},
+				Version:   11,
+				Timestamp: 2,
+			},
+			expectedDoc: &ThingDocument{
+				State: ThingState{
+					Desired: NestedState{
+						"key":  "value",
+						"key2": "value2",
+					},
+					Delta: NestedState{
+						"key2": "value2",
+					},
+					Reported: NestedState{},
+				},
+				Metadata: ThingStateMetadata{
+					Desired: NestedMetadata{
+						"key":  Metadata{Timestamp: 1},
+						"key2": Metadata{Timestamp: 2},
+					},
+					Delta: NestedMetadata{
+						"key2": Metadata{Timestamp: 2},
+					},
+					Reported: NestedMetadata{},
+				},
+				Version:   11,
+				Timestamp: 2,
+			},
+		},
+		{
+			expectedDelta: NestedState{
+				"key": "value3",
+			},
+			req: &thingDelta{
+				State: NestedState{
+					"key": "value3",
+				},
+				Metadata: NestedMetadata{
+					"key": Metadata{Timestamp: 4},
+				},
+				Version:   13,
+				Timestamp: 4,
+			},
+			expectedDoc: &ThingDocument{
+				State: ThingState{
+					Desired: NestedState{
+						"key":  "value3",
+						"key2": "value2",
+					},
+					Delta: NestedState{
+						"key": "value3",
+					},
+					Reported: NestedState{},
+				},
+				Metadata: ThingStateMetadata{
+					Desired: NestedMetadata{
+						"key":  Metadata{Timestamp: 4},
+						"key2": Metadata{Timestamp: 2},
+					},
+					Delta: NestedMetadata{
+						"key": Metadata{Timestamp: 4},
+					},
+					Reported: NestedMetadata{},
+				},
+				Version:         13,
+				Timestamp:       4,
+				MaybeIncomplete: true,
+			},
+		},
 	}
 
-	done := make(chan struct{})
-	s.OnDelta(func(delta NestedState) {
-		if !reflect.DeepEqual(expected, delta) {
-			t.Fatalf("Expected delta:\n%+v\ngot:\n%+v", expected, delta)
-		}
-		close(done)
-	})
+	for i, seq := range testSeq {
+		expectedDelta := seq.expectedDelta
+		req := seq.req
+		expectedDoc := seq.expectedDoc
 
-	req := &thingDelta{
-		State: NestedState{
-			"key": "value",
-		},
-		Version: 10,
-	}
-	breq, err := json.Marshal(req)
-	if err != nil {
-		t.Fatal(err)
-	}
-	cli.Serve(&mqtt.Message{
-		Topic:   s.(*shadow).topic("update/delta"),
-		Payload: breq,
-	})
+		t.Run(fmt.Sprintf("Seq%d", i), func(t *testing.T) {
+			done := make(chan struct{})
+			s.OnDelta(func(delta NestedState) {
+				if !reflect.DeepEqual(expectedDelta, delta) {
+					t.Fatalf("Expected delta:\n%+v\ngot:\n%+v", expectedDelta, delta)
+				}
+				close(done)
+			})
 
-	select {
-	case <-done:
-	case <-ctx.Done():
-		t.Fatal("Timeout")
+			breq, err := json.Marshal(req)
+			if err != nil {
+				t.Fatal(err)
+			}
+			cli.Serve(&mqtt.Message{
+				Topic:   s.(*shadow).topic("update/delta"),
+				Payload: breq,
+			})
+
+			select {
+			case <-done:
+			case <-ctx.Done():
+				t.Fatal("Timeout")
+			}
+
+			doc := s.Document()
+			if !reflect.DeepEqual(expectedDoc, doc) {
+				t.Errorf("Expected document:\n%+v\ngot:\n%+v", expectedDoc, doc)
+			}
+		})
 	}
 }