adding ref mat'l, Service tests done
This commit is contained in:
parent
eda1777431
commit
94ae20829e
@ -7,3 +7,7 @@ https://people.gnome.org/~stefw/libsecret-docs/index.html
|
|||||||
Quick reference URLs:
|
Quick reference URLs:
|
||||||
|
|
||||||
Dbus paths: https://specifications.freedesktop.org/secret-service/latest/ch12.html
|
Dbus paths: https://specifications.freedesktop.org/secret-service/latest/ch12.html
|
||||||
|
Message types: https://dbus.freedesktop.org/doc/dbus-specification.html#type-system
|
||||||
|
Use this for reference for errors like:
|
||||||
|
Type of message, “(ao)”, does not match expected type “(aoo)”
|
||||||
|
See dbus_types subdir for Golang structs that can be used in the future to improve these error messages.
|
116
.ref/dbus_types/structs.go
Normal file
116
.ref/dbus_types/structs.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package dbus_types
|
||||||
|
|
||||||
|
// https://dbus.freedesktop.org/doc/dbus-specification.html#type-system
|
||||||
|
|
||||||
|
type DbusType struct {
|
||||||
|
TypeName string
|
||||||
|
Symbol rune
|
||||||
|
Desc string
|
||||||
|
ZeroValue interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
BASIC TYPES
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DbusByte DbusType = DbusType{
|
||||||
|
TypeName: "BYTE",
|
||||||
|
Symbol: 'y',
|
||||||
|
Desc: "Unsigned 8-bit integer",
|
||||||
|
ZeroValue: byte(0x0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusBoolean DbusType = DbusType{
|
||||||
|
TypeName: "BOOLEAN",
|
||||||
|
Symbol: 'b',
|
||||||
|
Desc: "Boolean value: 0 is false, 1 is true, any other value allowed by the marshalling format is invalid",
|
||||||
|
ZeroValue: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusInt16 DbusType = DbusType{
|
||||||
|
TypeName: "INT16",
|
||||||
|
Symbol: 'n',
|
||||||
|
Desc: "Signed (two's complement) 16-bit integer",
|
||||||
|
ZeroValue: int16(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusUint16 DbusType = DbusType{
|
||||||
|
TypeName: "UINT16",
|
||||||
|
Symbol: 'q',
|
||||||
|
Desc: "Unsigned 16-bit integer",
|
||||||
|
ZeroValue: uint16(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusInt32 DbusType = DbusType{
|
||||||
|
TypeName: "INT32",
|
||||||
|
Symbol: 'i',
|
||||||
|
Desc: "Signed (two's complement) 32-bit integer",
|
||||||
|
ZeroValue: int32(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusUint32 DbusType = DbusType{
|
||||||
|
TypeName: "UINT32",
|
||||||
|
Symbol: 'u',
|
||||||
|
Desc: "Unsigned 32-bit integer",
|
||||||
|
ZeroValue: uint32(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusInt64 DbusType = DbusType{
|
||||||
|
TypeName: "INT64",
|
||||||
|
Symbol: 'x',
|
||||||
|
Desc: "Signed (two's complement) 64-bit integer (mnemonic: x and t are the first characters in \"sixty\" not already used for something more common)",
|
||||||
|
ZeroValue: int64(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusUint64 DbusType = DbusType{
|
||||||
|
TypeName: "UINT64",
|
||||||
|
Symbol: 't',
|
||||||
|
Desc: "Unsigned 64-bit integer",
|
||||||
|
ZeroValue: uint64(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusDoubleFloat DbusType = DbusType{
|
||||||
|
TypeName: "DOUBLE",
|
||||||
|
Symbol: 'd',
|
||||||
|
Desc: "IEEE 754 double-precision floating point",
|
||||||
|
ZeroValue: float64(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusUnixFD DbusType = DbusType{
|
||||||
|
TypeName: "UNIX_FD",
|
||||||
|
Symbol: 'h',
|
||||||
|
Desc: "Unsigned 32-bit integer representing an index into an out-of-band array of file descriptors, transferred via some platform-specific mechanism (mnemonic: h for handle)",
|
||||||
|
ZeroValue: uint32(0), // See https://pkg.go.dev/github.com/godbus/dbus#UnixFDIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusString DbusType = DbusType{
|
||||||
|
TypeName: "STRING",
|
||||||
|
Symbol: 'o',
|
||||||
|
Desc: "No extra constraints",
|
||||||
|
ZeroValue: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusObjectPath DbusType = DbusType{
|
||||||
|
TypeName: "OBJECT_PATH",
|
||||||
|
Symbol: 'o',
|
||||||
|
Desc: "A syntactically valid Path for Dbus",
|
||||||
|
ZeroValue: nil, // ???
|
||||||
|
}
|
||||||
|
|
||||||
|
var DbusSignature DbusType = DbusType{
|
||||||
|
TypeName: "SIGNATURE",
|
||||||
|
Symbol: 'g',
|
||||||
|
Desc: "0 or more single complete types", // ???
|
||||||
|
ZeroValue: nil, // ???
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CONTAINER TYPES
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
TODO: not sure how to struct this natively, but:
|
||||||
|
Dbus Struct: (<symbol(s)...>) // Note: structs can be nested e.g. (i(ii))
|
||||||
|
Dbus Array: a<symbol> // The symbol can be any type (even nested arrays, e.g. aai), but only one type is allowed. Arrays are like Golang slices; no fixed size.
|
||||||
|
Dbus Variant: v<symbol> // Dbus equivalent of interface{}, more or less. See https://dbus.freedesktop.org/doc/dbus-specification.html#container-types
|
||||||
|
Dbus Dict: [kv] // Where k is the key's type and v is the value's type.
|
||||||
|
*/
|
@ -1,6 +1,24 @@
|
|||||||
package gosecret
|
package gosecret
|
||||||
|
|
||||||
|
import (
|
||||||
|
`github.com/google/uuid`
|
||||||
|
)
|
||||||
|
|
||||||
// Paths.
|
// Paths.
|
||||||
const (
|
const (
|
||||||
DbusDefaultCollectionPath string = DbusPath + "/collections/login"
|
DbusDefaultCollectionPath string = DbusPath + "/collections/login"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Strings.
|
||||||
|
const (
|
||||||
|
defaultCollection string = "default" // SHOULD point to a collection named "login"; "default" is the alias.
|
||||||
|
testAlias string = "GOSECRET_TESTING_ALIAS"
|
||||||
|
testSecretContent string = "This is a test secret for gosecret."
|
||||||
|
testItemLabel string = "gosecret_test_item"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Objects.
|
||||||
|
var (
|
||||||
|
collectionName uuid.UUID = uuid.New()
|
||||||
|
collectionAlias uuid.UUID = uuid.New()
|
||||||
|
)
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
NewErrors returns a new MultiError based on a slice of error.Error (errs).
|
NewErrors returns a new MultiError based on a slice of error.Error (errs).
|
||||||
Any nil errors are trimmed. If there are no actual errors after trimming, err will be nil.
|
Any nil errors are trimmed. If there are no actual errors after trimming, err will be nil.
|
||||||
*/
|
*/
|
||||||
func NewErrors(errs ...error) (err *MultiError) {
|
func NewErrors(errs ...error) (err error) {
|
||||||
|
|
||||||
if errs == nil || len(errs) == 0 {
|
if errs == nil || len(errs) == 0 {
|
||||||
return
|
return
|
||||||
@ -46,7 +46,7 @@ func (e *MultiError) Error() (errStr string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for idx, err := range e.Errors {
|
for idx, err := range e.Errors {
|
||||||
if (idx +1 ) < numErrs {
|
if (idx + 1) < numErrs {
|
||||||
errStr += fmt.Sprintf(err.Error(), e.ErrorSep)
|
errStr += fmt.Sprintf(err.Error(), e.ErrorSep)
|
||||||
} else {
|
} else {
|
||||||
errStr += err.Error()
|
errStr += err.Error()
|
||||||
|
@ -23,6 +23,8 @@ func (p *Prompt) Prompt() (promptValue *dbus.Variant, err error) {
|
|||||||
var c chan *dbus.Signal
|
var c chan *dbus.Signal
|
||||||
var result *dbus.Signal
|
var result *dbus.Signal
|
||||||
|
|
||||||
|
promptValue = new(dbus.Variant)
|
||||||
|
|
||||||
// Prompts are asynchronous; we connect to the signal and block with a channel until we get a response.
|
// Prompts are asynchronous; we connect to the signal and block with a channel until we get a response.
|
||||||
c = make(chan *dbus.Signal, 10)
|
c = make(chan *dbus.Signal, 10)
|
||||||
defer close(c)
|
defer close(c)
|
||||||
@ -31,7 +33,7 @@ func (p *Prompt) Prompt() (promptValue *dbus.Variant, err error) {
|
|||||||
defer p.Conn.RemoveSignal(c)
|
defer p.Conn.RemoveSignal(c)
|
||||||
|
|
||||||
if err = p.Dbus.Call(
|
if err = p.Dbus.Call(
|
||||||
DbusPrompterInterface, 0, "", // TODO: This last argument, the string, is for "window ID". I'm unclear what for.
|
DbusPrompterInterface, 0, "GoSecret.Prompt", // TODO: This last argument, the string, is for "window ID". I'm unclear what for.
|
||||||
).Store(); err != nil {
|
).Store(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,6 @@ func (s *Service) CreateAliasedCollection(label, alias string) (collection *Coll
|
|||||||
if isPrompt(promptPath) {
|
if isPrompt(promptPath) {
|
||||||
|
|
||||||
prompt = NewPrompt(s.Conn, promptPath)
|
prompt = NewPrompt(s.Conn, promptPath)
|
||||||
|
|
||||||
if variant, err = prompt.Prompt(); err != nil {
|
if variant, err = prompt.Prompt(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -161,20 +160,38 @@ func (s *Service) GetCollection(name string) (c *Collection, err error) {
|
|||||||
*/
|
*/
|
||||||
func (s *Service) GetSecrets(itemPaths ...dbus.ObjectPath) (secrets map[dbus.ObjectPath]*Secret, err error) {
|
func (s *Service) GetSecrets(itemPaths ...dbus.ObjectPath) (secrets map[dbus.ObjectPath]*Secret, err error) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Results are in the form of a map with the value consisting of:
|
||||||
|
[]interface {}{
|
||||||
|
"/org/freedesktop/secrets/session/sNNN", // 0, session path
|
||||||
|
[]uint8{}, // 1, "params"
|
||||||
|
[]uint8{0x0}, // 2, value
|
||||||
|
"text/plain", // 3, content type
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
var results map[dbus.ObjectPath][]interface{}
|
||||||
|
|
||||||
if itemPaths == nil || len(itemPaths) == 0 {
|
if itemPaths == nil || len(itemPaths) == 0 {
|
||||||
err = ErrMissingPaths
|
err = ErrMissingPaths
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets = make(map[dbus.ObjectPath]*Secret, len(itemPaths))
|
secrets = make(map[dbus.ObjectPath]*Secret, len(itemPaths))
|
||||||
|
results = make(map[dbus.ObjectPath][]interface{}, len(itemPaths))
|
||||||
|
|
||||||
// TODO: trigger a Service.Unlock for any locked items?
|
// TODO: trigger a Service.Unlock for any locked items?
|
||||||
if err = s.Dbus.Call(
|
if err = s.Dbus.Call(
|
||||||
DbusServiceGetSecrets, 0, itemPaths,
|
DbusServiceGetSecrets, 0, itemPaths, s.Session.Dbus.Path(),
|
||||||
).Store(&secrets); err != nil {
|
).Store(&results); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for p, r := range results {
|
||||||
|
secrets[p] = NewSecret(
|
||||||
|
s.Session, r[1].([]byte), r[2].([]byte), r[3].(string),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,39 +213,28 @@ func (s *Service) GetSession() (ssn *Session, err error) {
|
|||||||
*/
|
*/
|
||||||
func (s *Service) Lock(objectPaths ...dbus.ObjectPath) (err error) {
|
func (s *Service) Lock(objectPaths ...dbus.ObjectPath) (err error) {
|
||||||
|
|
||||||
var errs []error = make([]error, 0)
|
|
||||||
// We only use these as destinations.
|
// We only use these as destinations.
|
||||||
var locked []dbus.ObjectPath
|
var locked []dbus.ObjectPath
|
||||||
var prompt *Prompt
|
var prompt *Prompt
|
||||||
var resultPath dbus.ObjectPath
|
var promptPath dbus.ObjectPath
|
||||||
|
|
||||||
if objectPaths == nil || len(objectPaths) == 0 {
|
if objectPaths == nil || len(objectPaths) == 0 {
|
||||||
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
|
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range objectPaths {
|
if err = s.Dbus.Call(
|
||||||
if err = s.Dbus.Call(
|
DbusServiceLock, 0, objectPaths,
|
||||||
DbusServiceLock, 0, p,
|
).Store(&locked, &promptPath); err != nil {
|
||||||
).Store(&locked, &resultPath); err != nil {
|
return
|
||||||
errs = append(errs, err)
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if isPrompt(resultPath) {
|
|
||||||
|
|
||||||
prompt = NewPrompt(s.Conn, resultPath)
|
|
||||||
|
|
||||||
if _, err = prompt.Prompt(); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if errs != nil && len(errs) > 0 {
|
if isPrompt(promptPath) {
|
||||||
err = NewErrors(errs...)
|
|
||||||
|
prompt = NewPrompt(s.Conn, promptPath)
|
||||||
|
|
||||||
|
if _, err = prompt.Prompt(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -407,7 +413,6 @@ func (s *Service) SetAlias(alias string, objectPath dbus.ObjectPath) (err error)
|
|||||||
*/
|
*/
|
||||||
func (s *Service) Unlock(objectPaths ...dbus.ObjectPath) (err error) {
|
func (s *Service) Unlock(objectPaths ...dbus.ObjectPath) (err error) {
|
||||||
|
|
||||||
var errs []error = make([]error, 0)
|
|
||||||
var unlocked []dbus.ObjectPath
|
var unlocked []dbus.ObjectPath
|
||||||
var prompt *Prompt
|
var prompt *Prompt
|
||||||
var resultPath dbus.ObjectPath
|
var resultPath dbus.ObjectPath
|
||||||
@ -416,29 +421,19 @@ func (s *Service) Unlock(objectPaths ...dbus.ObjectPath) (err error) {
|
|||||||
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
|
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range objectPaths {
|
if err = s.Dbus.Call(
|
||||||
if err = s.Dbus.Call(
|
DbusServiceUnlock, 0, objectPaths,
|
||||||
DbusServiceUnlock, 0, p,
|
).Store(&unlocked, &resultPath); err != nil {
|
||||||
).Store(&unlocked, &resultPath); err != nil {
|
return
|
||||||
errs = append(errs, err)
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if isPrompt(resultPath) {
|
|
||||||
|
|
||||||
prompt = NewPrompt(s.Conn, resultPath)
|
|
||||||
|
|
||||||
if _, err = prompt.Prompt(); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if errs != nil && len(errs) > 0 {
|
if isPrompt(resultPath) {
|
||||||
err = NewErrors(errs...)
|
|
||||||
|
prompt = NewPrompt(s.Conn, resultPath)
|
||||||
|
|
||||||
|
if _, err = prompt.Prompt(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -3,17 +3,7 @@ package gosecret
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
`github.com/godbus/dbus/v5`
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
collectionName uuid.UUID = uuid.New()
|
|
||||||
collectionAlias uuid.UUID = uuid.New()
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultCollection string = "Login"
|
|
||||||
testAlias string = "GOSECRET_TESTING_ALIAS"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,7 +54,7 @@ func TestService_Collections(t *testing.T) {
|
|||||||
t.Fatalf("could not get new Service via NewService: %v", err.Error())
|
t.Fatalf("could not get new Service via NewService: %v", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = svc.Collections(); err != nil {
|
if colls, err = svc.Collections(); err != nil {
|
||||||
t.Errorf("could not get Service.Collections: %v", err.Error())
|
t.Errorf("could not get Service.Collections: %v", err.Error())
|
||||||
} else {
|
} else {
|
||||||
t.Logf("found %v collections via Service.Collections", len(colls))
|
t.Logf("found %v collections via Service.Collections", len(colls))
|
||||||
@ -89,6 +79,7 @@ func TestService_Collections(t *testing.T) {
|
|||||||
(By extension, Service.CreateCollection is also tested as it's a very thin wrapper
|
(By extension, Service.CreateCollection is also tested as it's a very thin wrapper
|
||||||
around Service.CreateAliasedCollection).
|
around Service.CreateAliasedCollection).
|
||||||
*/
|
*/
|
||||||
|
/* DISABLED. Currently, *only* the alias "default" is allowed. TODO: revisit in future?
|
||||||
func TestService_CreateAliasedCollection(t *testing.T) {
|
func TestService_CreateAliasedCollection(t *testing.T) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -105,6 +96,12 @@ func TestService_CreateAliasedCollection(t *testing.T) {
|
|||||||
collectionName.String(), collectionAlias.String(), err.Error(),
|
collectionName.String(), collectionAlias.String(), err.Error(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
if err = svc.SetAlias(testAlias, collection.Dbus.Path()); err != nil {
|
||||||
|
t.Errorf(
|
||||||
|
"error when setting an alias '%v' for aliased collection '%v' (original alias '%v')",
|
||||||
|
testAlias, collectionName.String(), collectionAlias.String(),
|
||||||
|
)
|
||||||
|
}
|
||||||
if err = collection.Delete(); err != nil {
|
if err = collection.Delete(); err != nil {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error when deleting aliased collection '%v' with alias '%v': %v",
|
"error when deleting aliased collection '%v' with alias '%v': %v",
|
||||||
@ -113,17 +110,11 @@ func TestService_CreateAliasedCollection(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = svc.SetAlias(testAlias, collection.Dbus.Path()); err != nil {
|
|
||||||
t.Errorf(
|
|
||||||
"error when setting an alias '%v' for aliased collection '%v' (original alias '%v')",
|
|
||||||
testAlias, collectionName.String(), collectionAlias.String(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = svc.Close(); err != nil {
|
if err = svc.Close(); err != nil {
|
||||||
t.Errorf("could not close Service.Session: %v", err.Error())
|
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TestService_GetCollection tests the following internal functions/methods via nested calls:
|
TestService_GetCollection tests the following internal functions/methods via nested calls:
|
||||||
@ -133,6 +124,8 @@ func TestService_CreateAliasedCollection(t *testing.T) {
|
|||||||
(all calls in TestService_Collections)
|
(all calls in TestService_Collections)
|
||||||
Service.ReadAlias
|
Service.ReadAlias
|
||||||
|
|
||||||
|
The default collection (login) is fetched instead of creating one as this collection should exist,
|
||||||
|
and tests fetching existing collections instead of newly-created ones.
|
||||||
*/
|
*/
|
||||||
func TestService_GetCollection(t *testing.T) {
|
func TestService_GetCollection(t *testing.T) {
|
||||||
|
|
||||||
@ -162,29 +155,176 @@ func TestService_GetCollection(t *testing.T) {
|
|||||||
(all calls in TestService_CreateAliasedCollection)
|
(all calls in TestService_CreateAliasedCollection)
|
||||||
Service.CreateCollection
|
Service.CreateCollection
|
||||||
Service.SearchItems
|
Service.SearchItems
|
||||||
|
NewItem
|
||||||
|
NewErrors
|
||||||
Service.GetSecrets
|
Service.GetSecrets
|
||||||
|
NewSecret
|
||||||
|
Collection.CreateItem
|
||||||
|
Item.Label
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/* TODO: left off on this.
|
|
||||||
func TestService_Secrets(t *testing.T) {
|
func TestService_Secrets(t *testing.T) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var svc *Service
|
var svc *Service
|
||||||
var collection *Collection
|
var collection *Collection
|
||||||
|
var itemResultsUnlocked []*Item
|
||||||
|
var itemResultsLocked []*Item
|
||||||
|
var itemName string
|
||||||
|
var resultItemName string
|
||||||
|
var testItem *Item
|
||||||
|
var testSecret *Secret
|
||||||
|
var secretsResult map[dbus.ObjectPath]*Secret
|
||||||
var itemPaths []dbus.ObjectPath
|
var itemPaths []dbus.ObjectPath
|
||||||
|
var itemAttrs map[string]string = map[string]string{
|
||||||
|
"GOSECRET": "yes",
|
||||||
|
}
|
||||||
|
|
||||||
if svc, err = NewService(); err != nil {
|
if svc, err = NewService(); err != nil {
|
||||||
t.Fatalf("could not get new Service via NewService: %v", err.Error())
|
t.Fatalf("could not get new Service via NewService: %v", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if collection, err = svc.CreateCollection(collectionName.String()); err != nil {
|
if collection, err = svc.CreateCollection(collectionName.String()); err != nil {
|
||||||
t.Errorf("could not create collection '%v': %v", collectionName.String(), err.Error())
|
if err = svc.Close(); err != nil {
|
||||||
|
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||||
|
}
|
||||||
|
t.Fatalf("could not create collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a secret
|
||||||
|
testSecret = NewSecret(svc.Session, nil, []byte(testSecretContent), "text/plain")
|
||||||
|
if testItem, err = collection.CreateItem(testItemLabel, itemAttrs, testSecret, true); err != nil {
|
||||||
|
if err = svc.Close(); err != nil {
|
||||||
|
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||||
|
}
|
||||||
|
t.Fatalf("could not create Item in collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if itemName, err = testItem.Label(); err != nil {
|
||||||
|
t.Errorf(
|
||||||
|
"could not get label for newly-created item '%v' in collection '%v': %v",
|
||||||
|
string(testItem.Dbus.Path()), collectionName.String(), err.Error(),
|
||||||
|
)
|
||||||
|
itemName = testItemLabel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search items
|
||||||
|
if itemResultsUnlocked, itemResultsLocked, err = svc.SearchItems(itemAttrs); err != nil {
|
||||||
|
t.Errorf("did not find Item '%v' in collection '%v' SearchItems: %v", itemName, collectionName.String(), err.Error())
|
||||||
|
} else {
|
||||||
|
if len(itemResultsLocked) != 0 && itemResultsUnlocked != nil {
|
||||||
|
t.Errorf("at least one locked item in collection '%v'", collectionName.String())
|
||||||
|
}
|
||||||
|
if len(itemResultsUnlocked) != 1 {
|
||||||
|
t.Errorf("number of unlocked items in collection '%v' is not equal to 1", collectionName.String())
|
||||||
|
}
|
||||||
|
if resultItemName, err = itemResultsUnlocked[0].Label(); err != nil {
|
||||||
|
t.Errorf("cannot fetch test Item name from collection '%v' in SearchItems: %v", collectionName.String(), err.Error())
|
||||||
|
} else {
|
||||||
|
if resultItemName != itemName {
|
||||||
|
t.Errorf("seem to have fetched an improper Item from collection '%v' in SearchItems", collectionName.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch secrets
|
||||||
|
itemPaths = make([]dbus.ObjectPath, len(itemResultsUnlocked))
|
||||||
|
if len(itemResultsUnlocked) >= 1 {
|
||||||
|
itemPaths[0] = itemResultsUnlocked[0].Dbus.Path()
|
||||||
|
if secretsResult, err = svc.GetSecrets(itemPaths...); err != nil {
|
||||||
|
t.Errorf("failed to fetch Item path '%v' via Service.GetSecrets: %v", string(itemPaths[0]), err.Error())
|
||||||
|
} else if len(secretsResult) != 1 {
|
||||||
|
t.Errorf("received %v secrets from Service.GetSecrets instead of 1", len(secretsResult))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the collection to clean up.
|
||||||
|
if err = collection.Delete(); err != nil {
|
||||||
|
t.Errorf(
|
||||||
|
"error when deleting collection '%v' when testing Service: %v",
|
||||||
|
collectionName.String(), err.Error(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = svc.Close(); err != nil {
|
if err = svc.Close(); err != nil {
|
||||||
t.Errorf("could not close Service.Session: %v", err.Error())
|
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// service.Lock & service.Unlock
|
// service.Lock & service.Unlock
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestService_Locking tests the following internal functions/methods via nested calls:
|
||||||
|
|
||||||
|
(all calls in TestNewService)
|
||||||
|
(all calls in TestService_CreateAliasedCollection)
|
||||||
|
Service.Lock
|
||||||
|
Service.Unlock
|
||||||
|
Collection.Locked
|
||||||
|
|
||||||
|
*/
|
||||||
|
func TestService_Locking(t *testing.T) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var isLocked bool
|
||||||
|
var stateChangeLock bool
|
||||||
|
var svc *Service
|
||||||
|
var collection *Collection
|
||||||
|
|
||||||
|
if svc, err = NewService(); err != nil {
|
||||||
|
t.Fatalf("could not get new Service via NewService: %v", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if collection, err = svc.CreateCollection(collectionName.String()); err != nil {
|
||||||
|
if err = svc.Close(); err != nil {
|
||||||
|
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||||
|
}
|
||||||
|
t.Errorf("could not create collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if isLocked, err = collection.Locked(); err != nil {
|
||||||
|
t.Errorf("received error when checking collection '%v' lock status: %v", collectionName.String(), err.Error())
|
||||||
|
if err = collection.Delete(); err != nil {
|
||||||
|
t.Errorf(
|
||||||
|
"error when deleting collection '%v' when testing Service: %v",
|
||||||
|
collectionName.String(), err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err = svc.Close(); err != nil {
|
||||||
|
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
t.Logf("collection '%v' original lock status: %v", collectionName.String(), isLocked)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the state.
|
||||||
|
if isLocked {
|
||||||
|
if err = svc.Unlock(collection.Dbus.Path()); err != nil {
|
||||||
|
t.Errorf("could not unlock collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
if stateChangeLock, err = collection.Locked(); err != nil {
|
||||||
|
t.Errorf("received error when checking collection '%v' lock status: %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
if err = svc.Lock(collection.Dbus.Path()); err != nil {
|
||||||
|
t.Errorf("could not lock collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = svc.Lock(collection.Dbus.Path()); err != nil {
|
||||||
|
t.Errorf("could not lock collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
if stateChangeLock, err = collection.Locked(); err != nil {
|
||||||
|
t.Errorf("received error when checking collection '%v' lock status: %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
if err = svc.Unlock(collection.Dbus.Path()); err != nil {
|
||||||
|
t.Errorf("could not unlock collection '%v': %v", collectionName.String(), err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if stateChangeLock != !isLocked {
|
||||||
|
t.Errorf(
|
||||||
|
"flipped lock state for collection '%v' (locked: %v) is not opposite of original lock state (locked: %v)",
|
||||||
|
collectionName.String(), stateChangeLock, isLocked,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user