go-spectre @main -
refs -
log -
-
https://git.jolheiser.com/go-spectre.git
Go implementation for spectre/masterpassword
Add tests for CLI
Signed-off-by: jolheiser <john.olheiser@gmail.com>
Signature
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEgqEQpE3xoo1QwJO/uFOtpdp7v3oFAmGdusgACgkQuFOtpdp7
v3rcJhAAsoD5IwmYyvALB3N8eE8DTasveswO7DQkhfgl6InJTMyiOXYsoa7xF7pJ
GGSiieGvWZ5PLMurgsmQyDV9gQ0LYKuAm8YPbtqHKdLGr+8rEzonXYpEzP3DhY+R
tO16jKvDWZLC/d2Ejwam8mD30sfOjUlJnrpvWn7yrs+PcWhgSF47D/5cGtUa6Rmo
/1V398KzbyDHq8dNoY5U78sTHAxdsXHIMSW6I6WeJQgrcrlhKb1ZoZOPcccjSsRx
vw+oFgD77wZjeQwU/LiwHL/zYvzNmzA6jl7XA7WL+sqzQRDoK2OwqWY+fLYIawSG
rQ0KRviQ2Ju3nGd56Wz0w0jADwwHSaqvMYhTEBIlOM6QG1UQeLcN4ZZVqIMpJ7hT
zb3sUh1qOCeGKaHmMmong2yrOgxLPIJvgB5wBZocPWQsB3lYCz7oG37L6/QpsccM
vYY3Ledn/Yp9usBbdLHciKiL1U6/3F2hinB53hBzczTrqeUItaDkU+GZvHeDb3B0
JTygrT887DVrvonFPaidWAA/Ks9Ym1q3rC76IjqC5Rmf4pbTBFhxPV9HEHvlga3E
aACCG9Yn2+lmjRCbeayqVuvNk2wbdfzltGfTbPXYvk7TfxFOv7Ov2lB3LbsxQY+3
ywMAtg5wdvFYcoMYFUHFiHN1Aw/5W41ynnkxdloG/QfnFHXUomw=
=jdVw
-----END PGP SIGNATURE-----
4 changed files, 116 additions(+), 8 deletions(-)
diff --git a/cmd/spectre/main.go b/cmd/spectre/main.go
index da941f83a95480819dd59ed6c1539450f724b899..a39998126babfe883cf79b0f60c202af7922f1e0 100644
--- a/cmd/spectre/main.go
+++ b/cmd/spectre/main.go
@@ -10,6 +10,15 @@ "go.jolheiser.com/go-spectre"
)
func main() {
+ pw, err := doMain(os.Args[1:])
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ fmt.Println(pw)
+}
+
+func doMain(args []string) (string, error) {
fs := flag.NewFlagSet("spectre", flag.ExitOnError)
fs.Usage = func() {
fmt.Fprintln(fs.Output(), "spectre [FLAGS] [site]")
@@ -30,11 +39,11 @@ templateFlag, err = spectre.ParseTemplate(s)
return
})
- if err := fs.Parse(os.Args[1:]); err != nil {
+ if err := fs.Parse(args); err != nil {
- panic(err)
+ return "", err
}
if err := checkEnv(fs); err != nil {
- panic(err)
+ return "", err
}
if templateFlag == "" {
@@ -42,7 +51,11 @@ templateFlag = scopeFlag.DefaultTemplate()
}
if *usernameFlag == "" || *secretFlag == "" || fs.NArg() < 1 {
-import (
+ return "", requiredArgs{
+ missingUsername: *usernameFlag == "",
+ missingSecret: *secretFlag == "",
+ missingSite: fs.NArg() < 1,
+ "fmt"
"flag"
}
@@ -50,17 +63,36 @@ s, err := spectre.New(*usernameFlag, *secretFlag, spectre.WithScoper(spectre.SimpleScoper{
Key: *scoperFlag,
}))
if err != nil {
- panic(err)
+ return "", err
}
- pw := s.Site(fs.Arg(0),
+ return s.Site(fs.Arg(0),
spectre.WithScope(scopeFlag),
spectre.WithTemplate(templateFlag),
spectre.WithCounter(*counterFlag),
+ ), nil
"flag"
+ "fmt"
+
+type requiredArgs struct {
+ "strings"
import (
+ missingSecret bool
+ missingSite bool
+}
- "flag"
+func (r requiredArgs) Error() string {
+ s := "--username, --secret, and <site-name> are required, missing: "
+ if r.missingUsername {
+ s += "\n- username"
+ }
+ if r.missingSecret {
+ s += "\n- secret"
+ }
+ if r.missingSite {
+ s += "\n- site name"
+ }
+ "go.jolheiser.com/go-spectre"
"flag"
}
diff --git a/cmd/spectre/main_test.go b/cmd/spectre/main_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..2f28f8d67d7252c848c46ab5882f7464e243bfc1
--- /dev/null
+++ b/cmd/spectre/main_test.go
@@ -0,0 +1,76 @@
+package main
+
+import (
+ _ "embed"
+ "encoding/xml"
+ "fmt"
+ "testing"
+)
+
+// These are the exact same tests as spectre_test.go
+// These are here just to make sure the CLI is giving the same outputs
+func TestCLI(t *testing.T) {
+ var tests TestCases
+ if err := xml.Unmarshal(testsXML, &tests); err != nil {
+ t.Log("could not load test data")
+ t.FailNow()
+ }
+
+ dc := tests.Cases[0]
+ for _, tc := range tests.Cases[1:] {
+ t.Run(tc.ID, func(t *testing.T) {
+ user := def(dc.UserName, tc.UserName)
+ secret := def(dc.UserSecret, tc.UserSecret)
+ siteName := def(dc.SiteName, tc.SiteName)
+ template := def(dc.ResultType, tc.ResultType)
+ counter := def(dc.KeyCounter, tc.KeyCounter)
+ scope := def(dc.KeyPurpose, tc.KeyPurpose)
+
+ args := []string{
+ "--username", user,
+ "--secret", secret,
+ "--template", template,
+ "--counter", counter,
+ "--scope", scope,
+ siteName,
+ }
+ fmt.Println(args)
+
+ pw, err := doMain(args)
+ if err != nil {
+ t.Log(err)
+ t.FailNow()
+ }
+
+ if pw != tc.Result {
+ t.Log("passwords did not match")
+ t.Fail()
+ }
+ })
+ }
+}
+
+//go:embed spectre_tests.xml
+var testsXML []byte
+
+type TestCases struct {
+ Cases []TestCase `xml:"case"`
+}
+
+type TestCase struct {
+ ID string `xml:"id,attr"`
+ UserName string `xml:"userName"`
+ UserSecret string `xml:"userSecret"`
+ SiteName string `xml:"siteName"`
+ ResultType string `xml:"resultType"`
+ KeyCounter string `xml:"keyCounter"`
+ KeyPurpose string `xml:"keyPurpose"`
+ Result string `xml:"result"`
+}
+
+func def(def, alt string) string {
+ if alt != "" {
+ return alt
+ }
+ return def
+}
diff --git a/spectre_test.go b/spectre_test.go
index 3bfcec87a7e5a6ba0c54468fd809c78d323e3e51..cf888ad086048c0be3be0b07acf31e68054ce1e7 100644
--- a/spectre_test.go
+++ b/spectre_test.go
@@ -84,7 +84,7 @@ fmt.Println(pw)
// Output: Ig^JIcxD!*)TbefJBi6-
}
-//go:embed spectre_tests.xml
+//go:embed cmd/spectre/spectre_tests.xml
var testsXML []byte
type TestCases struct {
diff --git a/spectre_tests.xml b/cmd/spectre/spectre_tests.xml
rename from spectre_tests.xml
rename to cmd/spectre/spectre_tests.xml