bastion 0.53.2
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
// stepupApproveRequest spends a code only when the approval actually lands
|
||||
// (stepupIssueLocked): a request answered meanwhile, or a store that cannot be
|
||||
// written, leaves the code good for the person's next try. Every value here is
|
||||
// invented.
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestACodeIsNotSpentWhenTheApprovalCannotBeSaved(t *testing.T) {
|
||||
dir, idA, _, _, _ := pipeBox(t)
|
||||
code := pipeCodeNow()
|
||||
// approvals.json cannot be written: a directory stands where it goes.
|
||||
blocker := approvalsPath(dir)
|
||||
if err := os.MkdirAll(filepath.Join(blocker, "x"), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := stepupApproveRequest(dir, idA, code); err == nil {
|
||||
t.Fatal("the approval could not be saved, yet the approve succeeded")
|
||||
}
|
||||
if r := stateOf(t, dir, idA); r.State != "pending" {
|
||||
t.Fatalf("the request is %s after a failed approve; it must still be pending", r.State)
|
||||
}
|
||||
if err := os.RemoveAll(blocker); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The same code, the next moment: it was never spent.
|
||||
if _, err := stepupApproveRequest(dir, idA, code); err != nil {
|
||||
t.Fatalf("the person's code was spent by an approve that did not land: %v", err)
|
||||
}
|
||||
if r := stateOf(t, dir, idA); r.State != "approved" || r.Approval == "" {
|
||||
t.Fatalf("not approved: %+v", r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestACodeIsNotSpentWhenTheRequestIsDeniedMeanwhile(t *testing.T) {
|
||||
dir, idA, _, idB, _ := pipeBox(t)
|
||||
code := pipeCodeNow()
|
||||
// Another process (the service, a terminal) denies A between the code
|
||||
// check and the approval landing: it shares the files, not the lock.
|
||||
stepupLandingHook = func() {
|
||||
m := requestsLoad(dir)
|
||||
r := m[idA]
|
||||
r.State = "denied"
|
||||
m[idA] = r
|
||||
if err := requestsSave(dir, m); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
t.Cleanup(func() { stepupLandingHook = nil })
|
||||
_, err := stepupApproveRequest(dir, idA, code)
|
||||
if err == nil || !strings.Contains(err.Error(), "no longer pending") {
|
||||
t.Fatalf("a request denied meanwhile must not be approved: %v", err)
|
||||
}
|
||||
if r := stateOf(t, dir, idA); r.State != "denied" || r.Approval != "" {
|
||||
t.Fatalf("the deny must stand, with no approval on it: %+v", r)
|
||||
}
|
||||
if n := len(approvalsLoad(dir)); n != 0 {
|
||||
t.Fatalf("%d approval(s) stand for a request that was denied", n)
|
||||
}
|
||||
stepupLandingHook = nil
|
||||
// The code the person typed still works, here for the other request.
|
||||
if _, err := stepupApproveRequest(dir, idB, code); err != nil {
|
||||
t.Fatalf("the code was spent on an approval that did not land: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestACodeThatLandsIsSpent(t *testing.T) {
|
||||
dir, idA, _, idB, _ := pipeBox(t)
|
||||
code := pipeCodeNow()
|
||||
if _, err := stepupApproveRequest(dir, idA, code); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := stepupApproveRequest(dir, idB, code); err == nil || err.Error() != "code already used" {
|
||||
t.Fatalf("a code that approved one request must not approve another: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user