diff --git a/runtime/stdlib/contracts/test.cdc b/runtime/stdlib/contracts/test.cdc index c303ae0422..83c0d3cdc2 100644 --- a/runtime/stdlib/contracts/test.cdc +++ b/runtime/stdlib/contracts/test.cdc @@ -504,4 +504,20 @@ access(all) contract Test { access(all) native fun beLessThan(_ value: Number): Test.Matcher {} + /// Read a local file, and return the content as a string. + /// + access(all) + native fun readFile(_ path: String): String {} + + /// Fails the test-case if the given condition is false, + /// and reports a message which explains how the condition is false. + /// + access(all) + native fun assert(_ condition: Bool, message: String): Void {} + + /// Fails the test-case with a message. + /// + access(all) + native fun fail(message: String): Void {} + } diff --git a/runtime/stdlib/test_test.go b/runtime/stdlib/test_test.go index 8ae63d78dc..6772ec871e 100644 --- a/runtime/stdlib/test_test.go +++ b/runtime/stdlib/test_test.go @@ -664,6 +664,74 @@ func TestTestEqualMatcher(t *testing.T) { }) } +func TestAssertFunction(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testAssertWithNoArgs() { + Test.assert(true) + } + + pub fun testAssertWithNoArgsFail() { + Test.assert(false) + } + + pub fun testAssertWithMessage() { + Test.assert(true, message: "some reason") + } + + pub fun testAssertWithMessageFail() { + Test.assert(false, message: "some reason") + } + ` + + inter, err := newTestContractInterpreter(t, script) + require.NoError(t, err) + + _, err = inter.Invoke("testAssertWithNoArgs") + require.NoError(t, err) + + _, err = inter.Invoke("testAssertWithNoArgsFail") + require.Error(t, err) + assert.ErrorContains(t, err, "assertion failed") + + _, err = inter.Invoke("testAssertWithMessage") + require.NoError(t, err) + + _, err = inter.Invoke("testAssertWithMessageFail") + require.Error(t, err) + require.ErrorContains(t, err, "assertion failed: some reason") +} + +func TestFailFunction(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testFailWithoutMessage() { + Test.fail() + } + + pub fun testFailWithMessage() { + Test.fail(message: "some error") + } + ` + + inter, err := newTestContractInterpreter(t, script) + require.NoError(t, err) + + _, err = inter.Invoke("testFailWithoutMessage") + require.Error(t, err) + require.ErrorContains(t, err, "assertion failed") + + _, err = inter.Invoke("testFailWithMessage") + require.Error(t, err) + require.ErrorContains(t, err, "assertion failed: some error") +} + func TestAssertEqual(t *testing.T) { t.Parallel() @@ -2649,6 +2717,77 @@ func TestBlockchain(t *testing.T) { assert.True(t, getAccountInvoked) }) + t.Run("readFile", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun test() { + let content = Test.readFile("some_file.cdc") + Test.assertEqual("Hey there!", content) + } + ` + + readFileInvoked := false + + testFramework := &mockedTestFramework{ + emulatorBackend: func() stdlib.Blockchain { + return &mockedBlockchain{} + }, + readFile: func(path string) (string, error) { + readFileInvoked = true + assert.Equal(t, "some_file.cdc", path) + + return "Hey there!", nil + }, + } + + inter, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + require.NoError(t, err) + + _, err = inter.Invoke("test") + require.NoError(t, err) + + assert.True(t, readFileInvoked) + }) + + t.Run("readFile with failure", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun test() { + let content = Test.readFile("some_file.cdc") + Test.assertEqual("Hey there!", content) + } + ` + + readFileInvoked := false + + testFramework := &mockedTestFramework{ + emulatorBackend: func() stdlib.Blockchain { + return &mockedBlockchain{} + }, + readFile: func(path string) (string, error) { + readFileInvoked = true + assert.Equal(t, "some_file.cdc", path) + + return "", fmt.Errorf("could not read file: %s", path) + }, + } + + inter, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + require.NoError(t, err) + + _, err = inter.Invoke("test") + require.Error(t, err) + assert.ErrorContains(t, err, "could not read file: some_file.cdc") + + assert.True(t, readFileInvoked) + }) + // TODO: Add more tests for the remaining functions. }