package api
import (
"os"
"strings"
"testing"
)
func srcOf(t *testing.T, name string) string {
t.Helper()
b, err := os.ReadFile(name)
if err != nil {
t.Fatal(err)
}
return string(b)
}
// An omitted switch is unchanged, not off.
//
// bucketPolicyIn carried plain bools and SetBucketPolicy was handed
// them directly, so a caller who sent {"archives": true} and omitted
// the other switch turned delete-on-removal OFF without asking, and an
// empty body turned both off and answered 200. That is dc748de1's
// shape — a partial write clearing what it was not told about — which
// repo.update had already been fixed for with pointers and this op had
// not.
//
// Found while checking that a bucket can be bound through the API at
// all: the probe for "is this op even reachable" was an empty POST to
// it, and the empty POST succeeded.
//
// Asserted in source because the defect is structural and the harness
// binds no bucket: the input must carry POINTERS, and the Run must
// read the current binding before applying what it was told.
func TestThePolicyOpReadsBeforeItWrites(t *testing.T) {
src := srcOf(t, "attachwrite.go")
for _, want := range []string{
"Archives *bool `json:\"archives\"`",
"DeleteObjects *bool `json:\"deleteObjects\"`",
"archives, deleteObjects := cur.Archives, cur.DeleteObjects",
"if in.Archives != nil {",
"if in.DeleteObjects != nil {",
} {
if !strings.Contains(src, want) {
t.Errorf("FAIL: bucket.policy is missing %q; an omitted switch will be written "+
"as false and clear what the caller never mentioned", want)
}
}
if strings.Contains(src, "SetBucketPolicy(in.Repo, in.Archives, in.DeleteObjects)") {
t.Error("FAIL: bucket.policy still passes its input straight through, so an empty " +
"body clears both switches")
}
}
// And the HTML form still names BOTH switches, which is correct and is
// what makes the pointers safe.
//
// A form knows its whole state, so it sends every switch and an
// unchecked box is an explicit false. An API caller may know only one
// field, so it may name only one. If the form ever stopped sending
// both, an unchecked box would read as "unchanged" and a switch could
// never be turned off from the page.
func TestTheSettingsFormStillNamesBothSwitches(t *testing.T) {
src := srcOf(t, "../web/web.go")
for _, want := range []string{
`"archives": {strconv.FormatBool(req.FormValue("archives") != "")}`,
`"deleteObjects": {strconv.FormatBool(req.FormValue("deleteObjects") != "")}`,
} {
if !strings.Contains(src, want) {
t.Errorf("FAIL: the settings form no longer sends %s explicitly; with pointers "+
"an unchecked box would read as unchanged and the switch could not be "+
"turned off from the page", want)
}
}
}