diff --git a/client/client.go b/client/client.go index df3a2621..1ecf01ef 100644 --- a/client/client.go +++ b/client/client.go @@ -28,6 +28,7 @@ import ( "github.com/plgd-dev/device/v2/client/core" "github.com/plgd-dev/device/v2/client/core/otm" "github.com/plgd-dev/device/v2/pkg/net/coap" + "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/go-coap/v3/net/blockwise" "github.com/plgd-dev/go-coap/v3/options" coapSync "github.com/plgd-dev/go-coap/v3/pkg/sync" @@ -397,3 +398,29 @@ func NewDeviceOwnerFromConfig(cfg *Config, dialTLS core.DialTLS, dialDTLS core.D } return newDeviceOwnershipNone(), nil } + +func (c *Client) GetDeviceLinkForHref( + ctx context.Context, + deviceID string, + href string, + discoveryCfg core.DiscoveryConfiguration, + callback LinkNotFoundCallback, +) (*core.Device, schema.ResourceLink, error) { + d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(discoveryCfg)) + if err != nil { + return nil, schema.ResourceLink{}, err + } + + link, err := core.GetResourceLink(links, href) + if err != nil { + if callback.linkNotFoundCallback != nil { + link, err = callback.linkNotFoundCallback(links, href) + if err != nil { + return nil, schema.ResourceLink{}, err + } + } else { + return nil, schema.ResourceLink{}, err + } + } + return d, link, nil +} diff --git a/client/core/provisionDevice_test.go b/client/core/provisionDevice_test.go index 540ad320..24b50685 100644 --- a/client/core/provisionDevice_test.go +++ b/client/core/provisionDevice_test.go @@ -126,6 +126,7 @@ func TestSettingCloudResource(t *testing.T) { AuthorizationProvider: "testAuthorizationProvider", URL: "testURL", AuthorizationCode: "testAuthorizationCode", + CloudID: "00000000-0000-0000-0000-000000000000", } err = pc.SetCloudResource(context.Background(), r) require.NoError(t, err) diff --git a/client/createResource.go b/client/createResource.go index f882fdf6..68b68c99 100644 --- a/client/createResource.go +++ b/client/createResource.go @@ -45,15 +45,10 @@ func (c *Client) CreateResource( cfg = o.applyOnCreate(cfg) } - d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration)) + device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback}) if err != nil { return err } - link, err := core.GetResourceLink(links, href) - if err != nil { - return err - } - - return d.UpdateResourceWithCodec(ctx, link, cfg.codec, request, response, cfg.opts...) + return device.UpdateResourceWithCodec(ctx, link, cfg.codec, request, response, cfg.opts...) } diff --git a/client/createResource_test.go b/client/createResource_test.go index 8f11ae73..f503a7fe 100644 --- a/client/createResource_test.go +++ b/client/createResource_test.go @@ -22,6 +22,7 @@ import ( "github.com/plgd-dev/device/v2/client" "github.com/plgd-dev/device/v2/client/core" + "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/device/v2/test" @@ -60,6 +61,32 @@ func TestClientCreateResource(t *testing.T) { }, }), }, + { + name: "test link not found callback", + args: args{ + deviceID: deviceID, + href: "/link/not/found", + body: test.MakeSwitchResourceDefaultData(), + opts: []client.CreateOption{ + client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()), + client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) { + _, linkFound := links.GetResourceLink(href) + require.False(t, linkFound) + resourceLink, linkFound := links.GetResourceLink(test.TestResourceSwitchesHref) + require.True(t, linkFound) + return resourceLink, nil + }), + }, + }, + want: test.MakeSwitchResourceData(map[string]interface{}{ + "href": test.TestResourceSwitchesInstanceHref("2"), + "rep": map[interface{}]interface{}{ + "if": []interface{}{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE}, + "rt": []interface{}{types.BINARY_SWITCH}, + "value": false, + }, + }), + }, { name: "invalid href", args: args{ diff --git a/client/deleteResource.go b/client/deleteResource.go index 737509f3..16568952 100644 --- a/client/deleteResource.go +++ b/client/deleteResource.go @@ -40,15 +40,10 @@ func (c *Client) DeleteResource( cfg = o.applyOnDelete(cfg) } - d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration)) + device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback}) if err != nil { return err } - link, err := core.GetResourceLink(links, href) - if err != nil { - return err - } - - return d.DeleteResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...) + return device.DeleteResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...) } diff --git a/client/deleteResource_test.go b/client/deleteResource_test.go index ffdabc04..4ef2bd1e 100644 --- a/client/deleteResource_test.go +++ b/client/deleteResource_test.go @@ -24,6 +24,7 @@ import ( "github.com/plgd-dev/device/v2/client" "github.com/plgd-dev/device/v2/client/core" "github.com/plgd-dev/device/v2/schema" + "github.com/plgd-dev/device/v2/schema/configuration" "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/device/v2/schema/resources" @@ -51,7 +52,28 @@ func createSwitches(ctx context.Context, t *testing.T, c *client.Client, deviceI func TestClientDeleteResource(t *testing.T) { deviceID := test.MustFindDeviceByName(test.DevsimName) - const switchID = "1" + const ( + switchID_1 = "1" + switchID_2 = "2" + ) + + c, err := NewTestSecureClient() + require.NoError(t, err) + defer func() { + errC := c.Close(context.Background()) + require.NoError(t, errC) + }() + ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) + defer cancel() + deviceID, err = c.OwnDevice(ctx, deviceID, client.WithOTMs([]client.OTMType{client.OTMType_JustWorks})) + require.NoError(t, err) + defer disown(t, c, deviceID) + + createSwitches(ctx, t, c, deviceID, 2) + var nonDiscoverableResource map[string]interface{} + err = c.CreateResource(ctx, deviceID, test.TestResourceSwitchesHref, test.MakeNonDiscoverableSwitchData(), &nonDiscoverableResource) + require.NoError(t, err) + type args struct { deviceID string href string @@ -66,10 +88,28 @@ func TestClientDeleteResource(t *testing.T) { name: "valid", args: args{ deviceID: deviceID, - href: test.TestResourceSwitchesInstanceHref(switchID), + href: test.TestResourceSwitchesInstanceHref(switchID_1), opts: []client.DeleteOption{client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration())}, }, }, + { + name: "delete non-discoverable resource", + args: args{ + deviceID: deviceID, + href: nonDiscoverableResource["href"].(string), + opts: []client.DeleteOption{ + client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()), + // create the link for non-discoverable resource by utilizing the linkNotFoundCallback + // as the only thing that we need in the link is the href and endpoints we will reuse + // some known discoverable resource + client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) { + resourceLink, _ := links.GetResourceLink(configuration.ResourceURI) + resourceLink.Href = href + return resourceLink, nil + }), + }, + }, + }, { name: "invalid href", args: args{ @@ -88,20 +128,6 @@ func TestClientDeleteResource(t *testing.T) { }, } - c, err := NewTestSecureClient() - require.NoError(t, err) - defer func() { - errC := c.Close(context.Background()) - require.NoError(t, errC) - }() - ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) - defer cancel() - deviceID, err = c.OwnDevice(ctx, deviceID, client.WithOTMs([]client.OTMType{client.OTMType_JustWorks})) - require.NoError(t, err) - defer disown(t, c, deviceID) - - createSwitches(ctx, t, c, deviceID, 1) - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := c.DeleteResource(ctx, tt.args.deviceID, tt.args.href, nil, tt.args.opts...) diff --git a/client/getResource.go b/client/getResource.go index f641b03e..39e60ff5 100644 --- a/client/getResource.go +++ b/client/getResource.go @@ -39,15 +39,11 @@ func (c *Client) GetResource( for _, o := range opts { cfg = o.applyOnGet(cfg) } - d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration)) - if err != nil { - return err - } - link, err := core.GetResourceLink(links, href) + device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback}) if err != nil { return err } - return d.GetResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...) + return device.GetResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...) } diff --git a/client/getResource_test.go b/client/getResource_test.go index 48fd0c92..4687dc77 100644 --- a/client/getResource_test.go +++ b/client/getResource_test.go @@ -43,6 +43,22 @@ import ( func TestClientGetResource(t *testing.T) { deviceID := test.MustFindDeviceByName(test.DevsimName) + c, err := NewTestSecureClient() + require.NoError(t, err) + defer func() { + errC := c.Close(context.Background()) + require.NoError(t, errC) + }() + ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) + defer cancel() + deviceID, err = c.OwnDevice(ctx, deviceID) + require.NoError(t, err) + defer disown(t, c, deviceID) + + var nonDiscoverableResource map[string]interface{} + err = c.CreateResource(ctx, deviceID, test.TestResourceSwitchesHref, test.MakeNonDiscoverableSwitchData(), &nonDiscoverableResource) + require.NoError(t, err) + type args struct { deviceID string href string @@ -85,6 +101,33 @@ func TestClientGetResource(t *testing.T) { }, }, }, + { + name: "get non-discoverable resource", + args: args{ + deviceID: deviceID, + href: nonDiscoverableResource["href"].(string), + opts: []client.GetOption{ + client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()), + // create the link for non-discoverable resource by utilizing the linkNotFoundCallback + // as the only thing that we need in the link is the href and endpoints we will reuse + // some known discoverable resource + client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) { + resourceLink, ok := links.GetResourceLink(configuration.ResourceURI) + if !ok { + return schema.ResourceLink{}, fmt.Errorf("failed to get resource link: %w", err) + } + resourceLink.Href = href + return resourceLink, nil + }), + }, + }, + want: coap.DetailedResponse[interface{}]{ + Code: codes.Content, + Body: map[interface{}]interface{}{ + "value": false, + }, + }, + }, { name: "invalid href", args: args{ @@ -103,17 +146,6 @@ func TestClientGetResource(t *testing.T) { }, } - c, err := NewTestSecureClient() - require.NoError(t, err) - defer func() { - errC := c.Close(context.Background()) - require.NoError(t, errC) - }() - ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) - defer cancel() - deviceID, err = c.OwnDevice(ctx, deviceID) - require.NoError(t, err) - defer disown(t, c, deviceID) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var got coap.DetailedResponse[interface{}] diff --git a/client/observeResource.go b/client/observeResource.go index 7c278b4a..c8c9ea7f 100644 --- a/client/observeResource.go +++ b/client/observeResource.go @@ -225,22 +225,17 @@ func (c *Client) ObserveResource( return getObservationID(key, resourceObservationID.String()), nil } - d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration)) + device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback}) if err != nil { return "", err } - link, err := core.GetResourceLink(links, href) + observationID, err = device.ObserveResourceWithCodec(ctx, link, observerCodec{contentFormat: cfg.codec.ContentFormat()}, h, cfg.opts...) if err != nil { return "", err } - observationID, err = d.ObserveResourceWithCodec(ctx, link, observerCodec{contentFormat: cfg.codec.ContentFormat()}, h, cfg.opts...) - if err != nil { - return "", err - } - - dev, _ := c.deviceCache.UpdateOrStoreDevice(d) + dev, _ := c.deviceCache.UpdateOrStoreDevice(device) h.observationID = observationID h.device = dev diff --git a/client/observeResource_test.go b/client/observeResource_test.go index 453bd6bb..c0e73cc6 100644 --- a/client/observeResource_test.go +++ b/client/observeResource_test.go @@ -37,6 +37,7 @@ import ( "github.com/plgd-dev/device/v2/schema/resources" "github.com/plgd-dev/device/v2/schema/softwareupdate" "github.com/plgd-dev/device/v2/test" + "github.com/plgd-dev/device/v2/test/resource/types" "github.com/plgd-dev/go-coap/v3/message/codes" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -207,6 +208,79 @@ func TestObservingResource(t *testing.T) { testDevice(t, test.DevsimName, runObservingResourceTest) } +func TestObservingNonDiscoverableResource(t *testing.T) { + testDevice(t, test.DevsimName, func(ctx context.Context, t *testing.T, c *client.Client, deviceID string) { + // link not found callback + linkNotFoundCallback := func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) { + // as the resource in not discoverable, we need to provide the link with the correct href + // and endpoints. We will done it by using some known discoverable resource and patching the href + resourceLink, _ := links.GetResourceLink(test.TestResourceLightInstanceHref("1")) + resourceLink.Href = href + return resourceLink, nil + } + + // create a non-discoverable switch resource + var got map[string]interface{} + err := c.CreateResource(ctx, deviceID, test.TestResourceSwitchesHref, test.MakeNonDiscoverableSwitchData(), &got) + require.NoError(t, err) + defer func() { + errCleanup := c.DeleteResource(ctx, deviceID, test.TestResourceSwitchesInstanceHref("1"), nil, client.WithLinkNotFoundCallback(linkNotFoundCallback)) + require.NoError(t, errCleanup) + }() + // remove the instance parameter as the number is assigned by the device and we can't predict its value + delete(got, "ins") + require.Equal(t, test.MakeSwitchResourceData(map[string]interface{}{ + "href": test.TestResourceSwitchesInstanceHref("1"), + "rep": map[interface{}]interface{}{ + "if": []interface{}{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE}, + "rt": []interface{}{types.BINARY_SWITCH}, + "value": false, + }, + "p": map[interface{}]interface{}{ + "bm": uint64(schema.Observable), // resource is only observable + }, + }), got) + + // start observing the non-discoverable switch resource + observation := makeObservationHandler() + id, err := c.ObserveResource(ctx, deviceID, test.TestResourceSwitchesInstanceHref("1"), observation, client.WithLinkNotFoundCallback(linkNotFoundCallback)) + require.NoError(t, err) + defer func(observationID string) { + _, errC := c.StopObservingResource(ctx, observationID) + require.NoError(t, errC) + }(id) + + // first notification contains the current value + responseDecoder, err := observation.waitForNotification(ctx) + require.NoError(t, err) + response := coap.DetailedResponse[map[string]interface{}]{} + err = responseDecoder(&response) + require.NoError(t, err) + require.False(t, response.Body["value"].(bool)) + + // change the value of the switch and wait for the observation notification + err = c.UpdateResource(ctx, deviceID, test.TestResourceSwitchesInstanceHref("1"), map[string]interface{}{ + "value": true, + }, nil, client.WithLinkNotFoundCallback(linkNotFoundCallback)) + require.NoError(t, err) + + defer func() { + // restore to original value + errRestore := c.UpdateResource(ctx, deviceID, test.TestResourceSwitchesInstanceHref("1"), map[string]interface{}{ + "value": false, + }, nil, client.WithLinkNotFoundCallback(linkNotFoundCallback)) + require.NoError(t, errRestore) + }() + + // second notification contains the new value + responseDecoder, err = observation.waitForNotification(ctx) + require.NoError(t, err) + err = responseDecoder(&response) + require.NoError(t, err) + require.True(t, response.Body["value"].(bool)) + }) +} + func TestObservingDiscoveryResource(t *testing.T) { testDevice(t, test.DevsimName, func(ctx context.Context, t *testing.T, c *client.Client, deviceID string) { h := makeObservationHandler() diff --git a/client/onboardDevice_test.go b/client/onboardDevice_test.go index bf32ed87..87581263 100644 --- a/client/onboardDevice_test.go +++ b/client/onboardDevice_test.go @@ -46,7 +46,7 @@ func TestClientOnboardDevice(t *testing.T) { authorizationProvider: "authorizationProvider", authorizationCode: "authorizationCode", cloudURL: "coaps+tcp://test:5684", - cloudID: "cloudID", + cloudID: "12e02711-b12e-42c9-b83f-784932ad066e", }, }, { @@ -56,7 +56,7 @@ func TestClientOnboardDevice(t *testing.T) { authorizationProvider: "authorizationProvider", authorizationCode: "authorizationCode", cloudURL: "coaps+tcp://test:5684", - cloudID: "cloudID", + cloudID: "12e02711-b12e-42c9-b83f-784932ad066e", }, wantErr: true, }, diff --git a/client/options.go b/client/options.go index 8647bd97..91d29842 100644 --- a/client/options.go +++ b/client/options.go @@ -227,6 +227,46 @@ func WithDiscoveryConfiguration(cfg core.DiscoveryConfiguration) DiscoveryConfig } } +type LinkNotFoundCallback struct { + linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) +} + +func (r LinkNotFoundCallback) applyOnCreate(opts createOptions) createOptions { + opts.linkNotFoundCallback = r.linkNotFoundCallback + return opts +} + +func (r LinkNotFoundCallback) applyOnGet(opts getOptions) getOptions { + opts.linkNotFoundCallback = r.linkNotFoundCallback + return opts +} + +func (r LinkNotFoundCallback) applyOnUpdate(opts updateOptions) updateOptions { + opts.linkNotFoundCallback = r.linkNotFoundCallback + return opts +} + +func (r LinkNotFoundCallback) applyOnObserve(opts observeOptions) observeOptions { + opts.linkNotFoundCallback = r.linkNotFoundCallback + return opts +} + +func (r LinkNotFoundCallback) applyOnDelete(opts deleteOptions) deleteOptions { + opts.linkNotFoundCallback = r.linkNotFoundCallback + return opts +} + +// WithLinkNotFoundCallback is used if the target of the link is not known e.g. the resource is not present on the device +// or the resource is non-discoverable. +// linkNotFoundCallback is a function which is called with links and href of the resource. +// It returns a link and an error. If the error is not nil, then the link is skipped. +// Otherwise the link is replaced with the returned link. +func WithLinkNotFoundCallback(linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error)) LinkNotFoundCallback { + return LinkNotFoundCallback{ + linkNotFoundCallback: linkNotFoundCallback, + } +} + // GetOption option definition. type GetOption = interface { applyOnGet(opts getOptions) getOptions @@ -236,24 +276,28 @@ type getOptions struct { opts []coap.OptionFunc codec coap.Codec discoveryConfiguration core.DiscoveryConfiguration + linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) } type updateOptions struct { opts []coap.OptionFunc codec coap.Codec discoveryConfiguration core.DiscoveryConfiguration + linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) } type createOptions struct { opts []coap.OptionFunc codec coap.Codec discoveryConfiguration core.DiscoveryConfiguration + linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) } type deleteOptions struct { opts []coap.OptionFunc codec coap.Codec discoveryConfiguration core.DiscoveryConfiguration + linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) } // CreateOption option definition. @@ -388,6 +432,7 @@ type observeOptions struct { opts []coap.OptionFunc resourceInterface string discoveryConfiguration core.DiscoveryConfiguration + linkNotFoundCallback func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) } // ObserveOption option definition. diff --git a/client/updateResource.go b/client/updateResource.go index 0e22d049..518ac28c 100644 --- a/client/updateResource.go +++ b/client/updateResource.go @@ -42,15 +42,10 @@ func (c *Client) UpdateResource( cfg = o.applyOnUpdate(cfg) } - d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration)) + device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback}) if err != nil { return err } - link, err := core.GetResourceLink(links, href) - if err != nil { - return err - } - - return d.UpdateResourceWithCodec(ctx, link, cfg.codec, request, response, cfg.opts...) + return device.UpdateResourceWithCodec(ctx, link, cfg.codec, request, response, cfg.opts...) } diff --git a/client/updateResource_test.go b/client/updateResource_test.go index 5d0e03f9..f0574678 100644 --- a/client/updateResource_test.go +++ b/client/updateResource_test.go @@ -23,6 +23,7 @@ import ( "github.com/plgd-dev/device/v2/client" "github.com/plgd-dev/device/v2/client/core" "github.com/plgd-dev/device/v2/pkg/net/coap" + "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/configuration" "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" @@ -33,6 +34,24 @@ import ( func TestClientUpdateResource(t *testing.T) { deviceID := test.MustFindDeviceByName(test.DevsimName) + ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) + defer cancel() + + c, err := NewTestSecureClient() + require.NoError(t, err) + defer func() { + errC := c.Close(context.Background()) + require.NoError(t, errC) + }() + + deviceID, err = c.OwnDevice(ctx, deviceID) + require.NoError(t, err) + defer disown(t, c, deviceID) + + var nonDiscoverableResource map[string]interface{} + err = c.CreateResource(ctx, deviceID, test.TestResourceSwitchesHref, test.MakeNonDiscoverableSwitchData(), &nonDiscoverableResource) + require.NoError(t, err) + type args struct { deviceID string href string @@ -79,6 +98,33 @@ func TestClientUpdateResource(t *testing.T) { }, }, }, + { + name: "update non-discoverable resource", + args: args{ + deviceID: deviceID, + href: nonDiscoverableResource["href"].(string), + data: map[string]interface{}{ + "value": true, + }, + opts: []client.UpdateOption{ + client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()), + // create the link for non-discoverable resource by utilizing the linkNotFoundCallback + // as the only thing that we need in the link is the href and endpoints we will reuse + // some known discoverable resource + client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) { + resourceLink, _ := links.GetResourceLink(configuration.ResourceURI) + resourceLink.Href = href + return resourceLink, nil + }), + }, + }, + want: coap.DetailedResponse[interface{}]{ + Code: codes.Changed, + Body: map[interface{}]interface{}{ + "value": true, + }, + }, + }, { name: "valid - revert update", args: args{ @@ -115,19 +161,6 @@ func TestClientUpdateResource(t *testing.T) { wantErr: true, }, } - ctx, cancel := context.WithTimeout(context.Background(), TestTimeout) - defer cancel() - - c, err := NewTestSecureClient() - require.NoError(t, err) - defer func() { - errC := c.Close(context.Background()) - require.NoError(t, errC) - }() - - deviceID, err = c.OwnDevice(ctx, deviceID) - require.NoError(t, err) - defer disown(t, c, deviceID) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/test/test.go b/test/test.go index 6d3713ce..ae972960 100644 --- a/test/test.go +++ b/test/test.go @@ -263,6 +263,17 @@ func MakeSwitchResourceData(overrides map[string]interface{}) map[string]interfa return data } +func MakeNonDiscoverableSwitchData() map[string]interface{} { + // create a non-discoverable switch resource + overrideParameters := map[string]interface{}{ + "if": []interface{}{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE}, + "p": map[interface{}]interface{}{ + "bm": uint64(schema.Observable), // let's make the resource only observable + }, + } + return MakeSwitchResourceData(overrideParameters) +} + func DefaultDevsimResourceLinks() schema.ResourceLinks { res := TestDevsimResources res = append(res, TestDevsimSecResources...)