diff --git a/authorize_test.go b/authorize_test.go index f0c7de758..0e7bade7f 100644 --- a/authorize_test.go +++ b/authorize_test.go @@ -17,7 +17,7 @@ import ( ) func TestMissingAuthorization(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) body := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaa") bodyrdr := bytes.NewReader(body) @@ -35,7 +35,7 @@ func TestMissingAuthorization(t *testing.T) { } func TestBogusAuthorization(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) body := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaa") bodyrdr := bytes.NewReader(body) @@ -54,7 +54,7 @@ func TestBogusAuthorization(t *testing.T) { } func TestBadPayload(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) body := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaa") bodyrdr := bytes.NewReader(body) @@ -78,7 +78,7 @@ func TestBadPayload(t *testing.T) { } func TestExpiredAuth(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) body := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaa") bodyrdr := bytes.NewReader(body) @@ -98,6 +98,8 @@ func TestExpiredAuth(t *testing.T) { } func TestDuplicateNonce(t *testing.T) { + ag, conf := newTestAutographer(t) + body := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaa") bodyrdr := bytes.NewReader(body) req, err := http.NewRequest("POST", "http://foo.bar/sign/data", bodyrdr) @@ -125,6 +127,8 @@ func TestDuplicateNonce(t *testing.T) { } func TestNonceFromLRU(t *testing.T) { + ag, conf := newTestAutographer(t) + req, err := http.NewRequest("POST", "http://foo.bar/sign/data", nil) if err != nil { t.Fatal(err) @@ -170,7 +174,7 @@ func TestNonceFromLRU(t *testing.T) { } func TestSignerNotFound(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) _, err := ag.authBackend.getSignerForUser(`unknown018qoegdxc`, `unkown093ytid`) if err == nil { @@ -179,7 +183,7 @@ func TestSignerNotFound(t *testing.T) { } func TestDefaultSignerNotFound(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) _, err := ag.authBackend.getSignerForUser(`unknown018qoegdxc`, ``) if err == nil { @@ -188,7 +192,7 @@ func TestDefaultSignerNotFound(t *testing.T) { } func TestAutographerAddAuthorizationsFails(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) testcases := []struct { name string @@ -213,11 +217,11 @@ func TestAutographerAddAuthorizationsFails(t *testing.T) { name: "authorization without a signer ID fails", auths: []authorization{ { - ID: "alice", + ID: "bernie", Signers: []string{}, }, }, - errStr: `auth id "alice" must have at least one signer configured`, + errStr: `auth id "bernie" must have at least one signer configured`, }, { name: "invalid empty string auth ID fails", @@ -274,9 +278,7 @@ func TestAutographerAddAuthorizationsFails(t *testing.T) { for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { - tmpag := newAutographer(1) - tmpag.addSigners(conf.Signers) - err := tmpag.addAuthorizations(testcase.auths) + err := ag.addAuthorizations(testcase.auths) if err == nil { t.Fatalf("%s: addAuthorizations did not fail as expected", testcase.name) } @@ -290,16 +292,14 @@ func TestAutographerAddAuthorizationsFails(t *testing.T) { // set an authorization with a ts validity of 2 seconds, then sleep 5 seconds // to trigger the hawk skew error func TestHawkTimestampSkewFail(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) var err error - tmpag := newAutographer(1) - tmpag.hawkMaxTimestampSkew, err = time.ParseDuration("2s") + ag.hawkMaxTimestampSkew, err = time.ParseDuration("2s") if err != nil { t.Fatal(err) } - tmpag.addSigners(conf.Signers) - tmpag.addAuthorizations([]authorization{ + ag.addAuthorizations([]authorization{ { ID: "alice", Key: "1862300e9bd18eafab2eb8d6", @@ -316,7 +316,7 @@ func TestHawkTimestampSkewFail(t *testing.T) { authheader := getAuthHeader(req, "alice", "1862300e9bd18eafab2eb8d6", sha256.New, id(), "application/json", body) req.Header.Set("Authorization", authheader) time.Sleep(5 * time.Second) - _, _, err = tmpag.authorizeHeader(req) + _, _, err = ag.authorizeHeader(req) if err.Error() != hawk.ErrTimestampSkew.Error() { t.Errorf("expected auth to fail with skewed timestamp but got error: %v", err) } diff --git a/handlers_racing_test.go b/handlers_racing_test.go index 0dc8845b2..da833d181 100644 --- a/handlers_racing_test.go +++ b/handlers_racing_test.go @@ -25,6 +25,7 @@ import ( func TestSignaturePass(t *testing.T) { t.Parallel() + ag, conf := newTestAutographer(t) var TESTCASES = []struct { endpoint string diff --git a/handlers_test.go b/handlers_test.go index 8887dab0b..b3ec64199 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -60,7 +60,7 @@ type HandlerTestCase struct { expectedBody string } -func (testcase *HandlerTestCase) NewRequest(t *testing.T) *http.Request { +func (testcase *HandlerTestCase) NewRequest(ag *autographer, t *testing.T) *http.Request { // test request setup var ( req *http.Request @@ -115,9 +115,9 @@ func (testcase *HandlerTestCase) ValidateResponse(t *testing.T, w *httptest.Resp } } -func (testcase *HandlerTestCase) Run(t *testing.T, handler func(http.ResponseWriter, *http.Request)) { +func (testcase *HandlerTestCase) Run(ag *autographer, t *testing.T, handler func(http.ResponseWriter, *http.Request)) { // test request setup - var req = testcase.NewRequest(t) + var req = testcase.NewRequest(ag, t) // run the request w := httptest.NewRecorder() @@ -128,7 +128,7 @@ func (testcase *HandlerTestCase) Run(t *testing.T, handler func(http.ResponseWri } func TestBadRequest(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) var TESTCASES = []struct { endpoint string @@ -204,7 +204,6 @@ func TestBadRequest(t *testing.T) { testcase := testcase t.Run(fmt.Sprintf("returns 400 for invalid %s %s %s", testcase.method, testcase.endpoint, testcase.body), func(t *testing.T) { - t.Parallel() body := strings.NewReader(testcase.body) req, err := http.NewRequest(testcase.method, "http://foo.bar"+testcase.endpoint, body) @@ -235,7 +234,7 @@ func TestBadRequest(t *testing.T) { } func TestRequestTooLarge(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) blob := strings.Repeat("foobar", 200) body := strings.NewReader(blob) @@ -264,7 +263,7 @@ func TestRequestTooLarge(t *testing.T) { } func TestBadContentType(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) blob := "foofoofoofoofoofoofoofoofoofoofoofoofoofoo" body := strings.NewReader(blob) @@ -293,7 +292,7 @@ func TestBadContentType(t *testing.T) { } func TestAuthFail(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) var TESTCASES = []struct { user string @@ -333,8 +332,6 @@ func TestAuthFail(t *testing.T) { } func TestLBHeartbeat(t *testing.T) { - t.Parallel() - var TESTCASES = []struct { expect int method string @@ -358,7 +355,7 @@ func TestLBHeartbeat(t *testing.T) { } } -func checkHeartbeatReturnsExpectedStatusAndBody(t *testing.T, name, method string, expectedStatusCode int, expectedBody []byte) { +func checkHeartbeatReturnsExpectedStatusAndBody(ag *autographer, t *testing.T, name, method string, expectedStatusCode int, expectedBody []byte) { req, err := http.NewRequest(method, "http://foo.bar/__heartbeat__", nil) if err != nil { t.Fatal(err) @@ -375,7 +372,8 @@ func checkHeartbeatReturnsExpectedStatusAndBody(t *testing.T, name, method strin } func TestHeartbeat(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) + ag.heartbeatConf = &heartbeatConfig{} var TESTCASES = []struct { name string @@ -389,11 +387,12 @@ func TestHeartbeat(t *testing.T) { {"returns 405 for HEAD", `HEAD`, http.StatusMethodNotAllowed, "HEAD method not allowed; endpoint accepts GET only\r\nrequest-id: -\n"}, } for _, testcase := range TESTCASES { - checkHeartbeatReturnsExpectedStatusAndBody(t, testcase.name, testcase.method, testcase.expectedHTTPStatus, []byte((testcase.expectedBody))) + checkHeartbeatReturnsExpectedStatusAndBody(ag, t, testcase.name, testcase.method, testcase.expectedHTTPStatus, []byte((testcase.expectedBody))) } } func TestHeartbeatChecksHSMStatusFails(t *testing.T) { + ag, _ := newTestAutographer(t) // NB: do not run in parallel with TestHeartbeat* ag.heartbeatConf = &heartbeatConfig{ HSMCheckTimeout: time.Second, @@ -402,21 +401,19 @@ func TestHeartbeatChecksHSMStatusFails(t *testing.T) { expectedStatus := http.StatusInternalServerError expectedBody := []byte("{\"hsmAccessible\":false}") - checkHeartbeatReturnsExpectedStatusAndBody(t, "returns 500 for GET with HSM inaccessible", `GET`, expectedStatus, expectedBody) - - ag.heartbeatConf = nil + checkHeartbeatReturnsExpectedStatusAndBody(ag, t, "returns 500 for GET with HSM inaccessible", `GET`, expectedStatus, expectedBody) } func TestHeartbeatChecksHSMStatusFailsWhenNotConfigured(t *testing.T) { + ag, _ := newTestAutographer(t) // NB: do not run in parallel with TestHeartbeat* - ag.heartbeatConf = nil - expectedStatus := http.StatusInternalServerError expectedBody := []byte("Missing heartbeat config\r\nrequest-id: -\n") - checkHeartbeatReturnsExpectedStatusAndBody(t, "returns 500 for GET without heartbeat config HSM", `GET`, expectedStatus, expectedBody) + checkHeartbeatReturnsExpectedStatusAndBody(ag, t, "returns 500 for GET without heartbeat config HSM", `GET`, expectedStatus, expectedBody) } func TestHeartbeatChecksDBStatusOKAndTimesout(t *testing.T) { + ag, _ := newTestAutographer(t) // NB: do not run in parallel with TestHeartbeat* or DB tests host := database.GetTestDBHost() db, err := database.Connect(database.Config{ @@ -436,14 +433,14 @@ func TestHeartbeatChecksDBStatusOKAndTimesout(t *testing.T) { // check OK run locally requires running DB container expectedStatus := http.StatusOK expectedBody := []byte("{\"dbAccessible\":true}") - checkHeartbeatReturnsExpectedStatusAndBody(t, "returns 200 for GET with DB accessible", `GET`, expectedStatus, expectedBody) + checkHeartbeatReturnsExpectedStatusAndBody(ag, t, "returns 200 for GET with DB accessible", `GET`, expectedStatus, expectedBody) // drop timeout ag.heartbeatConf.DBCheckTimeout = 1 * time.Nanosecond // check DB request times out expectedStatus = http.StatusOK expectedBody = []byte("{\"dbAccessible\":false}") - checkHeartbeatReturnsExpectedStatusAndBody(t, "returns 200 for GET with DB time out", `GET`, expectedStatus, expectedBody) + checkHeartbeatReturnsExpectedStatusAndBody(ag, t, "returns 200 for GET with DB time out", `GET`, expectedStatus, expectedBody) // restore longer timeout and close the DB connection ag.heartbeatConf.DBCheckTimeout = 1 * time.Second @@ -451,14 +448,10 @@ func TestHeartbeatChecksDBStatusOKAndTimesout(t *testing.T) { // check DB request still fails expectedStatus = http.StatusOK expectedBody = []byte("{\"dbAccessible\":false}") - checkHeartbeatReturnsExpectedStatusAndBody(t, "returns 200 for GET with DB inaccessible", `GET`, expectedStatus, expectedBody) - - ag.db = nil + checkHeartbeatReturnsExpectedStatusAndBody(ag, t, "returns 200 for GET with DB inaccessible", `GET`, expectedStatus, expectedBody) } func TestVersion(t *testing.T) { - t.Parallel() - var TESTCASES = []struct { expect int method string @@ -487,7 +480,7 @@ func TestVersion(t *testing.T) { // * `appkey1` and `appkey2` for `alice` // * `appkey2` only for `bob` func TestSignerAuthorized(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) var TESTCASES = []struct { userid string @@ -577,7 +570,7 @@ func TestSignerAuthorized(t *testing.T) { // verify that user `bob` is not allowed to sign with `appkey1` func TestSignerUnauthorized(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) var TESTCASES = []formats.SignatureRequest{ // request signature that need to prepend the content-signature:\x00 header @@ -616,7 +609,7 @@ func TestSignerUnauthorized(t *testing.T) { } func TestContentType(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) var TESTCASES = []formats.SignatureRequest{ formats.SignatureRequest{ @@ -650,6 +643,7 @@ func TestContentType(t *testing.T) { } func TestDebug(t *testing.T) { + ag, _ := newTestAutographer(t) ag.enableDebug() if !ag.debug { t.Fatalf("expected debug mode to be enabled, but is disabled") @@ -661,7 +655,7 @@ func TestDebug(t *testing.T) { } func TestHandleGetAuthKeyIDs(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) const autographDevAliceKeyIDsJSON = "[\"apk_cert_with_ecdsa_sha256\",\"apk_cert_with_ecdsa_sha256_v3\",\"appkey1\",\"appkey2\",\"dummyrsa\",\"dummyrsapss\",\"extensions-ecdsa\",\"extensions-ecdsa-expired-chain\",\"legacy_apk_with_rsa\",\"normandy\",\"pgpsubkey\",\"pgpsubkey-debsign\",\"randompgp\",\"randompgp-debsign\",\"remote-settings\",\"testapp-android\",\"testapp-android-legacy\",\"testapp-android-v3\",\"testauthenticode\",\"testmar\",\"testmarecdsa\",\"webextensions-rsa\",\"webextensions-rsa-with-recommendation\"]" @@ -790,7 +784,7 @@ func TestHandleGetAuthKeyIDs(t *testing.T) { }, } for _, testcase := range testcases { - testcase.Run(t, ag.handleGetAuthKeyIDs) + testcase.Run(ag, t, ag.handleGetAuthKeyIDs) } } diff --git a/main_test.go b/main_test.go index 75d5d5a40..50acb1bcd 100644 --- a/main_test.go +++ b/main_test.go @@ -12,22 +12,19 @@ import ( "testing" "time" + "github.com/mozilla-services/autograph/database" log "github.com/sirupsen/logrus" ) -var ( - ag *autographer - mo *monitor - conf configuration -) +func newTestAutographer(t *testing.T) (*autographer, configuration) { + var conf configuration -func TestMain(m *testing.M) { // load the signers err := conf.loadFromFile("autograph.yaml") if err != nil { log.Fatal(err) } - ag = newAutographer(1) + ag := newAutographer(1) err = ag.addSigners(conf.Signers) if err != nil { log.Fatal(err) @@ -52,26 +49,26 @@ func TestMain(m *testing.M) { } else { ag.hawkMaxTimestampSkew = time.Minute } - // ok this is lame but the contentsignaturepki signer will upload a file dated - // at the given second so we don't want anything else to run at the same second - // otherwise that file may get rewritten. Easiest way to solve it? Sleep. - time.Sleep(time.Second) - - // Initialize a monitor. - mo = newMonitor(ag, conf.MonitorInterval) - - // run the tests and exit - r := m.Run() - // Shutdown the monitor - close(ag.exit) + t.Cleanup(func() { + host := database.GetTestDBHost() + db, err := database.Connect(database.Config{ + Name: "autograph", + User: "myautographdbuser", + Password: "myautographdbpassword", + Host: host + ":5432", + MonitorPollInterval: 10 * time.Second, + }) + if err == nil { + db.Exec("truncate table endentities;") + } + close(ag.exit) + }) - os.Exit(r) + return ag, conf } func TestConfigLoad(t *testing.T) { - t.Parallel() - testcases := []struct { name string pass bool @@ -221,8 +218,6 @@ authorizations: } func TestDuplicateSigners(t *testing.T) { - t.Parallel() - var conf configuration // write conf file to /tmp and read it back fd, err := os.CreateTemp("", "autographtestconf") @@ -276,8 +271,6 @@ signers: } func TestDuplicateAuthorization(t *testing.T) { - t.Parallel() - var conf configuration // write conf file to /tmp and read it back fd, err := os.CreateTemp("", "autographtestconf") @@ -346,8 +339,6 @@ authorizations: } func TestUnknownSignerInAuthorization(t *testing.T) { - t.Parallel() - var conf configuration // write conf file to /tmp and read it back fd, err := os.CreateTemp("", "autographtestconf") @@ -413,23 +404,20 @@ authorizations: // An authorization without at least one signer configured must fail func TestAuthWithoutSigner(t *testing.T) { - t.Parallel() + ag, _ := newTestAutographer(t) + var authorizations = []authorization{ authorization{ ID: "alice", }, } - tmpag := newAutographer(1) - tmpag.addSigners(conf.Signers) - err := tmpag.addAuthorizations(authorizations) + err := ag.addAuthorizations(authorizations) if err == nil { t.Fatalf("should have failed with must have one signer but succeeded") } } func TestConfigLoadFileNotExist(t *testing.T) { - t.Parallel() - var conf configuration err := conf.loadFromFile("/tmp/a/b/c/d/e/f/e/d/c/b/a/oned97fy2qoelfahd018oehfa9we8ohf219") if err == nil { @@ -438,8 +426,6 @@ func TestConfigLoadFileNotExist(t *testing.T) { } func TestDefaultPort(t *testing.T) { - t.Parallel() - expected := "0.0.0.0:8000" _, listen, _ := parseArgsAndLoadConfig([]string{}) if listen != expected { @@ -448,8 +434,6 @@ func TestDefaultPort(t *testing.T) { } func TestPortOverride(t *testing.T) { - t.Parallel() - expected := "0.0.0.0:8080" _, listen, _ := parseArgsAndLoadConfig([]string{"-p", "8080"}) if listen != expected { diff --git a/monitor_handler_racing_test.go b/monitor_handler_racing_test.go index d11b2b09e..7a5dc8d59 100644 --- a/monitor_handler_racing_test.go +++ b/monitor_handler_racing_test.go @@ -31,7 +31,7 @@ import ( const autographDevRootHash = `5E:36:F2:14:DE:82:3F:8B:29:96:89:23:5F:03:41:AC:AF:A0:75:AF:82:CB:4C:D4:30:7C:3D:B3:43:39:2A:FE` -func getLocalX5U(x5u string) (body []byte, err error) { +func getLocalX5U(ag *autographer, x5u string, t *testing.T) (body []byte, err error) { parsed, err := url.Parse(x5u) if err != nil { return nil, err @@ -69,7 +69,8 @@ func getLocalX5U(x5u string) (body []byte, err error) { } func TestMonitorPass(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) + mo := newMonitor(ag, conf.MonitorInterval) var empty []byte req, err := http.NewRequest("GET", "http://foo.bar/__monitor__", bytes.NewReader(empty)) @@ -104,7 +105,7 @@ func TestMonitorPass(t *testing.T) { t.Fatalf("verification of monitoring response failed: %v", err) } case contentsignaturepki.Type: - body, err := getLocalX5U(response.X5U) + body, err := getLocalX5U(ag, response.X5U, t) if err != nil { t.Fatal(err) } @@ -158,7 +159,8 @@ func TestMonitorPass(t *testing.T) { } func TestMonitorHasSignerParameters(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) + mo := newMonitor(ag, conf.MonitorInterval) var empty []byte req, err := http.NewRequest("GET", "http://foo.bar/__monitor__", bytes.NewReader(empty)) diff --git a/monitor_handler_test.go b/monitor_handler_test.go index 258d8cdef..8279be90e 100644 --- a/monitor_handler_test.go +++ b/monitor_handler_test.go @@ -9,8 +9,6 @@ import ( ) func TestMonitorNoConfig(t *testing.T) { - t.Parallel() - tmpag := newAutographer(1) var nomonitor configuration tmpag.addMonitoring(nomonitor.Monitoring) @@ -21,8 +19,6 @@ func TestMonitorNoConfig(t *testing.T) { } func TestMonitorAddDuplicate(t *testing.T) { - t.Parallel() - tmpag := newAutographer(1) var monitorconf configuration monitorconf.Monitoring.Key = "xxxxxxx" @@ -40,7 +36,8 @@ func TestMonitorAddDuplicate(t *testing.T) { } func TestMonitorBadRequest(t *testing.T) { - t.Parallel() + ag, conf := newTestAutographer(t) + mo := newMonitor(ag, conf.MonitorInterval) var TESTCASES = []struct { user string