add support for testing redirection
This commit is contained in:
parent
d9ab7e77c1
commit
85dacbe2de
91
test.go
91
test.go
@ -1,9 +1,100 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var sem chan Empty // semaphore to limit requess in flight
|
||||
|
||||
// test accepts a slice of type Redirect and returns an error
|
||||
// it performs actual HTTP GET requests on each source URL and validates that a redirect occurs
|
||||
// to the destination URL and that the redirect type/status code is correct
|
||||
func test(redirects []Redirect) error { //TBD: implement
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
mu := &sync.Mutex{}
|
||||
var summaryOutput string
|
||||
|
||||
sem = make(Semaphore, *maxConcurrentRequests)
|
||||
|
||||
for _, redirect := range redirects {
|
||||
wg.Add(1)
|
||||
P(1)
|
||||
|
||||
go func(redirect Redirect) {
|
||||
defer V(1)
|
||||
defer wg.Done()
|
||||
client := &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
|
||||
// writing to std out is critical section
|
||||
mu.Lock()
|
||||
fmt.Printf("Checking redirect for: %s\n", redirect.sourceURL)
|
||||
mu.Unlock()
|
||||
|
||||
// Make the request
|
||||
resp, err := client.Get(redirect.sourceURL)
|
||||
if err != nil {
|
||||
log.Printf("HTTP GET failed for source URL '%s': %v", redirect.sourceURL, err)
|
||||
}
|
||||
|
||||
// Check the status code
|
||||
if resp.StatusCode != redirect.statusCode {
|
||||
// Modifying output is critical section
|
||||
mu.Lock()
|
||||
summaryOutput += fmt.Sprintf("redirect for source URL '%s': expected status code'%d': got '%d\n", redirect.sourceURL, redirect.statusCode, resp.StatusCode)
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// Check that the redirect went to the correct location
|
||||
destURL, err := resp.Location()
|
||||
if err != nil {
|
||||
log.Printf("failed to parse response location to URL: %v", err)
|
||||
}
|
||||
|
||||
if destURL.String() != redirect.destinationURL {
|
||||
// Modifying output is critical section
|
||||
mu.Lock()
|
||||
summaryOutput += fmt.Sprintf("redirect for source URL '%s': expected '%s': got '%s\n", redirect.sourceURL, redirect.destinationURL, destURL.String())
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
}(redirect)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
fmt.Printf("\ndone tests.\n---------------------------------------------\nSummary:\n\n%s", summaryOutput)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Semaphore helper functions
|
||||
|
||||
// Empty is an empty struct used by the semaphores
|
||||
type Empty struct{}
|
||||
|
||||
// Semaphore is a channel which passes empty structs and acts as a resource lock
|
||||
type Semaphore chan Empty
|
||||
|
||||
// P acquire n resources - standard semaphore design pattern to limit number of requests in flight
|
||||
func P(n int) {
|
||||
e := Empty{}
|
||||
for i := 0; i < n; i++ {
|
||||
sem <- e
|
||||
}
|
||||
}
|
||||
|
||||
// V release n resources - standard semaphore design pattern to limit number of requests in flight
|
||||
func V(n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
<-sem
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user