package cmd_test import ( "testing" "time" "github.com/activecm/rita/v5/cmd" "github.com/activecm/rita/v5/database" "github.com/spf13/afero" "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" ) func (c *CmdTestSuite) TestDeleteCommand() { commands := []*cli.Command{cmd.DeleteCommand} flags := []cli.Flag{} tests := []struct { name string args []string dbs []string expectedDeletedDbs []string expectedRemainingDbs []string expectedError error }{ // TODO: in order to check the actual deletion step from calling the command, we need a way to // pass in or use the test clickhouse DBConnection, right now it gets overridden when load config gets called // { // name: "No Wildcards - Database Matching Trimmed Name Exactly", // args: []string{"app", "delete", "--ni", "--config=../config.hjson", "bingbong"}, // dbs: []string{"bingbong", "prefix_bingbong", "bingbong123", "prefix_bingbong123"}, // expectedDeletedDbs: []string{"bingbong"}, // expectedRemainingDbs: []string{"prefix_bingbong", "bingbong123", "prefix_bingbong123"}, // expectedError: nil, // }, // { // name: "Prefix Wildcard - Databases Ending with Trimmed Name", // args: []string{"app", "delete", "--ni", "--config=../config.hjson", "*bingbong"}, // dbs: []string{"bingbong", "prefix_bingbong", "bingbong123", "prefix_bingbong123"}, // expectedDeletedDbs: []string{"bingbong", "prefix_bingbong"}, // expectedRemainingDbs: []string{"bingbong123", "prefix_bingbong123"}, // expectedError: nil, // }, // { // name: "Suffix Wildcard - Databases Starting with Trimmed Name", // args: []string{"app", "delete", "--ni", "--config=../config.hjson", "bingbong*"}, // dbs: []string{"bingbong", "prefix_bingbong", "bingbong123", "prefix_bingbong123"}, // expectedDeletedDbs: []string{"bingbong", "bingbong123"}, // expectedRemainingDbs: []string{"prefix_bingbong", "prefix_bingbong123"}, // expectedError: nil, // }, // { // name: "Both Wildcards - Databases Containing Trimmed Name", // args: []string{"app", "delete", "--ni", "--config=../config.hjson", "*bingbong*"}, // dbs: []string{"bingbong", "prefix_bingbong", "bingbong123", "prefix_bingbong123"}, // expectedDeletedDbs: []string{"bingbong", "prefix_bingbong", "bingbong123", "prefix_bingbong123"}, // expectedRemainingDbs: []string{}, // expectedError: nil, // }, { name: "Too Many Arguments", args: []string{"app", "delete", "dbname", "extra"}, expectedError: cmd.ErrTooManyArguments, }, { name: "No Arguments", args: []string{"app", "delete"}, expectedError: cmd.ErrMissingDatabaseName, }, } for _, test := range tests { c.Run(test.name, func() { require := require.New(c.T()) // create a new app and context app, ctx := setupTestApp(commands, flags) // run app with test.args err := app.RunContext(ctx, test.args) if test.expectedError != nil { require.Error(err, "error should not be nil") require.Contains(err.Error(), test.expectedError.Error(), "error should contain expected value") } else { require.NoError(err, "error should be nil") } }) } } func (c *CmdTestSuite) TestRunDeleteCmd() { type importDB struct { name string logDir string } tests := []struct { name string entry string afs afero.Fs dbs []importDB expectedDeletedDbs []string expectedRemainingDbs []string expectedError error }{ { name: "No Wildcards - Database Matching Trimmed Name Exactly", entry: "bingbong", afs: afero.NewOsFs(), dbs: []importDB{ {"bingbong", "../test_data/open_conns/open"}, {"prefix_bingbong", "../test_data/open_conns/open"}, {"bingbong123", "../test_data/open_conns/open"}, {"prefix_bingbong123", "../test_data/open_conns/open"}, }, expectedDeletedDbs: []string{"bingbong"}, expectedRemainingDbs: []string{"prefix_bingbong", "bingbong123", "prefix_bingbong123"}, }, { name: "Prefix Wildcard - Databases Ending with Trimmed Name", entry: "*bingbong", afs: afero.NewOsFs(), dbs: []importDB{ {"bingbong", "../test_data/open_conns/open"}, {"prefix_bingbong", "../test_data/open_conns/open"}, {"bingbong123", "../test_data/open_conns/open"}, {"prefix_bingbong123", "../test_data/open_conns/open"}, }, expectedDeletedDbs: []string{"bingbong", "prefix_bingbong"}, expectedRemainingDbs: []string{"bingbong123", "prefix_bingbong123"}, expectedError: nil, }, { name: "Suffix Wildcard - Databases Starting with Trimmed Name", entry: "bingbong*", afs: afero.NewOsFs(), dbs: []importDB{ {"bingbong", "../test_data/open_conns/open"}, {"prefix_bingbong", "../test_data/open_conns/open"}, {"bingbong123", "../test_data/open_conns/open"}, {"prefix_bingbong123", "../test_data/open_conns/open"}, }, expectedDeletedDbs: []string{"bingbong", "bingbong123"}, expectedRemainingDbs: []string{"prefix_bingbong", "prefix_bingbong123"}, expectedError: nil, }, { name: "Both Wildcards - Databases Containing Trimmed Name", entry: "*bingbong*", afs: afero.NewOsFs(), dbs: []importDB{ {"bingbong", "../test_data/open_conns/open"}, {"prefix_bingbong", "../test_data/open_conns/open"}, {"bingbong123", "../test_data/open_conns/open"}, {"prefix_bingbong123", "../test_data/open_conns/open"}, }, expectedDeletedDbs: []string{"bingbong", "prefix_bingbong", "bingbong123", "prefix_bingbong123"}, expectedRemainingDbs: []string{}, expectedError: nil, }, } for _, test := range tests { c.Run(test.name, func() { t := c.T() importStartedAt := time.Now() // import all dbs for _, db := range test.dbs { importResults, err := cmd.RunImportCmd(importStartedAt, c.cfg, test.afs, db.logDir, db.name, false, true) require.NoError(t, err, "running import command should not produce an error") require.NotNil(t, importResults, "import results should not be nil") } // trim leading and trailing wildcards trimmedName, err := cmd.TrimWildcards(test.entry) require.NoError(t, err, "trimming wildcards should not produce an error") // validate the trimmed name err = cmd.ValidateDatabaseName(trimmedName) require.NoError(t, err, "validating database name should not produce an error") // run the delete command err = cmd.RunDeleteCmd(c.cfg, test.entry, trimmedName, false) if test.expectedError != nil { require.Contains(t, err.Error(), test.expectedError.Error(), "error should contain expected value") } else { require.NoError(t, err, "error should be nil") } // get list of import databases dbs, err := c.server.ListImportDatabases() require.NoError(t, err, "listing databases should not produce an error") dbString := database.GetFlatDatabaseList(dbs) // validate that the expected databases were deleted for _, db := range test.expectedDeletedDbs { require.NotContains(t, dbString, db, "database %s should have been deleted", db) } // validate that the expected databases remain require.ElementsMatch(t, test.expectedRemainingDbs, dbString, "remaining databases should match expected value") // cleanup for _, db := range test.dbs { err := c.server.DeleteSensorDB(db.name) require.NoError(t, err, "dropping database should not produce an error") } }) } } func TestTrimWildcards(t *testing.T) { tests := []struct { name string dbName string want string expectedError error }{ {"Start Wildcard", "*bingbong", "bingbong", nil}, {"End Wildcard", "bingbong*", "bingbong", nil}, {"Both Wildcards", "*bingbong*", "bingbong", nil}, {"No Wildcard", "bingbong", "bingbong", nil}, {"Only Wildcard", "*", "", cmd.ErrTrimmedNameEmpty}, {"Only Wildcards", "**", "", cmd.ErrTrimmedNameEmpty}, {"Empty String", "", "", cmd.ErrTrimmedNameEmpty}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { trimmedName, err := cmd.TrimWildcards(test.dbName) require.Equal(t, test.expectedError, err, "error should match expected value") require.Equal(t, test.want, trimmedName, "trimmed name should match expected value") }) } } //lint:ignore U1000 // will be used in the future func validateCommandsExist(t *testing.T, commands []*cli.Command, expected []string) { t.Helper() expectedCmds := make(map[string]bool) for _, expectedCmd := range expected { expectedCmds[expectedCmd] = false } for _, command := range commands { if _, ok := expectedCmds[command.Name]; ok { expectedCmds[command.Name] = true } } for expectedSubCmd, present := range expectedCmds { if !present { t.Errorf("expected (sub)command %s is missing", expectedSubCmd) } } }