The user.js answer carried declared addresses and hosts (ADR 0316 §16). An adopted identity's outgoing server may be shared with an account the module does not own, whose sending the declared values would change at every start: refused with the remedy, since ADR 0317 §2 leaves the identity's server and the lists as they are; a recorded adoption follows the identity's current server. Owl installed by policy cannot be removed, so a newer Owl than the pin is a fact whose remedy is moving the pin.
175 lines
6.8 KiB
Go
175 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/zip"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// What the mesh installs, as the tools say it (novox/hq ADR 0316 §16): the version against the pin and the
|
|
// newest published build, the policy, Owl against its pin; and the reminder test, visibly a test.
|
|
|
|
func (f *fake) xpi(path, version string) {
|
|
f.t.Helper()
|
|
full := filepath.Join(f.Root, path)
|
|
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
|
|
f.t.Fatal(err)
|
|
}
|
|
out, err := os.Create(full)
|
|
if err != nil {
|
|
f.t.Fatal(err)
|
|
}
|
|
w := zip.NewWriter(out)
|
|
m, _ := w.Create("manifest.json")
|
|
m.Write([]byte(`{"version": "` + version + `", "browser_specific_settings": {"gecko": {"id": "owl@beonex.com"}}}`))
|
|
w.Close()
|
|
out.Close()
|
|
}
|
|
|
|
// placedByTheMesh is a node after the switch: the release, the policy and Owl's xpi in /opt/betterbird, and
|
|
// the profile running Owl at the pin.
|
|
func (f *fake) placedByTheMesh() {
|
|
f.noPackage()
|
|
f.write(appIni, "[App]\nVendor=Betterbird Project\nVersion=153.4.0\nBuildID=20260929222610\n")
|
|
raw, err := os.ReadFile(filepath.Join("..", "..", "install", "distribution", "policies.json"))
|
|
if err != nil {
|
|
f.t.Fatal(err)
|
|
}
|
|
f.write(policyFile, string(raw))
|
|
f.xpi(owlFile, "1.5.6.1")
|
|
f.write(profileDir+"/extensions.json", `{"addons":[{"id":"owl@beonex.com","version":"1.5.6.1","active":true,"location":"app-profile"}]}`)
|
|
}
|
|
|
|
func TestTheStatusSaysTheInstallationAgainstThePinTheNewestBuildThePolicyAndOwl(t *testing.T) {
|
|
f := newFake(t)
|
|
f.betterbird()
|
|
f.placedByTheMesh()
|
|
links(t, nil)
|
|
publishedBuilds = func() (string, error) {
|
|
return "blocklist,{}\nLinux,153,20261101000000\nLinux,140,20260829111240\n", nil
|
|
}
|
|
t.Cleanup(func() { publishedBuilds = func() (string, error) { return "", os.ErrDeadlineExceeded } })
|
|
s, err := f.Status()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
in := s.Installation
|
|
if in.From != "the mesh" || in.Version != "153.4.0" || in.Newest != "20261101000000" || !in.Behind ||
|
|
!strings.HasPrefix(in.Policy, "placed:") || in.Owl == nil || in.Owl.Pinned != "1.5.6.1" || !in.Owl.AtThePin || !in.Owl.Active {
|
|
t.Fatalf("%+v %+v", in, in.Owl)
|
|
}
|
|
c, err := f.Check()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
found := false
|
|
for _, x := range c.Findings {
|
|
found = found || strings.Contains(x.What, "behind the newest published build 20261101000000")
|
|
}
|
|
if !found {
|
|
t.Fatalf("a release left behind is said: %+v", c.Findings)
|
|
}
|
|
}
|
|
|
|
func TestTheCommunityPackageAPolicyThatIsNotTheModulesAndAnOwlOffItsPinAreSaid(t *testing.T) {
|
|
f := newFake(t)
|
|
f.betterbird()
|
|
f.placedByTheMesh()
|
|
links(t, nil)
|
|
f.write(policyFile, `{"policies": {"ExtensionSettings": {"owl@beonex.com": {"installation_mode": "force_installed",
|
|
"install_url": "https://vendor.example/owl.xpi", "updates_disabled": true}}}}`)
|
|
f.write(profileDir+"/extensions.json", `{"addons":[{"id":"owl@beonex.com","version":"1.5.7","active":true,"location":"app-profile"}]}`)
|
|
in := f.installation(filepath.Join(f.Root, profileDir))
|
|
if !strings.Contains(in.Policy, "DisableAppUpdate") || in.Owl.AtThePin || in.Owl.InProfile != "1.5.7" {
|
|
t.Fatalf("%+v %+v", in, in.Owl)
|
|
}
|
|
// A newer Owl than the pin is a fact with the real remedy, never a finding to remove it.
|
|
if !strings.Contains(in.Owl.Note, "move the module's pin") {
|
|
t.Fatalf("%+v", in.Owl)
|
|
}
|
|
f.write(policyFile, `{"policies": {"DisableAppUpdate": true, "ExtensionSettings": {"owl@beonex.com": {"installation_mode": "force_installed",
|
|
"install_url": "file:///opt/betterbird/owl/owl.xpi", "updates_disabled": true}}}}`)
|
|
c, _ := f.Check()
|
|
for _, x := range c.Findings {
|
|
if strings.Contains(x.What, "Owl") {
|
|
t.Errorf("a newer Owl is not a finding: %+v", x)
|
|
}
|
|
}
|
|
f.write(profileDir+"/extensions.json", `{"addons":[{"id":"owl@beonex.com","version":"1.5.5","active":true,"location":"app-profile"}]}`)
|
|
c, _ = f.Check()
|
|
found := false
|
|
for _, x := range c.Findings {
|
|
found = found || (strings.Contains(x.What, "older than the mesh's pin") && strings.Contains(x.Do, "move the module's Owl pin"))
|
|
}
|
|
if !found {
|
|
t.Fatalf("an older Owl is a finding whose remedy is the pin: %+v", c.Findings)
|
|
}
|
|
f.write(policyFile, `{"policies": {"DisableAppUpdate": true, "ExtensionSettings": {"owl@beonex.com": {"installation_mode": "force_installed",
|
|
"install_url": "https://vendor.example/owl.xpi", "updates_disabled": true}}}}`)
|
|
if in := f.installation(""); !strings.Contains(in.Policy, "not from the mesh's xpi") {
|
|
t.Fatalf("%s", in.Policy)
|
|
}
|
|
f.answer = func(name string, args []string) Output {
|
|
if name == "pacman" && args[0] == "-Q" {
|
|
return Output{Stdout: "betterbird-bin 153.1.0esr-1\n"}
|
|
}
|
|
return Output{}
|
|
}
|
|
in = f.installation("")
|
|
if !strings.HasPrefix(in.From, "the community package betterbird-bin 153.1.0esr-1") || !strings.Contains(in.From, "operator") {
|
|
t.Fatalf("%s", in.From)
|
|
}
|
|
raw, _ := json.Marshal(in)
|
|
if strings.Contains(string(raw), "example.org") {
|
|
t.Fatalf("%s", raw)
|
|
}
|
|
}
|
|
|
|
func TestTheReminderTestIsVisiblyATestAndSaysItOpensAWindow(t *testing.T) {
|
|
f := newFake(t)
|
|
f.desktopSession()
|
|
f.betterbird()
|
|
links(t, nil)
|
|
f.declare("// none")
|
|
f.declareAccounts(personal)
|
|
a, err := f.ReminderTest(40*time.Second, nil, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
dir := filepath.Join("/run/user/1000", testUnit)
|
|
css := f.read(dir + "/profile/chrome/userChrome.css")
|
|
user := f.read(dir + "/profile/user.js")
|
|
cal := f.read(dir + "/test.ics")
|
|
if !strings.Contains(css, "MESH TEST") || !strings.Contains(css, `:root:not([windowtype="Calendar:AlarmWindow"])`) {
|
|
t.Fatalf("the test's windows but the reminder carry a MESH TEST band: %s", css)
|
|
}
|
|
if !strings.Contains(user, `user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);`) ||
|
|
strings.Contains(user, "mesh_personal") || strings.Contains(user, "example.org") {
|
|
t.Fatalf("the test profile reads its userChrome.css and holds no declared account: %s", user)
|
|
}
|
|
if !strings.Contains(cal, "SUMMARY:MESH TEST reminder") || !strings.Contains(a.OnScreen, "operator's screen") {
|
|
t.Fatalf("the event and the answer say it is a test on the operator's screen: %s %+v", cal, a)
|
|
}
|
|
if !f.called("systemd-run --user --collect --quiet --unit="+testUnit) || !strings.Contains(strings.Join(f.calls, "\n"), startBin+" --no-remote") {
|
|
t.Fatalf("the test starts Betterbird itself, never the module's start: %v", f.calls)
|
|
}
|
|
for _, tool := range tools() {
|
|
if tool.Name == "betterbird_reminder_test" && !strings.HasPrefix(tool.Description, "OPENS WINDOWS ON THE OPERATOR'S SCREEN") {
|
|
t.Fatalf("the description says first that a window opens on the operator's screen: %s", tool.Description)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTheUserJSDescriptionSaysAdoption(t *testing.T) {
|
|
for _, tool := range tools() {
|
|
if tool.Name == "betterbird_user_js" && (!strings.Contains(tool.Description, "adopted under its own keys") ||
|
|
strings.Contains(tool.Description, "refuses the apply")) {
|
|
t.Fatalf("%s", tool.Description)
|
|
}
|
|
}
|
|
}
|