diff --git a/.github/workflows/pr-integration-tests.yml b/.github/workflows/pr-integration-tests.yml index ae4ee6f9..4658d8e2 100644 --- a/.github/workflows/pr-integration-tests.yml +++ b/.github/workflows/pr-integration-tests.yml @@ -43,3 +43,40 @@ jobs: go get -v -t -d ./... - name: Run integration tests with Elasticsearch `v8.1.1` run: make integration-tests ES_VERSION=8.1.1 + test-3: + name: OpenSearch v1.2.4 + runs-on: ubuntu-latest + steps: + - name: Set up Go 1.x + uses: actions/setup-go@v2 + with: + go-version: ^1.15.6 + id: go + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + go get -v -t -d ./... + - name: Run integration tests with OpenSearch `v1.2.4` + run: make integration-tests-open-search OPEN_VERSION=1.2.4 + + test-4: + name: OpenSearch v1.3.2 + runs-on: ubuntu-latest + steps: + - name: Set up Go 1.x + uses: actions/setup-go@v2 + with: + go-version: ^1.15.6 + id: go + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + go get -v -t -d ./... + - name: Run integration tests with OpenSearch `v1.3.2` + run: make integration-tests-open-search OPEN_VERSION=1.3.2 diff --git a/Makefile b/Makefile index 85faa9c3..e999b544 100644 --- a/Makefile +++ b/Makefile @@ -25,3 +25,10 @@ stop-cluster: delete-cluster-data: cd scripts && ./script.sh delete + +integration-tests-open-search: + @echo " > Running integration tests open search" + cd scripts && ./script.sh start_open_search ${OPEN_VERSION} + go test -v ./integrationtests -tags integrationtests + cd scripts && ./script.sh delete + cd scripts && ./script.sh stop_open_search diff --git a/integrationtests/createNFTWithTags_test.go b/integrationtests/createNFTWithTags_test.go new file mode 100644 index 00000000..8fa30cf4 --- /dev/null +++ b/integrationtests/createNFTWithTags_test.go @@ -0,0 +1,143 @@ +package integrationtests + +import ( + "encoding/json" + indexerdata "github.com/ElrondNetwork/elastic-indexer-go" + "github.com/ElrondNetwork/elastic-indexer-go/mock" + "github.com/ElrondNetwork/elrond-go-core/core" + coreData "github.com/ElrondNetwork/elrond-go-core/data" + dataBlock "github.com/ElrondNetwork/elrond-go-core/data/block" + "github.com/ElrondNetwork/elrond-go-core/data/esdt" + "github.com/ElrondNetwork/elrond-go-core/data/indexer" + "github.com/ElrondNetwork/elrond-go-core/data/transaction" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" + "github.com/stretchr/testify/require" + "math/big" + "testing" +) + +func TestCreateNFTWithTags(t *testing.T) { + setLogLevelDebug() + + esClient, err := createESClient(esURL) + require.Nil(t, err) + + esdtToken := &esdt.ESDigitalToken{ + Value: big.NewInt(1000), + Properties: []byte("ok"), + TokenMetaData: &esdt.MetaData{ + Creator: []byte("creator"), + Attributes: []byte("tags:hello,something,ceva,an,so,on;metadata:QmZ2QqaGq4bqsEzs5JLTjRmmvR2GAR4qXJZBN8ibfDdaud"), + }, + } + + feeComputer := &mock.EconomicsHandlerMock{} + shardCoordinator := &mock.ShardCoordinatorMock{ + SelfID: 0, + } + + header := &dataBlock.Header{ + Round: 51, + TimeStamp: 5600, + } + + addr := "aaaabbbb" + mockAccount := &mock.UserAccountStub{ + RetrieveValueFromDataTrieTrackerCalled: func(key []byte) ([]byte, error) { + return json.Marshal(esdtToken) + }, + AddressBytesCalled: func() []byte { + return []byte(addr) + }, + } + accounts := &mock.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return mockAccount, nil + }, + } + esProc, err := CreateElasticProcessor(esClient, accounts, shardCoordinator, feeComputer) + require.Nil(t, err) + + esdtDataBytes, _ := json.Marshal(esdtToken) + + // CREATE A FIRST NFT WITH THE TAGS + pool := &indexer.Pool{ + Logs: []*coreData.LogData{ + { + TxHash: "h1", + LogHandler: &transaction.Log{ + Events: []*transaction.Event{ + { + Address: []byte("aaaabbbb"), + Identifier: []byte(core.BuiltInFunctionESDTNFTCreate), + Topics: [][]byte{[]byte("DESK-abcd"), big.NewInt(1).Bytes(), big.NewInt(1).Bytes(), esdtDataBytes}, + }, + nil, + }, + }, + }, + }, + } + + body := &dataBlock.Body{} + err = esProc.SaveTransactions(body, header, pool) + require.Nil(t, err) + + ids := []string{"6161616162626262-DESK-abcd-01"} + genericResponse := &GenericResponse{} + err = esClient.DoMultiGet(ids, indexerdata.AccountsESDTIndex, true, genericResponse) + require.Nil(t, err) + require.JSONEq(t, readExpectedResult("./testdata/createNFTWithTags/accounts-esdt-address-balance.json"), string(genericResponse.Docs[0].Source)) + + ids = []string{"aGVsbG8=", "Y2V2YQ==", "YW4=", "b24=", "c28=", "c28="} + genericResponse = &GenericResponse{} + err = esClient.DoMultiGet(ids, indexerdata.TagsIndex, true, genericResponse) + require.Nil(t, err) + + for idx, id := range ids { + expectedDoc := getElementFromSlice("./testdata/createNFTWithTags/tags1.json", idx) + for _, doc := range genericResponse.Docs { + if doc.ID == id { + require.JSONEq(t, expectedDoc, string(doc.Source)) + } + } + } + + // CREATE A SECOND NFT WITH THE SAME TAGS + pool = &indexer.Pool{ + Logs: []*coreData.LogData{ + { + TxHash: "h1", + LogHandler: &transaction.Log{ + Events: []*transaction.Event{ + { + Address: []byte("aaaabbbb"), + Identifier: []byte(core.BuiltInFunctionESDTNFTCreate), + Topics: [][]byte{[]byte("DESK-abcd"), big.NewInt(2).Bytes(), big.NewInt(1).Bytes(), esdtDataBytes}, + }, + nil, + }, + }, + }, + }, + } + + body = &dataBlock.Body{} + err = esProc.SaveTransactions(body, header, pool) + require.Nil(t, err) + + ids = []string{"aGVsbG8=", "Y2V2YQ==", "YW4=", "b24=", "c28=", "c28="} + genericResponse = &GenericResponse{} + err = esClient.DoMultiGet(ids, indexerdata.TagsIndex, true, genericResponse) + require.Nil(t, err) + + for idx, id := range ids { + expectedDoc := getElementFromSlice("./testdata/createNFTWithTags/tags2.json", idx) + for _, doc := range genericResponse.Docs { + if doc.ID == id { + require.JSONEq(t, expectedDoc, string(doc.Source)) + } + } + } + +} diff --git a/integrationtests/testdata/createNFTWithTags/accounts-esdt-address-balance.json b/integrationtests/testdata/createNFTWithTags/accounts-esdt-address-balance.json new file mode 100644 index 00000000..0c66b78c --- /dev/null +++ b/integrationtests/testdata/createNFTWithTags/accounts-esdt-address-balance.json @@ -0,0 +1,25 @@ +{ + "identifier": "DESK-abcd-01", + "address": "6161616162626262", + "balance": "1000", + "balanceNum": 1e-15, + "data": { + "creator": "63726561746f72", + "metadata": "QmZ2QqaGq4bqsEzs5JLTjRmmvR2GAR4qXJZBN8ibfDdaud", + "whiteListedStorage": false, + "attributes": "dGFnczpoZWxsbyxzb21ldGhpbmcsY2V2YSxhbixzbyxvbjttZXRhZGF0YTpRbVoyUXFhR3E0YnFzRXpzNUpMVGpSbW12UjJHQVI0cVhKWkJOOGliZkRkYXVk", + "nonEmptyURIs": false, + "tags": [ + "hello", + "something", + "ceva", + "an", + "so", + "on" + ] + }, + "tokenNonce": 1, + "properties": "6f6b", + "token": "DESK-abcd", + "timestamp": 5600 +} diff --git a/integrationtests/testdata/createNFTWithTags/tags1.json b/integrationtests/testdata/createNFTWithTags/tags1.json new file mode 100644 index 00000000..17f7c213 --- /dev/null +++ b/integrationtests/testdata/createNFTWithTags/tags1.json @@ -0,0 +1,56 @@ +[ + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "Y2V2YQ==", + "_score": 1, + "_source": { + "count": 1 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "YW4=", + "_score": 1, + "_source": { + "count": 1 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "c2FsdXQ=", + "_score": 1, + "_source": { + "count": 1 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "c28=", + "_score": 1, + "_source": { + "count": 1 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "b24=", + "_score": 1, + "_source": { + "count": 1 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "c29tZXRoaW5n", + "_score": 1, + "_source": { + "count": 1 + } + } +] diff --git a/integrationtests/testdata/createNFTWithTags/tags2.json b/integrationtests/testdata/createNFTWithTags/tags2.json new file mode 100644 index 00000000..dc6b116f --- /dev/null +++ b/integrationtests/testdata/createNFTWithTags/tags2.json @@ -0,0 +1,56 @@ +[ + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "Y2V2YQ==", + "_score": 1, + "_source": { + "count": 2 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "YW4=", + "_score": 1, + "_source": { + "count": 2 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "c2FsdXQ=", + "_score": 1, + "_source": { + "count": 2 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "c28=", + "_score": 1, + "_source": { + "count": 2 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "b24=", + "_score": 1, + "_source": { + "count": 2 + } + }, + { + "_index": "tags-000001", + "_type": "_doc", + "_id": "c29tZXRoaW5n", + "_score": 1, + "_source": { + "count": 2 + } + } +] diff --git a/integrationtests/utils.go b/integrationtests/utils.go index 79ea4ed0..f6710cb6 100644 --- a/integrationtests/utils.go +++ b/integrationtests/utils.go @@ -47,7 +47,7 @@ func CreateElasticProcessor( AccountsDB: accountsDB, ShardCoordinator: shardCoordinator, TransactionFeeCalculator: feeProcessor, - EnabledIndexes: []string{indexer.TransactionsIndex, indexer.LogsIndex, indexer.AccountsESDTIndex, indexer.ScResultsIndex, indexer.ReceiptsIndex, indexer.BlockIndex, indexer.AccountsIndex, indexer.TokensIndex}, + EnabledIndexes: []string{indexer.TransactionsIndex, indexer.LogsIndex, indexer.AccountsESDTIndex, indexer.ScResultsIndex, indexer.ReceiptsIndex, indexer.BlockIndex, indexer.AccountsIndex, indexer.TokensIndex, indexer.TagsIndex}, Denomination: 18, IsInImportDBMode: false, } @@ -73,3 +73,12 @@ func readExpectedResult(path string) string { return string(byteValue) } + +func getElementFromSlice(path string, index int) string { + fileBytes := readExpectedResult(path) + slice := make([]map[string]interface{}, 0) + _ = json.Unmarshal([]byte(fileBytes), &slice) + res, _ := json.Marshal(slice[index]["_source"]) + + return string(res) +} diff --git a/scripts/script.sh b/scripts/script.sh index aeebb2bb..292c40c5 100755 --- a/scripts/script.sh +++ b/scripts/script.sh @@ -29,4 +29,28 @@ delete() { curl -XDELETE http://localhost:9200/_template/* } + +IMAGE_OPEN_SEARCH=open-container +DEFAULT_OPEN_SEARCH_VERSION=1.2.4 + +start_open_search() { + OPEN_VERSION=$1 + if [ -z "${OPEN_VERSION}" ]; then + OPEN_VERSION=${DEFAULT_OPEN_SEARCH_VERSION} + fi + + echo ${OPEN_VERSION} + + docker pull opensearchproject/opensearch:${OPEN_VERSION} + + docker run -d --name "${IMAGE_OPEN_SEARCH}" -p 9200:9200 -p 9600:9600 \ + -e "discovery.type=single-node" -e "plugins.security.disabled=true" -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \ + opensearchproject/opensearch:${OPEN_VERSION} + +} + +stop_open_search() { + docker stop "${IMAGE_OPEN_SEARCH}" +} + "$@"