diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml deleted file mode 100644 index d3289a834c..0000000000 --- a/.github/workflows/bindings-ts.yml +++ /dev/null @@ -1,50 +0,0 @@ - -name: bindings typescript - -on: - push: - branches: [main, release/**] - pull_request: - -jobs: - test: - name: test generated libraries - runs-on: ubuntu-22.04 - services: - rpc: - image: stellar/quickstart:testing@sha256:6377ce642644e06e42444d2b00a8ce52eee7529f5a5f1d02cb64a29f88f05bfa - ports: - - 8000:8000 - env: - ENABLE_LOGS: true - NETWORK: local - ENABLE_SOROBAN_RPC: true - options: >- - --health-cmd "curl --no-progress-meter --fail-with-body -X POST \"http://localhost:8000/soroban/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}' && curl --no-progress-meter \"http://localhost:8000/friendbot\" | grep '\"invalid_field\": \"addr\"'" - --health-interval 10s - --health-timeout 5s - --health-retries 50 - steps: - - run: echo $CARGO_TARGET_DIR - - uses: actions/checkout@v3 - - run: "curl --fail-with-body -X POST \"http://localhost:8000/soroban/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}'" - - run: curl --no-progress-meter "http://localhost:8000/friendbot?addr=$(./soroban config identity address)" - working-directory: cmd/crates/soroban-spec-typescript/ts-tests - - run: ./soroban config identity fund --network standalone - working-directory: cmd/crates/soroban-spec-typescript/ts-tests - - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - run: rustup update - - run: cargo build - - run: rustup target add wasm32-unknown-unknown - - run: make build-test-wasms - - run: curl "http://localhost:8000/friendbot?addr=$(./soroban config identity address)" - - run: npm ci && npm run test - working-directory: cmd/crates/soroban-spec-typescript/ts-tests diff --git a/.github/workflows/soroban-rpc.yml b/.github/workflows/soroban-rpc.yml index bd3bf21122..95daa3e1ee 100644 --- a/.github/workflows/soroban-rpc.yml +++ b/.github/workflows/soroban-rpc.yml @@ -100,8 +100,8 @@ jobs: CGO_ENABLED: 1 GOARCH: ${{ matrix.go_arch }} - cli: - name: CLI integration tests + integration: + name: Integration tests strategy: matrix: os: [ubuntu-20.04] @@ -170,80 +170,6 @@ jobs: - name: Build libpreflight run: make build-libpreflight - - name: Run CLI tests + - name: Run Soroban RPC Integration Tests run: | - go test -race -run '.*CLI.*' -timeout 60m -v ./cmd/soroban-rpc/internal/test/... - - non-cli: - name: TypeScript Bindings - strategy: - matrix: - os: [ubuntu-20.04] - go: [1.20.1] - env: - SOROBAN_RPC_INTEGRATION_TESTS_ENABLED: true - SOROBAN_RPC_INTEGRATION_TESTS_CAPTIVE_CORE_BIN: /usr/bin/stellar-core - PROTOCOL_20_CORE_DEBIAN_PKG_VERSION: 19.13.1-1481.3acf6dd26.focal - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - with: - # For pull requests, build and test the PR head not a merge of the PR with the destination. - ref: ${{ github.event.pull_request.head.sha || github.ref }} - # We need to full history for git-restore-mtime to know what modification dates to use. - # Otherwise, the Go test cache will fail (due to the modification time of fixtures changing). - fetch-depth: "0" - - - uses: ./.github/actions/setup-go - with: - go-version: ${{ matrix.go }} - - uses: stellar/actions/rust-cache@main - - name: Build soroban contract fixtures - run: | - rustup update - rustup target add wasm32-unknown-unknown - make build_rust - make build-test-wasms - - - name: Install Captive Core - run: | - # Workaround for https://github.com/actions/virtual-environments/issues/5245, - # libc++1-8 won't be installed if another version is installed (but apt won't give you a helpful - # message about why the installation fails) - sudo apt-get remove -y libc++1-10 libc++abi1-10 || true - - sudo wget -qO - https://apt.stellar.org/SDF.asc | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=true sudo apt-key add - - sudo bash -c 'echo "deb https://apt.stellar.org focal unstable" > /etc/apt/sources.list.d/SDF-unstable.list' - sudo apt-get update && sudo apt-get install -y stellar-core="$PROTOCOL_20_CORE_DEBIAN_PKG_VERSION" - echo "Using stellar core version $(stellar-core version)" - - # Docker-compose's remote contexts on Ubuntu 20 started failing with an OpenSSL versioning error. - # See https://stackoverflow.com/questions/66579446/error-executing-docker-compose-building-webserver-unable-to-prepare-context-un - - name: Work around Docker Compose problem - run: | - sudo apt-get update - sudo apt-get install -y ca-certificates curl gnupg - - # Install docker apt repo - sudo install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - sudo chmod a+r /etc/apt/keyrings/docker.gpg - echo \ - "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ - "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ - sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - - # Install docker-compose v2 from apt repo - sudo apt-get update - sudo apt-get remove -y moby-compose - sudo apt-get install -y docker-compose-plugin - - echo "Docker Compose Version:" - docker-compose version - - - name: Build libpreflight - run: make build-libpreflight - - - name: Run non-CLI tests (including TypeScript Bindings) - run: | - go test -race -run '^Test(([^C])|(C[^L])|(CL[^I])).*$' -timeout 60m -v ./cmd/soroban-rpc/internal/test/... + go test -race -timeout 25m -v ./cmd/soroban-rpc/internal/test/... diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index 55368916da..bb3a789acc 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -47,38 +47,23 @@ func TestCLICargoTest(t *testing.T) { func TestCLIWrapCustom(t *testing.T) { NewCLITest(t) testAccount := getCLIDefaultAccount(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("lab token wrap --asset=deadbeef:%s", testAccount)) - require.Equal(t, "true", runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) - runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id=%s -- mint --to=%s --amount 1", strkeyContractID, testAccount)) -} - -func TestTypeScriptBindings(t *testing.T) { - NewCLITest(t) - testDir := "../../../crates/soroban-spec-typescript/ts-tests" - rpcUrl := fmt.Sprintf("SOROBAN_RPC_URL=http://localhost:%d/", sorobanRPCPort) - networkPassphrase := fmt.Sprintf("SOROBAN_NETWORK_PASSPHRASE=%s", StandaloneNetworkPassphrase) - install := newCommand(t, "npm i") - test := newCommand(t, "npm run test") - install.Dir = testDir - test.Dir = testDir - install.Env = append(os.Environ(), rpcUrl, networkPassphrase) - test.Env = append(os.Environ(), rpcUrl, networkPassphrase) - runSuccessfulCmd(t, install) - runSuccessfulCmd(t, test) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("lab token wrap --asset=deadbeef:%s", testAccount)) + require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) + runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- mint --to=%s --amount 1", strkeyContractID, testAccount)) } func TestCLIWrapNative(t *testing.T) { NewCLITest(t) testAccount := getCLIDefaultAccount(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("lab token wrap --asset=native:%s", testAccount)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("lab token wrap --asset=native:%s", testAccount)) require.Equal(t, "CAMTHSPKXZJIRTUXQP5QWJIFH3XIDMKLFAWVQOFOXPTKAW5GKV37ZC4N", strkeyContractID) - require.Equal(t, "true", runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) - require.Equal(t, "\"9223372036854775807\"", runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id=%s -- balance --id %s", strkeyContractID, testAccount))) + require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) + require.Equal(t, "\"9223372036854775807\"", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- balance --id %s", strkeyContractID, testAccount))) } func TestCLIContractInstall(t *testing.T) { NewCLITest(t) - output := runSuccessfulSorobanCmd(t, "contract install --wasm "+helloWorldContractPath) + output := runSuccessfulCLICmd(t, "contract install --wasm "+helloWorldContractPath) wasm := getHelloWorldContract(t) contractHash := xdr.Hash(sha256.Sum256(wasm)) require.Contains(t, output, contractHash.HexString()) @@ -86,16 +71,16 @@ func TestCLIContractInstall(t *testing.T) { func TestCLIContractInstallAndDeploy(t *testing.T) { NewCLITest(t) - runSuccessfulSorobanCmd(t, "contract install --wasm "+helloWorldContractPath) + runSuccessfulCLICmd(t, "contract install --wasm "+helloWorldContractPath) wasm := getHelloWorldContract(t) contractHash := xdr.Hash(sha256.Sum256(wasm)) - output := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt %s --wasm-hash %s", hex.EncodeToString(testSalt[:]), contractHash.HexString())) + output := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt %s --wasm-hash %s", hex.EncodeToString(testSalt[:]), contractHash.HexString())) outputsContractIDInLastLine(t, output) } func TestCLIContractDeploy(t *testing.T) { NewCLITest(t) - output := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt %s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + output := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt %s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) outputsContractIDInLastLine(t, output) } @@ -115,17 +100,17 @@ func outputsContractIDInLastLine(t *testing.T, output string) { func TestCLIContractDeployAndInvoke(t *testing.T) { NewCLITest(t) - contractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) - output := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- hello --world=world", contractID)) + contractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + output := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- hello --world=world", contractID)) require.Contains(t, output, `["Hello","world"]`) } func TestCLIRestorePreamble(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) - count := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) - count = runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + count = runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "2", count) // Wait for the counter ledger entry to expire and successfully invoke the `inc` contract function again @@ -134,14 +119,14 @@ func TestCLIRestorePreamble(t *testing.T) { client := jrpc2.NewClient(ch, nil) waitForLedgerEntryToExpire(t, client, getExpirationKeyForCounterLedgerEntry(t, strkeyContractID)) - count = runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + count = runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "3", count) } func TestCLIBump(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) - count := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) @@ -150,7 +135,7 @@ func TestCLIBump(t *testing.T) { expirationKey := getExpirationKeyForCounterLedgerEntry(t, strkeyContractID) initialExpirationSeq := getExpirationForLedgerEntry(t, client, expirationKey) - bumpOutput := runSuccessfulSorobanCmd( + bumpOutput := runSuccessfulCLICmd( t, fmt.Sprintf( "contract bump --id %s --key COUNTER --durability persistent --ledgers-to-expire 20", @@ -164,8 +149,8 @@ func TestCLIBump(t *testing.T) { } func TestCLIBumpTooLow(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) - count := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) @@ -186,8 +171,8 @@ func TestCLIBumpTooLow(t *testing.T) { func TestCLIBumpTooHigh(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) - count := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) @@ -205,8 +190,8 @@ func TestCLIBumpTooHigh(t *testing.T) { func TestCLIRestore(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) - count := runSuccessfulSorobanCmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) @@ -218,7 +203,7 @@ func TestCLIRestore(t *testing.T) { // This ensures that the CLI restores the entry (using the RestorePreamble in the simulateTransaction response) waitForLedgerEntryToExpire(t, client, expirationKey) - restoreOutput := runSuccessfulSorobanCmd( + restoreOutput := runSuccessfulCLICmd( t, fmt.Sprintf( "contract restore --id %s --key COUNTER --durability persistent", @@ -243,13 +228,8 @@ func parseContractStrKey(t *testing.T, strkeyContractID string) [32]byte { return contractID } -func runSuccessfulSorobanCmd(t *testing.T, cmdStr string) string { - cmd := newSorobanCommand(t, cmdStr) - return runSuccessfulCmd(t, cmd) -} - -func runSuccessfulCmd(t *testing.T, cmd icmd.Cmd) string { - res := icmd.RunCmd(cmd) +func runSuccessfulCLICmd(t *testing.T, cmd string) string { + res := runCLICommand(t, cmd) stdout, stderr := res.Stdout(), res.Stderr() outputs := fmt.Sprintf("stderr:\n%s\nstdout:\n%s\n", stderr, stdout) require.NoError(t, res.Error, outputs) @@ -257,7 +237,7 @@ func runSuccessfulCmd(t *testing.T, cmd icmd.Cmd) string { return strings.TrimSpace(stdout) } -func newSorobanCommand(t *testing.T, cmd string) icmd.Cmd { +func runCLICommand(t *testing.T, cmd string) *icmd.Result { args := []string{"run", "-q", "--", "--vv"} parsedArgs, err := shlex.Split(cmd) require.NoError(t, err, cmd) @@ -267,22 +247,16 @@ func newSorobanCommand(t *testing.T, cmd string) icmd.Cmd { fmt.Sprintf("SOROBAN_RPC_URL=http://localhost:%d/", sorobanRPCPort), fmt.Sprintf("SOROBAN_NETWORK_PASSPHRASE=%s", StandaloneNetworkPassphrase), ) - return c -} - -func newCommand(t *testing.T, cmd string) icmd.Cmd { - args, err := shlex.Split(cmd) - require.NoError(t, err, cmd) - return icmd.Command(args[0], args[1:]...) + return icmd.RunCmd(c) } func getCLIDefaultAccount(t *testing.T) string { - return runSuccessfulSorobanCmd(t, "config identity address --hd-path 0") + return runSuccessfulCLICmd(t, "config identity address --hd-path 0") } func NewCLITest(t *testing.T) *Test { test := NewTest(t) - fundAccount(t, test, getCLIDefaultAccount(t), "10000000000") + fundAccount(t, test, getCLIDefaultAccount(t), "1000000") return test } @@ -320,7 +294,7 @@ func parseInt(t *testing.T, s string) uint64 { func bump(t *testing.T, contractId string, amount string, rest string) uint64 { - res := runSuccessfulSorobanCmd( + res := runSuccessfulCLICmd( t, fmt.Sprintf( "contract bump --expiration-ledger-only --id=%s --durability persistent --ledgers-to-expire=%s %s",