214 lines
8.8 KiB
Go
214 lines
8.8 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package identifytxs
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/hyperledger/fabric/common/ledger/testutil"
|
|
"github.com/hyperledger/fabric/internal/ledgerutil/jsonrw"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
TestDataDir = "../testdata/"
|
|
SampleFileSystemDir = TestDataDir + "sample_prod/"
|
|
SampleDiffRecordsDir = TestDataDir + "sample_diffRecords/"
|
|
SampleComparisonsDir = TestDataDir + "sample_comparisons/"
|
|
)
|
|
|
|
func TestIdentifyTxs(t *testing.T) {
|
|
testCases := map[string]struct {
|
|
sampleDiffRecordsPath string
|
|
sampleFileSystemPath string
|
|
expectedFirstBlock uint64
|
|
expectedLastBlock uint64
|
|
expectedResultFilesCount int
|
|
expectedResultsPath string
|
|
resultsDirname string
|
|
expectedOutputType string
|
|
expectedError string
|
|
}{
|
|
"two-private-one-public": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "two_private_one_public.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(1),
|
|
expectedLastBlock: uint64(4),
|
|
expectedResultFilesCount: 3,
|
|
expectedResultsPath: SampleComparisonsDir + "two_private_one_public",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "json",
|
|
},
|
|
"two-private-two-public": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "two_private_two_public.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(1),
|
|
expectedLastBlock: uint64(7),
|
|
expectedResultFilesCount: 4,
|
|
expectedResultsPath: SampleComparisonsDir + "two_private_two_public",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "json",
|
|
},
|
|
"one-public": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "one_public.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(1),
|
|
expectedLastBlock: uint64(3),
|
|
expectedResultFilesCount: 1,
|
|
expectedResultsPath: SampleComparisonsDir + "one_public",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "json",
|
|
},
|
|
"one-private": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "one_private.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(1),
|
|
expectedLastBlock: uint64(2),
|
|
expectedResultFilesCount: 1,
|
|
expectedResultsPath: SampleComparisonsDir + "one_private",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "json",
|
|
},
|
|
"two-private": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "two_private.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(1),
|
|
expectedLastBlock: uint64(1),
|
|
expectedResultFilesCount: 2,
|
|
expectedResultsPath: SampleComparisonsDir + "two_private",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "json",
|
|
},
|
|
"empty-list": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "empty_list.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(0),
|
|
expectedLastBlock: uint64(0),
|
|
expectedResultsPath: SampleComparisonsDir + "empty_list",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "bad-json-error",
|
|
expectedError: "no records were read. JSON record list is either empty or not properly formatted. Aborting identifytxs",
|
|
},
|
|
"already-exists": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "two_private_one_public.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(1),
|
|
expectedLastBlock: uint64(4),
|
|
expectedResultFilesCount: 3,
|
|
expectedResultsPath: SampleComparisonsDir + "two_private_one_public",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "exists-error",
|
|
},
|
|
"invalid-key": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "invalid_key.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(0),
|
|
expectedLastBlock: uint64(0),
|
|
expectedResultFilesCount: 1,
|
|
expectedResultsPath: SampleComparisonsDir + "invalid_key",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "general-error",
|
|
expectedError: "invalid input json. Each record entry must contain both a \"namespace\" and a \"key\" field. Aborting identifytxs",
|
|
},
|
|
"duplicate-records": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "duplicate_records.json",
|
|
sampleFileSystemPath: SampleFileSystemDir,
|
|
expectedFirstBlock: uint64(0),
|
|
expectedLastBlock: uint64(0),
|
|
expectedResultFilesCount: 1,
|
|
expectedResultsPath: SampleComparisonsDir + "duplicate_records",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "general-error",
|
|
expectedError: "invalid input json. Contains duplicate record for {\"namespace\":\"marbles\",\"key\":\"marble3\"}. Aborting identifytxs",
|
|
},
|
|
"empty-block-store": {
|
|
sampleDiffRecordsPath: SampleDiffRecordsDir + "two_private_one_public.json",
|
|
expectedFirstBlock: uint64(0),
|
|
expectedLastBlock: uint64(0),
|
|
expectedResultFilesCount: 3,
|
|
expectedResultsPath: SampleComparisonsDir + "two_private_one_public",
|
|
resultsDirname: "mychannel_identified_transactions",
|
|
expectedOutputType: "empty-bs-error",
|
|
},
|
|
}
|
|
|
|
for testName, testCase := range testCases {
|
|
t.Run(testName, func(t *testing.T) {
|
|
// Temporary directory for identifytxs results
|
|
outputDir := t.TempDir()
|
|
// Temporary directory for file system
|
|
var fsDir string
|
|
var err error
|
|
if testCase.expectedOutputType == "empty-bs-error" {
|
|
fsDir = t.TempDir()
|
|
err = os.MkdirAll(filepath.Join(fsDir, "ledgersData", "chains"), 0o700)
|
|
require.NoError(t, err)
|
|
} else {
|
|
fsDir = t.TempDir()
|
|
err = testutil.CopyDir(testCase.sampleFileSystemPath, fsDir, false)
|
|
require.NoError(t, err)
|
|
}
|
|
// Check identifytxs returned values
|
|
firstBlock, lastBlock, err := IdentifyTxs(testCase.sampleDiffRecordsPath, fsDir, outputDir)
|
|
require.Equal(t, testCase.expectedFirstBlock, firstBlock)
|
|
require.Equal(t, testCase.expectedLastBlock, lastBlock)
|
|
// Prepare results directory
|
|
resultsPath := filepath.Join(outputDir, testCase.resultsDirname)
|
|
dirEntries, readDirErr := os.ReadDir(resultsPath)
|
|
switch testCase.expectedOutputType {
|
|
case "bad-json-error":
|
|
require.ErrorContains(t, err, testCase.expectedError)
|
|
// Check identifytxs results directory
|
|
require.ErrorContains(t, readDirErr, "no such file or directory")
|
|
case "exists-error":
|
|
firstBlock, lastBlock, err = IdentifyTxs(testCase.sampleDiffRecordsPath, fsDir, outputDir)
|
|
require.Equal(t, uint64(0), firstBlock)
|
|
require.Equal(t, uint64(0), lastBlock)
|
|
require.ErrorContains(t, err, fmt.Sprintf("%s already exists in %s. Choose a different location or remove the existing results. Aborting identifytxs", testCase.resultsDirname, outputDir))
|
|
// Check identifytxs results directory
|
|
require.NoError(t, readDirErr)
|
|
require.Equal(t, testCase.expectedResultFilesCount, len(dirEntries))
|
|
case "general-error":
|
|
require.ErrorContains(t, err, testCase.expectedError)
|
|
// Check identifytxs results directory
|
|
require.NoError(t, readDirErr)
|
|
require.Equal(t, testCase.expectedResultFilesCount, len(dirEntries))
|
|
case "empty-bs-error":
|
|
require.ErrorContains(t, err, fmt.Sprintf("provided path %s is empty. Aborting identifytxs", fsDir))
|
|
// Check identifytxs results directory
|
|
require.NoError(t, readDirErr)
|
|
require.Equal(t, testCase.expectedResultFilesCount, len(dirEntries))
|
|
case "json":
|
|
require.NoError(t, err)
|
|
// Check identifytxs results directory
|
|
require.NoError(t, readDirErr)
|
|
require.Equal(t, testCase.expectedResultFilesCount, len(dirEntries))
|
|
// Check identifytxs individual txList results files
|
|
for i := 1; i <= testCase.expectedResultFilesCount; i++ {
|
|
txListFilename := fmt.Sprintf("txlist%d.json", i)
|
|
expectedTxListJSON, err := jsonrw.OutputFileToString(txListFilename, testCase.expectedResultsPath)
|
|
require.NoError(t, err)
|
|
actualTxListJSON, err := jsonrw.OutputFileToString(txListFilename, resultsPath)
|
|
require.NoError(t, err)
|
|
require.Equal(t, expectedTxListJSON, actualTxListJSON)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecodeHashedNs(t *testing.T) {
|
|
sampleUndecoded := "_lifecycle$$h_implicit_org_Org1MSP"
|
|
sampleDecodedNs, sampleDecodedColl, err := decodeHashedNs(sampleUndecoded)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "_lifecycle", sampleDecodedNs)
|
|
require.Equal(t, "_implicit_org_Org1MSP", sampleDecodedColl)
|
|
}
|