transaction: Add a test finalizer checking if transaction has ended
Check if a transaction is ended in in tests.
This commit is contained in:
@@ -173,7 +173,7 @@ func Start(service, user string, handler ConversationHandler) (*Transaction, err
|
|||||||
// StartFunc registers the handler func as a conversation handler and starts
|
// StartFunc registers the handler func as a conversation handler and starts
|
||||||
// the transaction (see Start() documentation).
|
// the transaction (see Start() documentation).
|
||||||
func StartFunc(service, user string, handler func(Style, string) (string, error)) (*Transaction, error) {
|
func StartFunc(service, user string, handler func(Style, string) (string, error)) (*Transaction, error) {
|
||||||
return Start(service, user, ConversationFunc(handler))
|
return start(service, user, ConversationFunc(handler), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartConfDir initiates a new PAM transaction. Service is treated identically to
|
// StartConfDir initiates a new PAM transaction. Service is treated identically to
|
||||||
@@ -212,6 +212,7 @@ func start(service, user string, handler ConversationHandler, confDir string) (*
|
|||||||
conv: &C.struct_pam_conv{},
|
conv: &C.struct_pam_conv{},
|
||||||
c: cgo.NewHandle(handler),
|
c: cgo.NewHandle(handler),
|
||||||
}
|
}
|
||||||
|
|
||||||
C.init_pam_conv(t.conv, C.uintptr_t(t.c))
|
C.init_pam_conv(t.conv, C.uintptr_t(t.c))
|
||||||
s := C.CString(service)
|
s := C.CString(service)
|
||||||
defer C.free(unsafe.Pointer(s))
|
defer C.free(unsafe.Pointer(s))
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func maybeEndTransaction(t *testing.T, tx *Transaction) {
|
func maybeEndTransaction(t *testing.T, tx *Transaction) {
|
||||||
@@ -21,6 +25,19 @@ func maybeEndTransaction(t *testing.T, tx *Transaction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ensureTransactionEnds(t *testing.T, tx *Transaction) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
runtime.SetFinalizer(tx, func(tx *Transaction) {
|
||||||
|
// #nosec:G103 - the pointer conversion is checked.
|
||||||
|
handle := atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tx.handle)))
|
||||||
|
if handle == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Fatalf("transaction has not been finalized")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestPAM_001(t *testing.T) {
|
func TestPAM_001(t *testing.T) {
|
||||||
u, _ := user.Current()
|
u, _ := user.Current()
|
||||||
if u.Uid != "0" {
|
if u.Uid != "0" {
|
||||||
@@ -30,6 +47,7 @@ func TestPAM_001(t *testing.T) {
|
|||||||
tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) {
|
tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -62,6 +80,7 @@ func TestPAM_002(t *testing.T) {
|
|||||||
}
|
}
|
||||||
return "", errors.New("unexpected")
|
return "", errors.New("unexpected")
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -97,6 +116,7 @@ func TestPAM_003(t *testing.T) {
|
|||||||
Password: "secret",
|
Password: "secret",
|
||||||
}
|
}
|
||||||
tx, err := Start("", "", c)
|
tx, err := Start("", "", c)
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -116,6 +136,7 @@ func TestPAM_004(t *testing.T) {
|
|||||||
Password: "secret",
|
Password: "secret",
|
||||||
}
|
}
|
||||||
tx, err := Start("", "test", c)
|
tx, err := Start("", "test", c)
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -134,6 +155,7 @@ func TestPAM_005(t *testing.T) {
|
|||||||
tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) {
|
tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) {
|
||||||
return "secret", nil
|
return "secret", nil
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -152,6 +174,7 @@ func TestPAM_006(t *testing.T) {
|
|||||||
tx, err := StartFunc("passwd", u.Username, func(s Style, msg string) (string, error) {
|
tx, err := StartFunc("passwd", u.Username, func(s Style, msg string) (string, error) {
|
||||||
return "secret", nil
|
return "secret", nil
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -174,6 +197,7 @@ func TestPAM_007(t *testing.T) {
|
|||||||
tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) {
|
tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) {
|
||||||
return "", errors.New("Sorry, it didn't work")
|
return "", errors.New("Sorry, it didn't work")
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -256,6 +280,7 @@ func TestPAM_ConfDir_InfoMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
return "", errors.New("unexpected")
|
return "", errors.New("unexpected")
|
||||||
}), "test-services")
|
}), "test-services")
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -272,6 +297,7 @@ func TestPAM_ConfDir_InfoMessage(t *testing.T) {
|
|||||||
func TestPAM_ConfDir_Deny(t *testing.T) {
|
func TestPAM_ConfDir_Deny(t *testing.T) {
|
||||||
u, _ := user.Current()
|
u, _ := user.Current()
|
||||||
tx, err := StartConfDir("deny-service", u.Username, Credentials{}, "test-services")
|
tx, err := StartConfDir("deny-service", u.Username, Credentials{}, "test-services")
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -296,6 +322,7 @@ func TestPAM_ConfDir_PromptForUserName(t *testing.T) {
|
|||||||
Password: "wrongsecret",
|
Password: "wrongsecret",
|
||||||
}
|
}
|
||||||
tx, err := StartConfDir("succeed-if-user-test", "", c, "test-services")
|
tx, err := StartConfDir("succeed-if-user-test", "", c, "test-services")
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if !CheckPamHasStartConfdir() {
|
if !CheckPamHasStartConfdir() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -319,6 +346,7 @@ func TestPAM_ConfDir_WrongUserName(t *testing.T) {
|
|||||||
Password: "wrongsecret",
|
Password: "wrongsecret",
|
||||||
}
|
}
|
||||||
tx, err := StartConfDir("succeed-if-user-test", "", c, "test-services")
|
tx, err := StartConfDir("succeed-if-user-test", "", c, "test-services")
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if !CheckPamHasStartConfdir() {
|
if !CheckPamHasStartConfdir() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -344,6 +372,7 @@ func TestItem(t *testing.T) {
|
|||||||
tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) {
|
tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -382,6 +411,7 @@ func TestEnv(t *testing.T) {
|
|||||||
tx, err := StartFunc("", "", func(s Style, msg string) (string, error) {
|
tx, err := StartFunc("", "", func(s Style, msg string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
})
|
})
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -525,6 +555,7 @@ func Test_Error(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tx, err := StartConfDir(serviceName, "user", c, servicePath)
|
tx, err := StartConfDir(serviceName, "user", c, servicePath)
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
defer maybeEndTransaction(t, tx)
|
defer maybeEndTransaction(t, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("start #error: %v", err)
|
t.Fatalf("start #error: %v", err)
|
||||||
@@ -558,6 +589,25 @@ func Test_Error(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Finalizer(t *testing.T) {
|
||||||
|
if !CheckPamHasStartConfdir() {
|
||||||
|
t.Skip("this requires PAM with Conf dir support")
|
||||||
|
}
|
||||||
|
|
||||||
|
func() {
|
||||||
|
tx, err := StartConfDir("permit-service", "", nil, "test-services")
|
||||||
|
ensureTransactionEnds(t, tx)
|
||||||
|
defer maybeEndTransaction(t, tx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("start #error: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
runtime.GC()
|
||||||
|
// sleep to switch to finalizer goroutine
|
||||||
|
time.Sleep(5 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFailure_001(t *testing.T) {
|
func TestFailure_001(t *testing.T) {
|
||||||
tx := Transaction{}
|
tx := Transaction{}
|
||||||
_, err := tx.GetEnvList()
|
_, err := tx.GetEnvList()
|
||||||
|
|||||||
Reference in New Issue
Block a user