Skip to content

Deploy flags e2e #2755

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

Closed
wants to merge 14 commits into from
Closed

Deploy flags e2e #2755

wants to merge 14 commits into from

Conversation

sukantoraymond
Copy link
Collaborator

@sukantoraymond sukantoraymond commented Apr 17, 2025

Our current E2E for tests/e2e/testcases is pretty extensive for local network across all commands. However, it does not test flags input extensively for happy path and error path.

For example, our E2E tests for blockchain deploy in https://github.com/ava-labs/avalanche-cli/blob/main/tests/e2e/testcases/subnet/sov/ currently tests that we are able to deploy to local network using PoA / PoS / Initialize Validator Manager. However, it does not test the multiple ways that we can achieve each objectives (for example we can use deploy an L1 with by setting num-local-machine=2 instead of using default value of 1).

This PR proposes using json files as input that is fed into a general function (TestCommandWithJSONConfig), which can be reused for all blockchain subcommands (e.g. blockchain addValidator, etc) simply by feeding it with different JSON file. Reusing same core testing logic enables us to achieve extensive happy path and error path coverage without huge additional testing code.

@sukantoraymond sukantoraymond marked this pull request as draft April 17, 2025 22:55
Comment on lines 8 to 12
"happyPath": [
{
"name": "local_deploy",
"flags": {}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can set globalFlags in each testCases as well, which will override the globalFlags value

@sukantoraymond sukantoraymond marked this pull request as ready for review April 18, 2025 16:19
var _ = ginkgo.Describe("[Blockchain Deploy Flags]", ginkgo.Ordered, func() {
_ = ginkgo.BeforeEach(func() {
// Create test subnet config
commands.CreateSubnetEvmConfigSOV(subnetName, utils.SubnetEvmGenesisPath, ewoqEVMAddress)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use ewoq here because we use ewoq as validator manager owner when we deploy in local network

}

// TestCommandWithJSONConfig tests a CLI command with flag inputs from a JSON file
func TestCommandWithJSONConfig(command string, configPath string, testCase *TestCase) (string, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love the idea - any plan to move it to some test common directories to enable it reusable by all other commands?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Yes i will move it to external directories

Copy link
Collaborator Author

@sukantoraymond sukantoraymond Apr 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generalized the function

@sukantoraymond
Copy link
Collaborator Author

sukantoraymond commented Apr 21, 2025

Example of how this PR reduces code while increasing code coverage:

Currently, when we are testing key transfer:

func KeyTransferSend(keyName string, targetAddr string, amount string) (string, error) {
	// Create config
	args := []string{
		KeyCmd,
		"transfer",
		"--local",
		"--key",
		keyName,
		"--destination-addr",
		targetAddr,
		"--amount",
		amount,
		"--p-chain-sender",
		"--p-chain-receiver",
		"--" + constants.SkipUpdateFlag,
	}
	cmd := exec.Command(CLIBinary, args...)

	out, err := cmd.CombinedOutput()
	return string(out), err
}

We have to write a custom function to call key transfer command (and this function only does p chain to p chain transfer). Additionally, since we will be testing transfer from c to p chain, we have to make several more custom functions -> each function is 20 lines!

Compare that with using TestCommandWithJSONConfig. We no longer need to write custom function. Just create a json file with any scenarios you want (P->C, C->X, etc) and we can test happy path and error path! (e.g. balance not enough for transfer, etc).

Using JSON ensures that every possible flag is tested, compared to doing this right now, where we can't verify that we have tested every scenario:

ginkgo.It("can transfer between keys", func() {
		_ = utils.DeleteKey(keyName)
		_ = utils.DeleteKey(ewoqKeyName)
		output, err := commands.CreateKeyFromPath(ewoqKeyName, utils.EwoqKeyPath)
		if err != nil {
			fmt.Println(output)
			utils.PrintStdErr(err)
		}
		gomega.Expect(err).Should(gomega.BeNil())
		output, err = commands.CreateKey(keyName)
		if err != nil {
			fmt.Println(output)
			utils.PrintStdErr(err)
		}
		gomega.Expect(err).Should(gomega.BeNil())
		commands.StartNetworkWithVersion("")

		amount := 0.2
		amountStr := fmt.Sprintf("%.2f", amount)
		amountNAvax := uint64(amount * float64(units.Avax))

		// send/receive without recovery

		output, err = commands.ListKeys("local", true, true)
		gomega.Expect(err).Should(gomega.BeNil())
		keyAddr, keyBalance1, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName)
		gomega.Expect(err).Should(gomega.BeNil())
		_, ewoqKeyBalance1, err := utils.ParseAddrBalanceFromKeyListOutput(output, ewoqKeyName)
		gomega.Expect(err).Should(gomega.BeNil())

		output, err = commands.KeyTransferSend(ewoqKeyName, keyAddr, amountStr)
		if err != nil {
			fmt.Println(output)
		}
		gomega.Expect(err).Should(gomega.BeNil())

		feeNAvax, err := utils.GetKeyTransferFee(output)
		gomega.Expect(err).Should(gomega.BeNil())

		output, err = commands.ListKeys("local", true, true)
		gomega.Expect(err).Should(gomega.BeNil())
		_, keyBalance2, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName)
		gomega.Expect(err).Should(gomega.BeNil())
		_, ewoqKeyBalance2, err := utils.ParseAddrBalanceFromKeyListOutput(output, ewoqKeyName)
		gomega.Expect(err).Should(gomega.BeNil())
		gomega.Expect(feeNAvax + amountNAvax).Should(gomega.Equal(ewoqKeyBalance1 - ewoqKeyBalance2))
		gomega.Expect(keyBalance2 - keyBalance1).Should(gomega.Equal(amountNAvax))

		output, err = commands.ListKeys("local", true, true)
		gomega.Expect(err).Should(gomega.BeNil())
		_, keyBalance3, err := utils.ParseAddrBalanceFromKeyListOutput(output, keyName)
		gomega.Expect(err).Should(gomega.BeNil())
		_, ewoqKeyBalance3, err := utils.ParseAddrBalanceFromKeyListOutput(output, ewoqKeyName)
		gomega.Expect(err).Should(gomega.BeNil())
		gomega.Expect(ewoqKeyBalance1 - ewoqKeyBalance3).Should(gomega.Equal(feeNAvax + amountNAvax))
		gomega.Expect(keyBalance3 - keyBalance1).Should(gomega.Equal(amountNAvax))
	})

@@ -85,7 +85,7 @@ func CreateSubnetEvmConfigWithVersionNonSOV(subnetName string, genesisPath strin
gomega.Expect(exists).Should(gomega.BeTrue())
}

func CreateSubnetEvmConfigWithVersionSOV(subnetName string, genesisPath string, version string) {
func CreateSubnetEvmConfigGenesisPathWithVersionSOV(subnetName string, genesisPath string, version string, validatorManagerOwner string) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need a generic function that just take the command name, the non flag args, and a map for flags, and
stopping doing this

@@ -236,9 +236,9 @@ func CreateCustomVMConfigSOV(subnetName string, genesisPath string, vmPath strin
genesisPath,
"--proof-of-authority",
"--validator-manager-owner",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also need to stop using flag constants here, and take those from cmd/flags

@@ -35,6 +35,7 @@ jobs:
"\\[Node create\\]",
"\\[Node devnet\\]",
"\\[Docker\\]",
"\\[Blockchain Deploy Flags\\]",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure we want to start modifying CI at this stage

@@ -0,0 +1,22 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this cmd tree. probably this can have a default name, like test_table.json

type CommandGroup string

const (
BlockchainCmd CommandGroup = "blockchain"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather add this constant on cmd/blockchaincmd/ and import that here

// TestCase represents a single test case configuration
type TestCase struct {
Name string `json:"name"`
Flags map[string]string `json:"flags"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also need non flag args here

}

// Append any additional arguments
if len(args) > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should belong to the test case

ginkgo.By(fmt.Sprintf("Running test case: %s", testCase.Name))
_, err = commandse2e.TestCommandWithJSONConfig(
commandse2e.BlockchainCmd,
"deploy",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a constant on cmd/blockchaincmd/

// Cleanup test subnet config
commands.DeleteSubnetConfig(subnetName)
})
blockchainCmdArgs := []string{subnetName}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should belong to the json test case IMO

var _ = ginkgo.Describe("[Blockchain Deploy Flags]", ginkgo.Ordered, func() {
_ = ginkgo.BeforeEach(func() {
// Create test subnet config
commands.CreateSubnetEvmConfigSOV(subnetName, ewoqEVMAddress, commands.PoA)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should be added to the json spec (how to setup required env)

@sukantoraymond sukantoraymond marked this pull request as draft April 30, 2025 15:36
@github-project-automation github-project-automation bot moved this from Backlog 🧊 to Done 🎉 in avalanchego May 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants