diff --git a/example/cmd/device-simple/Attribution.txt b/example/cmd/device-simple/Attribution.txt index 2860f5247..b69f1fb95 100644 --- a/example/cmd/device-simple/Attribution.txt +++ b/example/cmd/device-simple/Attribution.txt @@ -96,6 +96,9 @@ https://github.com/pmezard/go-difflib/blob/master/LICENSE stretchr/testify (MIT) https://github.com/stretchr/testify https://github.com/stretchr/testify/blob/master/LICENSE +ugorji/go (MIT) https://github.com/ugorji/go +https://github.com/ugorji/go/blob/master/LICENSE + kr/logfmt (MIT) https://github.com/kr/logfmt https://github.com/kr/logfmt/blob/master/Readme diff --git a/go.mod b/go.mod index 1b458b626..efc323ce0 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/gorilla/mux v1.7.1 github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.5.1 + github.com/ugorji/go v1.1.4 gopkg.in/yaml.v2 v2.2.8 ) diff --git a/internal/autoevent/executor.go b/internal/autoevent/executor.go index 2d71c15bb..f940e6205 100644 --- a/internal/autoevent/executor.go +++ b/internal/autoevent/executor.go @@ -12,11 +12,12 @@ import ( "sync" "time" - "github.com/OneOfOne/xxhash" "github.com/edgexfoundry/device-sdk-go/internal/common" "github.com/edgexfoundry/device-sdk-go/internal/handler" dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models" contract "github.com/edgexfoundry/go-mod-core-contracts/models" + + "github.com/OneOfOne/xxhash" ) type Executor interface { @@ -84,7 +85,7 @@ func readResource(e *executor) (*dsModels.Event, common.AppError) { vars[common.NameVar] = e.deviceName vars[common.CommandVar] = e.autoEvent.Resource - evt, appErr := handler.CommandHandler(vars, "", common.GetCmdMethod, "") + evt, appErr := handler.CommandHandler(vars, "", nil) return evt, appErr } diff --git a/internal/common/types.go b/internal/common/types.go index 1663836b2..62dfeb948 100644 --- a/internal/common/types.go +++ b/internal/common/types.go @@ -16,7 +16,8 @@ import ( // WritableInfo is a struct which contains configuration settings that can be changed in the Registry . type WritableInfo struct { // Level is the logging level of writing log message - LogLevel string + LogLevel string + ChecksumAlgo string } // ServiceInfo is a struct which contains service related configuration diff --git a/internal/controller/restfuncs.go b/internal/controller/restfuncs.go index 7f8037ed7..90091d084 100644 --- a/internal/controller/restfuncs.go +++ b/internal/controller/restfuncs.go @@ -20,6 +20,7 @@ import ( "github.com/edgexfoundry/device-sdk-go/internal/handler/callback" "github.com/edgexfoundry/go-mod-core-contracts/clients" contract "github.com/edgexfoundry/go-mod-core-contracts/models" + "github.com/gorilla/mux" ) @@ -105,7 +106,7 @@ func commandFunc(w http.ResponseWriter, req *http.Request) { return } - event, appErr := handler.CommandHandler(vars, body, req.Method, req.URL.RawQuery) + event, appErr := handler.CommandHandler(vars, body, req) if appErr != nil { http.Error(w, fmt.Sprintf("%s %s", appErr.Message(), req.URL.Path), appErr.Code()) @@ -124,7 +125,6 @@ func commandFunc(w http.ResponseWriter, req *http.Request) { } else { common.LoggingClient.Trace("DeviceCommand: EventClient.MarshalEvent passed through encoded event", "device", event.Device, "event", event) } - // TODO: Resolve why this header is not included in response from Core-Command to originating caller (while the written body is). w.Header().Set(clients.ContentType, clients.ContentTypeCBOR) w.Write(event.EncodedEvent) } else { @@ -149,7 +149,7 @@ func commandAllFunc(w http.ResponseWriter, req *http.Request) { return } - events, appErr := handler.CommandAllHandler(vars[common.CommandVar], body, req.Method, req.URL.RawQuery) + events, appErr := handler.CommandAllHandler(vars[common.CommandVar], body, req) if appErr != nil { http.Error(w, appErr.Message(), appErr.Code()) } else if len(events) > 0 { diff --git a/internal/handler/command.go b/internal/handler/command.go index ea125921b..5565547d6 100644 --- a/internal/handler/command.go +++ b/internal/handler/command.go @@ -10,6 +10,7 @@ package handler import ( "encoding/json" "fmt" + "net/http" "strconv" "strings" "sync" @@ -19,12 +20,23 @@ import ( "github.com/edgexfoundry/device-sdk-go/internal/common" "github.com/edgexfoundry/device-sdk-go/internal/transformer" dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models" + + "github.com/edgexfoundry/go-mod-core-contracts/clients" contract "github.com/edgexfoundry/go-mod-core-contracts/models" + + "github.com/ugorji/go/codec" ) // Note, every HTTP request to ServeHTTP is made in a separate goroutine, which // means care needs to be taken with respect to shared data accessed through *Server. -func CommandHandler(vars map[string]string, body string, method string, queryParams string) (*dsModels.Event, common.AppError) { +func CommandHandler(vars map[string]string, body string, req *http.Request) (*dsModels.Event, common.AppError) { + if req == nil { + return nil, common.NewNotFoundError("error in request parameter that was passed in", nil) + } + + method := req.Method + queryParams := req.URL.RawQuery + dKey := vars[common.IdVar] cmd := vars[common.CommandVar] @@ -78,13 +90,13 @@ func CommandHandler(vars map[string]string, body string, method string, queryPar if strings.ToLower(method) == common.GetCmdMethod { evt, appErr = execReadDeviceResource(&d, &dr, queryParams) } else { - appErr = execWriteDeviceResource(&d, &dr, body) + appErr = execWriteDeviceResource(&d, &dr, body, req) } } else { if strings.ToLower(method) == common.GetCmdMethod { evt, appErr = execReadCmd(&d, cmd, queryParams) } else { - appErr = execWriteCmd(&d, cmd, body) + appErr = execWriteCmd(&d, cmd, body, req) } } @@ -92,7 +104,11 @@ func CommandHandler(vars map[string]string, body string, method string, queryPar return evt, appErr } -func execReadDeviceResource(device *contract.Device, dr *contract.DeviceResource, queryParams string) (*dsModels.Event, common.AppError) { +func execReadDeviceResource( + device *contract.Device, + dr *contract.DeviceResource, + queryParams string) (*dsModels.Event, common.AppError) { + var reqs []dsModels.CommandRequest var req dsModels.CommandRequest common.LoggingClient.Debug(fmt.Sprintf("Handler - execReadCmd: deviceResource: %s", dr.Name)) @@ -249,8 +265,13 @@ func execReadCmd(device *contract.Device, cmd string, queryParams string) (*dsMo return cvsToEvent(device, results, cmd) } -func execWriteDeviceResource(device *contract.Device, dr *contract.DeviceResource, params string) common.AppError { - paramMap, err := parseParams(params) +func execWriteDeviceResource( + device *contract.Device, + dr *contract.DeviceResource, + params string, + r *http.Request) common.AppError { + + paramMap, err := parseParams(params, r) if err != nil { msg := fmt.Sprintf("Handler - execWriteDeviceResource: Put parameters parsing failed: %s", params) common.LoggingClient.Error(msg) @@ -297,7 +318,7 @@ func execWriteDeviceResource(device *contract.Device, dr *contract.DeviceResourc return nil } -func execWriteCmd(device *contract.Device, cmd string, params string) common.AppError { +func execWriteCmd(device *contract.Device, cmd string, params string, r *http.Request) common.AppError { ros, err := cache.Profiles().ResourceOperations(device.Profile.Name, cmd, common.SetCmdMethod) if err != nil { msg := fmt.Sprintf("Handler - execWriteCmd: can't find ResrouceOperations in Profile(%s) and Command(%s), %v", device.Profile.Name, cmd, err) @@ -312,7 +333,7 @@ func execWriteCmd(device *contract.Device, cmd string, params string) common.App return common.NewServerError(msg, nil) } - cvs, err := parseWriteParams(device.Profile.Name, ros, params) + cvs, err := parseWriteParams(device.Profile.Name, ros, params, r) if err != nil { msg := fmt.Sprintf("Handler - execWriteCmd: Put parameters parsing failed: %s", params) common.LoggingClient.Error(msg) @@ -359,8 +380,12 @@ func execWriteCmd(device *contract.Device, cmd string, params string) common.App return nil } -func parseWriteParams(profileName string, ros []contract.ResourceOperation, params string) ([]*dsModels.CommandValue, error) { - paramMap, err := parseParams(params) +func parseWriteParams(profileName string, + ros []contract.ResourceOperation, + params string, + r *http.Request) ([]*dsModels.CommandValue, error) { + + paramMap, err := parseParams(params, r) if err != nil { return []*dsModels.CommandValue{}, err } @@ -410,8 +435,22 @@ func parseWriteParams(profileName string, ros []contract.ResourceOperation, para return result, nil } -func parseParams(params string) (paramMap map[string]string, err error) { - err = json.Unmarshal([]byte(params), ¶mMap) +func parseParams(params string, r *http.Request) (paramMap map[string]string, err error) { + + if r == nil { + return nil, fmt.Errorf("error in request parameter that was passed in") + } + + // Check the header value + switch r.Header.Get(clients.ContentType) { + case clients.ContentTypeCBOR: + err = codec.NewDecoderBytes([]byte(params), &codec.CborHandle{}).Decode(¶mMap) + case clients.ContentTypeJSON: + err = json.Unmarshal([]byte(params), ¶mMap) + default: + common.LoggingClient.Error(fmt.Sprintf("header value was neither JSON nor CBOR, instead was: %s", r.Header.Get(clients.ContentType))) + } + if err != nil { common.LoggingClient.Error(fmt.Sprintf("parsing Write parameters failed %s, %v", params, err)) return @@ -424,7 +463,11 @@ func parseParams(params string) (paramMap map[string]string, err error) { return } -func createCommandValueFromRO(profileName string, ro *contract.ResourceOperation, v string) (*dsModels.CommandValue, error) { +func createCommandValueFromRO( + profileName string, + ro *contract.ResourceOperation, + v string) (*dsModels.CommandValue, error) { + dr, ok := cache.Profiles().DeviceResource(profileName, ro.DeviceResource) if !ok { msg := fmt.Sprintf("createCommandValueForParam: no deviceResource: %s", ro.DeviceResource) @@ -505,8 +548,18 @@ func createCommandValueFromDR(dr *contract.DeviceResource, v string) (*dsModels. return result, err } -func CommandAllHandler(cmd string, body string, method string, queryParams string) ([]*dsModels.Event, common.AppError) { - common.LoggingClient.Debug(fmt.Sprintf("Handler - CommandAll: execute the %s command %s from all operational devices", method, cmd)) +func CommandAllHandler(cmd string, body string, req *http.Request) ([]*dsModels.Event, common.AppError) { + if req == nil { + return nil, common.NewNotFoundError("error in request parameter that was passed in", nil) + } + + method := req.Method + queryParams := req.URL.RawQuery + + common.LoggingClient.Debug(fmt.Sprintf( + "Handler - CommandAll: execute the %s command %s from all operational devices", + method, + cmd)) devices := filterOperationalDevices(cache.Devices().All()) devCount := len(devices) @@ -525,7 +578,7 @@ func CommandAllHandler(cmd string, body string, method string, queryParams strin if strings.ToLower(method) == common.GetCmdMethod { event, appErr = execReadCmd(device, cmd, queryParams) } else { - appErr = execWriteCmd(device, cmd, body) + appErr = execWriteCmd(device, cmd, body, req) } cmdResults <- struct { event *dsModels.Event diff --git a/internal/handler/command_test.go b/internal/handler/command_test.go index 9d1dce4d0..1aebd7b3d 100644 --- a/internal/handler/command_test.go +++ b/internal/handler/command_test.go @@ -8,19 +8,23 @@ package handler import ( "context" + "net/http" + "net/http/httptest" "strconv" "strings" "testing" - "github.com/edgexfoundry/go-mod-core-contracts/clients/logger" - contract "github.com/edgexfoundry/go-mod-core-contracts/models" - "github.com/google/uuid" - "github.com/stretchr/testify/assert" - "github.com/edgexfoundry/device-sdk-go/internal/cache" "github.com/edgexfoundry/device-sdk-go/internal/common" "github.com/edgexfoundry/device-sdk-go/internal/mock" dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models" + + "github.com/edgexfoundry/go-mod-core-contracts/clients" + "github.com/edgexfoundry/go-mod-core-contracts/clients/logger" + contract "github.com/edgexfoundry/go-mod-core-contracts/models" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" ) const ( @@ -83,8 +87,9 @@ func TestParseWriteParamsWrongParamName(t *testing.T) { profileName := "notFound" ro := []contract.ResourceOperation{{Index: ""}} params := "{ \"key\": \"value\" }" + r := newRequestWithContentType(clients.ContentTypeJSON) - _, err := parseWriteParams(profileName, ro, params) + _, err := parseWriteParams(profileName, ro, params, r) if err == nil { t.Error("expected error") @@ -96,7 +101,8 @@ func TestParseWriteParamsNoParams(t *testing.T) { ro := []contract.ResourceOperation{{Index: ""}} params := "{ }" - _, err := parseWriteParams(profileName, ro, params) + r := newRequestWithContentType(clients.ContentTypeJSON) + _, err := parseWriteParams(profileName, ro, params, r) if err == nil { t.Error("expected error") @@ -237,6 +243,7 @@ func TestParseWriteParams(t *testing.T) { rosTestDefaultValue, _ := cache.Profiles().ResourceOperations(profileName, "RandomValue_Int32", common.SetCmdMethod) rosTestMappingPass, _ := cache.Profiles().ResourceOperations(profileName, "ResourceTestMapping_Pass", common.SetCmdMethod) rosTestMappingFail, _ := cache.Profiles().ResourceOperations(profileName, "ResourceTestMapping_Fail", common.SetCmdMethod) + r := newRequestWithContentType(clients.ContentTypeJSON) tests := []struct { testName string @@ -258,7 +265,7 @@ func TestParseWriteParams(t *testing.T) { } for _, tt := range tests { t.Run(tt.testName, func(t *testing.T) { - _, err := parseWriteParams(tt.profile, tt.resourceOps, tt.params) + _, err := parseWriteParams(tt.profile, tt.resourceOps, tt.params, r) if !tt.expectErr && err != nil { t.Errorf("unexpected parse error params:%s %s", tt.params, err.Error()) return @@ -335,6 +342,9 @@ func TestExecWriteCmd(t *testing.T) { paramsTransformFail = `{"ResourceTestTransform_Fail":"123"}` paramsNoDeviceResourceForResult = `{"error":""}` ) + + r := newRequestWithContentType(clients.ContentTypeJSON) + tests := []struct { testName string device *contract.Device @@ -358,7 +368,7 @@ func TestExecWriteCmd(t *testing.T) { common.CurrentConfig.Device.MaxCmdOps = 128 }() } - appErr := execWriteCmd(tt.device, tt.cmd, tt.params) + appErr := execWriteCmd(tt.device, tt.cmd, tt.params, r) if !tt.expectErr && appErr != nil { t.Errorf("%s expectErr:%v error:%v", tt.testName, tt.expectErr, appErr.Error()) return @@ -386,9 +396,10 @@ func TestCommandAllHandler(t *testing.T) { {"PartOfWriteCommandExecutionSuccess", "RandomValue_Uint8", `{"RandomValue_Uint8":"123"}`, "", methodSet, false}, {"PartOfWriteCommandExecutionFail", "error", `{"RandomValue_Uint8":"123"}`, "", methodSet, true}, } + r := newRequestWithContentType(clients.ContentTypeJSON) for _, tt := range tests { t.Run(tt.testName, func(t *testing.T) { - _, appErr := CommandAllHandler(tt.cmd, tt.body, tt.method, tt.queryParams) + _, appErr := CommandAllHandler(tt.cmd, tt.body, r) if !tt.expectErr && appErr != nil { t.Errorf("%s expectErr:%v error:%v", tt.testName, tt.expectErr, appErr.Error()) return @@ -421,6 +432,8 @@ func TestCommandHandler(t *testing.T) { t.Errorf("Fail to update device, error: %v", err) } + r := newRequestWithContentType(clients.ContentTypeJSON) + tests := []struct { testName string vars map[string]string @@ -441,7 +454,7 @@ func TestCommandHandler(t *testing.T) { } for _, tt := range tests { t.Run(tt.testName, func(t *testing.T) { - _, appErr := CommandHandler(tt.vars, tt.body, tt.method, tt.queryParams) + _, appErr := CommandHandler(tt.vars, tt.body, r) if !tt.expectErr && appErr != nil { t.Errorf("%s expectErr:%v error:%v", tt.testName, tt.expectErr, appErr.Error()) return @@ -453,3 +466,21 @@ func TestCommandHandler(t *testing.T) { }) } } + +func TestParseWriteParamsCborHeader(t *testing.T) { + profileName := mock.ProfileBinary + ros, _ := cache.Profiles().ResourceOperations(profileName, "RandomValue_Binary", common.SetCmdMethod) + params := `°xEnableRandomization_Binarydtrue§nparameterNamesxEnableRandomization_BinarydPathx/api/v1/device/9f872d68/BinarycUrlxBhttp://localhost:48082/api/v1/device/9f872d68/command/7ff8d51ea50dbidx$9f872d68-2281-4af4-959d-29e4d51c2192dnametRandom-Binary-DevicejadminStatehUNLOCKEDnoperatingStategENABLED°xEnableRandomization_Binarydtrue` + r := newRequestWithHeaders(map[string]string{clients.ContentType: clients.ContentTypeCBOR}, http.MethodPut) + _, err := parseWriteParams(profileName, ros, params, r) + + if err != nil { + t.Error("unexpected error") + } +} + +func newRequestWithContentType(contentType string) *http.Request { + req := httptest.NewRequest(http.MethodGet, "/", strings.NewReader("Test body")) + req.Header.Set(clients.ContentType, contentType) + return req +} diff --git a/internal/handler/test_utils.go b/internal/handler/test_utils.go new file mode 100644 index 000000000..620d188d1 --- /dev/null +++ b/internal/handler/test_utils.go @@ -0,0 +1,18 @@ +package handler + +import ( + "net/http" + "strings" +) + +// newRequestWithHeaders accepts httpMethod and outlines, which is a map[string]string, +// and, by looping over the entries in outlines, populates the HTTP headers of the +// http.Request, which is returned from this function. +func newRequestWithHeaders(outlines map[string]string, httpMethod string) *http.Request { + req, _ := http.NewRequest(httpMethod, "/", strings.NewReader("Test body")) + for k, v := range outlines { + req.Header.Set(k, v) + } + + return req +} diff --git a/internal/mock/consts.go b/internal/mock/consts.go index 62aa2bc90..bd1f3894e 100644 --- a/internal/mock/consts.go +++ b/internal/mock/consts.go @@ -7,24 +7,27 @@ package mock const ( - DeviceBool = "Random-Boolean-Generator" - DeviceInt = "Random-Integer-Generator" - DeviceUint = "Random-UnsignedInteger-Generator" - DeviceFloat = "Random-Float-Generator" - DeviceNew = "New-Device" - DeviceNew02 = "New-Device-02" + DeviceBool = "Random-Boolean-Generator" + DeviceInt = "Random-Integer-Generator" + DeviceUint = "Random-UnsignedInteger-Generator" + DeviceFloat = "Random-Float-Generator" + DeviceNew = "New-Device" + DeviceNew02 = "New-Device-02" + DeviceBinary = "Random-Binary-Device" - ProfileBool = "Random-Boolean-Generator" - ProfileInt = "Random-Integer-Generator" - ProfileUint = "Random-UnsignedInteger-Generator" - ProfileFloat = "Random-Float-Generator" - ProfileNew = "New-Device" + ProfileBool = "Random-Boolean-Generator" + ProfileInt = "Random-Integer-Generator" + ProfileUint = "Random-UnsignedInteger-Generator" + ProfileFloat = "Random-Float-Generator" + ProfileNew = "New-Device" + ProfileBinary = "Random-Binary-Device" - WatcherBool = "Bool-Watcher" - WatcherInt = "Integer-Watcher" - WatcherUint = "UnsignedInteger-Watcher" - WatcherFloat = "Float-Watcher" - WatcherNew = "New-Watcher" + WatcherBool = "Bool-Watcher" + WatcherInt = "Integer-Watcher" + WatcherUint = "UnsignedInteger-Watcher" + WatcherFloat = "Float-Watcher" + WatcherNew = "New-Watcher" + WatcherBinary = "Binary-Watcher" ResourceObjectBool = "RandomValue_Bool" ResourceObjectInt8 = "RandomValue_Int8" @@ -38,4 +41,5 @@ const ( ResourceObjectFloat32 = "RandomValue_Float32" ResourceObjectFloat64 = "RandomValue_Float64" ResourceObjectRandFloat32 = "randfloat32" + ResourceObjectBinary = "RandomValue_Binary" ) diff --git a/internal/mock/mock_deviceclient.go b/internal/mock/mock_deviceclient.go index 092198c98..fe5b230a5 100644 --- a/internal/mock/mock_deviceclient.go +++ b/internal/mock/mock_deviceclient.go @@ -29,6 +29,7 @@ var ( DuplicateDeviceRandomFloatGenerator = contract.Device{} NewValidDevice = contract.Device{} OperatingStateDisabled = contract.Device{} + ValidDeviceRandomBinaryGenerator = contract.Device{} ) type DeviceClientMock struct{} @@ -161,6 +162,8 @@ func populateDeviceMock() error { _ = json.Unmarshal(profiles[DeviceNew], &NewValidDevice.Profile) _ = json.Unmarshal(devices[DeviceNew02], &OperatingStateDisabled) _ = json.Unmarshal(profiles[DeviceNew], &OperatingStateDisabled.Profile) + _ = json.Unmarshal(devices[DeviceBinary], &ValidDeviceRandomBinaryGenerator) + _ = json.Unmarshal(profiles[DeviceBinary], &ValidDeviceRandomBinaryGenerator.Profile) return nil } diff --git a/internal/mock/mock_deviceprofileclient.go b/internal/mock/mock_deviceprofileclient.go index ba2e84d66..8395e29f1 100644 --- a/internal/mock/mock_deviceprofileclient.go +++ b/internal/mock/mock_deviceprofileclient.go @@ -84,6 +84,7 @@ func populateDeviceProfileMock() error { _ = json.Unmarshal(profiles[ProfileFloat], &DeviceProfileRandomFloatGenerator) _ = json.Unmarshal(profiles[ProfileFloat], &DuplicateDeviceProfileRandomFloatGenerator) _ = json.Unmarshal(profiles[ProfileNew], &NewDeviceProfile) + _ = json.Unmarshal(profiles[ProfileBinary], &ValidDeviceRandomBinaryGenerator) return nil } diff --git a/internal/mock/mock_provisionwatcherclient.go b/internal/mock/mock_provisionwatcherclient.go index c55177b54..71045e725 100644 --- a/internal/mock/mock_provisionwatcherclient.go +++ b/internal/mock/mock_provisionwatcherclient.go @@ -22,6 +22,7 @@ var ( ValidFloatWatcher = contract.ProvisionWatcher{} DuplicateFloatWatcher = contract.ProvisionWatcher{} NewProvisionWatcher = contract.ProvisionWatcher{} + ValidBinaryWatcher = contract.ProvisionWatcher{} ) type ProvisionWatcherClientMock struct { @@ -100,6 +101,7 @@ func populateProvisionWatcherMock() error { _ = json.Unmarshal(watchers[WatcherFloat], &ValidFloatWatcher) _ = json.Unmarshal(watchers[WatcherFloat], &DuplicateFloatWatcher) _ = json.Unmarshal(watchers[WatcherNew], &NewProvisionWatcher) + _ = json.Unmarshal(watchers[WatcherBinary], &ValidBinaryWatcher) return nil } diff --git a/internal/mock/mock_valuedescriptorclient.go b/internal/mock/mock_valuedescriptorclient.go index fd02de262..8d02c6251 100644 --- a/internal/mock/mock_valuedescriptorclient.go +++ b/internal/mock/mock_valuedescriptorclient.go @@ -33,6 +33,7 @@ var ( ValueDescriptorFloat64 = contract.ValueDescriptor{} NewValueDescriptor = contract.ValueDescriptor{} DuplicateValueDescriptorInt16 = contract.ValueDescriptor{} + ValueDescriptorBinary = contract.ValueDescriptor{} descMap = make(map[string]contract.ValueDescriptor, 0) ) @@ -136,6 +137,7 @@ func populateValueDescriptorMock() error { ValueDescriptorFloat64 = descMap[ResourceObjectFloat64] DuplicateValueDescriptorInt16 = descMap[ResourceObjectInt16] NewValueDescriptor = descMap[ResourceObjectRandFloat32] + ValueDescriptorBinary = descMap[ResourceObjectBinary] return nil } diff --git a/pkg/models/event.go b/pkg/models/event.go index 8742cc61a..186f69f60 100644 --- a/pkg/models/event.go +++ b/pkg/models/event.go @@ -14,6 +14,7 @@ import ( type Event struct { contract.Event EncodedEvent []byte + Checksum string } // HasBinaryValue confirms whether an event contains one or more