func TestStatusSites(t *testing.T) {
	withNewMultiSiteServer(func(server *TestServer) {
		siteShouldRespondWithStatusCode(t, server, 200, "200")
		siteShouldRespondWithStatusCode(t, server, 404, "404")
		siteShouldRespondWithStatusCode(t, server, 599, "599")
	})
}
TODO: does every multi-site test needs to begin with "withNewMultiSiteServer(func...)?"
package main
import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os/exec"
	"path"
	"strings"
	"testing"
	"time"
)
const (
	ANY_DB_DRIVER    = ""
	MULTI_SITE_MODE  = ""
	TEST_DEPLOYED_ON = "localhost:9999"
	TEST_POSTGRES_DB = "goslow_test"
)
var DATA_SOURCE = map[string]string{
	"sqlite3":  DEFAULT_CONFIG.dataSource,
	"postgres": "postgres://localhost/" + TEST_POSTGRES_DB,
}
type TestServer struct {
	goSlowServer  *Server
	runningServer *httptest.Server
}
type ServerTest func(*TestServer)
func TestCreateSite(t *testing.T) {
	withNewMultiSiteServer(func(server *TestServer) {
		shouldCreateSiteWithEndpoint(t, server, &Endpoint{Method: "GET", Path: "/path/", Response: []byte("long")})
		shouldCreateSiteWithEndpoint(t, server, &Endpoint{Method: "GET", Path: "/path", Response: []byte("short")})
	})
}
func shouldCreateSiteWithEndpoint(t *testing.T, server *TestServer, endpoint *Endpoint) {
	site := server.createSite(endpoint)
	req := server.makeRequestFor(&Endpoint{Site: site, Method: endpoint.Method, Path: endpoint.Path})
	shouldRespondWith(t, endpoint.Response, req)
}
func TestZeroSite(t *testing.T) {
	withNewMultiSiteServer(func(server *TestServer) {
		shouldRespondWith(t, DEFAULT_RESPONSE,
			createGET(server.getURL(), "/", makeFullDomain("0")))
	})
}
func withNewMultiSiteServer(serverTest ServerTest) {
	withNewServer(MULTI_SITE_MODE, serverTest)
}
func withNewServer(adminPathPrefix string, serverTest ServerTest) {
	for _, driver := range getDrivers() {
		withNewServerUsing(driver, adminPathPrefix, serverTest)
	}
}
func getDrivers() []string {
	drivers := []string{"sqlite3"}
	if !testing.Short() {
		drivers = append(drivers, "postgres")
	}
	return drivers
}
func withNewServerUsing(driver string, adminPathPrefix string, serverTest ServerTest) {
	if driver == "postgres" {
		createDb(TEST_POSTGRES_DB)
		defer dropDb(TEST_POSTGRES_DB)
	}
	goSlowServer := newGoSlowServer(driver, adminPathPrefix)
	runningServer := httptest.NewServer(goSlowServer)
	defer runningServer.Close()
	defer goSlowServer.storage.db.Close()  
	serverTest(&TestServer{goSlowServer: goSlowServer, runningServer: runningServer})
}
func withServers(adminPathPrefixes []string, serverTest ServerTest) {
	for _, adminPathPrefix := range adminPathPrefixes {
		withNewServer(adminPathPrefix, serverTest)
	}
}
func shouldRespondWith(t *testing.T, expectedResponse []byte, req *http.Request) {
	resp := do(req)
	bytesShouldBeEqual(t, expectedResponse, read(resp))
}
func TestTooLargeDelay(t *testing.T) {
	withServers([]string{MULTI_SITE_MODE, "/goslow"}, func(server *TestServer) {
		dontAllowToCreateEndpointWithDelay(t, server, time.Duration(1000)*time.Second)
	})
}
func dontAllowToCreateEndpointWithDelay(t *testing.T, server *TestServer, delay time.Duration) {
	server.withNewSite(func(site string) {
		resp := server.createEndpoint(&Endpoint{Site: site, Path: "/", Delay: delay})
		shouldHaveStatusCode(t, http.StatusBadRequest, resp)
		shouldHaveStatusCode(t, http.StatusNotFound, GET(server.getURL(), "/", makeFullDomain(site)))
	})
}
type SiteTest func(site string)
func (server *TestServer) withNewSite(siteTest SiteTest) {
	var site string
	if server.isInSingleSiteMode() {
		site = EMPTY_SITE
	} else {
		site = server.createSite(&Endpoint{Path: "/-fake-path-just-to-create-new-site"})
	}
	siteTest(site)
}
func (server *TestServer) isInSingleSiteMode() bool {
	return server.goSlowServer.isInSingleSiteMode()
}
func (server *TestServer) createSite(endpoint *Endpoint) string {
	if server.isInSingleSiteMode() {
		log.Fatalf("Can't create site: running in single site mode. Site endpoint: %v", endpoint)
	}
	resp := POST(server.getURL(), fmt.Sprintf("%s?output=short&method=%s", endpoint.Path, endpoint.Method),
		makeFullDomain("create"), endpoint.Response)
	domain := string(read(resp))
	return getSubdomain(domain)
}
func (server *TestServer) getURL() string {
	return server.runningServer.URL
}
func (server *TestServer) getAdminPathPrefix() string {
	return server.goSlowServer.config.adminPathPrefix
}
func (server *TestServer) createEndpoint(endpoint *Endpoint) *http.Response {
	site := "admin-" + endpoint.Site
	path := endpoint.Path
	if server.isInSingleSiteMode() {
		site = EMPTY_SITE
		path = join(server.getAdminPathPrefix(), endpoint.Path)
	}
	req := createPOST(server.getURL(), path, makeFullDomain(site),
		endpoint.Response)
	req.URL.RawQuery = getQueryString(endpoint)
	return do(req)
}
func TestChangeBuiltinSites(t *testing.T) {
	withNewMultiSiteServer(func(server *TestServer) {
		dontAllowToChangeSite(t, server, http.StatusForbidden, "0")
		dontAllowToChangeSite(t, server, http.StatusForbidden, "599")
		dontAllowToChangeSite(t, server, http.StatusForbidden, "create")
	})
}
func dontAllowToChangeSite(t *testing.T, server *TestServer, expectedStatusCode int, site string) {
	resp := server.createEndpoint(&Endpoint{Site: site, Method: "GET", Path: "/test", Response: []byte("hop")})
	shouldHaveStatusCode(t, expectedStatusCode, resp)
}
func TestChangeUnknownSites(t *testing.T) {
	withNewMultiSiteServer(func(server *TestServer) {
		dontAllowToChangeSite(t, server, http.StatusNotFound, "")
		dontAllowToChangeSite(t, server, http.StatusNotFound, "uknown-site")
		dontAllowToChangeSite(t, server, http.StatusNotFound, "admin-500")
		dontAllowToChangeSite(t, server, http.StatusNotFound, "admin-create")
	})
}
func TestDelaySites(t *testing.T) {
	withNewMultiSiteServer(func(server *TestServer) {
		shouldRespondInTimeInterval(t, 0, 0.1,  
			createGET(server.getURL(), "/", makeFullDomain("0")))
		shouldRespondInTimeInterval(t, 1, 1.1,  
			createGET(server.getURL(), "/", makeFullDomain("1")))
	})
}