transaction: Add a test finalizer checking if transaction has ended

Check if a transaction is ended in in tests.
This commit is contained in:
Marco Trevisan (Treviño)
2023-10-11 23:09:04 +02:00
parent c635cfc38a
commit c7ecbf20dc
2 changed files with 52 additions and 1 deletions

View File

@@ -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))

View File

@@ -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()