added concurrent search test
All checks were successful
Run Integration Tests / test (push) Successful in 28s
All checks were successful
Run Integration Tests / test (push) Successful in 28s
This commit is contained in:
parent
7498f4128a
commit
28a721887c
1 changed files with 141 additions and 12 deletions
|
@ -3,12 +3,17 @@ package tests
|
|||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -17,11 +22,12 @@ import (
|
|||
)
|
||||
|
||||
type TestSummary struct {
|
||||
Passed []string
|
||||
Failed []string
|
||||
CPUUsage []float64
|
||||
RAMUsage []uint64
|
||||
CacheTests []CacheTestResult
|
||||
Passed []string
|
||||
Failed []string
|
||||
CPUUsage []float64
|
||||
RAMUsage []uint64
|
||||
CacheTests []CacheTestResult
|
||||
ConcurrentTestStats ConcurrentTestStats
|
||||
}
|
||||
|
||||
type CacheTestResult struct {
|
||||
|
@ -31,9 +37,21 @@ type CacheTestResult struct {
|
|||
IsCacheEffective bool
|
||||
}
|
||||
|
||||
type ConcurrentTestStats struct {
|
||||
TotalRequests int
|
||||
TotalFailures int
|
||||
RequestsPerType map[string]int
|
||||
FailuresPerType map[string]int
|
||||
}
|
||||
|
||||
func TestApplication(t *testing.T) {
|
||||
// Initialize test summary
|
||||
summary := &TestSummary{}
|
||||
summary := &TestSummary{
|
||||
ConcurrentTestStats: ConcurrentTestStats{
|
||||
RequestsPerType: make(map[string]int),
|
||||
FailuresPerType: make(map[string]int),
|
||||
},
|
||||
}
|
||||
|
||||
// Ensure the test runs from the root directory
|
||||
rootDir := "../" // Path to the root directory of the repository
|
||||
|
@ -136,6 +154,9 @@ func TestApplication(t *testing.T) {
|
|||
runTest(t, summary, "Test Search Types and Cache Effectiveness", func(t *testing.T) {
|
||||
testSearchTypesAndCache(t, summary)
|
||||
})
|
||||
runTest(t, summary, "Test Concurrent Random Requests", func(t *testing.T) {
|
||||
testConcurrentRandomRequests(t, summary)
|
||||
})
|
||||
runTest(t, summary, "Check Resource Usage After Tests", func(t *testing.T) {
|
||||
checkResourceUsage(t, summary, appProcess)
|
||||
})
|
||||
|
@ -187,6 +208,14 @@ func printSummary(summary *TestSummary, t *testing.T) {
|
|||
t.Logf(" Cache Effective: No")
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("\nConcurrent Random Requests Test Stats:")
|
||||
t.Logf(" Total Requests Sent: %d", summary.ConcurrentTestStats.TotalRequests)
|
||||
t.Logf(" Total Failures: %d", summary.ConcurrentTestStats.TotalFailures)
|
||||
for stype, reqCount := range summary.ConcurrentTestStats.RequestsPerType {
|
||||
failCount := summary.ConcurrentTestStats.FailuresPerType[stype]
|
||||
t.Logf(" Type '%s': %d requests, %d failures", stype, reqCount, failCount)
|
||||
}
|
||||
t.Logf("\n======================\n")
|
||||
}
|
||||
|
||||
|
@ -199,7 +228,6 @@ func checkResourceUsage(t *testing.T, summary *TestSummary, appProcess *process.
|
|||
} 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)
|
||||
|
@ -224,7 +252,6 @@ func checkResourceUsage(t *testing.T, summary *TestSummary, appProcess *process.
|
|||
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)
|
||||
|
@ -278,12 +305,16 @@ func testEndpoints(t *testing.T) {
|
|||
|
||||
func testSearchTypesAndCache(t *testing.T, summary *TestSummary) {
|
||||
searchTypes := []string{"text", "image", "video", "forum", "map", "file"}
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
for _, searchType := range searchTypes {
|
||||
url := "http://localhost:5000/search?q=test&t=" + searchType
|
||||
|
||||
// Initial search
|
||||
start := time.Now()
|
||||
resp, err := http.Get(url)
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to GET %s: %v", url, err)
|
||||
continue
|
||||
|
@ -303,10 +334,16 @@ func testSearchTypesAndCache(t *testing.T, summary *TestSummary) {
|
|||
}
|
||||
t.Logf("Search type '%s' took %v", searchType, initialDuration)
|
||||
|
||||
// If initial search took longer than 10 seconds, skip
|
||||
if initialDuration > 10*time.Second {
|
||||
t.Logf("Search type '%s' took too long (%v), skipping cached search", searchType, initialDuration)
|
||||
continue
|
||||
}
|
||||
|
||||
// Cached search
|
||||
time.Sleep(1 * time.Second) // Short delay to simulate time between searches
|
||||
time.Sleep(1 * time.Second)
|
||||
start = time.Now()
|
||||
resp, err = http.Get(url)
|
||||
resp, err = client.Get(url)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to GET %s (cached): %v", url, err)
|
||||
continue
|
||||
|
@ -332,7 +369,6 @@ func testSearchTypesAndCache(t *testing.T, summary *TestSummary) {
|
|||
t.Errorf("Cache not effective for search type '%s'", searchType)
|
||||
}
|
||||
|
||||
// Record the results
|
||||
summary.CacheTests = append(summary.CacheTests, CacheTestResult{
|
||||
SearchType: searchType,
|
||||
InitialDuration: initialDuration,
|
||||
|
@ -368,3 +404,96 @@ func testSuggestionsAPI(t *testing.T) {
|
|||
func bToMb(b uint64) uint64 {
|
||||
return b / 1024 / 1024
|
||||
}
|
||||
|
||||
func testConcurrentRandomRequests(t *testing.T, summary *TestSummary) {
|
||||
searchTypes := []string{"text", "image", "video", "forum", "map", "file"}
|
||||
numRequests := 10 // Number of requests per search type
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for _, stype := range searchTypes {
|
||||
summary.ConcurrentTestStats.RequestsPerType[stype] = numRequests
|
||||
for i := 0; i < numRequests; i++ {
|
||||
wg.Add(1)
|
||||
go func(searchType string) {
|
||||
defer wg.Done()
|
||||
query := getRandomUserQuery(searchType)
|
||||
fullURL := fmt.Sprintf("http://localhost:5000/search?q=%s&t=%s", url.QueryEscape(query), searchType)
|
||||
resp, err := client.Get(fullURL)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to GET %s: %v", fullURL, err)
|
||||
summary.ConcurrentTestStats.TotalFailures++
|
||||
summary.ConcurrentTestStats.FailuresPerType[searchType]++
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Search type '%s' with query '%s' returned status code %d", searchType, query, resp.StatusCode)
|
||||
summary.ConcurrentTestStats.TotalFailures++
|
||||
summary.ConcurrentTestStats.FailuresPerType[searchType]++
|
||||
}
|
||||
}(stype)
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all requests to complete
|
||||
wg.Wait()
|
||||
|
||||
summary.ConcurrentTestStats.TotalRequests = numRequests * len(searchTypes)
|
||||
t.Logf("Concurrent random requests test completed: %d requests sent", summary.ConcurrentTestStats.TotalRequests)
|
||||
if summary.ConcurrentTestStats.TotalFailures > 0 {
|
||||
t.Errorf("Number of failed requests: %d", summary.ConcurrentTestStats.TotalFailures)
|
||||
}
|
||||
}
|
||||
|
||||
// getRandomUserQuery returns a random user-like search query based on the search type
|
||||
func getRandomUserQuery(searchType string) string {
|
||||
var queries []string
|
||||
switch searchType {
|
||||
case "text":
|
||||
queries = []string{
|
||||
"weather forecast", "latest tech news", "open source software", "how to cook pasta",
|
||||
"learn golang", "famous quotes", "best laptops 2024", "history of linux",
|
||||
"simple bread recipe", "mountain climbing tips",
|
||||
}
|
||||
case "image":
|
||||
queries = []string{
|
||||
"cute cat pictures", "beautiful landscapes", "famous paintings", "colorful birds",
|
||||
"space wallpapers", "vintage cars", "r/unixporn", "minimalist backgrounds",
|
||||
}
|
||||
case "video":
|
||||
queries = []string{
|
||||
"cute cats", "music videos", "sports highlights", "coding tutorials",
|
||||
"documentaries about space", "stand-up comedy clips", "top movie trailers",
|
||||
}
|
||||
case "forum":
|
||||
queries = []string{
|
||||
"linux help forum", "DIY electronics discussion", "programming Q&A",
|
||||
"travel tips community", "best gaming computers", "homebrewing advice",
|
||||
"gardening support", "car maintenance forum", "best homelab setup",
|
||||
}
|
||||
case "map":
|
||||
queries = []string{
|
||||
"coffee shops in New York", "best pizza places in Chicago", "tourist attractions Tokyo",
|
||||
"Brazil", "public parks in Berlin", "bookstores in London", "Japan",
|
||||
}
|
||||
case "file":
|
||||
queries = []string{
|
||||
"debian iso", "free ebooks", "open source fonts", "linux distribution torrents",
|
||||
"arch iso", "alpine linux",
|
||||
}
|
||||
default:
|
||||
// fallback if unknown type
|
||||
queries = []string{"test query", "random search", "hello world"}
|
||||
}
|
||||
|
||||
// Pick a random query
|
||||
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(queries))))
|
||||
if err != nil {
|
||||
return queries[0] // fallback to first if error occurs
|
||||
}
|
||||
return queries[n.Int64()]
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue