From 0cc992b4e3ed26c0f9f8dab94024985c87853a64 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Tue, 24 May 2022 15:12:17 -0500 Subject: [PATCH] gpg: refactor tests for macos compatibility Refactor lib/crypto/gpg tests to facilitate unit test runs on macos. Macos creates temporary directories with names too long to call gpg-agent (108 characters). Additionally, too many concurrent test calls created IPC errors to gpg-agent. To get around this, tests were given shorter names and refactored into subtests to create fewer concurrent tests Tested on Linux and MacOS. Signed-off-by: Tim Culverhouse Acked-by: Robin Jarry --- lib/crypto/gpg/gpg_test.go | 22 ++-- lib/crypto/gpg/reader_test.go | 211 ++++++++++++++-------------------- lib/crypto/gpg/writer_test.go | 111 +++++++++--------- 3 files changed, 157 insertions(+), 187 deletions(-) diff --git a/lib/crypto/gpg/gpg_test.go b/lib/crypto/gpg/gpg_test.go index d833830..e34cc2b 100644 --- a/lib/crypto/gpg/gpg_test.go +++ b/lib/crypto/gpg/gpg_test.go @@ -31,41 +31,41 @@ func toCRLF(s string) string { return strings.ReplaceAll(s, "\n", "\r\n") } -func deepEqual(t *testing.T, r *models.MessageDetails, expect *models.MessageDetails) { +func deepEqual(t *testing.T, name string, r *models.MessageDetails, expect *models.MessageDetails) { var resBuf bytes.Buffer if _, err := io.Copy(&resBuf, r.Body); err != nil { - t.Fatalf("io.Copy() = %v", err) + t.Fatalf("%s: io.Copy() = %v", name, err) } var expBuf bytes.Buffer if _, err := io.Copy(&expBuf, expect.Body); err != nil { - t.Fatalf("io.Copy() = %v", err) + t.Fatalf("%s: io.Copy() = %v", name, err) } if resBuf.String() != expBuf.String() { - t.Errorf("MessagesDetails.Body = \n%v\n but want \n%v", resBuf.String(), expBuf.String()) + t.Errorf("%s: MessagesDetails.Body = \n%v\n but want \n%v", name, resBuf.String(), expBuf.String()) } if r.IsEncrypted != expect.IsEncrypted { - t.Errorf("IsEncrypted = \n%v\n but want \n%v", r.IsEncrypted, expect.IsEncrypted) + t.Errorf("%s: IsEncrypted = \n%v\n but want \n%v", name, r.IsEncrypted, expect.IsEncrypted) } if r.IsSigned != expect.IsSigned { - t.Errorf("IsSigned = \n%v\n but want \n%v", r.IsSigned, expect.IsSigned) + t.Errorf("%s: IsSigned = \n%v\n but want \n%v", name, r.IsSigned, expect.IsSigned) } if r.SignedBy != expect.SignedBy { - t.Errorf("SignedBy = \n%v\n but want \n%v", r.SignedBy, expect.SignedBy) + t.Errorf("%s: SignedBy = \n%v\n but want \n%v", name, r.SignedBy, expect.SignedBy) } if r.SignedByKeyId != expect.SignedByKeyId { - t.Errorf("SignedByKeyId = \n%v\n but want \n%v", r.SignedByKeyId, expect.SignedByKeyId) + t.Errorf("%s: SignedByKeyId = \n%v\n but want \n%v", name, r.SignedByKeyId, expect.SignedByKeyId) } if r.SignatureError != expect.SignatureError { - t.Errorf("SignatureError = \n%v\n but want \n%v", r.SignatureError, expect.SignatureError) + t.Errorf("%s: SignatureError = \n%v\n but want \n%v", name, r.SignatureError, expect.SignatureError) } if r.DecryptedWith != expect.DecryptedWith { - t.Errorf("DecryptedWith = \n%v\n but want \n%v", r.DecryptedWith, expect.DecryptedWith) + t.Errorf("%s: DecryptedWith = \n%v\n but want \n%v", name, r.DecryptedWith, expect.DecryptedWith) } if r.DecryptedWithKeyId != expect.DecryptedWithKeyId { - t.Errorf("DecryptedWithKeyId = \n%v\n but want \n%v", r.DecryptedWithKeyId, expect.DecryptedWithKeyId) + t.Errorf("%s: DecryptedWithKeyId = \n%v\n but want \n%v", name, r.DecryptedWithKeyId, expect.DecryptedWithKeyId) } } diff --git a/lib/crypto/gpg/reader_test.go b/lib/crypto/gpg/reader_test.go index 06cf7a3..957a727 100644 --- a/lib/crypto/gpg/reader_test.go +++ b/lib/crypto/gpg/reader_test.go @@ -1,8 +1,6 @@ package gpg import ( - "bytes" - "io" "strings" "testing" @@ -20,135 +18,100 @@ func importPublicKey() { gpgbin.Import(r) } -func TestReader_encryptedSignedPGPMIME(t *testing.T) { - initGPGtest(t) - - var expect = models.MessageDetails{ - IsEncrypted: true, - IsSigned: true, - SignedBy: "John Doe (This is a test key) ", - SignedByKeyId: 3490876580878068068, - SignatureError: "", - DecryptedWith: "John Doe (This is a test key) ", - DecryptedWithKeyId: 3490876580878068068, - Body: strings.NewReader(testEncryptedBody), - Micalg: "pgp-sha512", - } - - importSecretKey() - sr := strings.NewReader(testPGPMIMEEncryptedSigned) - r, err := Read(sr) - if err != nil { - t.Fatalf("pgpmail.Read() = %v", err) - } - - deepEqual(t, r.MessageDetails, &expect) +type readerTestCase struct { + name string + want models.MessageDetails + input string } -func TestReader_signedPGPMIME(t *testing.T) { +func TestReader(t *testing.T) { initGPGtest(t) - - var expect = models.MessageDetails{ - IsEncrypted: false, - IsSigned: true, - SignedBy: "John Doe (This is a test key) ", - SignedByKeyId: 3490876580878068068, - SignatureError: "", - DecryptedWith: "", - DecryptedWithKeyId: 0, - Body: strings.NewReader(testSignedBody), - Micalg: "pgp-sha256", - } - - importSecretKey() importPublicKey() - sr := strings.NewReader(testPGPMIMESigned) - r, err := Read(sr) - if err != nil { - t.Fatalf("pgpmail.Read() = %v", err) - } - - deepEqual(t, r.MessageDetails, &expect) -} - -func TestReader_encryptedSignedEncapsulatedPGPMIME(t *testing.T) { - initGPGtest(t) - - var expect = models.MessageDetails{ - IsEncrypted: true, - IsSigned: true, - SignedBy: "John Doe (This is a test key) ", - SignedByKeyId: 3490876580878068068, - SignatureError: "", - DecryptedWith: "John Doe (This is a test key) ", - DecryptedWithKeyId: 3490876580878068068, - Body: strings.NewReader(testSignedBody), - Micalg: "pgp-sha256", - } - importSecretKey() - importPublicKey() - sr := strings.NewReader(testPGPMIMEEncryptedSignedEncapsulated) - r, err := Read(sr) - if err != nil { - t.Fatalf("pgpmail.Read() = %v", err) + + testCases := []readerTestCase{ + { + name: "Encrypted and Signed", + input: testPGPMIMEEncryptedSigned, + want: models.MessageDetails{ + IsEncrypted: true, + IsSigned: true, + SignedBy: "John Doe (This is a test key) ", + SignedByKeyId: 3490876580878068068, + SignatureValidity: 0, + SignatureError: "", + DecryptedWith: "John Doe (This is a test key) ", + DecryptedWithKeyId: 3490876580878068068, + Body: strings.NewReader(testEncryptedBody), + Micalg: "pgp-sha512", + }, + }, + { + name: "Signed", + input: testPGPMIMESigned, + want: models.MessageDetails{ + IsEncrypted: false, + IsSigned: true, + SignedBy: "John Doe (This is a test key) ", + SignedByKeyId: 3490876580878068068, + SignatureValidity: 0, + SignatureError: "", + DecryptedWith: "", + DecryptedWithKeyId: 0, + Body: strings.NewReader(testSignedBody), + Micalg: "pgp-sha256", + }, + }, + { + name: "Encapsulated Signature", + input: testPGPMIMEEncryptedSignedEncapsulated, + want: models.MessageDetails{ + IsEncrypted: true, + IsSigned: true, + SignedBy: "John Doe (This is a test key) ", + SignedByKeyId: 3490876580878068068, + SignatureValidity: 0, + SignatureError: "", + DecryptedWith: "John Doe (This is a test key) ", + DecryptedWithKeyId: 3490876580878068068, + Body: strings.NewReader(testSignedBody), + }, + }, + { + name: "Invalid Signature", + input: testPGPMIMESignedInvalid, + want: models.MessageDetails{ + IsEncrypted: false, + IsSigned: true, + SignedBy: "John Doe (This is a test key) ", + SignedByKeyId: 3490876580878068068, + SignatureValidity: 0, + SignatureError: "gpg: invalid signature", + DecryptedWith: "", + DecryptedWithKeyId: 0, + Body: strings.NewReader(testSignedInvalidBody), + Micalg: "", + }, + }, + { + name: "Plain text", + input: testPlaintext, + want: models.MessageDetails{ + IsEncrypted: false, + IsSigned: false, + Body: strings.NewReader(testPlaintext), + }, + }, } - deepEqual(t, r.MessageDetails, &expect) - - var buf bytes.Buffer - if _, err := io.Copy(&buf, r.MessageDetails.Body); err != nil { - t.Fatalf("io.Copy() = %v", err) - } -} -func TestReader_signedPGPMIMEInvalid(t *testing.T) { - initGPGtest(t) - - var expect = models.MessageDetails{ - IsEncrypted: false, - IsSigned: true, - SignedBy: "John Doe (This is a test key) ", - SignedByKeyId: 3490876580878068068, - SignatureError: "gpg: invalid signature", - DecryptedWith: "", - DecryptedWithKeyId: 0, - Body: strings.NewReader(testSignedInvalidBody), - Micalg: "", - } - - importSecretKey() - importPublicKey() - sr := strings.NewReader(testPGPMIMESignedInvalid) - r, err := Read(sr) - if err != nil { - t.Fatalf("pgpmail.Read() = %v", err) - } - deepEqual(t, r.MessageDetails, &expect) -} - -func TestReader_plaintext(t *testing.T) { - initGPGtest(t) - - sr := strings.NewReader(testPlaintext) - r, err := Read(sr) - if err != nil { - t.Fatalf("pgpmail.Read() = %v", err) - } - - var buf bytes.Buffer - if _, err := io.Copy(&buf, r.MessageDetails.Body); err != nil { - t.Fatalf("io.Copy() = %v", err) - } - - if r.MessageDetails.IsEncrypted { - t.Errorf("MessageDetails.IsEncrypted != false") - } - if r.MessageDetails.IsSigned { - t.Errorf("MessageDetails.IsSigned != false") - } - - if s := buf.String(); s != testPlaintext { - t.Errorf("MessagesDetails.UnverifiedBody = \n%v\n but want \n%v", s, testPlaintext) + for _, tc := range testCases { + t.Logf("Test case: %s", tc.name) + sr := strings.NewReader(tc.input) + r, err := Read(sr) + if err != nil { + t.Fatalf("gpg.Read() = %v", err) + } + deepEqual(t, tc.name, r.MessageDetails, &tc.want) } } diff --git a/lib/crypto/gpg/writer_test.go b/lib/crypto/gpg/writer_test.go index e8defc1..0355db5 100644 --- a/lib/crypto/gpg/writer_test.go +++ b/lib/crypto/gpg/writer_test.go @@ -15,39 +15,76 @@ func init() { forceBoundary = "foo" } -func TestEncrypt(t *testing.T) { - initGPGtest(t) +type writerTestCase struct { + name string + method string + body string +} +func TestWriter(t *testing.T) { + initGPGtest(t) importPublicKey() importSecretKey() + + testCases := []writerTestCase{ + { + name: "Encrypt", + method: "encrypt", + body: "This is an encrypted message!\r\n", + }, + { + name: "Sign", + method: "sign", + body: "This is a signed message!\r\n", + }, + } var h textproto.Header h.Set("From", "John Doe ") h.Set("To", "John Doe ") - var encryptedHeader textproto.Header - encryptedHeader.Set("Content-Type", "text/plain") - - var encryptedBody = "This is an encrypted message!\r\n" + var header textproto.Header + header.Set("Content-Type", "text/plain") to := []string{"john.doe@example.org"} from := "john.doe@example.org" - var buf bytes.Buffer - cleartext, err := Encrypt(&buf, h, to, from) - if err != nil { - t.Fatalf("Encrypt() = %v", err) - } - - if err = textproto.WriteHeader(cleartext, encryptedHeader); err != nil { - t.Fatalf("textproto.WriteHeader() = %v", err) - } - if _, err = io.WriteString(cleartext, encryptedBody); err != nil { - t.Fatalf("io.WriteString() = %v", err) - } - if err = cleartext.Close(); err != nil { - t.Fatalf("ciphertext.Close() = %v", err) + var err error + for _, tc := range testCases { + var ( + buf bytes.Buffer + cleartext io.WriteCloser + ) + switch tc.method { + case "encrypt": + cleartext, err = Encrypt(&buf, h, to, from) + if err != nil { + t.Fatalf("Encrypt() = %v", err) + } + case "sign": + cleartext, err = Sign(&buf, h, from) + if err != nil { + t.Fatalf("Encrypt() = %v", err) + } + } + if err = textproto.WriteHeader(cleartext, header); err != nil { + t.Fatalf("textproto.WriteHeader() = %v", err) + } + if _, err = io.WriteString(cleartext, tc.body); err != nil { + t.Fatalf("io.WriteString() = %v", err) + } + if err = cleartext.Close(); err != nil { + t.Fatalf("ciphertext.Close() = %v", err) + } + switch tc.method { + case "encrypt": + validateEncrypt(t, buf) + case "sign": + validateSign(t, buf) + } } +} +func validateEncrypt(t *testing.T, buf bytes.Buffer) { md, err := gpgbin.Decrypt(&buf) if err != nil { t.Errorf("Encrypt error: could not decrypt test encryption") @@ -59,37 +96,7 @@ func TestEncrypt(t *testing.T) { } } -func TestSign(t *testing.T) { - initGPGtest(t) - - importPublicKey() - importSecretKey() - var h textproto.Header - h.Set("From", "John Doe ") - h.Set("To", "John Doe ") - - var signedHeader textproto.Header - signedHeader.Set("Content-Type", "text/plain") - - var signedBody = "This is a signed message!\r\n" - - var buf bytes.Buffer - cleartext, err := Sign(&buf, h, "john.doe@example.org") - if err != nil { - t.Fatalf("Encrypt() = %v", err) - } - - if err = textproto.WriteHeader(cleartext, signedHeader); err != nil { - t.Fatalf("textproto.WriteHeader() = %v", err) - } - if _, err = io.WriteString(cleartext, signedBody); err != nil { - t.Fatalf("io.WriteString() = %v", err) - } - - if err = cleartext.Close(); err != nil { - t.Fatalf("ciphertext.Close() = %v", err) - } - +func validateSign(t *testing.T, buf bytes.Buffer) { parts := strings.Split(buf.String(), "\r\n--foo\r\n") msg := strings.NewReader(parts[1]) sig := strings.NewReader(parts[2]) @@ -98,7 +105,7 @@ func TestSign(t *testing.T) { t.Fatalf("gpg.Verify() = %v", err) } - deepEqual(t, md, &wantSigned) + deepEqual(t, "Sign", md, &wantSigned) } var wantEncrypted = toCRLF(`Content-Type: text/plain