diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f93a18912..d42c02003 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -231,7 +231,7 @@ jobs: - name: Zip log files on failure if: ${{ failure() }} timeout-minutes: 1 # timeout after 1 minute - run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log + run: 7z a logs-itest-${{ matrix.name }}.zip itest/**/*.log - name: Upload log files on failure uses: actions/upload-artifact@v2.2.4 @@ -260,97 +260,10 @@ jobs: - name: run itest run: make itest-parallel windows=1 tranches=2 parallel=2 - - name: Zip log files on failure - if: ${{ failure() }} - run: 7z a logs-itest-windows.zip lntest/itest/**/*.log - - - name: Upload log files on failure - uses: actions/upload-artifact@v2 - if: ${{ failure() }} - with: - name: logs-itest-windows - path: logs-itest-windows.zip - retention-days: 5 - - ######################## - # run new integration tests - ######################## - new-integration-test: - name: run new itests - runs-on: ubuntu-latest - if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')' - strategy: - # Allow other tests in the matrix to continue if one fails. - fail-fast: false - matrix: - include: - - name: btcd - args: backend=btcd - - name: bitcoind - args: backend=bitcoind - - name: bitcoind-notxindex - args: backend="bitcoind notxindex" - - name: bitcoind-rpcpolling - args: backend="bitcoind rpcpolling" - - name: bitcoind-etcd - args: backend=bitcoind dbbackend=etcd - - name: bitcoind-postgres - args: backend=bitcoind dbbackend=postgres - - name: bitcoind-sqlite - args: backend=bitcoind dbbackend=sqlite - - name: neutrino - args: backend=neutrino - steps: - - name: git checkout - uses: actions/checkout@v3 - - - name: setup go ${{ env.GO_VERSION }} - uses: ./.github/actions/setup-go - with: - go-version: '${{ env.GO_VERSION }}' - - - name: install bitcoind - run: ./scripts/install_bitcoind.sh - - - name: run new ${{ matrix.name }} - run: make itest-parallel temptest=true ${{ matrix.args }} - - name: Zip log files on failure if: ${{ failure() }} timeout-minutes: 1 # timeout after 1 minute - run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log - - - name: Upload log files on failure - uses: actions/upload-artifact@v2.2.4 - if: ${{ failure() }} - with: - name: logs-itest-${{ matrix.name }} - path: logs-itest-${{ matrix.name }}.zip - retention-days: 5 - - ######################## - # run new windows integration test - ######################## - new-windows-integration-test: - name: run new windows itest - runs-on: windows-latest - if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')' - steps: - - name: git checkout - uses: actions/checkout@v3 - - - name: setup go ${{ env.GO_VERSION }} - uses: ./.github/actions/setup-go - with: - go-version: '${{ env.GO_VERSION }}' - - - name: run new itest - run: make itest-parallel temptest=true windows=1 tranches=2 parallel=2 - - - name: Zip log files on failure - if: ${{ failure() }} - timeout-minutes: 1 # timeout after 1 minute - run: 7z a logs-itest-windows.zip lntest/itest/**/*.log + run: 7z a logs-itest-windows.zip itest/**/*.log - name: Upload log files on failure uses: actions/upload-artifact@v2 diff --git a/lntest/itest/list_off_test.go b/lntest/itest/list_off_test.go index e34443092..c2e2f67aa 100644 --- a/lntest/itest/list_off_test.go +++ b/lntest/itest/list_off_test.go @@ -5,5 +5,4 @@ package itest import "github.com/lightningnetwork/lnd/lntemp" -// TODO(yy): remove the temp. -var allTestCasesTemp = []*lntemp.TestCase{} +var allTestCases = []*lntemp.TestCase{} diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index dcf85817c..7f2ed6f0d 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -5,8 +5,7 @@ package itest import "github.com/lightningnetwork/lnd/lntemp" -// TODO(yy): remove the temp. -var allTestCasesTemp = []*lntemp.TestCase{ +var allTestCases = []*lntemp.TestCase{ { Name: "update channel status", TestFunc: testUpdateChanStatus, diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 1f0dbd4cb..fa3606d0a 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -3,29 +3,135 @@ package itest import ( "flag" "fmt" + "io" "os" + "path/filepath" + "runtime" "strings" "testing" "time" "github.com/btcsuite/btcd/integration/rpctest" + "github.com/lightningnetwork/lnd/lntemp" "github.com/lightningnetwork/lnd/lntest" "github.com/stretchr/testify/require" + "google.golang.org/grpc/grpclog" +) + +const ( + // defaultSplitTranches is the default number of tranches we split the + // test cases into. + defaultSplitTranches uint = 1 + + // defaultRunTranche is the default index of the test cases tranche that + // we run. + defaultRunTranche uint = 0 ) var ( - // tempTest is a flag used to mark whether we should run the old or the - // new test cases. Used here so we can transit smoothly during our new - // itest construction. - // - // TODO(yy): remove temp flag. - tempTest = flag.Bool("temptest", false, "run the new tests(temp)") + // testCasesSplitParts is the number of tranches the test cases should + // be split into. By default this is set to 1, so no splitting happens. + // If this value is increased, then the -runtranche flag must be + // specified as well to indicate which part should be run in the current + // invocation. + testCasesSplitTranches = flag.Uint( + "splittranches", defaultSplitTranches, "split the test cases "+ + "in this many tranches and run the tranche at "+ + "0-based index specified by the -runtranche flag", + ) + + // testCasesRunTranche is the 0-based index of the split test cases + // tranche to run in the current invocation. + testCasesRunTranche = flag.Uint( + "runtranche", defaultRunTranche, "run the tranche of the "+ + "split test cases with the given (0-based) index", + ) + + // dbBackendFlag specifies the backend to use. + dbBackendFlag = flag.String("dbbackend", "bbolt", "Database backend "+ + "(bbolt, etcd, postgres)") ) +// TestLightningNetworkDaemon performs a series of integration tests amongst a +// programmatically driven network of lnd nodes. +func TestLightningNetworkDaemon(t *testing.T) { + // If no tests are registered, then we can exit early. + if len(allTestCases) == 0 { + t.Skip("integration tests not selected with flag 'rpctest'") + } + + // Get the test cases to be run in this tranche. + testCases, trancheIndex, trancheOffset := getTestCaseSplitTranche() + lntest.ApplyPortOffset(uint32(trancheIndex) * 1000) + + // Create a simple fee service. + feeService := lntemp.NewFeeService(t) + + // Get the binary path and setup the harness test. + binary := getLndBinary(t) + harnessTest := lntemp.SetupHarness( + t, binary, *dbBackendFlag, feeService, + ) + defer harnessTest.Stop() + + // Setup standby nodes, Alice and Bob, which will be alive and shared + // among all the test cases. + harnessTest.SetupStandbyNodes() + + // Run the subset of the test cases selected in this tranche. + for idx, testCase := range testCases { + testCase := testCase + name := fmt.Sprintf("tranche%02d/%02d-of-%d/%s/%s", + trancheIndex, trancheOffset+uint(idx)+1, + len(allTestCases), harnessTest.ChainBackendName(), + testCase.Name) + + success := t.Run(name, func(t1 *testing.T) { + // Create a separate harness test for the testcase to + // avoid overwriting the external harness test that is + // tied to the parent test. + ht := harnessTest.Subtest(t1) + + // TODO(yy): split log files. + cleanTestCaseName := strings.ReplaceAll( + testCase.Name, " ", "_", + ) + ht.SetTestName(cleanTestCaseName) + + logLine := fmt.Sprintf( + "STARTING ============ %v ============\n", + testCase.Name, + ) + + ht.Alice.AddToLogf(logLine) + ht.Bob.AddToLogf(logLine) + + ht.EnsureConnected(ht.Alice, ht.Bob) + + ht.RunTestCase(testCase) + }) + + // Stop at the first failure. Mimic behavior of original test + // framework. + if !success { + // Log failure time to help relate the lnd logs to the + // failure. + t.Logf("Failure time: %v", time.Now().Format( + "2006-01-02 15:04:05.000", + )) + break + } + } + + _, height := harnessTest.Miner.GetBestBlock() + t.Logf("=========> tests finished for tranche: %v, tested %d "+ + "cases, end height: %d\n", trancheIndex, len(testCases), height) +} + // getTestCaseSplitTranche returns the sub slice of the test cases that should // be run as the current split tranche as well as the index and slice offset of // the tranche. -func getTestCaseSplitTrancheOld() ([]*testCase, uint, uint) { +func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) { numTranches := defaultSplitTranches if testCasesSplitTranches != nil { numTranches = *testCasesSplitTranches @@ -52,190 +158,40 @@ func getTestCaseSplitTrancheOld() ([]*testCase, uint, uint) { trancheEnd = numCases } - return allTestCases[trancheOffset:trancheEnd], threadID, trancheOffset + return allTestCases[trancheOffset:trancheEnd], threadID, + trancheOffset } -// TestLightningNetworkDaemon performs a series of integration tests amongst a -// programmatically driven network of lnd nodes. -func TestLightningNetworkDaemon(t *testing.T) { - if *tempTest { - t.Skip("Running new tests, old tests are skipped") +func getLndBinary(t *testing.T) string { + binary := itestLndBinary + lndExec := "" + if lndExecutable != nil && *lndExecutable != "" { + lndExec = *lndExecutable + } + if lndExec == "" && runtime.GOOS == "windows" { + // Windows (even in a bash like environment like git bash as on + // Travis) doesn't seem to like relative paths to exe files... + currentDir, err := os.Getwd() + require.NoError(t, err, "unable to get working directory") + + targetPath := filepath.Join(currentDir, "../../lnd-itest.exe") + binary, err = filepath.Abs(targetPath) + require.NoError(t, err, "unable to get absolute path") + } else if lndExec != "" { + binary = lndExec } - // If no tests are registered, then we can exit early. - if len(allTestCases) == 0 { - t.Skip("integration tests not selected with flag 'rpctest'") - } - - // Parse testing flags that influence our test execution. - logDir := lntest.GetLogDir() - require.NoError(t, os.MkdirAll(logDir, 0700)) - testCases, trancheIndex, trancheOffset := getTestCaseSplitTrancheOld() - lntest.ApplyPortOffset(uint32(trancheIndex) * 1000) + return binary +} +func init() { // Before we start any node, we need to make sure that any btcd node - // that is started through the RPC harness uses a unique port as well to - // avoid any port collisions. + // that is started through the RPC harness uses a unique port as well + // to avoid any port collisions. rpctest.ListenAddressGenerator = lntest.GenerateBtcdListenerAddresses - // Declare the network harness here to gain access to its - // 'OnTxAccepted' call back. - var lndHarness *lntest.NetworkHarness - - // Create an instance of the btcd's rpctest.Harness that will act as - // the miner for all tests. This will be used to fund the wallets of - // the nodes within the test network and to drive blockchain related - // events within the network. Revert the default setting of accepting - // non-standard transactions on simnet to reject them. Transactions on - // the lightning network should always be standard to get better - // guarantees of getting included in to blocks. - // - // We will also connect it to our chain backend. - miner, err := lntest.NewMiner() - require.NoError(t, err, "failed to create new miner") - defer func() { - require.NoError(t, miner.Stop(), "failed to stop miner") - }() - - // Start a chain backend. - chainBackend, cleanUp, err := lntest.NewBackend( - miner.P2PAddress(), harnessNetParams, - ) - require.NoError(t, err, "new backend") - defer func() { - require.NoError(t, cleanUp(), "cleanup") - }() - - // Before we start anything, we want to overwrite some of the connection - // settings to make the tests more robust. We might need to restart the - // miner while there are already blocks present, which will take a bit - // longer than the 1 second the default settings amount to. Doubling - // both values will give us retries up to 4 seconds. - miner.MaxConnRetries = rpctest.DefaultMaxConnectionRetries * 2 - miner.ConnectionRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2 - - // Set up miner and connect chain backend to it. - require.NoError(t, miner.SetUp(true, 50)) - require.NoError(t, miner.Client.NotifyNewTransactions(false)) - require.NoError(t, chainBackend.ConnectMiner(), "connect miner") - - // Parse database backend - var dbBackend lntest.DatabaseBackend - switch *dbBackendFlag { - case "bbolt": - dbBackend = lntest.BackendBbolt - - case "etcd": - dbBackend = lntest.BackendEtcd - - case "postgres": - dbBackend = lntest.BackendPostgres - - case "sqlite": - dbBackend = lntest.BackendSqlite - - default: - require.Fail(t, "unknown db backend") - } - - // Now we can set up our test harness (LND instance), with the chain - // backend we just created. - ht := newHarnessTest(t, nil) - binary := ht.getLndBinary() - lndHarness, err = lntest.NewNetworkHarness( - miner, chainBackend, binary, dbBackend, - ) - if err != nil { - ht.Fatalf("unable to create lightning network harness: %v", err) - } - defer lndHarness.Stop() - - // Spawn a new goroutine to watch for any fatal errors that any of the - // running lnd processes encounter. If an error occurs, then the test - // case should naturally as a result and we log the server error here to - // help debug. - go func() { - for { - select { - case err, more := <-lndHarness.ProcessErrors(): - if !more { - return - } - ht.Logf("lnd finished with error (stderr):\n%v", - err) - } - } - }() - - // Next mine enough blocks in order for segwit and the CSV package - // soft-fork to activate on SimNet. - numBlocks := harnessNetParams.MinerConfirmationWindow * 2 - if _, err := miner.Client.Generate(numBlocks); err != nil { - ht.Fatalf("unable to generate blocks: %v", err) - } - - // With the btcd harness created, we can now complete the - // initialization of the network. args - list of lnd arguments, - // example: "--debuglevel=debug" - // TODO(roasbeef): create master balanced channel with all the monies? - aliceBobArgs := []string{ - "--default-remote-max-htlcs=483", - "--dust-threshold=5000000", - } - - // Run the subset of the test cases selected in this tranche. - for idx, testCase := range testCases { - testCase := testCase - name := fmt.Sprintf("tranche%02d/%02d-of-%d/%s/%s", - trancheIndex, trancheOffset+uint(idx)+1, - len(allTestCases), chainBackend.Name(), testCase.name) - - success := t.Run(name, func(t1 *testing.T) { - cleanTestCaseName := strings.ReplaceAll( - testCase.name, " ", "_", - ) - - err = lndHarness.SetUp( - t1, cleanTestCaseName, aliceBobArgs, - ) - require.NoError(t1, - err, "unable to set up test lightning network", - ) - defer func() { - require.NoError(t1, lndHarness.TearDown()) - }() - - lndHarness.EnsureConnected( - t1, lndHarness.Alice, lndHarness.Bob, - ) - - logLine := fmt.Sprintf( - "STARTING ============ %v ============\n", - testCase.name, - ) - - lndHarness.Alice.AddToLogf(logLine) - lndHarness.Bob.AddToLogf(logLine) - - // Start every test with the default static fee estimate. - lndHarness.SetFeeEstimate(12500) - - // Create a separate harness test for the testcase to - // avoid overwriting the external harness test that is - // tied to the parent test. - ht := newHarnessTest(t1, lndHarness) - ht.RunTestCase(testCase) - }) - - // Stop at the first failure. Mimic behavior of original test - // framework. - if !success { - // Log failure time to help relate the lnd logs to the - // failure. - t.Logf("Failure time: %v", time.Now().Format( - "2006-01-02 15:04:05.000", - )) - break - } - } + // Swap out grpc's default logger with out fake logger which drops the + // statements on the floor. + fakeLogger := grpclog.NewLoggerV2(io.Discard, io.Discard, io.Discard) + grpclog.SetLoggerV2(fakeLogger) } diff --git a/lntest/itest/lnd_test_list_off_test.go b/lntest/itest/lnd_test_list_off_test.go deleted file mode 100644 index bf21584f3..000000000 --- a/lntest/itest/lnd_test_list_off_test.go +++ /dev/null @@ -1,6 +0,0 @@ -//go:build !rpctest -// +build !rpctest - -package itest - -var allTestCases = []*testCase{} diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go deleted file mode 100644 index d760ec2ce..000000000 --- a/lntest/itest/lnd_test_list_on_test.go +++ /dev/null @@ -1,6 +0,0 @@ -//go:build rpctest -// +build rpctest - -package itest - -var allTestCases = []*testCase{} diff --git a/lntest/itest/temp_lnd_test.go b/lntest/itest/temp_lnd_test.go deleted file mode 100644 index 4b816b93b..000000000 --- a/lntest/itest/temp_lnd_test.go +++ /dev/null @@ -1,197 +0,0 @@ -package itest - -import ( - "flag" - "fmt" - "io" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - "github.com/btcsuite/btcd/integration/rpctest" - "github.com/lightningnetwork/lnd/lntemp" - "github.com/lightningnetwork/lnd/lntest" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/grpclog" -) - -const ( - // defaultSplitTranches is the default number of tranches we split the - // test cases into. - defaultSplitTranches uint = 1 - - // defaultRunTranche is the default index of the test cases tranche that - // we run. - defaultRunTranche uint = 0 -) - -var ( - // testCasesSplitParts is the number of tranches the test cases should - // be split into. By default this is set to 1, so no splitting happens. - // If this value is increased, then the -runtranche flag must be - // specified as well to indicate which part should be run in the current - // invocation. - testCasesSplitTranches = flag.Uint( - "splittranches", defaultSplitTranches, "split the test cases "+ - "in this many tranches and run the tranche at "+ - "0-based index specified by the -runtranche flag", - ) - - // testCasesRunTranche is the 0-based index of the split test cases - // tranche to run in the current invocation. - testCasesRunTranche = flag.Uint( - "runtranche", defaultRunTranche, "run the tranche of the "+ - "split test cases with the given (0-based) index", - ) - - // dbBackendFlag specifies the backend to use. - dbBackendFlag = flag.String("dbbackend", "bbolt", "Database backend "+ - "(bbolt, etcd, postgres, sqlite)") -) - -// TestLightningNetworkDaemonTemp performs a series of integration tests -// amongst a programmatically driven network of lnd nodes. -func TestLightningNetworkDaemonTemp(t *testing.T) { - if !*tempTest { - t.Skip("Running old tests, new tests are skipped") - } - - // If no tests are registered, then we can exit early. - if len(allTestCasesTemp) == 0 { - t.Skip("integration tests not selected with flag 'rpctest'") - } - - // Get the test cases to be run in this tranche. - testCases, trancheIndex, trancheOffset := getTestCaseSplitTranche() - lntest.ApplyPortOffset(uint32(trancheIndex) * 1000) - - // Create a simple fee service. - feeService := lntemp.NewFeeService(t) - - // Get the binary path and setup the harness test. - binary := getLndBinary(t) - harnessTest := lntemp.SetupHarness( - t, binary, *dbBackendFlag, feeService, - ) - defer harnessTest.Stop() - - // Setup standby nodes, Alice and Bob, which will be alive and shared - // among all the test cases. - harnessTest.SetupStandbyNodes() - - // Run the subset of the test cases selected in this tranche. - for idx, testCase := range testCases { - testCase := testCase - name := fmt.Sprintf("tranche%02d/%02d-of-%d/%s/%s", - trancheIndex, trancheOffset+uint(idx)+1, - len(allTestCases), harnessTest.ChainBackendName(), - testCase.Name) - - success := t.Run(name, func(t1 *testing.T) { - // Create a separate harness test for the testcase to - // avoid overwriting the external harness test that is - // tied to the parent test. - ht := harnessTest.Subtest(t1) - - // TODO(yy): split log files. - cleanTestCaseName := strings.ReplaceAll( - testCase.Name, " ", "_", - ) - ht.SetTestName(cleanTestCaseName) - - logLine := fmt.Sprintf( - "STARTING ============ %v ============\n", - testCase.Name, - ) - - ht.Alice.AddToLogf(logLine) - ht.Bob.AddToLogf(logLine) - - ht.EnsureConnected(ht.Alice, ht.Bob) - - ht.RunTestCase(testCase) - }) - - // Stop at the first failure. Mimic behavior of original test - // framework. - if !success { - // Log failure time to help relate the lnd logs to the - // failure. - t.Logf("Failure time: %v", time.Now().Format( - "2006-01-02 15:04:05.000", - )) - break - } - } -} - -// getTestCaseSplitTranche returns the sub slice of the test cases that should -// be run as the current split tranche as well as the index and slice offset of -// the tranche. -func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) { - numTranches := defaultSplitTranches - if testCasesSplitTranches != nil { - numTranches = *testCasesSplitTranches - } - runTranche := defaultRunTranche - if testCasesRunTranche != nil { - runTranche = *testCasesRunTranche - } - - // There's a special flake-hunt mode where we run the same test multiple - // times in parallel. In that case the tranche index is equal to the - // thread ID, but we need to actually run all tests for the regex - // selection to work. - threadID := runTranche - if numTranches == 1 { - runTranche = 0 - } - - numCases := uint(len(allTestCasesTemp)) - testsPerTranche := numCases / numTranches - trancheOffset := runTranche * testsPerTranche - trancheEnd := trancheOffset + testsPerTranche - if trancheEnd > numCases || runTranche == numTranches-1 { - trancheEnd = numCases - } - - return allTestCasesTemp[trancheOffset:trancheEnd], threadID, - trancheOffset -} - -func getLndBinary(t *testing.T) string { - binary := itestLndBinary - lndExec := "" - if lndExecutable != nil && *lndExecutable != "" { - lndExec = *lndExecutable - } - if lndExec == "" && runtime.GOOS == "windows" { - // Windows (even in a bash like environment like git bash as on - // Travis) doesn't seem to like relative paths to exe files... - currentDir, err := os.Getwd() - require.NoError(t, err, "unable to get working directory") - - targetPath := filepath.Join(currentDir, "../../lnd-itest.exe") - binary, err = filepath.Abs(targetPath) - require.NoError(t, err, "unable to get absolute path") - } else if lndExec != "" { - binary = lndExec - } - - return binary -} - -func init() { - // Before we start any node, we need to make sure that any btcd node - // that is started through the RPC harness uses a unique port as well - // to avoid any port collisions. - rpctest.ListenAddressGenerator = lntest.GenerateBtcdListenerAddresses - - // Swap out grpc's default logger with out fake logger which drops the - // statements on the floor. - fakeLogger := grpclog.NewLoggerV2(io.Discard, io.Discard, io.Discard) - grpclog.SetLoggerV2(fakeLogger) -} diff --git a/make/testing_flags.mk b/make/testing_flags.mk index dda519925..d18a04881 100644 --- a/make/testing_flags.mk +++ b/make/testing_flags.mk @@ -9,11 +9,6 @@ NUM_ITEST_TRANCHES = 4 ITEST_PARALLELISM = $(NUM_ITEST_TRANCHES) POSTGRES_START_DELAY = 5 -# Build temp tests only. TODO(yy): remove. -ifneq ($(temptest),) -ITEST_FLAGS += -temptest=$(temptest) -endif - # If rpc option is set also add all extra RPC tags to DEV_TAGS ifneq ($(with-rpc),) DEV_TAGS += $(RPC_TAGS)