From 0afc4d58da7ff4e78503cf0f146d0efcec238a85 Mon Sep 17 00:00:00 2001 From: "Ali R. Vahdati" <3798865+kavir1698@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:52:29 +0200 Subject: [PATCH 1/2] Use the `nonInteractiveFlag` flag in `CheckForNewVersion` function calls --- cmd/datasetArchiver/main.go | 2 +- cmd/datasetCleaner/main.go | 2 +- cmd/datasetIngestor/main.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/datasetArchiver/main.go b/cmd/datasetArchiver/main.go index 98deadb..a330a41 100644 --- a/cmd/datasetArchiver/main.go +++ b/cmd/datasetArchiver/main.go @@ -58,7 +58,7 @@ func main() { } // check for program version only if running interactively - datasetUtils.CheckForNewVersion(client, APP, VERSION, true) + datasetUtils.CheckForNewVersion(client, APP, VERSION, *nonInteractiveFlag) if *testenvFlag { APIServer = TEST_API_SERVER diff --git a/cmd/datasetCleaner/main.go b/cmd/datasetCleaner/main.go index 0199aec..ef0f1f5 100644 --- a/cmd/datasetCleaner/main.go +++ b/cmd/datasetCleaner/main.go @@ -83,7 +83,7 @@ func main() { // check for program version only if running interactively - datasetUtils.CheckForNewVersion(client, APP, VERSION, true) + datasetUtils.CheckForNewVersion(client, APP, VERSION, *nonInteractiveFlag) datasetUtils.CheckForServiceAvailability(client, *testenvFlag, true) //} diff --git a/cmd/datasetIngestor/main.go b/cmd/datasetIngestor/main.go index ae5af47..9840ef6 100644 --- a/cmd/datasetIngestor/main.go +++ b/cmd/datasetIngestor/main.go @@ -138,9 +138,9 @@ func main() { fmt.Printf("%s\n", VERSION) return } - // check for program version only if running interactively - datasetUtils.CheckForNewVersion(client, APP, VERSION, !(*noninteractiveFlag)) + // check for program version only if running interactively + datasetUtils.CheckForNewVersion(client, APP, VERSION, *noninteractiveFlag) datasetUtils.CheckForServiceAvailability(client, *testenvFlag, *autoarchiveFlag) //} From 609cde45ec3c59070bceb6a5aadd1db836d8ea8b Mon Sep 17 00:00:00 2001 From: "Ali R. Vahdati" <3798865+kavir1698@users.noreply.github.com> Date: Wed, 3 Apr 2024 16:33:24 +0200 Subject: [PATCH 2/2] Add tests to check interactive mode --- cmd/datasetArchiver/main.go | 5 +- cmd/datasetCleaner/main.go | 6 ++- cmd/datasetGetProposal/main.go | 5 +- cmd/datasetIngestor/main.go | 7 ++- cmd/datasetRetriever/main.go | 5 +- datasetUtils/checkForNewVersion.go | 32 ++++++++---- datasetUtils/checkForNewVersion_test.go | 65 ++++++++++++++++++++----- 7 files changed, 96 insertions(+), 29 deletions(-) diff --git a/cmd/datasetArchiver/main.go b/cmd/datasetArchiver/main.go index a330a41..18907af 100644 --- a/cmd/datasetArchiver/main.go +++ b/cmd/datasetArchiver/main.go @@ -58,7 +58,10 @@ func main() { } // check for program version only if running interactively - datasetUtils.CheckForNewVersion(client, APP, VERSION, *nonInteractiveFlag) + err := datasetUtils.CheckForNewVersion(client, APP, VERSION, !*nonInteractiveFlag, datasetUtils.StdinUserInput{}) + if err != nil { + log.Fatalf("Error checking for new version: %v", err) + } if *testenvFlag { APIServer = TEST_API_SERVER diff --git a/cmd/datasetCleaner/main.go b/cmd/datasetCleaner/main.go index ef0f1f5..35b17bb 100644 --- a/cmd/datasetCleaner/main.go +++ b/cmd/datasetCleaner/main.go @@ -82,8 +82,10 @@ func main() { } // check for program version only if running interactively - - datasetUtils.CheckForNewVersion(client, APP, VERSION, *nonInteractiveFlag) + err := datasetUtils.CheckForNewVersion(client, APP, VERSION, !*nonInteractiveFlag, datasetUtils.StdinUserInput{}) + if err != nil { + log.Fatalf("Error checking for new version: %v", err) + } datasetUtils.CheckForServiceAvailability(client, *testenvFlag, true) //} diff --git a/cmd/datasetGetProposal/main.go b/cmd/datasetGetProposal/main.go index 62d63a5..0d3e78f 100644 --- a/cmd/datasetGetProposal/main.go +++ b/cmd/datasetGetProposal/main.go @@ -53,7 +53,10 @@ func main() { } // check for program version only if running interactively - datasetUtils.CheckForNewVersion(client, APP, VERSION, true) + err := datasetUtils.CheckForNewVersion(client, APP, VERSION, true, datasetUtils.StdinUserInput{}) + if err != nil { + log.Fatalf("Error checking for new version: %v", err) + } if *testenvFlag { APIServer = TEST_API_SERVER diff --git a/cmd/datasetIngestor/main.go b/cmd/datasetIngestor/main.go index 9840ef6..5813b3a 100644 --- a/cmd/datasetIngestor/main.go +++ b/cmd/datasetIngestor/main.go @@ -109,7 +109,7 @@ func main() { devenvFlag := flag.Bool("devenv", false, "Use development environment instead of production environment (developers only)") localenvFlag := flag.Bool("localenv", false, "Use local environment instead of production environment (developers only)") tunnelenvFlag := flag.Bool("tunnelenv", false, "Use tunneled API server at port 5443 to access development instance (developers only)") - noninteractiveFlag := flag.Bool("noninteractive", false, "If set no questions will be asked and the default settings for all undefined flags will be assumed") + noninteractiveFlag := flag.Bool("noninteractive", false, "If true, no questions will be asked and the default settings for all undefined flags will be assumed") userpass := flag.String("user", "", "Defines optional username:password string. This can be used both for access to the data catalog API and for access to the intermediate storage server for the decentral use case") token := flag.String("token", "", "Defines API token for access to the data catalog API. It is now mandatory for normal user accounts, but optional for functional accounts. It takes precedence over username/pw.") copyFlag := flag.Bool("copy", false, "Defines if files should be copied from your local system to a central server before ingest (i.e. your data is not centrally available and therefore needs to be copied ='decentral' case). copyFlag has higher priority than nocopyFlag. If neither flag is defined the tool will try to make the best guess.") @@ -140,7 +140,10 @@ func main() { } // check for program version only if running interactively - datasetUtils.CheckForNewVersion(client, APP, VERSION, *noninteractiveFlag) + err := datasetUtils.CheckForNewVersion(client, APP, VERSION, !*noninteractiveFlag, datasetUtils.StdinUserInput{}) + if err != nil { + log.Fatalf("Error checking for new version: %v", err) + } datasetUtils.CheckForServiceAvailability(client, *testenvFlag, *autoarchiveFlag) //} diff --git a/cmd/datasetRetriever/main.go b/cmd/datasetRetriever/main.go index 6510f1b..25f6333 100644 --- a/cmd/datasetRetriever/main.go +++ b/cmd/datasetRetriever/main.go @@ -74,7 +74,10 @@ func main() { return } - datasetUtils.CheckForNewVersion(client, APP, VERSION, true) + err := datasetUtils.CheckForNewVersion(client, APP, VERSION, true, datasetUtils.StdinUserInput{}) + if err != nil { + log.Fatalf("Error checking for new version: %v", err) + } var env string if *testenvFlag { diff --git a/datasetUtils/checkForNewVersion.go b/datasetUtils/checkForNewVersion.go index a987012..788cd84 100644 --- a/datasetUtils/checkForNewVersion.go +++ b/datasetUtils/checkForNewVersion.go @@ -52,11 +52,11 @@ func generateDownloadURL(deployLocation, latestVersion, osName string) string { return fmt.Sprintf("%s/v%s/scicat-cli_.%s_%s_x86_64.tar.gz", deployLocation, latestVersion, latestVersion, strings.Title(osName)) } -func CheckForNewVersion(client *http.Client, APP string, VERSION string, interactiveFlag bool) { +func CheckForNewVersion(client *http.Client, APP string, VERSION string, interactiveFlag bool, userInput UserInput) error { latestVersion, err := fetchLatestVersion(client) if err != nil { log.Printf("Can not find info about latest version for this program: %s\n", err) - return + return err } latestVersion = strings.TrimPrefix(latestVersion, "v") @@ -88,15 +88,27 @@ func CheckForNewVersion(client *http.Client, APP string, VERSION string, interac log.Printf("Browser: %s\nCommand: curl -L -O %s; tar xzf scicat-cli_.%s_%s_x86_64.tar.gz; cd scicat-cli; chmod +x %s\n", downloadURL, downloadURL, latestVersion, strings.Title(osName), APP) } - if interactiveFlag { - log.Print("Do you want to continue with current version (y/N) ? ") - scanner.Scan() - continueyn := scanner.Text() - if continueyn != "y" { - log.Fatalf("Execution stopped, please update program now.\n") - } - } + if interactiveFlag { + log.Print("Do you want to continue with current version (y/N) ? ") + continueyn, _ := userInput.ReadLine() + if continueyn != "y\n" { + return fmt.Errorf("Execution stopped, please update the program now.") + } + } } else { log.Println("Your version of this program is up-to-date") } + return nil +} + +// UserInput is an interface that defines a method to read a line of input. We use this so that we can test interactive mode. +type UserInput interface { + ReadLine() (string, error) +} + +type StdinUserInput struct {} + +func (StdinUserInput) ReadLine() (string, error) { + reader := bufio.NewReader(os.Stdin) + return reader.ReadString('\n') } diff --git a/datasetUtils/checkForNewVersion_test.go b/datasetUtils/checkForNewVersion_test.go index 4e227a8..99e17b1 100644 --- a/datasetUtils/checkForNewVersion_test.go +++ b/datasetUtils/checkForNewVersion_test.go @@ -7,6 +7,7 @@ import ( "testing" "bytes" "log" + "errors" ) func TestFetchLatestVersion(t *testing.T) { @@ -59,14 +60,22 @@ func TestGenerateDownloadURL(t *testing.T) { }, } - for _, testCase := range testCases { - actualURL := generateDownloadURL(deployLocation, latestVersion, testCase.osName) - - if actualURL != testCase.expectedURL { - t.Errorf("Expected URL to be %s, but got %s", testCase.expectedURL, actualURL) - } + for _, testCase := range testCases { + actualURL := generateDownloadURL(deployLocation, latestVersion, testCase.osName) + + if actualURL != testCase.expectedURL { + t.Errorf("Expected URL to be %s, but got %s", testCase.expectedURL, actualURL) } } +} + +type MockUserInput struct { + Input string +} + +func (m MockUserInput) ReadLine() (string, error) { + return m.Input, nil +} func TestCheckForNewVersion(t *testing.T) { tests := []struct { @@ -74,18 +83,45 @@ func TestCheckForNewVersion(t *testing.T) { currentVersion string mockResponse string expectedLog string + expectedError error + interactiveFlag bool + userInput string }{ { - name: "New version available", + name: "New version available, non-interactive mode", currentVersion: "0.9.0", mockResponse: `{"tag_name": "v1.0.0"}`, expectedLog: "You should upgrade to a newer version", + expectedError: nil, + interactiveFlag: false, + userInput: "y\n", }, { - name: "No new version available", + name: "No new version available, non-interactive mode", currentVersion: "1.0.0", mockResponse: `{"tag_name": "v1.0.0"}`, expectedLog: "Your version of this program is up-to-date", + expectedError: nil, + interactiveFlag: false, + userInput: "y\n", + }, + { + name: "New version available, interactive mode", + currentVersion: "0.9.0", + mockResponse: `{"tag_name": "v1.0.0"}`, + expectedLog: "You should upgrade to a newer version", + expectedError: nil, + interactiveFlag: true, + userInput: "y\n", + }, + { + name: "New version available, interactive mode, no upgrade", + currentVersion: "0.9.0", + mockResponse: `{"tag_name": "v1.0.0"}`, + expectedLog: "Execution stopped, please update the program now.", + expectedError: errors.New("Execution stopped, please update the program now."), + interactiveFlag: true, + userInput: "n\n", }, } @@ -107,12 +143,17 @@ func TestCheckForNewVersion(t *testing.T) { client := server.Client() // Call CheckForNewVersion - CheckForNewVersion(client, "test", tt.currentVersion, false) + err := CheckForNewVersion(client, "test", tt.currentVersion, tt.interactiveFlag, MockUserInput{Input: tt.userInput}) + if err != nil && err.Error() != tt.expectedLog { + t.Errorf("got error %v, want %v", err, tt.expectedLog) + } // Check the log output - logOutput := getLogOutput() - if !strings.Contains(logOutput, tt.expectedLog) { - t.Errorf("Expected log message not found: %s", logOutput) + if tt.userInput == "y\n" { + logOutput := getLogOutput() + if !strings.Contains(logOutput, tt.expectedLog) { + t.Errorf("Expected log message not found: %s", logOutput) + } } // Clear the log buffer after each test