aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/sbbuilder/test_toml.js
blob: c86741d9e5c425bcf8efc05abba7de6f51127a56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// Run: node desktop/modules/sbbuilder/test_toml.js
// Toml.js is a QML library, so its .pragma line is stripped before node
// evaluates it.

const fs = require("fs");
const assert = require("assert");

const src = fs.readFileSync(__dirname + "/Toml.js", "utf8")
    .replace(/^\.pragma library$/m, "");
const T = new Function(src + "\nreturn { sections, entries, get, set, remove };")();

const file = [
    "# helper config",
    "# Every key is optional.",
    "",
    'state_dir       = "/var/lib/x"',
    'overlays        = ["one", "two"]   # searched in order',
    "# upstream_branch = 'current'",
    "",
    "# bundled deps: package = its deps list URL",
    "[manifests]",
    'neovim = "https://example.org/v{VERSION}/deps.txt"',
    '"gtk+3" = "https://example.org/gtk"',
    "",
    "[refresh]",
    "jobs = 5",
    "on = true",
    "",
].join("\n");

// Top-level keys are section "".
assert.strictEqual(T.get(file, "", "state_dir"), "/var/lib/x");
assert.deepStrictEqual(T.get(file, "", "overlays"), ["one", "two"]);
assert.strictEqual(T.get(file, "", "upstream_branch"), undefined);
assert.strictEqual(T.get(file, "refresh", "jobs"), 5);
assert.strictEqual(T.get(file, "refresh", "on"), true);
// A quoted key reads unquoted; a commented line with = is not a key.
assert.deepStrictEqual(T.entries(file, "manifests").map(e => e.key), ["neovim", "gtk+3"]);
assert.deepStrictEqual(T.entries(file, "").map(e => e.key), ["state_dir", "overlays"]);

// Replacing keeps the padding-free form, the inline comment and the line count.
let t = T.set(file, "", "overlays", ["a"]);
assert.strictEqual(t.split("\n")[4], 'overlays = ["a"]   # searched in order');
assert.strictEqual(t.split("\n").length, file.split("\n").length);
// Setting a commented key activates its line, single-quoted or not.
t = T.set(file, "", "upstream_branch", "main");
assert.strictEqual(t.split("\n")[5], 'upstream_branch = "main"');
// Unsetting comments a key out in place, and it reads back as unset.
t = T.set(file, "refresh", "jobs", null);
assert.strictEqual(t.split("\n")[13], "# jobs = 5");
assert.strictEqual(T.get(t, "refresh", "jobs"), undefined);
// ...and setting it again reactivates that line.
assert.strictEqual(T.set(t, "refresh", "jobs", 9).split("\n")[13], "jobs = 9");
// A new top-level key lands after the last top-level key, not after the
// [manifests] comment, which belongs to its section.
t = T.set(file, "", "genreprc", "/root/.genreprc");
assert.strictEqual(t.split("\n")[5], 'genreprc = "/root/.genreprc"');
assert.strictEqual(T.get(t, "", "genreprc"), "/root/.genreprc");
// A new key in a file with only comments goes after the leading comments.
t = T.set("# head\n# more\n", "", "x", 1);
assert.strictEqual(t, "# head\n# more\nx = 1\n");
// A new key in a section lands after that section's last key.
t = T.set(file, "manifests", "foo.bar", "u");
assert.strictEqual(t.split("\n")[11], '"foo.bar" = "u"');
assert.strictEqual(T.get(t, "manifests", "foo.bar"), "u");
// A missing section is appended, and an empty file gets no blank lead.
t = T.set(file, "vm", "domain", "x");
assert.ok(t.endsWith('\n\n[vm]\ndomain = "x"\n'), JSON.stringify(t));
assert.strictEqual(T.set("", "vm", "autostart", false), "[vm]\nautostart = false\n");
assert.strictEqual(T.set("", "", "target", "h"), 'target = "h"\n');
// Strings are escaped and read back the same.
t = T.set(file, "", "state_dir", 'a "b" \\ c');
assert.strictEqual(T.get(t, "", "state_dir"), 'a "b" \\ c');
// The same key in another section is untouched.
assert.strictEqual(T.set("[a]\nx = 1\n\n[b]\nx = 2\n", "b", "x", 3), "[a]\nx = 1\n\n[b]\nx = 3\n");
// A value spanning lines is refused, never duplicated.
assert.throws(() => T.set("o = [\n  \"a\",\n]\n", "", "o", ["b"]), /cannot edit/);
// A value followed by junk is refused too: a multi-line string opens with
// an empty one, and trailing text is no comment.
assert.throws(() => T.set('x = """\nabc\n"""\n', "", "x", "n"), /cannot edit/);
assert.throws(() => T.set('x = "a" junk\n', "", "x", "n"), /cannot edit/);
assert.strictEqual(T.get('x = "a" junk\n', "", "x"), undefined);

// remove deletes the line outright.
t = T.remove(file, "manifests", "gtk+3");
assert.deepStrictEqual(T.entries(t, "manifests").map(e => e.key), ["neovim"]);
assert.strictEqual(T.remove(file, "manifests", "nope"), file);

// sections tells a missing table from an empty one, which entries cannot.
assert.deepStrictEqual(T.sections(file), ["manifests", "refresh"]);
assert.deepStrictEqual(T.sections("a = 1\n[manifests]\n"), ["manifests"]);
assert.deepStrictEqual(T.sections("a = 1\n"), []);

console.log("test_toml: ok");