This commit is contained in:
parent
72d76c85ed
commit
c8a5ae02c0
8 changed files with 511 additions and 21 deletions
31
.forgejo/workflows/test.yml
Normal file
31
.forgejo/workflows/test.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
name: Run Integration Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: alpine-1.20
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set Up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.20'
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
- name: Run Integration Tests
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
go test -v
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@ image_cache/
|
||||||
cache/
|
cache/
|
||||||
*.min.js
|
*.min.js
|
||||||
*.min.css
|
*.min.css
|
||||||
|
qgato
|
23
run.bat
23
run.bat
|
@ -5,6 +5,8 @@ rem Initialize variables
|
||||||
set SKIP_CONFIG=""
|
set SKIP_CONFIG=""
|
||||||
set PORT=""
|
set PORT=""
|
||||||
set DOMAIN=""
|
set DOMAIN=""
|
||||||
|
set BUILD_MODE=false
|
||||||
|
set BUILD_OUTPUT=qgato.exe
|
||||||
|
|
||||||
rem Parse arguments
|
rem Parse arguments
|
||||||
:parse_args
|
:parse_args
|
||||||
|
@ -26,6 +28,11 @@ if "%~1"=="--skip-config-check" (
|
||||||
shift
|
shift
|
||||||
goto parse_args
|
goto parse_args
|
||||||
)
|
)
|
||||||
|
if "%~1"=="--build" (
|
||||||
|
set BUILD_MODE=true
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
echo Unknown argument: %~1
|
echo Unknown argument: %~1
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
|
@ -34,12 +41,25 @@ exit /b 1
|
||||||
rem Use the current directory where the script is executed
|
rem Use the current directory where the script is executed
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
rem Collect all .go files in the current directory
|
rem Collect all .go files in the current directory excluding *_test.go
|
||||||
set GO_FILES=
|
set GO_FILES=
|
||||||
for %%f in (*.go) do (
|
for %%f in (*.go) do (
|
||||||
|
echo %%f | findstr "_test.go" >nul
|
||||||
|
if errorlevel 1 (
|
||||||
set GO_FILES=!GO_FILES! %%f
|
set GO_FILES=!GO_FILES! %%f
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%BUILD_MODE%"=="true" (
|
||||||
|
rem Build mode
|
||||||
|
echo Building application...
|
||||||
|
go build -o "%BUILD_OUTPUT%" !GO_FILES!
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo Build failed!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo Build successful! Output: %CD%\%BUILD_OUTPUT%
|
||||||
|
) else (
|
||||||
rem Construct the command
|
rem Construct the command
|
||||||
set CMD=go run !GO_FILES! !SKIP_CONFIG!
|
set CMD=go run !GO_FILES! !SKIP_CONFIG!
|
||||||
if not "%PORT%"=="" set CMD=!CMD! --port %PORT%
|
if not "%PORT%"=="" set CMD=!CMD! --port %PORT%
|
||||||
|
@ -50,6 +70,7 @@ echo Starting application with command: !CMD!
|
||||||
|
|
||||||
rem Run the Go program with the constructed command
|
rem Run the Go program with the constructed command
|
||||||
call !CMD!
|
call !CMD!
|
||||||
|
)
|
||||||
|
|
||||||
rem Return to the original directory
|
rem Return to the original directory
|
||||||
popd
|
popd
|
||||||
|
|
28
run.sh
28
run.sh
|
@ -4,6 +4,8 @@
|
||||||
SKIP_CONFIG=""
|
SKIP_CONFIG=""
|
||||||
PORT=""
|
PORT=""
|
||||||
DOMAIN=""
|
DOMAIN=""
|
||||||
|
BUILD_MODE=false
|
||||||
|
BUILD_OUTPUT="qgato"
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
|
@ -20,6 +22,10 @@ while [ $# -gt 0 ]; do
|
||||||
SKIP_CONFIG="--skip-config-check"
|
SKIP_CONFIG="--skip-config-check"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--build)
|
||||||
|
BUILD_MODE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown argument: $1"
|
echo "Unknown argument: $1"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -27,16 +33,30 @@ while [ $# -gt 0 ]; do
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
# List all Go files in this directory
|
# Get the directory of the script
|
||||||
GO_FILES=$(find . -name '*.go' -print)
|
SCRIPT_DIR=$(dirname "$0")
|
||||||
|
|
||||||
# Construct the command
|
# List all Go files in the script directory (excluding test files)
|
||||||
|
GO_FILES=$(find "$SCRIPT_DIR" -name '*.go' ! -name '*_test.go' -print)
|
||||||
|
|
||||||
|
if $BUILD_MODE; then
|
||||||
|
# Build mode
|
||||||
|
echo "Building application..."
|
||||||
|
go build -o "$SCRIPT_DIR/$BUILD_OUTPUT" $GO_FILES
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Build successful! Output: $SCRIPT_DIR/$BUILD_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "Build failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Run mode
|
||||||
CMD="go run $GO_FILES $SKIP_CONFIG"
|
CMD="go run $GO_FILES $SKIP_CONFIG"
|
||||||
[ -n "$PORT" ] && CMD="$CMD --port $PORT"
|
[ -n "$PORT" ] && CMD="$CMD --port $PORT"
|
||||||
[ -n "$DOMAIN" ] && CMD="$CMD --domain $DOMAIN"
|
[ -n "$DOMAIN" ] && CMD="$CMD --domain $DOMAIN"
|
||||||
|
|
||||||
# Informative output
|
|
||||||
echo "Starting application with command: $CMD"
|
echo "Starting application with command: $CMD"
|
||||||
|
|
||||||
# Run the Go program with the constructed command
|
# Run the Go program with the constructed command
|
||||||
eval $CMD
|
eval $CMD
|
||||||
|
fi
|
||||||
|
|
15
tests/README.md
Normal file
15
tests/README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
These tests perform the following:
|
||||||
|
|
||||||
|
1. **Start and compile the application using `run.sh`.**
|
||||||
|
2. **Check idle resource usage (RAM, CPU).**
|
||||||
|
3. **Test all endpoints such as `/settings`.**
|
||||||
|
4. **Test all search types and measure response times:**
|
||||||
|
- `/search?q=test&t=text`
|
||||||
|
- `/search?q=test&t=image`
|
||||||
|
- `/search?q=test&t=video`
|
||||||
|
- `/search?q=test&t=forum`
|
||||||
|
- `/search?q=test&t=map`
|
||||||
|
- `/search?q=test&t=file`
|
||||||
|
5. **Check resource usage after searches (RAM, CPU).**
|
||||||
|
6. **Re-run all search types to test cache performance.**
|
||||||
|
7. **Test the suggestions API at `/suggestions?q=test`.**
|
14
tests/go.mod
Normal file
14
tests/go.mod
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module tests
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
|
github.com/stretchr/testify v1.10.0 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.8.0 // indirect
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
|
)
|
18
tests/go.sum
Normal file
18
tests/go.sum
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||||
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||||
|
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||||
|
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
370
tests/integration_test.go
Normal file
370
tests/integration_test.go
Normal file
|
@ -0,0 +1,370 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/process"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestSummary struct {
|
||||||
|
Passed []string
|
||||||
|
Failed []string
|
||||||
|
CPUUsage []float64
|
||||||
|
RAMUsage []uint64
|
||||||
|
CacheTests []CacheTestResult
|
||||||
|
}
|
||||||
|
|
||||||
|
type CacheTestResult struct {
|
||||||
|
SearchType string
|
||||||
|
InitialDuration time.Duration
|
||||||
|
CachedDuration time.Duration
|
||||||
|
IsCacheEffective bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplication(t *testing.T) {
|
||||||
|
// Initialize test summary
|
||||||
|
summary := &TestSummary{}
|
||||||
|
|
||||||
|
// Ensure the test runs from the root directory
|
||||||
|
rootDir := "../" // Path to the root directory of the repository
|
||||||
|
|
||||||
|
// Build the application using `run.sh --build`
|
||||||
|
buildCmd := exec.Command("sh", "./run.sh", "--build")
|
||||||
|
buildCmd.Dir = rootDir
|
||||||
|
|
||||||
|
buildOutput, err := buildCmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to build application: %v\nOutput:\n%s", err, string(buildOutput))
|
||||||
|
}
|
||||||
|
t.Log("Application built successfully")
|
||||||
|
|
||||||
|
// Path to the built executable relative to rootDir
|
||||||
|
executablePath := "./qgato" // Since cmd.Dir is rootDir, this path is relative to rootDir
|
||||||
|
|
||||||
|
// Ensure the executable has execute permissions
|
||||||
|
execFullPath := filepath.Join(rootDir, "qgato")
|
||||||
|
if err := os.Chmod(execFullPath, 0755); err != nil {
|
||||||
|
t.Fatalf("Failed to set execute permissions on the executable: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a context with cancellation
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel() // Ensure resources are cleaned up
|
||||||
|
|
||||||
|
// Start the application using the built executable
|
||||||
|
cmd := exec.CommandContext(ctx, executablePath, "--skip-config-check")
|
||||||
|
cmd.Dir = rootDir // Set the working directory to the root directory
|
||||||
|
|
||||||
|
// Set process group ID so we can kill it and its children
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setpgid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture application output for logging
|
||||||
|
appStdout, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to capture stdout: %v", err)
|
||||||
|
}
|
||||||
|
appStderr, err := cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to capture stderr: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the application
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
t.Fatalf("Failed to start application: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read application logs concurrently
|
||||||
|
go func() {
|
||||||
|
scanner := bufio.NewScanner(appStdout)
|
||||||
|
for scanner.Scan() {
|
||||||
|
t.Logf("[APP STDOUT] %s", scanner.Text())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
scanner := bufio.NewScanner(appStderr)
|
||||||
|
for scanner.Scan() {
|
||||||
|
t.Logf("[APP STDERR] %s", scanner.Text())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Defer cleanup to ensure process is killed after the test
|
||||||
|
defer func() {
|
||||||
|
// Kill the process group
|
||||||
|
pgid, err := syscall.Getpgid(cmd.Process.Pid)
|
||||||
|
if err == nil {
|
||||||
|
syscall.Kill(-pgid, syscall.SIGKILL)
|
||||||
|
} else {
|
||||||
|
t.Logf("Failed to get process group ID: %v", err)
|
||||||
|
cmd.Process.Kill()
|
||||||
|
}
|
||||||
|
cmd.Wait()
|
||||||
|
|
||||||
|
// Print summary
|
||||||
|
printSummary(summary, t)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for the server to start
|
||||||
|
if !waitForServer("http://localhost:5000", 15*time.Second) {
|
||||||
|
t.Fatalf("Server did not start within the expected time")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("Application is running")
|
||||||
|
|
||||||
|
// Create a process instance for the application
|
||||||
|
appProcess, err := process.NewProcess(int32(cmd.Process.Pid))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create process instance: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run test functions and collect results
|
||||||
|
runTest(t, summary, "Check Idle Resource Usage", func(t *testing.T) {
|
||||||
|
checkResourceUsage(t, summary, appProcess)
|
||||||
|
})
|
||||||
|
runTest(t, summary, "Test Endpoints", testEndpoints)
|
||||||
|
runTest(t, summary, "Test Search Types and Cache Effectiveness", func(t *testing.T) {
|
||||||
|
testSearchTypesAndCache(t, summary)
|
||||||
|
})
|
||||||
|
runTest(t, summary, "Check Resource Usage After Tests", func(t *testing.T) {
|
||||||
|
checkResourceUsage(t, summary, appProcess)
|
||||||
|
})
|
||||||
|
runTest(t, summary, "Test Suggestions API", testSuggestionsAPI)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTest(t *testing.T, summary *TestSummary, name string, testFunc func(t *testing.T)) {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
t.Errorf("Test '%s' panicked: %v", name, r)
|
||||||
|
summary.Failed = append(summary.Failed, name)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
testFunc(t)
|
||||||
|
if !t.Failed() {
|
||||||
|
summary.Passed = append(summary.Passed, name)
|
||||||
|
} else {
|
||||||
|
summary.Failed = append(summary.Failed, name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSummary(summary *TestSummary, t *testing.T) {
|
||||||
|
t.Logf("\n==== TEST SUMMARY ====")
|
||||||
|
t.Logf("PASSED TESTS: %d", len(summary.Passed))
|
||||||
|
for _, test := range summary.Passed {
|
||||||
|
t.Logf(" - %s", test)
|
||||||
|
}
|
||||||
|
t.Logf("FAILED TESTS: %d", len(summary.Failed))
|
||||||
|
for _, test := range summary.Failed {
|
||||||
|
t.Logf(" - %s", test)
|
||||||
|
}
|
||||||
|
t.Logf("\nResource Usage:")
|
||||||
|
for i, cpu := range summary.CPUUsage {
|
||||||
|
t.Logf(" CPU Usage Sample %d: %.2f%%", i+1, cpu)
|
||||||
|
}
|
||||||
|
for i, ram := range summary.RAMUsage {
|
||||||
|
t.Logf(" RAM Usage Sample %d: %d MiB", i+1, ram)
|
||||||
|
}
|
||||||
|
t.Logf("\nCache Test Results:")
|
||||||
|
for _, result := range summary.CacheTests {
|
||||||
|
t.Logf(" Search Type: %s", result.SearchType)
|
||||||
|
t.Logf(" Initial Duration: %v", result.InitialDuration)
|
||||||
|
t.Logf(" Cached Duration: %v", result.CachedDuration)
|
||||||
|
if result.IsCacheEffective {
|
||||||
|
t.Logf(" Cache Effective: Yes")
|
||||||
|
} else {
|
||||||
|
t.Logf(" Cache Effective: No")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Logf("\n======================\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkResourceUsage(t *testing.T, summary *TestSummary, appProcess *process.Process) {
|
||||||
|
// Get CPU usage of the application process
|
||||||
|
cpuPercent, err := appProcess.Percent(time.Second)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to get CPU usage: %v", err)
|
||||||
|
summary.CPUUsage = append(summary.CPUUsage, 0.0)
|
||||||
|
} else {
|
||||||
|
// Sum the CPU usage of the main process and its children
|
||||||
|
totalCPU := cpuPercent
|
||||||
|
// Get child processes
|
||||||
|
children, err := appProcess.Children()
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to get child processes: %v", err)
|
||||||
|
} else {
|
||||||
|
for _, child := range children {
|
||||||
|
childCPU, err := child.Percent(0)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to get CPU usage for child process %d: %v", child.Pid, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
totalCPU += childCPU
|
||||||
|
}
|
||||||
|
}
|
||||||
|
summary.CPUUsage = append(summary.CPUUsage, totalCPU)
|
||||||
|
t.Logf("Total CPU Usage (process and children): %.2f%%", totalCPU)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get memory info of the application process
|
||||||
|
memInfo, err := appProcess.MemoryInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to get memory info: %v", err)
|
||||||
|
summary.RAMUsage = append(summary.RAMUsage, 0)
|
||||||
|
} else {
|
||||||
|
totalRAM := memInfo.RSS
|
||||||
|
// Get memory info for child processes
|
||||||
|
children, err := appProcess.Children()
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to get child processes: %v", err)
|
||||||
|
} else {
|
||||||
|
for _, child := range children {
|
||||||
|
childMemInfo, err := child.MemoryInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to get memory info for child process %d: %v", child.Pid, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
totalRAM += childMemInfo.RSS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ramUsage := bToMb(totalRAM)
|
||||||
|
summary.RAMUsage = append(summary.RAMUsage, ramUsage)
|
||||||
|
t.Logf("Total Memory Usage (process and children): %d MiB", ramUsage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForServer(url string, timeout time.Duration) bool {
|
||||||
|
start := time.Now()
|
||||||
|
for {
|
||||||
|
if time.Since(start) > timeout {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err == nil && resp.StatusCode == http.StatusOK {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEndpoints(t *testing.T) {
|
||||||
|
endpoints := []string{
|
||||||
|
"/",
|
||||||
|
"/settings",
|
||||||
|
}
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
resp, err := http.Get("http://localhost:5000" + endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to GET %s: %v", endpoint, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("%s returned status code %d", endpoint, resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSearchTypesAndCache(t *testing.T, summary *TestSummary) {
|
||||||
|
searchTypes := []string{"text", "image", "video", "forum", "map", "file"}
|
||||||
|
for _, searchType := range searchTypes {
|
||||||
|
url := "http://localhost:5000/search?q=test&t=" + searchType
|
||||||
|
|
||||||
|
// Initial search
|
||||||
|
start := time.Now()
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to GET %s: %v", url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
initialDuration := time.Since(start)
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read response body for %s: %v", url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("Search type '%s' returned status code %d", searchType, resp.StatusCode)
|
||||||
|
}
|
||||||
|
if len(body) == 0 {
|
||||||
|
t.Errorf("Response body for %s is empty", url)
|
||||||
|
}
|
||||||
|
t.Logf("Search type '%s' took %v", searchType, initialDuration)
|
||||||
|
|
||||||
|
// Cached search
|
||||||
|
time.Sleep(1 * time.Second) // Short delay to simulate time between searches
|
||||||
|
start = time.Now()
|
||||||
|
resp, err = http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to GET %s (cached): %v", url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cachedDuration := time.Since(start)
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read response body for cached %s: %v", url, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("Cached search type '%s' returned status code %d", searchType, resp.StatusCode)
|
||||||
|
}
|
||||||
|
if len(body) == 0 {
|
||||||
|
t.Errorf("Response body for cached %s is empty", url)
|
||||||
|
}
|
||||||
|
t.Logf("Cached search type '%s' took %v", searchType, cachedDuration)
|
||||||
|
|
||||||
|
// Check if cache was effective
|
||||||
|
isCacheEffective := cachedDuration < initialDuration
|
||||||
|
if !isCacheEffective {
|
||||||
|
t.Errorf("Cache not effective for search type '%s'", searchType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the results
|
||||||
|
summary.CacheTests = append(summary.CacheTests, CacheTestResult{
|
||||||
|
SearchType: searchType,
|
||||||
|
InitialDuration: initialDuration,
|
||||||
|
CachedDuration: cachedDuration,
|
||||||
|
IsCacheEffective: isCacheEffective,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSuggestionsAPI(t *testing.T) {
|
||||||
|
url := "http://localhost:5000/suggestions?q=test"
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to GET %s: %v", url, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("Suggestions API returned status code %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read response body for suggestions API: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var data []interface{}
|
||||||
|
if err := json.Unmarshal(body, &data); err != nil {
|
||||||
|
t.Errorf("Failed to parse JSON response: %v", err)
|
||||||
|
t.Logf("Response body: %s", string(body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bToMb(b uint64) uint64 {
|
||||||
|
return b / 1024 / 1024
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue