Skip to content

Commit

Permalink
Test shutdown, update, restore
Browse files Browse the repository at this point in the history
  • Loading branch information
theotherp committed Mar 25, 2024
1 parent 520e2b0 commit 4aa8050
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 24 deletions.
Expand Up @@ -46,8 +46,8 @@ public class SystemControl {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;

public void exitWithReturnCode(final int returnCode) {
if (Boolean.parseBoolean(environment.getProperty("hydradontshutdown", "false"))) {
public void exitWithReturnCode(final int returnCode, boolean forceShutdown) {
if (Boolean.parseBoolean(environment.getProperty("hydradontshutdown", "false")) && !forceShutdown) {
logger.warn("Not shutting down because property hydradontshutdown is set");
return;
}
Expand All @@ -70,4 +70,8 @@ public void exitWithReturnCode(final int returnCode) {
}
}).start();
}

public void exitWithReturnCode(final int returnCode) {
exitWithReturnCode(returnCode, false);
}
}
Expand Up @@ -26,6 +26,7 @@
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand All @@ -40,18 +41,12 @@ public class SystemControlWeb {

@Secured({"ROLE_ADMIN"})
@RequestMapping(value = "/internalapi/control/shutdown", method = RequestMethod.GET)
public GenericResponse shutdown() throws Exception {
return doShutdown();
}

@NotNull
private GenericResponse doShutdown() {
public GenericResponse shutdown(@RequestParam(required = false) Integer returnCode, @RequestParam(required = false) Boolean forceShutdown) throws Exception {
logger.info("Shutting down due to external request");
systemControl.exitWithReturnCode(SystemControl.SHUTDOWN_RETURN_CODE);
systemControl.exitWithReturnCode(returnCode == null ? SystemControl.SHUTDOWN_RETURN_CODE : returnCode, forceShutdown != null && forceShutdown);
return GenericResponse.ok();
}


@Secured({"ROLE_ADMIN"})
@RequestMapping(value = "/internalapi/control/restart", method = RequestMethod.GET)
public GenericResponse restart() throws Exception {
Expand Down
7 changes: 5 additions & 2 deletions other/gowrapper/base/base.go
Expand Up @@ -509,7 +509,7 @@ func runMainProcess(executable string, arguments []string) int {
if !*argsQuiet {
println(line)
}
handleProcessUriInLogLine(line)
checkLogLine(line)
consoleLines = append(consoleLines, line)
if len(consoleLines) > 250 {
consoleLines = consoleLines[1:]
Expand All @@ -536,7 +536,7 @@ func runMainProcess(executable string, arguments []string) int {
return 0
}

func handleProcessUriInLogLine(line string) {
func checkLogLine(line string) {
markerLine := "You can access NZBHydra 2 in your browser via "
if strings.Contains(line, markerLine) {
Uri = strings.TrimSpace(line[strings.Index(line, markerLine)+len(markerLine):])
Expand All @@ -547,6 +547,9 @@ func handleProcessUriInLogLine(line string) {
urlToOpen := strings.TrimSpace(line[strings.Index(line, markerLine)+len(markerLine):])
OpenBrowser(urlToOpen)
}
if strings.Contains(line, "Started NzbHydra in") {
Log(logrus.InfoLevel, "Main process has started successfully")
}
}

func OpenBrowser(urlToOpen string) {
Expand Down
134 changes: 122 additions & 12 deletions other/gowrapper/base/base_test.go
@@ -1,42 +1,117 @@
package base

import (
"bufio"
"fmt"
"github.com/stretchr/testify/assert"
"net/http"
"os"
"strings"
"sync"
"testing"
"time"
)

type Predicate func(error error, response *http.Response) bool

var reachedLineNumber int

//goland:noinspection GoUnhandledErrorResult
func TestSimpleShutdown(t *testing.T) {
var wg sync.WaitGroup
dir := "d:\\NZBHydra\\nzbhydra2\\gowrappertest\\automated\\mainfolder\\"
os.RemoveAll(dir)
os.Create(dir)
Unzip("d:\\NZBHydra\\nzbhydra2\\gowrappertest\\automated\\sources\\nzbhydra2-5.3.10-windows-withData.zip", dir)
os.Chdir(dir)
Uri = "http://127.0.0.1:5076/"
var exitCode int
prepareAndRun(&wg)

wg.Add(1)
go runCode(&wg, &exitCode)
go func() {
defer wg.Done()
started, _ := wrapperLogContainsString("Main process has started successfully")
assert.True(t, started, "Process has not started")

shutdownWithCode(0)

shutdown, _ := wrapperLogContainsString("NZBHydra main process has stopped for shutdown")
assert.True(t, shutdown, "Process has not shut down")
}()
wg.Wait()
}

//goland:noinspection GoUnhandledErrorResult
func TestUpdate(t *testing.T) {
var wg sync.WaitGroup
prepareAndRun(&wg)

wg.Add(1)
go func() {
defer wg.Done()
getWaiting(Uri, func(error error, response *http.Response) bool { return response != nil && response.StatusCode == 200 })
getWaiting(Uri+"internalapi/control/shutdown?internalApiKey="+GetInternalApiKey(), func(error error, response *http.Response) bool { return error != nil })
wasShutdown := getWaiting(Uri, func(error error, response *http.Response) bool { return error != nil })
assert.True(t, wasShutdown, "Server was not shut down")
waitForServerUp()

shutdownWithCode(11)
updated, _ := wrapperLogContainsString("Update successful")
assert.True(t, updated, "Process was not updated")

restarted, _ := wrapperLogContainsString("Main process has started successfully")
assert.True(t, restarted, "Process has not restarted after update")

shutdownWithCode(0)
shutdown, _ := wrapperLogContainsString("NZBHydra main process has stopped for shutdown")
assert.True(t, shutdown, "Process has not shut down")
waitForServerDown(t)
}()
wg.Wait()
}

//goland:noinspection GoUnhandledErrorResult
func TestRestore(t *testing.T) {
var wg sync.WaitGroup
prepareAndRun(&wg)

wg.Add(1)
go func() {
defer wg.Done()
waitForServerUp()

shutdownWithCode(33)
restored, _ := wrapperLogContainsString("Moved all files from restore folder")
assert.True(t, restored, "Process has not restored")

restarted, _ := wrapperLogContainsString("Main process has started successfully")
assert.True(t, restarted, "Process has not restarted after restore")

shutdownWithCode(0)
shutdown, _ := wrapperLogContainsString("NZBHydra main process has stopped for shutdown")
assert.True(t, shutdown, "Process has not shut down")
waitForServerDown(t)
}()
wg.Wait()
}

func shutdownWithCode(code int) bool {
url := fmt.Sprintf("%sinternalapi/control/shutdown?returnCode=%d&internalApiKey=%s", Uri, code, GetInternalApiKey())
return getWaiting(url, func(error error, response *http.Response) bool { return error != nil })
}

func waitForServerDown(t *testing.T) {
wasShutdown := getWaiting(Uri, func(error error, response *http.Response) bool { return error != nil })
assert.True(t, wasShutdown, "Server was not shut down")
}

func waitForServerUp() bool {
return getWaiting(Uri, func(error error, response *http.Response) bool { return response != nil && response.StatusCode == 200 })
}

func prepareAndRun(wg *sync.WaitGroup) {
reachedLineNumber = 0
dir := "d:\\NZBHydra\\nzbhydra2\\gowrappertest\\automated\\mainfolder\\"
os.RemoveAll(dir)
os.Create(dir)
Unzip("d:\\NZBHydra\\nzbhydra2\\gowrappertest\\automated\\sources\\nzbhydra2-5.3.10-windows-testSource.zip", dir)
os.Chdir(dir)
Uri = "http://127.0.0.1:5076/"
var exitCode int
wg.Add(1)
go runCode(wg, &exitCode)
}

func getWaiting(url string, predicate Predicate) bool {
beganAt := time.Now()
for {
Expand All @@ -60,3 +135,38 @@ func runCode(wg *sync.WaitGroup, exitCode *int) {
}
Entrypoint(false, false)
}

func wrapperLogContainsString(searchString string) (bool, error) {
beganAt := time.Now()
for {
if beganAt.Add(time.Second * 10).Before(time.Now()) {
return false, nil
}
file, err := os.Open("d:\\NZBHydra\\nzbhydra2\\gowrappertest\\automated\\mainfolder\\data\\logs\\wrapper.log")
if err != nil {
//Assume file does not exist yet
continue
}

scanner := bufio.NewScanner(file)
lineNumber := 0
for scanner.Scan() {
lineNumber++
//Do not read the same line again
if lineNumber < reachedLineNumber {
continue
}
if strings.Contains(scanner.Text(), searchString) {
_ = file.Close()
reachedLineNumber = lineNumber
return true, nil
}
}
_ = file.Close()
if err := scanner.Err(); err != nil {
return false, err
}

time.Sleep(time.Millisecond * 500)
}
}

0 comments on commit 4aa8050

Please sign in to comment.