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:
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
`github.com/google/uuid`
|
||||
)
|
||||
|
||||
// Paths.
|
||||
const (
|
||||
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).
|
||||
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 {
|
||||
return
|
||||
|
@ -23,6 +23,8 @@ func (p *Prompt) Prompt() (promptValue *dbus.Variant, err error) {
|
||||
var c chan *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.
|
||||
c = make(chan *dbus.Signal, 10)
|
||||
defer close(c)
|
||||
@ -31,7 +33,7 @@ func (p *Prompt) Prompt() (promptValue *dbus.Variant, err error) {
|
||||
defer p.Conn.RemoveSignal(c)
|
||||
|
||||
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 {
|
||||
return
|
||||
}
|
||||
|
@ -95,7 +95,6 @@ func (s *Service) CreateAliasedCollection(label, alias string) (collection *Coll
|
||||
if isPrompt(promptPath) {
|
||||
|
||||
prompt = NewPrompt(s.Conn, promptPath)
|
||||
|
||||
if variant, err = prompt.Prompt(); err != nil {
|
||||
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) {
|
||||
|
||||
/*
|
||||
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 {
|
||||
err = ErrMissingPaths
|
||||
return
|
||||
}
|
||||
|
||||
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?
|
||||
if err = s.Dbus.Call(
|
||||
DbusServiceGetSecrets, 0, itemPaths,
|
||||
).Store(&secrets); err != nil {
|
||||
DbusServiceGetSecrets, 0, itemPaths, s.Session.Dbus.Path(),
|
||||
).Store(&results); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for p, r := range results {
|
||||
secrets[p] = NewSecret(
|
||||
s.Session, r[1].([]byte), r[2].([]byte), r[3].(string),
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -196,40 +213,29 @@ func (s *Service) GetSession() (ssn *Session, err error) {
|
||||
*/
|
||||
func (s *Service) Lock(objectPaths ...dbus.ObjectPath) (err error) {
|
||||
|
||||
var errs []error = make([]error, 0)
|
||||
// We only use these as destinations.
|
||||
var locked []dbus.ObjectPath
|
||||
var prompt *Prompt
|
||||
var resultPath dbus.ObjectPath
|
||||
var promptPath dbus.ObjectPath
|
||||
|
||||
if objectPaths == nil || len(objectPaths) == 0 {
|
||||
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
|
||||
}
|
||||
|
||||
for _, p := range objectPaths {
|
||||
if err = s.Dbus.Call(
|
||||
DbusServiceLock, 0, p,
|
||||
).Store(&locked, &resultPath); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
DbusServiceLock, 0, objectPaths,
|
||||
).Store(&locked, &promptPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if isPrompt(resultPath) {
|
||||
if isPrompt(promptPath) {
|
||||
|
||||
prompt = NewPrompt(s.Conn, resultPath)
|
||||
prompt = NewPrompt(s.Conn, promptPath)
|
||||
|
||||
if _, err = prompt.Prompt(); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errs != nil && len(errs) > 0 {
|
||||
err = NewErrors(errs...)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
var errs []error = make([]error, 0)
|
||||
var unlocked []dbus.ObjectPath
|
||||
var prompt *Prompt
|
||||
var resultPath dbus.ObjectPath
|
||||
@ -416,13 +421,10 @@ func (s *Service) Unlock(objectPaths ...dbus.ObjectPath) (err error) {
|
||||
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
|
||||
}
|
||||
|
||||
for _, p := range objectPaths {
|
||||
if err = s.Dbus.Call(
|
||||
DbusServiceUnlock, 0, p,
|
||||
DbusServiceUnlock, 0, objectPaths,
|
||||
).Store(&unlocked, &resultPath); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
return
|
||||
}
|
||||
|
||||
if isPrompt(resultPath) {
|
||||
@ -430,16 +432,9 @@ func (s *Service) Unlock(objectPaths ...dbus.ObjectPath) (err error) {
|
||||
prompt = NewPrompt(s.Conn, resultPath)
|
||||
|
||||
if _, err = prompt.Prompt(); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errs != nil && len(errs) > 0 {
|
||||
err = NewErrors(errs...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -3,17 +3,7 @@ package gosecret
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
collectionName uuid.UUID = uuid.New()
|
||||
collectionAlias uuid.UUID = uuid.New()
|
||||
)
|
||||
|
||||
const (
|
||||
defaultCollection string = "Login"
|
||||
testAlias string = "GOSECRET_TESTING_ALIAS"
|
||||
`github.com/godbus/dbus/v5`
|
||||
)
|
||||
|
||||
/*
|
||||
@ -64,7 +54,7 @@ func TestService_Collections(t *testing.T) {
|
||||
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())
|
||||
} else {
|
||||
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
|
||||
around Service.CreateAliasedCollection).
|
||||
*/
|
||||
/* DISABLED. Currently, *only* the alias "default" is allowed. TODO: revisit in future?
|
||||
func TestService_CreateAliasedCollection(t *testing.T) {
|
||||
|
||||
var err error
|
||||
@ -105,6 +96,12 @@ func TestService_CreateAliasedCollection(t *testing.T) {
|
||||
collectionName.String(), collectionAlias.String(), err.Error(),
|
||||
)
|
||||
} 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 {
|
||||
t.Errorf(
|
||||
"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 {
|
||||
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
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)
|
||||
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) {
|
||||
|
||||
@ -162,29 +155,176 @@ func TestService_GetCollection(t *testing.T) {
|
||||
(all calls in TestService_CreateAliasedCollection)
|
||||
Service.CreateCollection
|
||||
Service.SearchItems
|
||||
NewItem
|
||||
NewErrors
|
||||
Service.GetSecrets
|
||||
NewSecret
|
||||
Collection.CreateItem
|
||||
Item.Label
|
||||
|
||||
*/
|
||||
/* TODO: left off on this.
|
||||
func TestService_Secrets(t *testing.T) {
|
||||
|
||||
var err error
|
||||
var svc *Service
|
||||
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 itemAttrs map[string]string = map[string]string{
|
||||
"GOSECRET": "yes",
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
t.Errorf("could not close Service.Session: %v", err.Error())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// 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