Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Use Sandbox for Testing #360

Merged
merged 17 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from 8 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
14 changes: 14 additions & 0 deletions .test-env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Configs for testing repo download:
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
SDK_TESTING_BRANCH="trim-indexer"
tzaffi marked this conversation as resolved.
Show resolved Hide resolved
SDK_TESTING_HARNESS="test-harness"

VERBOSE_HARNESS=0

# WARNING: If set to 1, new features will be LOST when downloading the test harness.
# REGARDLESS: modified features are ALWAYS overwritten.
REMOVE_LOCAL_FEATURES=0

# WARNING: Be careful when turning on the next variable.
# In that case you'll need to provide all variables expected by `algorand-sdk-testing`'s `.env`
OVERWRITE_TESTING_ENVIRONMENT=0
tzaffi marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 18 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
SRCPATH := $(shell pwd)
TEST_SOURCES := $(shell cd $(SRCPATH) && go list ./...)
TEST_SOURCES_NO_CUCUMBER := $(shell cd $(SRCPATH) && go list ./... | grep -v test)
GO_IMAGE := golang:$(subst go,,$(shell go version | cut -d' ' -f 3 | cut -d'.' -f 1,2))-stretch

lint:
golint `go list ./... | grep -v /vendor/`
Expand All @@ -17,15 +18,28 @@ build: generate
test:
go test $(TEST_SOURCES_NO_CUCUMBER)

UNITS = "@unit.sourcemap,@unit.offline,@unit.algod,@unit.indexer,@unit.transactions.keyreg,@unit.rekey,@unit.tealsign,@unit.dryrun,@unit.responses,@unit.applications,@unit.transactions,@unit.indexer.rekey,@unit.responses.messagepack,@unit.responses.231,@unit.responses.messagepack.231,@unit.responses.genesis,@unit.feetest,@unit.indexer.logs,@unit.abijson,@unit.abijson.byname,@unit.transactions.payment,@unit.atomic_transaction_composer,@unit.responses.unlimited_assets,@unit.indexer.ledger_refactoring,@unit.algod.ledger_refactoring,@unit.dryrun.trace.application"
unit:
go test $(TEST_SOURCES_NO_CUCUMBER)
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@unit.sourcemap,@unit.offline,@unit.algod,@unit.indexer,@unit.transactions.keyreg,@unit.rekey,@unit.tealsign,@unit.dryrun,@unit.responses,@unit.applications,@unit.transactions,@unit.indexer.rekey,@unit.responses.messagepack,@unit.responses.231,@unit.responses.messagepack.231,@unit.responses.genesis,@unit.feetest,@unit.indexer.logs,@unit.abijson,@unit.abijson.byname,@unit.transactions.payment,@unit.atomic_transaction_composer,@unit.responses.unlimited_assets,@unit.indexer.ledger_refactoring,@unit.algod.ledger_refactoring,@unit.dryrun.trace.application" --test.v .
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags=$(UNITS) --test.v .

INTEGRATIONS = "@algod,@assets,@auction,@kmd,@send,@indexer,@rekey_v1,@send.keyregtxn,@dryrun,@compile,@applications.verified,@indexer.applications,@indexer.231,@abi,@c2c,@compile.sourcemap"
michaeldiamant marked this conversation as resolved.
Show resolved Hide resolved
integration:
go test $(TEST_SOURCES_NO_CUCUMBER)
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@algod,@assets,@auction,@kmd,@send,@indexer,@rekey_v1,@send.keyregtxn,@dryrun,@compile,@applications.verified,@indexer.applications,@indexer.231,@abi,@c2c,@compile.sourcemap" --test.v .
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags=$(INTEGRATIONS) --test.v .

harness:
./test-harness.sh

docker-gosdk-build:
echo "Building docker image from base $(GO_IMAGE)"
docker build -t go-sdk-testing --build-arg GO_IMAGE="$(GO_IMAGE)" -f test/docker/Dockerfile $(shell pwd)

docker-gosdk-run:
docker ps -a
docker run -it --network host go-sdk-testing:latest

docker-test: harness docker-gosdk-build docker-gosdk-run

docker-test:
./test/docker/run_docker.sh

.PHONY: test fmt
62 changes: 62 additions & 0 deletions test-harness.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash

set -euo pipefail

START=$(date "+%s")

THIS=$(basename "$0")
ENV_FILE=".test-env"
TEST_DIR="test"

set -a
source "$ENV_FILE"
set +a

rootdir=$(dirname "$0")
pushd "$rootdir"

## Reset test harness
if [ -d "$SDK_TESTING_HARNESS" ]; then
pushd "$SDK_TESTING_HARNESS"
./scripts/down.sh
popd
rm -rf "$SDK_TESTING_HARNESS"
else
echo "$THIS: directory $SDK_TESTING_HARNESS does not exist - NOOP"
fi

git clone --depth 1 --single-branch --branch "$SDK_TESTING_BRANCH" "$SDK_TESTING_URL" "$SDK_TESTING_HARNESS"


if [[ $OVERWRITE_TESTING_ENVIRONMENT == 1 ]]; then
echo "$THIS: OVERWRITE replaced $SDK_TESTING_HARNESS/.env with $ENV_FILE:"
cp "$ENV_FILE" "$SDK_TESTING_HARNESS"/.env
fi

## Copy feature files into the project resources
if [[ $REMOVE_LOCAL_FEATURES == 1 ]]; then
echo "$THIS: OVERWRITE wipes clean $TEST_DIR/features"
if [[ $VERBOSE_HARNESS == 1 ]]; then
( tree $TEST_DIR/features && echo "$THIS: see the previous for files deleted" ) || true
fi
rm -rf $TEST_DIR/features
fi
mkdir -p $TEST_DIR/features
cp -r "$SDK_TESTING_HARNESS"/features/* $TEST_DIR/features
if [[ $VERBOSE_HARNESS == 1 ]]; then
( tree $TEST_DIR/features && echo "$THIS: see the previous for files copied over" ) || true
fi
echo "$THIS: seconds it took to get to end of cloning and copying: $(($(date "+%s") - START))s"


## Start test harness environment
pushd "$SDK_TESTING_HARNESS"
./scripts/up.sh
popd
echo "$THIS: seconds it took to finish testing sdk's up.sh: $(($(date "+%s") - START))s"
echo ""
echo "--------------------------------------------------------------------------------"
echo "|"
echo "| To run sandbox commands, cd into $SDK_TESTING_HARNESS/.sandbox "
echo "|"
echo "--------------------------------------------------------------------------------"
3 changes: 1 addition & 2 deletions test/algodclientv2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"

"github.com/algorand/go-algorand-sdk/client/v2/algod"
"github.com/algorand/go-algorand-sdk/client/v2/common/models"
modelsV2 "github.com/algorand/go-algorand-sdk/client/v2/common/models"
"github.com/algorand/go-algorand-sdk/types"

Expand Down Expand Up @@ -198,7 +197,7 @@ func weMakeAGetBlockCallAgainstBlockNumberWithFormat(blocknum int, format string
return weMakeAGetBlockCallAgainstBlockNumber(blocknum)
}

var dryrunResponse models.DryrunResponse
var dryrunResponse modelsV2.DryrunResponse

func weMakeAnyDryrunCall() (err error) {
algodClient, err := algod.MakeClient(mockServer.URL, "")
Expand Down
120 changes: 2 additions & 118 deletions test/applications_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"regexp"
"strconv"
"strings"
"time"

"github.com/cucumber/godog"

Expand Down Expand Up @@ -211,7 +210,7 @@ func iBuildAnApplicationTransaction(
}

case "call":
tx, err = future.MakeApplicationCallTx(applicationId, args, accs,
tx, _ = future.MakeApplicationCallTx(applicationId, args, accs,
fApp, fAssets, types.NoOpOC, approvalP, clearP, gSchema, lSchema,
suggestedParams, transientAccount.Address, nil, types.Digest{}, [32]byte{}, types.Address{})
case "optin":
Expand Down Expand Up @@ -448,124 +447,11 @@ func theTransientAccountShouldHave(appCreated string, byteSlices, uints int,
}
}
if !found {
fmt.Errorf("Could not find key '%s'", key)
return fmt.Errorf("Could not find key '%s'", key)
}
return nil
}

func theUnconfirmedPendingTransactionByIDShouldHaveNoApplyDataFields() error {
status, _, err := algodV2client.PendingTransactionInformation(txid).Do(context.Background())
if err != nil {
return err
}
if status.ConfirmedRound == 0 {
if len(status.GlobalStateDelta) != 0 {
return fmt.Errorf("unexpected global state delta, there should be none: %v", status.GlobalStateDelta)
}
if len(status.LocalStateDelta) != 0 {
return fmt.Errorf("unexpected local state delta, there should be none: %v", status.LocalStateDelta)
}
}
return nil
}

func getAccountDelta(addr string, data []models.AccountStateDelta) []models.EvalDeltaKeyValue {
for _, v := range data {
if v.Address == addr {
return v.Delta
}
}
return nil
}
func theConfirmedPendingTransactionByIDShouldHaveAStateChangeForToIndexerShouldAlsoConfirmThis(stateLocation, key, newValue string, indexer int) error {
status, _, err := algodV2client.PendingTransactionInformation(txid).Do(context.Background())
if err != nil {
return err
}

c1 := make(chan models.Transaction, 1)

go func() {
for true {
indexerResponse, _ := indexerClients[indexer].SearchForTransactions().TXID(txid).Do(context.Background())
if len(indexerResponse.Transactions) == 1 {
c1 <- indexerResponse.Transactions[0]
}
time.Sleep(time.Second)
}
}()

var indexerTx models.Transaction
select {
case res := <-c1:
indexerTx = res
case <-time.After(5 * time.Second):
return fmt.Errorf("timeout waiting for indexer trasaction")
}

var algodKeyValues []models.EvalDeltaKeyValue
var indexerKeyValues []models.EvalDeltaKeyValue

switch stateLocation {
case "local":
addr := indexerTx.Sender
algodKeyValues = getAccountDelta(addr, status.LocalStateDelta)
indexerKeyValues = getAccountDelta(addr, indexerTx.LocalStateDelta)
case "global":
algodKeyValues = status.GlobalStateDelta
indexerKeyValues = indexerTx.GlobalStateDelta
default:
return fmt.Errorf("unknown location: " + stateLocation)
}

// algod
if len(algodKeyValues) != 1 {
return fmt.Errorf("expected 1 key value, found: %d", len(algodKeyValues))
}
if algodKeyValues[0].Key != key {
return fmt.Errorf("wrong key in algod: %s != %s", algodKeyValues[0].Key, key)
}

// indexer
if len(indexerKeyValues) != 1 {
return fmt.Errorf("expected 1 key value, found: %d", len(indexerKeyValues))
}
if indexerKeyValues[0].Key != key {
return fmt.Errorf("wrong key in indexer: %s != %s", indexerKeyValues[0].Key, key)
}

if indexerKeyValues[0].Value.Action != algodKeyValues[0].Value.Action {
return fmt.Errorf("action mismatch between algod and indexer")
}

switch algodKeyValues[0].Value.Action {
case uint64(1):
// bytes
if algodKeyValues[0].Value.Bytes != newValue {
return fmt.Errorf("algod value mismatch: %s != %s", algodKeyValues[0].Value.Bytes, newValue)
}
if indexerKeyValues[0].Value.Bytes != newValue {
return fmt.Errorf("indexer value mismatch: %s != %s", indexerKeyValues[0].Value.Bytes, newValue)
}
case uint64(2):
// int
newValueInt, err := strconv.ParseUint(newValue, 10, 64)
if err != nil {
return fmt.Errorf("problem parsing new int value: %s", newValue)
}

if algodKeyValues[0].Value.Uint != newValueInt {
return fmt.Errorf("algod value mismatch: %d != %s", algodKeyValues[0].Value.Uint, newValue)
}
if indexerKeyValues[0].Value.Uint != newValueInt {
return fmt.Errorf("indexer value mismatch: %d != %s", indexerKeyValues[0].Value.Uint, newValue)
}
default:
return fmt.Errorf("unexpected action: %d", algodKeyValues[0].Value.Action)
}

return nil
}

func suggestedParamsAlgodV2() error {
var err error
Expand Down Expand Up @@ -883,8 +769,6 @@ func ApplicationsContext(s *godog.Suite) {
s.Step(`^I get the account address for the current application and see that it matches the app id\'s hash$`, iGetTheAccountAddressForTheCurrentApp)
s.Step(`^The transient account should have the created app "([^"]*)" and total schema byte-slices (\d+) and uints (\d+), the application "([^"]*)" state contains key "([^"]*)" with value "([^"]*)"$`,
theTransientAccountShouldHave)
s.Step(`^the unconfirmed pending transaction by ID should have no apply data fields\.$`, theUnconfirmedPendingTransactionByIDShouldHaveNoApplyDataFields)
s.Step(`^the confirmed pending transaction by ID should have a "([^"]*)" state change for "([^"]*)" to "([^"]*)", indexer (\d+) should also confirm this\.$`, theConfirmedPendingTransactionByIDShouldHaveAStateChangeForToIndexerShouldAlsoConfirmThis)
s.Step(`^suggested transaction parameters from the algod v2 client$`, suggestedParamsAlgodV2)
s.Step(`^I add the current transaction with signer to the composer\.$`, iAddTheCurrentTransactionWithSignerToTheComposer)
s.Step(`^I clone the composer\.$`, iCloneTheComposer)
Expand Down
20 changes: 0 additions & 20 deletions test/applications_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package test

import (
"context"
"encoding/base64"
"fmt"
"github.com/algorand/go-algorand-sdk/types"

"github.com/cucumber/godog"

Expand Down Expand Up @@ -37,24 +35,6 @@ func feeFieldNotInTxn() error {
return nil
}

func getSuggestedParams(
fee, fv, lv uint64,
gen, ghb64 string,
flat bool) (types.SuggestedParams, error) {
gh, err := base64.StdEncoding.DecodeString(ghb64)
if err != nil {
return types.SuggestedParams{}, err
}
return types.SuggestedParams{
Fee: types.MicroAlgos(fee),
GenesisID: gen,
GenesisHash: gh,
FirstRoundValid: types.Round(fv),
LastRoundValid: types.Round(lv),
FlatFee: flat,
}, err
}

func weMakeAGetAssetByIDCall(assetID int) error {
clt, err := algod.MakeClient(mockServer.URL, "")
if err != nil {
Expand Down
25 changes: 0 additions & 25 deletions test/docker/run_docker.sh

This file was deleted.

21 changes: 0 additions & 21 deletions test/docker/sdk.py

This file was deleted.

Loading