cri-o/vendor/github.com/mtrmac/gpgme/gpgme_test.go
Mrunal Patel 8e5b17cf13 Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
2017-01-31 16:45:59 -08:00

406 lines
11 KiB
Go

package gpgme
import (
"bytes"
"flag"
"io"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
"testing"
)
const (
testGPGHome = "./testdata/gpghome"
testData = "data\n"
testCipherText = `-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
hQEMAw4698hF4WUhAQf/SdkbF/zUE6YjBxscDurrUZunSnt87kipLXypSxTDIdgj
O9huAaQwBz4uAJf2DuEN/7iAFGhi/v45NTujrG+7ocfjM3m/A2T80g4RVF5kKXBr
pFFgH7bMRY6VdZt1GKI9izSO/uFkoKXG8M31tCX3hWntQUJ9p+n1avGpu3wo4Ru3
CJhpL+ChDzXuZv4IK81ahrixEz4fJH0vd0TbsHpTXx4WPkTGXelM0R9PwiY7TovZ
onGZUIplrfA1HUUbQfzExyFw3oAo1/almzD5CBIfq5EnU8Siy5BNulDXm0/44h8A
lOUy6xqx7ITnWMYYf4a1cFoW80Yk+x6SYQqbcqHFQdJIAVr00V4pPV4ppFcXgdw/
BxKERzDupyqS0tcfVFCYLRmvtQp7ceOS6jRW3geXPPIz1U/VYBvKlvFu4XTMCS6z
4qY4SzZlFEsU
=IQOA
-----END PGP MESSAGE-----`
textSignedCipherText = `-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
hQEMAw4698hF4WUhAQf9FaI8zSltIMcDxqGtpcTfcBtC30rcKqE/oa1bacxuZQKW
uT671N7J2TjU8tLIsAO9lDSRHCsf6DbB+O6qOJsu6eJownyMUEmJ2oBON9Z2x+Ci
aS0KeRqcRxNJYbIth9/ffa2I4sSBA0GS93yCfGKHNL4JvNo/dgVjJwOPWZ5TKu49
n9h81LMwTQ8qpLGPeo7nsgBtSKNTi5s7pC0bd9HTii7gQcLUEeeqk5U7oG5CRN48
zKPrVud8pIDvSoYuymZmjWI1MmF4xQ+6IHK7hWKMyA2RkS4CpyBPERMifc+y+K2+
LnKLt2ul9jxgqv3fd/dU7UhyqdvJdj83tUvhN4Iru9LAuQHfVsP23keH8CHpUzCj
PkuUYvpgmRdMSC+l3yBCqnaaAI51rRdyJ+HX4DrrinOFst2JfXEICiQAg5UkO4i/
YYHsfD3xfk7MKMOY/DfV25OyAU6Yeq/5SMisONhtlzcosVU7HULudbIKSG6q/tCx
jRGu+oMIBdiQ+eipnaLVetyGxSEDzxHH367NbxC9ffxK7I+Srmwh+oS/yMNuZA8r
bUp6NbykK8Si7VNgVG1+yOIULLuR0VBO5+e2PKQU8FP0wABTn7h3zE8z4rCrcaZl
43bc/TBUyTdWY79e2P1otaCbhQGAjfF8ClPbAdsFppykf5I2ZDDf8c67d0Nqui74
Yry4/fF/2sAzyoyzdP6ktBw6pCA1MbwDqTGg7aEI8Es3X+jfh3qIaLnGmZ7jIyUl
D4jgGAEpFU+mpPH8eukKuT+OJ3P6gdmSiAJH7+C96tlcEg9BNxjYNkCTil/3yygQ
EV/5zFTEpzm4CtYHHdmY5uCaEJq/4hhE8BY8
=8mxI
-----END PGP MESSAGE-----`
testSignedText = `-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
owEBQwG8/pANAwACAQMn/7Ain2E2AcsTYgBW47+PVGVzdCBtZXNzYWdlCokBHAQA
AQIABgUCVuO/jwAKCRADJ/+wIp9hNh9lCACPiDkY0CqI9ss4EBcpToqnF/8NmV99
2wi6FmbQnUmY98OMM2VJXrX6PvfD/X+FsiLog0CZU4heMEAI3Dd3qELgTfaTFqNc
bbDkenzA0kO734WLsEU/z1F9iWAcfeF3crKqd3fBw5kZ1PkhuJFdcqQEOUQALvXY
8VAtQmQWzf3sn2KIQ7R1wyAJVoUZaN5Xwc9Y0F1l4Xxifax8nkFBl35X6gmHRxZ7
jlfmWMcAkXASNXl9/Yso2XGJMs85JPhZPJ3KJRuuurnhZSxAbDJMNBFJ+HbQv3y6
pupeR7ut6pWJxr6MND793yoFGoRYwKklQdfP4xzFCatYRU4RkPBp95KJ
=RMUj
-----END PGP MESSAGE-----
`
)
func TestMain(m *testing.M) {
flag.Parse()
os.Setenv("GNUPGHOME", testGPGHome)
unsetenvGPGAgentInfo()
os.Exit(m.Run())
}
func compareEngineInfo(t *testing.T, info *EngineInfo, proto Protocol, fileName, homeDir string) {
for info != nil && info.Protocol() != proto {
info = info.Next()
}
if info == nil {
t.Errorf("Expected engine info %d not found", proto)
return
}
if info.FileName() != fileName {
t.Errorf("Testing file name %s does not match %s", info.FileName(), fileName)
}
if info.HomeDir() != homeDir {
t.Errorf("Testing home directory %s does not match %s", info.HomeDir(), homeDir)
}
}
func TestEngineInfo(t *testing.T) {
testProto := ProtocolOpenPGP // Careful, this is global state!
defer func() {
SetEngineInfo(testProto, "", "") // Try to reset to defaults after we are done.
}()
testFN := "testFN"
testHomeDir := "testHomeDir"
checkError(t, SetEngineInfo(testProto, testFN, testHomeDir))
info, err := GetEngineInfo()
checkError(t, err)
compareEngineInfo(t, info, testProto, testFN, testHomeDir)
// SetEngineInfo with empty strings works, using defaults which we don't know,
// so just test that it doesn't fail.
checkError(t, SetEngineInfo(testProto, testFN, ""))
checkError(t, SetEngineInfo(testProto, "", testHomeDir))
}
func ctxWithCallback(t *testing.T) *Context {
ensureVersion(t, "1.", "can only set password callback for GPG v1.x")
ctx, err := New()
checkError(t, err)
checkError(t, ctx.SetCallback(func(uid_hint string, prev_was_bad bool, f *os.File) error {
if prev_was_bad {
t.Fatal("Bad passphrase")
}
_, err := io.WriteString(f, "password\n")
return err
}))
return ctx
}
func TestContext_Armor(t *testing.T) {
ctx, err := New()
checkError(t, err)
ctx.SetArmor(true)
if !ctx.Armor() {
t.Error("expected armor set")
}
ctx.SetArmor(false)
if ctx.Armor() {
t.Error("expected armor not set")
}
}
func TestContext_TextMode(t *testing.T) {
ctx, err := New()
checkError(t, err)
ctx.SetTextMode(true)
if !ctx.TextMode() {
t.Error("expected textmode set")
}
ctx.SetTextMode(false)
if ctx.TextMode() {
t.Error("expected textmode not set")
}
}
func TestContext_EngineInfo(t *testing.T) {
ctx, err := New()
checkError(t, err)
testProto := ProtocolOpenPGP
testFN := "testFN"
testHomeDir := "testHomeDir"
checkError(t, ctx.SetEngineInfo(testProto, testFN, testHomeDir))
info := ctx.EngineInfo()
compareEngineInfo(t, info, testProto, testFN, testHomeDir)
// SetEngineInfo with empty strings works, using defaults which we don't know,
// so just test that it doesn't fail.
checkError(t, ctx.SetEngineInfo(testProto, testFN, ""))
checkError(t, ctx.SetEngineInfo(testProto, "", testHomeDir))
}
func TestContext_Encrypt(t *testing.T) {
ctx, err := New()
checkError(t, err)
keys, err := FindKeys("test@example.com", true)
checkError(t, err)
plain, err := NewDataBytes([]byte(testData))
checkError(t, err)
var buf bytes.Buffer
cipher, err := NewDataWriter(&buf)
checkError(t, err)
checkError(t, ctx.Encrypt(keys, 0, plain, cipher))
if buf.Len() < 1 {
t.Error("Expected encrypted bytes, got empty buffer")
}
}
func TestContext_Decrypt(t *testing.T) {
ctx := ctxWithCallback(t)
cipher, err := NewDataBytes([]byte(testCipherText))
checkError(t, err)
var buf bytes.Buffer
plain, err := NewDataWriter(&buf)
checkError(t, err)
checkError(t, ctx.Decrypt(cipher, plain))
diff(t, buf.Bytes(), []byte("Test message\n"))
}
func TestContext_DecryptVerify(t *testing.T) {
ctx := ctxWithCallback(t)
cipher, err := NewDataBytes([]byte(textSignedCipherText))
checkError(t, err)
var buf bytes.Buffer
plain, err := NewDataWriter(&buf)
checkError(t, err)
checkError(t, ctx.DecryptVerify(cipher, plain))
diff(t, buf.Bytes(), []byte("Test message\n"))
}
func TestContext_Sign(t *testing.T) {
ctx := ctxWithCallback(t)
key, err := ctx.GetKey("test@example.com", true)
checkError(t, err)
plain, err := NewDataBytes([]byte(testData))
checkError(t, err)
var buf bytes.Buffer
signed, err := NewDataWriter(&buf)
checkError(t, err)
checkError(t, ctx.Sign([]*Key{key}, plain, signed, SigModeNormal))
if buf.Len() < 1 {
t.Error("Expected signed bytes, got empty buffer")
}
}
func TestContext_Verify(t *testing.T) {
ctx, err := New()
checkError(t, err)
_, err = ctx.GetKey("test@example.com", false)
checkError(t, err)
signed, err := NewDataBytes([]byte(testSignedText))
checkError(t, err)
var buf bytes.Buffer
plain, err := NewDataWriter(&buf)
checkError(t, err)
_, sigs, err := ctx.Verify(signed, nil, plain)
checkError(t, err)
if len(sigs) != 1 {
t.Error("Expected 1 signature")
}
sig := sigs[0]
// Normalize
expectedSig := Signature{
Summary: SigSumValid | SigSumGreen,
Fingerprint: "44B646DC347C31E867FF4F450327FFB0229F6136",
Status: nil,
Timestamp: sig.Timestamp, // Ignore in comparison
ExpTimestamp: sig.ExpTimestamp, // Ignore in comparison
WrongKeyUsage: false,
PKATrust: 0,
ChainModel: false,
Validity: ValidityFull,
ValidityReason: nil,
PubkeyAlgo: sig.PubkeyAlgo, // Ignore in comparison
HashAlgo: sig.HashAlgo, // Ignore in comparison
}
if sig != expectedSig {
t.Errorf("Signature verification does not match: %#v vs. %#v", sig, expectedSig)
}
diff(t, buf.Bytes(), []byte("Test message\n"))
}
func TestContext_Import(t *testing.T) {
homeDir, err := ioutil.TempDir("", "gpgme-import-test")
checkError(t, err)
defer os.RemoveAll(homeDir)
ctx, err := New()
checkError(t, err)
checkError(t, ctx.SetEngineInfo(ProtocolOpenPGP, "", homeDir))
f, err := os.Open("./testdata/pubkeys.gpg")
checkError(t, err)
defer f.Close()
dh, err := NewDataFile(f)
checkError(t, err)
defer dh.Close()
res, err := ctx.Import(dh)
checkError(t, err)
for _, v := range []struct {
Name string
Value int
Expected int
}{
{"Considered", res.Considered, 1},
{"NoUserID", res.NoUserID, 0},
{"Imported", res.Imported, 1},
// Do not test ImportedRSA, as of gnupg 2.1.11 the value is always 0.
{"Unchanged", res.Unchanged, 0},
{"NewUserIDs", res.NewUserIDs, 0},
{"NewSubKeys", res.NewSubKeys, 0},
{"NewSignatures", res.NewSignatures, 0},
{"NewRevocations", res.NewRevocations, 0},
{"SecretRead", res.SecretRead, 0},
{"SecretImported", res.SecretImported, 0},
{"SecretUnchanged", res.SecretUnchanged, 0},
{"NotImported", res.NotImported, 0},
} {
if v.Value != v.Expected {
t.Errorf("Unexpected import result field %s, value %d, expected %d", v.Name, v.Value, v.Expected)
}
}
expectedStatus := ImportStatus{
Fingerprint: "44B646DC347C31E867FF4F450327FFB0229F6136",
Result: nil,
Status: ImportNew,
}
if len(res.Imports) != 1 {
t.Errorf("Unexpected number of import status values %d", len(res.Imports))
} else if res.Imports[0] != expectedStatus {
t.Errorf("Import status does not match: %#v vs. %#v", res.Imports[0], expectedStatus)
}
}
func isVersion(t testing.TB, version string) bool {
var info *EngineInfo
info, err := GetEngineInfo()
checkError(t, err)
for info != nil {
if info.Protocol() == ProtocolOpenPGP {
if strings.Contains(info.FileName(), "gpg") && strings.HasPrefix(info.Version(), version) {
return true
}
return false
}
info = info.Next()
}
return false
}
var gpgBins = []string{"gpg2", "gpg1", "gpg"}
// ensureVersion tries to setup gpgme with a specific version or skip
func ensureVersion(t testing.TB, version, msg string) {
if isVersion(t, version) {
return
}
for _, bin := range gpgBins {
path, err := exec.LookPath(bin)
if err != nil {
continue
}
if err := SetEngineInfo(ProtocolOpenPGP, path, testGPGHome); err != nil {
continue
}
if isVersion(t, version) {
return
}
}
t.Skip(msg)
}
func diff(t *testing.T, dst, src []byte) {
line := 1
offs := 0 // line offset
for i := 0; i < len(dst) && i < len(src); i++ {
d := dst[i]
s := src[i]
if d != s {
t.Errorf("dst:%d: %s\n", line, dst[offs:i+1])
t.Errorf("src:%d: %s\n", line, src[offs:i+1])
return
}
if s == '\n' {
line++
offs = i + 1
}
}
if len(dst) != len(src) {
t.Errorf("len(dst) = %d, len(src) = %d\nsrc = %q", len(dst), len(src), src)
}
}
func checkError(t testing.TB, err error) {
if err == nil {
return
}
_, file, line, ok := runtime.Caller(1)
if ok {
// Truncate file name at last file name separator.
if index := strings.LastIndex(file, "/"); index >= 0 {
file = file[index+1:]
} else if index = strings.LastIndex(file, "\\"); index >= 0 {
file = file[index+1:]
}
} else {
file = "???"
line = 1
}
t.Fatalf("%s:%d: %s", file, line, err)
}