Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/workflows/wasm/host/internal/rawsdk/helpers_wasip1.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ func await[I, O proto.Message](input I, output O, fn awaitFn) {
bytes := fn(mptr, mlen, responsePtr, responseLen)

if bytes < 0 {
SendError(errors.New("awaitCapabilities returned an error"))
response = response[:-bytes]
SendError(fmt.Errorf("awaitCapabilities returned an error %s", string(response)))
}

if proto.Unmarshal(response[:bytes], output) != nil {
Expand Down
4 changes: 3 additions & 1 deletion pkg/workflows/wasm/host/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,9 @@ func truncateWasmWrite(caller *wasmtime.Caller, src []byte, ptr int32, size int3
src = src[:size]
}

return write(memory, src, ptr, size)
// truncateWasmWrite is only called for returning error strings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then maybe rename the function to make it more explicit?

// Therefore, we need to return the negated bytes written to indicate the failure to the guest.
return -write(memory, src, ptr, size)
}

// write copies the given src byte slice into the memory at the given pointer and max size.
Expand Down
31 changes: 31 additions & 0 deletions pkg/workflows/wasm/host/standard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,37 @@ func TestStandardCapabilityCallsAreAsync(t *testing.T) {
assert.Equal(t, "truefalse", result)
}

func TestStandardHostWasmWriteErrorsAreRespected(t *testing.T) {
t.Parallel()
mockExecutionHelper := NewMockExecutionHelper(t)
mockExecutionHelper.EXPECT().GetNodeTime().RunAndReturn(func() time.Time {
return time.Now()
}).Maybe()
mockExecutionHelper.EXPECT().GetWorkflowExecutionID().Return("id")
mockExecutionHelper.EXPECT().CallCapability(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, request *sdk.CapabilityRequest) (*sdk.CapabilityResponse, error) {
// In this test the response from the capability is successful,
// but the WASM didn't provide a large enough buffer to fit it
// 500 MB will suffice for the overflow on writes.

tooLargeResponse := make([]byte, 500000000)

// Since the bytes in the payload shouldn't be read, we don't need a valid proto
payload := &anypb.Any{
TypeUrl: "fake",
Value: tooLargeResponse,
}

return &sdk.CapabilityResponse{Response: &sdk.CapabilityResponse_Payload{Payload: payload}}, nil
})

m := makeTestModule(t)
request := triggerExecuteRequest(t, 0, &basictrigger.Outputs{CoolOutput: anyTestTriggerValue})
errStr := executeWithError(t, m, request, mockExecutionHelper)

// Use Contains instead of Equal for flexibility, as languages have different conventions for errors.
require.Contains(t, errStr, ResponseBufferTooSmall)
}

func TestStandardModeSwitch(t *testing.T) {
t.Parallel()
t.Run("successful mode switch", func(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/protoc/pkg/test_capabilities/basicaction"
"github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host/internal/rawsdk"
"github.com/smartcontractkit/chainlink-protos/cre/go/sdk"
)

func main() {
input := &basicaction.Inputs{InputThing: true}
rId := rawsdk.DoRequestAsync("basic-test-action@1.0.0", "PerformAction", sdk.Mode_MODE_DON, input)

rawsdk.Await(rId, &basicaction.Outputs{})
rawsdk.SendResponse("should not get here as Await sends error on errors...")
}
Loading