Slack comes from the AUR and Toolbox from JetBrains' self-updating tarball, so neither is declared: the host installs official packages only, and a pinned archive would fight Toolbox's own updates. Slack's start and the operator's i3 window rules become one node-display-session contribution, because Slack's own launch-on-login is a symlink in ~/.config/autostart. Toolbox keeps its own autostart entry as its one start. The shared desktop.go header now names all four bundles.
97 lines
3.2 KiB
Go
97 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// jetbrains-toolbox's shape (novox/hq ADR 0205, ADR 0208, ADR 0182): Toolbox is kept as found, so no
|
|
// package, no archive, no file and no start of the module's own (Toolbox writes its own autostart
|
|
// entry); the X display on its own machine; and the Go bundle serving exactly the listed toolbox_ tools.
|
|
|
|
type manifest struct {
|
|
Module string `json:"module"`
|
|
Version string `json:"version"`
|
|
Capabilities []string `json:"capabilities"`
|
|
Requires []string `json:"requires"`
|
|
Tools []string `json:"tools"`
|
|
Resources []map[string]any `json:"resources"`
|
|
Claims []any `json:"claims"`
|
|
Seats []any `json:"seats"`
|
|
Shell []any `json:"shell"`
|
|
Contributions []any `json:"contributions"`
|
|
Environment any `json:"environment"`
|
|
Build struct {
|
|
Artifacts []map[string]any `json:"artifacts"`
|
|
} `json:"build"`
|
|
}
|
|
|
|
func readManifest(t *testing.T) (manifest, string) {
|
|
t.Helper()
|
|
raw, err := os.ReadFile(filepath.Join("..", "..", "module.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
dec := json.NewDecoder(strings.NewReader(string(raw)))
|
|
dec.DisallowUnknownFields()
|
|
var m manifest
|
|
if err := dec.Decode(&m); err != nil {
|
|
t.Fatalf("module.json: %v", err)
|
|
}
|
|
return m, string(raw)
|
|
}
|
|
|
|
func TestItKeepsToolboxAsFound(t *testing.T) {
|
|
m, _ := readManifest(t)
|
|
if m.Module != "jetbrains-toolbox" || !reflect.DeepEqual(m.Requires, []string{"x11-display"}) {
|
|
t.Fatalf("%+v", m)
|
|
}
|
|
// Toolbox replaces its own files when it updates itself: a package, an archive or a file of the
|
|
// module's in its directory would be a second writer.
|
|
if m.Resources != nil || m.Capabilities != nil {
|
|
t.Fatalf("no package, no archive, no file: %v %v", m.Resources, m.Capabilities)
|
|
}
|
|
// Its own autostart entry is its one start: a contribution or a session slot would be a second.
|
|
if m.Claims != nil || m.Seats != nil || m.Environment != nil || m.Shell != nil || m.Contributions != nil {
|
|
t.Fatal("it holds no seat, sets no environment and adds no start")
|
|
}
|
|
}
|
|
|
|
func TestTheToolsAgreeWithTheManifest(t *testing.T) {
|
|
m, raw := readManifest(t)
|
|
served := map[string]bool{}
|
|
for _, tool := range tools() {
|
|
served[tool.Name] = true
|
|
if !strings.HasPrefix(tool.Name, "toolbox_") || strings.TrimSpace(tool.Description) == "" {
|
|
t.Errorf("%s: prefixed toolbox_ and described", tool.Name)
|
|
}
|
|
}
|
|
for _, name := range m.Tools {
|
|
if !served[name] {
|
|
t.Errorf("module.json lists %s, which the bundle does not serve", name)
|
|
}
|
|
delete(served, name)
|
|
}
|
|
for name := range served {
|
|
t.Errorf("the bundle serves %s, which module.json does not list", name)
|
|
}
|
|
if len(m.Build.Artifacts) != 1 {
|
|
t.Fatalf("%v", m.Build.Artifacts)
|
|
}
|
|
b := m.Build.Artifacts[0]
|
|
if b["kind"] != "bundle" || b["language"] != "go" || b["system"] != "arch" ||
|
|
b["from"] != "cmd/toolbox-tools" || b["binary"] != "toolbox-tools" {
|
|
t.Errorf("the Go tools bundle: %v", b)
|
|
}
|
|
s := strings.ToLower(raw)
|
|
for _, never := range []string{"/home/", "jochen", "g14", "shanks", "novox.be", "http", "password", "token"} {
|
|
if strings.Contains(s, never) {
|
|
t.Errorf("module.json names %q", never)
|
|
}
|
|
}
|
|
}
|