summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-03-25 06:42:35 -0300
committerEuAndreh <eu@euandre.org>2024-03-25 06:44:18 -0300
commit077b81b2bd2c0d418635b265b35f582d68cec16a (patch)
treeed3c928ea3b1d5df539b6e1902ab418caa937672
parentsrc/hero.mjs: Retire code (diff)
downloadpapod-077b81b2bd2c0d418635b265b35f582d68cec16a.tar.gz
papod-077b81b2bd2c0d418635b265b35f582d68cec16a.tar.xz
Node.js -> Go
-rw-r--r--.gitignore7
-rw-r--r--Makefile56
-rw-r--r--deps.mk26
-rw-r--r--doc/papo.en.3go.in (renamed from doc/papo.en.3js.in)0
-rw-r--r--go.mod5
-rw-r--r--go.sum2
-rwxr-xr-xmkdeps.sh8
-rw-r--r--src/accretion.mjs42
-rw-r--r--src/api.mjs20
-rwxr-xr-xsrc/bin.mjs4
-rw-r--r--src/cmd/papo.go28
-rw-r--r--src/db.mjs57
-rw-r--r--src/escape.mjs14
-rw-r--r--src/ircd.mjs19
-rw-r--r--src/package.json3
-rw-r--r--src/papo.go8
-rw-r--r--src/sqlite.cjs1
-rw-r--r--src/utils.mjs105
-rw-r--r--src/web.mjs38
-rw-r--r--tests/js/accretion.mjs48
-rw-r--r--tests/js/db.mjs110
-rw-r--r--tests/js/escape.mjs65
-rw-r--r--tests/js/ircd.mjs6
-rw-r--r--tests/js/rand.mjs96
-rw-r--r--tests/js/utils.mjs474
-rw-r--r--tests/js/web.mjs6
-rw-r--r--tests/lighttpd.conf35
-rw-r--r--tests/papo_test.go14
-rw-r--r--tests/rand.c83
-rw-r--r--tests/rand.mjs55
-rw-r--r--tests/runner.mjs31
31 files changed, 99 insertions, 1367 deletions
diff --git a/.gitignore b/.gitignore
index 2c28a19..b03deb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
-/doc/*.[0-9]
-/doc/*.3js
-/tests/hero-mkfifo-0.pipe
+/*.bin
/tests/*.bin
-/tests/bigger-rand-output.txt
+/doc/*.[0-9]
+/doc/*.3go
diff --git a/Makefile b/Makefile
index 6ea0735..78b1ca7 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ DESTDIR =
.SUFFIXES:
-.SUFFIXES: .in .c .bin
+.SUFFIXES: .in .go .bin .bin-check
.in:
sed \
@@ -34,14 +34,17 @@ DESTDIR =
< $< > $@
if [ -x $< ]; then chmod +x $@; fi
-.c.bin:
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
+.go.bin:
+ CGO_ENABLED=0 go test -c -o $@ -v \
+ -ldflags='-s -w -extldflags "-static"' $<
all:
include deps.mk
+tests.bin = $(tests.go:.go=.bin)
+
manpages = $(manpages.in:.in=)
sources = \
@@ -56,16 +59,14 @@ installable = \
derived-assets = \
$(manpages) \
- tests/rand.bin \
- tests/bigger-rand-output.txt \
+ main.bin \
+ $(tests.bin) \
side-assets = \
- tests/hero-*.pipe \
- tests/hero-*.socket \
- web.pipe \
+ ircd.pipe \
lighttpd.socket \
ircd.socket \
- web.socket \
+ wscat.socket \
@@ -73,22 +74,20 @@ side-assets = \
## and installation.
all: $(derived-assets)
-tests/bigger-rand-output.txt: tests/rand.bin
- printf '[\n\t%s\n]\n' \
- "`./$? | tr '\n' ',' | sed -e 's|,$$||' -e 's|,|,\n\t|g'`" > $@
-
-tests/rand.bin $(manpages): Makefile deps.mk
-tests/js/rand.mjs-check: tests/bigger-rand-output.txt
+main.bin: ALWAYS
+ CGO_ENABLED=0 go build -o $@ -v \
+ -ldflags='-s -w -extldflags "-static"' src/cmd/papo.go
+
+$(tests.bin): ALWAYS
-.SUFFIXES: .mjs .mjs-check
-tests.mjs-check = $(tests.mjs:.mjs=.mjs-check)
-$(tests.mjs-check):
- node $*.mjs
+tests.bin-check = $(tests.go:.go=.bin-check)
+$(tests.bin-check):
+ ./$*.bin
-check-unit: $(tests.mjs-check)
+check-unit: $(tests.bin-check)
integration-tests = \
@@ -129,7 +128,7 @@ install: all
mkdir -p "$$dir"; \
cp -P "$$f" "$$dir"; \
done
- sh tools/manpages.sh -ip '$(DESTDIR)$(MANDIR)' $(manpages)
+ doctool -ip '$(DESTDIR)$(MANDIR)' $(manpages)
## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror
## of the "install" target, and removes *all* that was installed.
@@ -139,14 +138,14 @@ uninstall:
'$(DESTDIR)$(BINDIR)'/$(NAME) \
'$(DESTDIR)$(JSLIBDIR)' \
'$(DESTDIR)$(SRCDIR)'
- sh tools/manpages.sh -up '$(DESTDIR)$(MANDIR)' $(manpages)
+ doctool -up '$(DESTDIR)$(MANDIR)' $(manpages)
run-ircd: all
./src/bin.mjs ircd ircd.socket
-run-web: all
- ./src/bin.mjs web web.socket web.pipe
+run-wscat: all
+ websockify --unix-listen=wscat.socket --unix-target=ircd.socket
run-proxy: all
lighttpd -Df tests/lighttpd.conf
@@ -154,17 +153,12 @@ run-proxy: all
run-binder: all
socat tcp-listen:6001,fork,reuseaddr unix:lighttpd.socket
-## Run the web and IRC server locally.
+## Run the IRC server locally and its helper programs.
run: all
- for c in ircd web proxy binder; do \
+ for c in ircd wscat proxy binder; do \
$(MAKE) run-$$c & \
done; \
wait
-## Show this help.
-help:
- sh tools/makehelp.sh < Makefile
-
-
ALWAYS:
diff --git a/deps.mk b/deps.mk
index df8aa4f..7cf1f0e 100644
--- a/deps.mk
+++ b/deps.mk
@@ -1,30 +1,20 @@
-sources.mjs = \
- src/accretion.mjs \
- src/api.mjs \
- src/bin.mjs \
- src/db.mjs \
- src/escape.mjs \
- src/ircd.mjs \
- src/utils.mjs \
- src/web.mjs \
+sources.go = \
+ src/papo.go \
-tests.mjs = \
- tests/js/accretion.mjs \
- tests/js/db.mjs \
- tests/js/escape.mjs \
- tests/js/ircd.mjs \
- tests/js/rand.mjs \
- tests/js/utils.mjs \
- tests/js/web.mjs \
+tests.go = \
+ tests/papo_test.go \
sources.sql = \
src/sql/migrations/2023-11-16T15:46:27-03:00-init-auth-data.sql \
manpages.en.in = \
doc/papo.en.1.in \
- doc/papo.en.3js.in \
+ doc/papo.en.3go.in \
doc/papo.recipes.en.7.in \
doc/papo.tutorial.en.7.in \
doc/papo.why.en.7.in \
manpages.in = $(manpages.en.in)
+
+
+tests/papo_test.bin-check: tests/papo_test.bin
diff --git a/doc/papo.en.3js.in b/doc/papo.en.3go.in
index e69de29..e69de29 100644
--- a/doc/papo.en.3js.in
+++ b/doc/papo.en.3go.in
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..8f00f40
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module euandre.org/papo
+
+go 1.21.5
+
+require github.com/mattn/go-sqlite3 v1.14.22 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..e8d092a
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
diff --git a/mkdeps.sh b/mkdeps.sh
index 954c62b..f174689 100755
--- a/mkdeps.sh
+++ b/mkdeps.sh
@@ -8,9 +8,13 @@ varlist() {
}
export LANG=POSIX.UTF-8
-find src/*.mjs | sort | varlist 'sources.mjs'
-find tests/js/*.mjs | sort | varlist 'tests.mjs'
+find src/*.go | sort | varlist 'sources.go'
+find tests/*_test.go | sort | varlist 'tests.go'
find src/sql/migrations/*.sql | sort | varlist 'sources.sql'
find doc/*.en.*.in | sort | varlist 'manpages.en.in'
echo 'manpages.in = $(manpages.en.in)'
+printf '\n\n'
+
+
+find tests/*_test.go | sort | sed 's|^\(.*\)\.go$|\1.bin-check:\t\1.bin|'
diff --git a/src/accretion.mjs b/src/accretion.mjs
deleted file mode 100644
index dd3372c..0000000
--- a/src/accretion.mjs
+++ /dev/null
@@ -1,42 +0,0 @@
-import assert from "node:assert/strict";
-import fs from "node:fs";
-import path from "node:path";
-import url from "node:url";
-
-import sqlite from "./sqlite.cjs";
-
-import * as u from "./utils.mjs";
-
-
-const DIRNAME = path.dirname(url.fileURLToPath(import.meta.url));
-export const MIGRATIONS_DIR = DIRNAME + "/sql/migrations/";
-
-export const runMigrations = async (logFn, db) => {
- assert(db);
-
- await db.exec(`
- BEGIN TRANSACTION;
- CREATE TABLE IF NOT EXISTS migrations (
- filename TEXT NOT NULL PRIMARY KEY
- );
- COMMIT TRANSACTION;
- `);
-
- const done = [...(await db.all("SELECT filename FROM migrations;"))]
- .map(row => row.filename);
- const allFiles = fs.readdirSync(MIGRATIONS_DIR, "UTF-8");
- const pending = u.difference(new Set(allFiles), new Set(done));
- const sortedPending = [...pending].sort(u.strSortFn);
-
- for (const filename of sortedPending) {
- logFn({ log: "exec-migration", filename });
- const sql = fs.readFileSync(MIGRATIONS_DIR + filename, "UTF-8");
- await db.exec("BEGIN TRANSACTION;");
- await db.exec(sql);
- await db.run(
- "INSERT INTO migrations (filename) VALUES ($filename);",
- { $filename: filename },
- );
- await db.exec("COMMIT TRANSACTION;")
- }
-};
diff --git a/src/api.mjs b/src/api.mjs
deleted file mode 100644
index 31bb09e..0000000
--- a/src/api.mjs
+++ /dev/null
@@ -1,20 +0,0 @@
-import process from "node:process";
-
-import * as ircd from "./ircd.mjs";
-import * as web from "./web.mjs";
-
-const SUBCOMMANDS = {
- ircd: ircd.app,
- web: web.app,
-};
-
-export const main = async () => {
- const [_node, _file, cmdName, ...args] = process.argv;
- const cmd = SUBCOMMANDS[cmdName];
- if (cmd === undefined) {
- console.error("Usage: papo SUBCOMMAND [OPTIONS]");
- return process.exit(2);
- }
-
- await cmd(...args);
-};
diff --git a/src/bin.mjs b/src/bin.mjs
deleted file mode 100755
index e79904f..0000000
--- a/src/bin.mjs
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env node
-import * as api from "./api.mjs";
-
-api.main();
diff --git a/src/cmd/papo.go b/src/cmd/papo.go
new file mode 100644
index 0000000..301e4b0
--- /dev/null
+++ b/src/cmd/papo.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+ "os"
+
+ _ "github.com/mattn/go-sqlite3"
+ "euandre.org/papo/src"
+)
+
+
+func main() {
+ os.Remove("./foo.db")
+
+ db, err := sql.Open("sqlite3", "./foo.db")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ message := papo.Hello("Xablau")
+ fmt.Println(message)
+ fmt.Println(message)
+ message = papo.Hello("Xupliu")
+ fmt.Println(message)
+}
diff --git a/src/db.mjs b/src/db.mjs
deleted file mode 100644
index 7d6c6c5..0000000
--- a/src/db.mjs
+++ /dev/null
@@ -1,57 +0,0 @@
-import assert from "node:assert/strict";
-import fs from "node:fs";
-import path from "node:path";
-import process from "node:process";
-import url from "node:url";
-import util from "node:util";
-
-import sqlite from "./sqlite.cjs";
-
-import * as u from "./utils.mjs";
-import * as accretion from "./accretion.mjs";
-
-
-export const promisifyDb = dbHandle => ({
- ref: dbHandle,
- all: util.promisify((...args) => dbHandle.all(...args)),
- exec: util.promisify((...args) => dbHandle.exec(...args)),
- run: util.promisify((...args) => dbHandle.run(...args)),
- each: (...args) =>
- new Promise((resolve, reject) => {
- const cb = args[args.length - 1];
- dbHandle.each(
- ...args.slice(0, args.length - 1),
- (err, row) => err ? reject(err) : cb(row),
- (err, data) => err ? reject(err) : resolve(data),
- );
- }),
- prepare: (...args) =>
- new Promise((resolve, reject) => {
- const mkStmt = stmtRef => ({
- ref: stmtRef,
- run: util.promisify((...args) => stmtRef.run(...args)),
- finalize: util.promisify((...args) => stmtRef.finalize(...args)),
- });
- const ref = dbHandle.prepare(
- ...args,
- err => err ? reject(err) : resolve(mkStmt(ref)),
- );
- }),
-});
-
-export const open = (...args) =>
- new Promise((resolve, reject) => {
- const dbName = args[0];
- assert(dbName);
- const ref = promisifyDb(new sqlite.Database(
- ...args,
- err => err ? reject(err) : resolve(ref),
- ));
- });
-
-export let handle = null;
-
-export const init = async (logFn, dbName = process.env.PAPO_DB_PATH || ":memory:") => {
- handle = await open(dbName);
- await accretion.runMigrations(logFn, handle);
-};
diff --git a/src/escape.mjs b/src/escape.mjs
deleted file mode 100644
index 78e08f8..0000000
--- a/src/escape.mjs
+++ /dev/null
@@ -1,14 +0,0 @@
-const FROM = /[&<>'"]/g;
-
-const ESCAPES = {
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- "'": '&#39;',
- '"': '&quot;'
-};
-
-const mappingFn = c => ESCAPES[c];
-
-export const escape = s =>
- String.prototype.replace.call(s, FROM, mappingFn);
diff --git a/src/ircd.mjs b/src/ircd.mjs
deleted file mode 100644
index 1924350..0000000
--- a/src/ircd.mjs
+++ /dev/null
@@ -1,19 +0,0 @@
-import fs from "node:fs";
-import net from "node:net";
-
-import * as hero from "./hero.mjs";
-
-
-const server = net.createServer(socket => {
- socket.write("olar\r\n");
- socket.pipe(socket);
-});
-
-export const app = async path => {
- if (fs.existsSync(path)) {
- fs.unlinkSync(path);
- }
- server.listen(path, () => {
- hero.log.info({ type: "starting-server", path });
- });
-};
diff --git a/src/package.json b/src/package.json
deleted file mode 100644
index fb3cb61..0000000
--- a/src/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "main": "api.mjs"
-}
diff --git a/src/papo.go b/src/papo.go
new file mode 100644
index 0000000..d83ac58
--- /dev/null
+++ b/src/papo.go
@@ -0,0 +1,8 @@
+package papo
+
+import "fmt"
+
+func Hello(name string) string {
+ message := fmt.Sprintf("Hi, %v. Welcome!", name)
+ return message
+}
diff --git a/src/sqlite.cjs b/src/sqlite.cjs
deleted file mode 100644
index a1b8ab7..0000000
--- a/src/sqlite.cjs
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require("sqlite3");
diff --git a/src/utils.mjs b/src/utils.mjs
deleted file mode 100644
index a3b36b3..0000000
--- a/src/utils.mjs
+++ /dev/null
@@ -1,105 +0,0 @@
-import util from "node:util";
-
-
-export const eq = util.isDeepStrictEqual;
-
-export const keys = (ks, obj) =>
- ks.reduce(
- (ret, k) =>
- obj.hasOwnProperty(k) ? {...ret, [k]: obj[k]} : ret,
- {},
- );
-
-export const difference = (a, b) => {
- const diff = new Set(a);
- for (const el of b) {
- diff.delete(el);
- }
- return diff;
-};
-
-export const assocIn = (obj, path, value) =>
- path.length === 0 ? obj :
- path.length === 1 ? { ...obj, [path[0]]: value } :
- {
- ...obj,
- [path[0]]: assocIn(
- (obj[path[0]] || {}),
- path.slice(1),
- value
- )
- };
-
-export const dissoc = (obj, key) => {
- const ret = { ...obj };
- delete ret[key]
- return ret;
-};
-
-export const getIn = (obj, path) =>
- path.length === 0 ? obj :
- getIn(obj?.[path[0]], path.slice(1));
-
-export const findFirst = (arr, fn) => {
- for (const x of arr) {
- const ret = fn(x);
- if (ret) {
- return ret;
- }
- }
-
- return null;
-};
-
-export const partial = (fn, ...startArgs) =>
- (...endArgs) =>
- fn(...startArgs, ...endArgs);
-
-export const strSortFn = (a, b) => a.localeCompare(b, "POSIX");
-
-export const undefinedAsNull = x => x === undefined ? null : x;
-
-export const first = a => a[0];
-export const rest = a => a.slice(1);
-export const butlast = a => a.slice(a, a.length - 1);
-export const last = a => a[a.length - 1];
-
-export const take = function*(n, gen) {
- let i = 0n;
- for (const x of gen) {
- if (i >= n) {
- break;
- }
- i++;
- yield x;
- }
-};
-
-export const range = function*(x, y, step = 1n) {
- if (x === undefined) {
- let i = 0n;
- while (true) {
- yield i++;
- }
- }
- const [from, to] = y === undefined ?
- [0n, x] :
- [x, y];
- const fromn = BigInt(from);
- const ton = BigInt(to);
- const stepn = BigInt(step);
- if (stepn === 0n) {
- while (true) {
- yield fromn;
- }
- }
- if (step < 0n) {
- for (let i = fromn; i > ton; i+= stepn) {
- yield i;
- }
- } else {
- for (let i = fromn; i < ton; i += stepn) {
- yield i;
- }
- }
-};
diff --git a/src/web.mjs b/src/web.mjs
deleted file mode 100644
index 69be59c..0000000
--- a/src/web.mjs
+++ /dev/null
@@ -1,38 +0,0 @@
-import * as u from "./utils.mjs";
-import * as hero from "./hero.mjs";
-
-
-const name = "papo";
-
-const newConnection = (req) => {
- const { socket, websocket } = req;
- websocket.onmessage(message => {
- console.log({ message });
- });
- // console.log({ req, socket, websocket });
- // websocket.onclose(() => console.log("closed"));
- // websocket.onerror(() => console.log("errored"));
- /*
- req.socket.on("data", data => {
- console.log("antes");
- console.log({ data });
- console.log({ data: new Uint8Array(data) });
- console.log("depois");
- });
- */
- // ws.on("error", console.error);
- // ws.on("message", x => console.log(x.toString()));
- // ws.send("hello from the server");
-};
-
-const routes = [
- [ "WEBSOCKET", "/api/socket", newConnection ],
-];
-
-export const app = async (socket, pipe) =>
- await hero.buildServer({
- name,
- routes,
- socket,
- pipe,
- }).start();
diff --git a/tests/js/accretion.mjs b/tests/js/accretion.mjs
deleted file mode 100644
index c6ec4b2..0000000
--- a/tests/js/accretion.mjs
+++ /dev/null
@@ -1,48 +0,0 @@
-import assert from "node:assert/strict";
-import fs from "node:fs";
-
-import sqlite from "../../src/sqlite.cjs";
-
-import * as runner from "../runner.mjs";
-import * as db from "../../src/db.mjs";
-import * as u from "../../src/utils.mjs";
-import {
- MIGRATIONS_DIR,
- runMigrations,
-} from "../../src/accretion.mjs";
-
-
-const test_runMigrations = async t => {
- t.start("runMigrations()");
-
- await t.test("running twice is a noop", async () => {
- const contents = [];
- const logFn = x => contents.push(x);
- const handle = await db.open(":memory:");
- const migrationsFn = () => handle.all("SELECT filename FROM migrations;");
-
- assert.rejects(
- migrationsFn,
- { message: "SQLITE_ERROR: no such table: migrations" },
- );
-
- await runMigrations(logFn, handle);
- const filled = await migrationsFn();
-
- await runMigrations(logFn, handle);
- const unchanged = await migrationsFn();
-
- assert.deepEqual(filled, unchanged);
-
- const migrationLogs = fs
- .readdirSync(MIGRATIONS_DIR)
- .sort(u.strSortFn)
- .map(filename => ({ log: "exec-migration", filename }));
- assert.deepEqual(contents, migrationLogs);
- });
-};
-
-
-await runner.runTests([
- test_runMigrations,
-]);
diff --git a/tests/js/db.mjs b/tests/js/db.mjs
deleted file mode 100644
index 12b7405..0000000
--- a/tests/js/db.mjs
+++ /dev/null
@@ -1,110 +0,0 @@
-import assert from "node:assert/strict";
-
-import sqlite from "../../src/sqlite.cjs";
-
-import * as runner from "../runner.mjs";
-import {
- promisifyDb,
- open,
- handle,
- init,
-} from "../../src/db.mjs";
-
-
-const test_promisifyDb = async t => {
- t.start("promisifyDb()");
-
- const createTable = "CREATE TABLE table_ (column INTEGER NOT NULL PRIMARY KEY);";
-
- await t.test("we can access the underlying database and statement ref", async () => {
- const db = await open(":memory:");
- assert.ok(db.ref instanceof sqlite.Database);
-
- const stmt = await db.prepare("SELECT 1;");
- assert.ok(stmt.ref instanceof sqlite.Statement);
- });
-
- await t.test("we can run the wrapped fns", async () => {
- const db = await open(":memory:");
-
- await db.exec(createTable);
-
- const stmt = await db.prepare("INSERT INTO table_ (column) VALUES ($column)");
- await stmt.run({ $column: 3 });
- await stmt.run({ $column: 1 });
- await stmt.finalize();
- assert.rejects(
- async () => await stmt.run({ $column: 2 }),
- {
- message: "SQLITE_MISUSE: Statement is already finalized",
- code: "SQLITE_MISUSE",
- },
- );
-
- const selectAll = "SELECT column FROM table_ ORDER BY column;";
-
- const all = await db.all(selectAll);
- assert.deepEqual(all, [{ column: 1 }, { column: 3 }]);
-
- const contents = [];
- const cb = row => contents.push(row);
- await db.each(selectAll, cb);
- assert.deepEqual(contents, [{ column: 1 }, { column: 3 }]);
- });
-};
-
-const test_open = async t => {
- t.start("open()");
-
- await t.test("we must provide a name", () => {
- assert.rejects(
- async () => await open(),
- assert.AssertionError,
- );
-
- assert.rejects(
- async () => await open(undefined),
- assert.AssertionError,
- );
-
- assert.rejects(
- async () => await open(null),
- assert.AssertionError,
- );
-
- assert.rejects(
- async () => await open(""),
- assert.AssertionError,
- );
- });
-
- await t.test("failure to open causes a promise rejection", () => {
- assert.rejects(
- async () => await open("tests/non/existing/directory/and/file"),
- {
- message: "SQLITE_CANTOPEN: unable to open database file",
- code: "SQLITE_CANTOPEN",
- },
- );
- });
-};
-
-const test_init = async t => {
- t.start("init()");
- await t.test("we only know how to deal with 1 database", async () => {
- const logFn = () => {};
- await init(logFn);
- const ref1 = handle;
- await init(logFn);
- const ref2 = handle;
-
- assert.notDeepEqual(ref1, ref2);
- });
-};
-
-
-await runner.runTests([
- test_promisifyDb,
- test_open,
- test_init,
-]);
diff --git a/tests/js/escape.mjs b/tests/js/escape.mjs
deleted file mode 100644
index 359348a..0000000
--- a/tests/js/escape.mjs
+++ /dev/null
@@ -1,65 +0,0 @@
-import assert from "node:assert/strict";
-
-import * as runner from "../runner.mjs";
-import {
- escape,
-} from "../../src/escape.mjs";
-
-const test_escape = async t => {
- t.start("escape()");
-
- await t.test("numbers", () => {
- assert.equal(escape(0), "0");
- assert.equal(escape(42), "42");
- assert.equal(escape(-1), "-1");
- });
-
- await t.test("object", () => {
- assert.equal(escape({}), "[object Object]");
- assert.equal(escape({ k: "v" }), "[object Object]");
- });
-
- await t.test("string with special chars", () => {
- assert.strictEqual(escape(`"`), "&quot;");
- assert.strictEqual(escape(`"bar`), "&quot;bar");
- assert.strictEqual(escape(`foo"`), "foo&quot;");
- assert.strictEqual(escape(`foo"bar`), "foo&quot;bar");
- assert.strictEqual(escape(`foo""bar`), "foo&quot;&quot;bar");
-
- assert.strictEqual(escape("&"), "&amp;");
- assert.strictEqual(escape("&bar"), "&amp;bar");
- assert.strictEqual(escape("foo&"), "foo&amp;");
- assert.strictEqual(escape("foo&bar"), "foo&amp;bar");
- assert.strictEqual(escape("foo&&bar"), "foo&amp;&amp;bar");
-
- assert.strictEqual(escape("'"), "&#39;");
- assert.strictEqual(escape("'bar"), "&#39;bar");
- assert.strictEqual(escape("foo'"), "foo&#39;");
- assert.strictEqual(escape("foo'bar"), "foo&#39;bar");
- assert.strictEqual(escape("foo''bar"), "foo&#39;&#39;bar");
-
- assert.strictEqual(escape("<"), "&lt;");
- assert.strictEqual(escape("<bar"), "&lt;bar");
- assert.strictEqual(escape("foo<"), "foo&lt;");
- assert.strictEqual(escape("foo<bar"), "foo&lt;bar");
- assert.strictEqual(escape("foo<<bar"), "foo&lt;&lt;bar");
-
- assert.strictEqual(escape(">"), "&gt;");
- assert.strictEqual(escape(">bar"), "&gt;bar");
- assert.strictEqual(escape("foo>"), "foo&gt;");
- assert.strictEqual(escape("foo>bar"), "foo&gt;bar");
- assert.strictEqual(escape("foo>>bar"), "foo&gt;&gt;bar");
- });
-
- await t.test("the combination of all special characters", () => {
- assert.strictEqual(
- escape(`foo, "bar", 'baz' & <quux>`),
- "foo, &quot;bar&quot;, &#39;baz&#39; &amp; &lt;quux&gt;",
- );
- });
-};
-
-
-await runner.runTests([
- test_escape,
-]);
diff --git a/tests/js/ircd.mjs b/tests/js/ircd.mjs
deleted file mode 100644
index d385a72..0000000
--- a/tests/js/ircd.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as runner from "../runner.mjs";
-
-
-
-await runner.runTests([
-]);
diff --git a/tests/js/rand.mjs b/tests/js/rand.mjs
deleted file mode 100644
index 4044bb8..0000000
--- a/tests/js/rand.mjs
+++ /dev/null
@@ -1,96 +0,0 @@
-import assert from "node:assert/strict";
-import fs from "node:fs";
-
-import * as runner from "../runner.mjs";
-import {
- makeRandom,
-} from "../rand.mjs";
-
-
-const test_makeRandom = async t => {
- t.start("makeRandom()");
-
- await t.test("known expected values", () => {
- const expected1 = [
- 545331265, 2211535594, 4152021490, 3857419313,
- 1118735928, 3031474347, 3853601519, 3345048107,
- 1618127707, 4001288224, 1444061399, 2700534436,
- 1938647176, 1459718602, 3608868106, 926825740,
- 528719691, 508226068, 2332279787, 357437743,
- 1602075314, 1655472598, 1924131686, 4125580919,
- 555943458, 4047836046, 3693150918, 1515015978,
- 3523541186, 753964207, 1512058436, 682070622,
- 983063469, 4097791860, 3336260823, 603291380,
- 2554576084, 139062484, 590788013, 3608810491,
- 3663176645, 3481732081, 1011496919, 2935401636,
- 628041163, 3997974947, 2533467101, 2287863463,
- 2465361808, 1196937660, 263152482, 618228754,
- 2535860367, 3089904367, 1053769440, 1270818139,
- 1462199892, 49766906, 4229377745, 445624458,
- 3949395950, 4102223196, 162228180, 352248782,
- 3700326028, 965464548, 3236553557, 1342363444,
- 1740229486, 4006226087, 1475432391, 2100043423,
- 734083679, 2197742340, 1695047538, 2684537025,
- 2755935210, 2185177924, 1179365521, 682202996,
- 1985796754, 1203188028, 3742512741, 2573038834,
- 1722845493, 971634808, 2622456659, 1542773708,
- 506664990, 516191900, 3015858858, 2439287065,
- 1778261054, 3352336947, 1470361474, 2832338531,
- 2559479753, 2841821596, 858410480, 1311022275,
- ];
-
- const expected2 = [
- 1867215825, 1512725508, 59490082, 898255083,
- 2128587452, 3375572255, 3011978101, 664390052,
- 712189293, 1309145867, 1574443536, 3005563625,
- 1937221174, 2592810353, 1221596501, 3864084723,
- 2447880554, 1373397507, 4101388729, 1434258649,
- 2876658371, 694177935, 1850641240, 2934786942,
- 3613830458, 3660625740, 1450431957, 978896710,
- 108365537, 1669305275, 1505684879, 1989942961,
- 4089952722, 2832268551, 27863256, 3866494241,
- 3916427650, 3309597508, 24597008, 3442418170,
- 1617059167, 175885832, 854293503, 3965431971,
- 3276364445, 4079612430, 1622146979, 1665096344,
- 2283667308, 2042586700, 2997013224, 1214521941,
- 860865914, 3204144669, 3352312876, 407025370,
- 1854088521, 1518454983, 2467488963, 3014922727,
- 667505194, 1382726996, 3519130642, 3473985175,
- 387425140, 826920070, 3222196824, 3272392876,
- 2814202151, 1958017767, 2343175108, 513394477,
- 983853656, 3389045986, 177790781, 1853562919,
- 1417029053, 115479138, 3505632337, 339954849,
- 2552460743, 1260703764, 1719642924, 3129628830,
- 1828716278, 3537151540, 4169628597, 444526909,
- 4191927207, 3891278677, 1954375449, 3973495864,
- 2231816005, 4062939046, 2084239497, 3470238230,
- 1145760705, 2114090486, 4245867725, 1687967890,
- ];
-
- const expected3 = JSON.parse(
- fs.readFileSync("tests/bigger-rand-output.txt"),
- );
-
- const given1 = Array.from(
- new Array(expected1.length),
- makeRandom(123456),
- );
- const given2 = Array.from(
- new Array(expected2.length),
- makeRandom(123457),
- );
- const given3 = Array.from(
- new Array(expected3.length),
- makeRandom(2222),
- );
-
- assert.deepEqual(given1, expected1);
- assert.deepEqual(given2, expected2);
- assert.deepEqual(given3, expected3);
- });
-};
-
-
-await runner.runTests([
- test_makeRandom,
-]);
diff --git a/tests/js/utils.mjs b/tests/js/utils.mjs
deleted file mode 100644
index 69fd54a..0000000
--- a/tests/js/utils.mjs
+++ /dev/null
@@ -1,474 +0,0 @@
-import assert from "node:assert/strict";
-
-import * as runner from "../runner.mjs";
-import {
- keys,
- difference,
- assocIn,
- dissoc,
- getIn,
- findFirst,
- partial,
- strSortFn,
- undefinedAsNull,
- first,
- rest,
- butlast,
- last,
- take,
- range,
-} from "../../src/utils.mjs";
-
-
-const test_keys = async t => {
- t.start("keys()");
- await t.test("happy paths", () => {
- assert.deepEqual(
- { a: 1, b: 2 },
- keys(["a", "b"], { a: 1, b: 2, c: 3 }),
- );
- });
-
- await t.test("stress scenarios", () => {
- assert.deepEqual(
- {},
- keys([], {}),
- "empty selection of empty object",
- );
-
- assert.deepEqual(
- {},
- keys([], {a: 1}),
- "empty selection of non-empty object",
- );
-
- assert.deepEqual(
- {},
- keys(["a"], {}),
- "non-empty selection of empty object",
- );
-
- assert.deepEqual(
- { a: undefined, b: null },
- keys(["a", "b", "c"], { a: undefined, b: null }),
- "falsy values",
- );
- });
-};
-
-const test_difference = async t => {
- t.start("difference()");
-
- await t.test("empty values", () => {
- assert.deepEqual(
- difference(new Set(), new Set()),
- new Set(),
- );
-
- assert.deepEqual(
- difference(new Set(), new Set([1, 2])),
- new Set(),
- );
-
- assert.deepEqual(
- difference(new Set([1, 2]), new Set()),
- new Set([1, 2]),
- );
- });
-
- await t.test("different subsets", () => {
- assert.deepEqual(
- difference(new Set([1, 2]), new Set([3, 4])),
- new Set([1, 2]),
- );
-
- assert.deepEqual(
- difference(new Set([1, 2, 3]), new Set([2, 4, 5])),
- new Set([1, 3]),
- );
-
- assert.deepEqual(
- difference(new Set([1]), new Set([1, 2, 3, 4, 5])),
- new Set(),
- );
-
- assert.deepEqual(
- difference(new Set([1, 2, 3]), new Set([1, 2, 3])),
- new Set(),
- );
- });
-};
-
-const test_assocIn = async t => {
- t.start("assocIn()");
-
- await t.test("empty values", () => {
- assert.deepEqual(assocIn({}, [], null), {});
- assert.deepEqual(assocIn({ k: "v" }, [], null), { k: "v" });
- });
-
- await t.test("adding values", () => {
- assert.deepEqual(assocIn({}, ["k"], "v"), { k: "v" });
- assert.deepEqual(assocIn({}, ["k1", "k2"], "v"), { k1: { k2: "v" }});
- assert.deepEqual(assocIn({}, ["k1", "k2", "k3"], "v"), { k1: { k2: { k3: "v" }}});
- assert.deepEqual(assocIn({ k: "v" }, ["k1", "k2"], "v"), { k: "v", k1: { k2: "v" }});
- });
-
- await t.test("replacing values", () => {
- assert.deepEqual(
- assocIn(
- { k1: { k2: { k3: "before" }}},
- ["k1", "k2", "k3"],
- "after"
- ),
- { k1: { k2: { k3: "after" }}}
- );
- });
-};
-
-const test_dissoc = async t => {
- t.start("dissoc()");
-
- await t.test("empty values", () => {
- assert.deepEqual(dissoc({}, "k"), {});
- });
-
- await t.test("noop when key does not exist", () => {
- assert.deepEqual(dissoc({ a: 1 }, "b"), { a: 1 });
- });
-
- await t.test("removes the key", () => {
- assert.deepEqual(dissoc({ a: 1, b: 2}, "b"), { a: 1 });
- });
-};
-
-const test_getIn = async t => {
- t.start("getIn()");
-
- await t.test("empty values", () => {
- assert.deepEqual(getIn({}, []), {});
- assert.deepEqual(getIn({ k: "v" }, []), { k: "v" });
- });
-
- await t.test("missing values", () => {
- assert.deepEqual(getIn({}, ["a", "b", "c"]), undefined);
- assert.deepEqual(getIn({ a: {}}, ["a", "b", "c"]), undefined);
- assert.deepEqual(getIn({ a: { b: {}}}, ["a", "b", "c"]), undefined);
- assert.deepEqual(getIn({ a: { b: {}, c: {}}}, ["a", "b", "c"]), undefined);
- });
-
- await t.test("nested valeues", () => {
- assert.deepEqual(getIn({ a: { b: { c: { d: "e" }}}}, ["a", "b", "c", "d"]), "e");
- });
-};
-
-const test_findFirst = async t => {
- t.start("findFirst()");
-
- await t.test("empty values", () => {
- assert.equal(findFirst([], () => {}), null);
- });
-
- await t.test("when function doesn't transform, it behaves similarly to [].find()", () => {
- const arr1 = [ 0, null, undefined, "", 1, 2 ];
- assert.equal(findFirst(arr1, x => x), 1);
- assert.equal(arr1.find(x => x), 1);
-
- const arr2 = [ 0, null, undefined, "", false ];
- assert.equal(findFirst(arr2, x => x), null);
- assert.equal(arr2.find(x => x), undefined);
- });
-
- await t.test("when it does transform, we return the transformed value", () => {
- const arr = [ 1, 3, 5, 6 ];
-
- assert.equal(
- findFirst(arr, x => x % 2 === 0 && "a brand new value"),
- "a brand new value",
- );
- });
-};
-
-const test_partial = async t => {
- t.start("partial()");
-
- await t.test("empty values", () => {
- const adder = (a, b, c) => a + b + c;
-
- const adder1 = partial(adder);
- assert.equal(adder1(1, 2, 3), 6);
-
- const adder2 = partial(adder, 4, 5, 6);
- assert.equal(adder2(), 15);
-
- const noargs = () => "static";
- assert.equal(partial(noargs)(), noargs());
- });
-
- await t.test("too few arguments", () => {
- const threeArgs = (a, b, c) => {
- assert.notEqual(c, undefined);
- return a + b + c
- };
-
- const add1 = partial(threeArgs, 1);
- assert.throws(
- () => add1(2),
- assert.AssertionError,
- );
-
- const add1And2 = partial(threeArgs, 1, 2);
- assert.throws(
- () => add1And2(),
- assert.AssertionError,
- );
-
- const addNothing = partial(threeArgs);
- assert.throws(
- () => addNothing(),
- assert.AssertionError,
- );
- });
-
- await t.test("too many arguments", () => {
- const twoArgs = (a, b) => a + b;
-
- assert.equal(partial(twoArgs, 1)(2, 3), 3);
- assert.equal(partial(twoArgs, 1, 2)(3), 3);
- });
-
- await t.test("daily usage", () => {
- const twoArg = (a, b) => a + b;
-
- const numbers = [ 1, 2, 3, 4, 5 ];
- assert.deepEqual(
- numbers.map(partial(twoArg, 2)),
- [ 3, 4, 5, 6, 7 ],
- );
- });
-
- await t.test("nested partials", () => {
- const threeArgs = (a, b, c) => a + b + c;
-
- const add1 = partial(threeArgs, 1);
- const add1And2 = partial(add1, 2);
-
- assert.equal(add1And2(3), 6);
- });
-};
-
-const test_strSortFn = async t => {
- t.start("strSortFn()");
-
- await t.test("empty value", () => {
- assert.equal(strSortFn("", ""), 0);
- });
-
- await t.test("default sort", () => {
- const arr = [ "a", "Z" ];
- assert.deepEqual(
- [...arr].sort(strSortFn),
- [...arr].sort().reverse(),
- );
- });
-};
-
-const test_undefinedAsNull = async t => {
- t.start("undefinedAsNull()");
-
- await t.test("null for undefined or null", () => {
- assert.equal(undefinedAsNull(undefined), null);
- assert.equal(undefinedAsNull(null), null);
- });
-
- await t.test("identity otherwise", () => {
- const expected = [
- " ", "", 0, 1, -1.1, true, false,
- [], [ "" ], {}, { k: "v" },
- ];
- const given = expected.map(undefinedAsNull);
- assert.deepEqual(given, expected);
- });
-};
-
-const test_first = async t => {
- t.start("first()");
-
- await t.test("undefined for an empty array", () => {
- assert.equal(undefined, first([]));
- assert.equal(undefined, first(""));
- });
-
- await t.test("the first element otherwise", () => {
- assert.equal(1, first([1, 2, 3]));
- assert.equal("a", first("abc"));
- });
-};
-
-const test_rest = async t => {
- t.start("rest()");
-
- await t.test("an empty array when no more elements are available", () => {
- assert.deepEqual([], rest([]));
- assert.deepEqual([], rest([1]));
- assert.equal("", rest(""));
- assert.equal("bc", rest("abc"));
- });
-
- await t.test("the rest of the collection otherwise", () => {
- assert.deepEqual([2, 3], rest([1, 2, 3]));
- assert.equal("bc", rest("abc"));
- });
-
- await t.test("combines with first() well", () => {
- const arr = ["anything", "can", "go", "here"];
- assert.deepEqual(arr, [ first(arr), ...rest(arr) ]);
- });
-};
-
-const test_butlast = async t => {
- t.start("butlast()");
-
- await t.test("empty array when ther are no more elements", () => {
- assert.deepEqual([], butlast([]));
- assert.deepEqual([], butlast([1]));
- assert.equal("", butlast(""));
- assert.equal("", butlast("c"));
- });
-
- await t.test("the beginning of the array otherwise", () => {
- assert.deepEqual([1, 2], butlast([1, 2, 3]));
- assert.equal("ab", butlast("abc"));
- });
-};
-
-const test_last = async t => {
- t.start("last()");
-
- await t.test("undefined for an empty array", () => {
- assert.equal(undefined, last([]));
- assert.equal(undefined, last(""));
- });
-
- await t.test("the last element otherwise", () => {
- assert.equal(3, last([1, 2, 3]));
- assert.equal("c", last("abc"));
- });
-
- await t.test("combines with butlast() well", () => {
- const arr = ["anything", "goes", "here", "too"];
- assert.deepEqual(arr, [ ...butlast(arr), last(arr) ]);
- });
-};
-
-const test_take = async t => {
- t.start("take()");
-
- await t.test("example usage", () => {
- assert.deepEqual(Array.from(take(3, [1, 2, 3, 4, 5, 6])), [1, 2, 3]);
- assert.deepEqual([...take(3, [1, 2, 3, 4, 5, 6])], [1, 2, 3]);
-
- const gen = function*() {
- yield* [1, 2, 3, 4, 5, 6];
- }
- assert.deepEqual([...take(3, gen())], [1, 2, 3]);
-
- assert.deepEqual([...take(3, [1, 2])], [1, 2]);
-
- assert.deepEqual([...take(1, [])], []);
- assert.deepEqual([...take(0, [1])], []);
- assert.deepEqual([...take(-1, [1])], []);
- });
-};
-
-const test_range = async t => {
- t.start("range()");
-
- await t.test("empty values", () => {
- const [] = range();
-
- const [ a ] = range();
- assert.equal(a, 0n);
-
- const [ b, c, d, e ] = range();
- assert.deepEqual(
- [ b, c, d, e ],
- [ 0n, 1n, 2n, 3n ],
- );
-
- assert.deepEqual(
- Array.from(take(5, range())),
- [ 0n, 1n, 2n, 3n, 4n ],
- );
-
- assert.deepEqual(
- Array.from(take(1, range())),
- [ 0n ],
- );
-
- assert.deepEqual(
- Array.from(take(0, range())),
- [],
- );
- });
-
- await t.test("example usage", () => {
- assert.deepEqual(
- [...range(-5, 5)],
- [ -5n, -4n, -3n, -2n, -1n, 0n, 1n, 2n, 3n, 4n ],
- );
- assert.deepEqual(
- [...range(-100, 100, 10)],
- [
- -100n, -90n, -80n, -70n, -60n, -50n, -40n, -30n,
- -20n, -10n, 0n, 10n, 20n, 30n, 40n, 50n, 60n,
- 70n, 80n, 90n,
- ],
- );
-
- assert.deepEqual([...range(0, 4, 2)], [0n, 2n]);
- assert.deepEqual([...range(0, 5, 2)], [0n, 2n, 4n]);
- assert.deepEqual([...range(0, 6, 2)], [0n, 2n, 4n]);
- assert.deepEqual([...range(0, 7, 2)], [0n, 2n, 4n, 6n]);
-
- assert.deepEqual(
- [...range(100, 0, -10)],
- [ 100n, 90n, 80n, 70n, 60n, 50n, 40n, 30n, 20n, 10n ]
- );
- assert.deepEqual(
- [...range(10, -10, -1)],
- [
- 10n, 9n, 8n, 7n, 6n, 5n, 4n, 3n, 2n, 1n, 0n,
- -1n, -2n, -3n, -4n, -5n, -6n, -7n, -8n, -9n,
- ],
- );
-
- assert.deepEqual(
- [...take(3, range(1, 10, 0))],
- [ 1n, 1n, 1n ],
- );
- assert.deepEqual(
- [...take(3, range(10, 1, 0))],
- [ 10n, 10n, 10n ],
- );
- });
-};
-
-
-await runner.runTests([
- test_keys,
- test_difference,
- test_assocIn,
- test_dissoc,
- test_getIn,
- test_findFirst,
- test_partial,
- test_strSortFn,
- test_undefinedAsNull,
- test_first,
- test_rest,
- test_butlast,
- test_last,
- test_take,
- test_range,
-]);
diff --git a/tests/js/web.mjs b/tests/js/web.mjs
deleted file mode 100644
index d385a72..0000000
--- a/tests/js/web.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as runner from "../runner.mjs";
-
-
-
-await runner.runTests([
-]);
diff --git a/tests/lighttpd.conf b/tests/lighttpd.conf
deleted file mode 100644
index e3cdce0..0000000
--- a/tests/lighttpd.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-server.modules += (
- "mod_proxy",
- "mod_accesslog",
-)
-
-server.bind = var.CWD + "/lighttpd.socket"
-server.document-root = var.CWD + "/src/static/"
-
-server.errorlog = "/dev/stdout"
-server.breakagelog = "/dev/stdout"
-accesslog.filename = "/dev/stdout"
-
-accesslog.format = ""
-accesslog.format += "{ "
-accesslog.format += "\"tool\": " + "\"lighttpd\", "
-accesslog.format += "\"http-host\": " + "\"%V\", "
-accesslog.format += "\"remote-addr\": " + "\"%h\", "
-accesslog.format += "\"remote-user\": " + "\"%u\", "
-accesslog.format += "\"request-method\": " + "\"%m\", "
-accesslog.format += "\"request\": " + "\"%r\", "
-accesslog.format += "\"status\": " + "%s, "
-accesslog.format += "\"body-bytes-sent\": " + "\"%b\", "
-accesslog.format += "\"duration-usec\": " + "%D, "
-accesslog.format += "\"http-referrer\": " + "\"%{Referer}i\", "
-accesslog.format += "\"http-user-agent\": " + "\"%{User-Agent}i\" "
-accesslog.format += "}"
-
-index-file.names = ( "index.html" )
-
-$HTTP["url"] =~ "^/api/" {
- proxy.server = ( "" => (( "host" => var.CWD + "/web.socket" )))
- $HTTP["url"] =~ "^/api/socket$" {
- proxy.header += ( "upgrade" => "enable" )
- }
-}
diff --git a/tests/papo_test.go b/tests/papo_test.go
new file mode 100644
index 0000000..ef424fb
--- /dev/null
+++ b/tests/papo_test.go
@@ -0,0 +1,14 @@
+package papo_test
+
+import (
+ "testing"
+
+ "euandre.org/papo/src"
+)
+
+
+func TestConvert(t *testing.T) {
+ if papo.Hello("World") != "Hi, World. Welcome!" {
+ t.Fail()
+ }
+}
diff --git a/tests/rand.c b/tests/rand.c
deleted file mode 100644
index 26146e8..0000000
--- a/tests/rand.c
+++ /dev/null
@@ -1,83 +0,0 @@
-// Derived from
-// http://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/CODES/mt19937ar.c
-
-#define _XOPEN_SOURCE 700
-
-#include <assert.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-
-#define N 624U
-static const uint16_t M = 397;
-static const uint32_t MATRIX_A = 0x9908b0dfUL;
-static const uint32_t UPPER_MASK = 0x80000000UL;
-static const uint32_t LOWER_MASK = 0x7fffffffUL;
-
-static uint32_t mt[N];
-static uint16_t mti;
-static bool initialized = false;
-
-static void
-init(uint32_t s) {
- initialized = true;
- mt[0] = s & 0xffffffffUL;
- for (mti = 1; mti < N; mti++) {
- mt[mti] = (1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >> 30))) + mti;
- }
-}
-
-/// Generates a random number on the [ 0, 0xffffffff ]-interval.
-static uint32_t
-generate(void) {
- assert(initialized == true);
- static uint32_t mag01[2] = { 0, MATRIX_A };
-
- if (mti >= N) {
- uint16_t kk;
-
- for (kk = 0; kk < N - M; kk++) {
- const uint32_t y0 =
- (mt[kk] & UPPER_MASK) |
- (mt[kk + 1] & LOWER_MASK);
- mt[kk] = mt[kk + M] ^ (y0 >> 1) ^ mag01[y0 & 1U];
- }
-
- for (; kk < N - 1; kk++) {
- const uint32_t y1 =
- (mt[kk] & UPPER_MASK) |
- (mt[kk + 1] & LOWER_MASK);
- mt[kk] = mt[kk + (M - N)] ^ (y1 >> 1) ^ mag01[y1 & 1U];
- }
-
- const uint32_t y2 =
- (mt[N - 1] & UPPER_MASK) |
- (mt[0] & LOWER_MASK);
- mt[N - 1] = mt[M - 1] ^ (y2 >> 1) ^ mag01[y2 & 1U];
- mti = 0;
- }
-
- uint32_t y = mt[mti++];
-
- y ^= (y >> 11);
- y ^= (y << 7) & 0x9d2c5680UL;
- y ^= (y << 15) & 0xefc60000UL;
- y ^= (y >> 18);
-
- return y;
-}
-
-
-int
-main(void) {
- init(2222);
-
- for (uint16_t i = 0; i < 10000; i++) {
- assert(
- printf("%" PRIu32 "\n", generate()) > 0
- );
- }
-
- return 0;
-}
diff --git a/tests/rand.mjs b/tests/rand.mjs
deleted file mode 100644
index ba4e3b1..0000000
--- a/tests/rand.mjs
+++ /dev/null
@@ -1,55 +0,0 @@
-const N = 624;
-const M = 397;
-const MATRIX_A = 0x9908b0df;
-const UPPER_MASK = 0x80000000;
-const LOWER_MASK = 0x7fffffff;
-const mag01 = [ 0x0, MATRIX_A ];
-const INIT_MUL = 1812433253;
-
-/// The given function generates random numbers on the [ 0, 0xffffffff ]-interval.
-export const makeRandom = (seed = (new Date()).getTime()) => {
- const mt = new Array(N);
- let mti = null;
-
- mt[0] = seed >>> 0;
- for (mti = 1; mti < N; mti++) {
- const s0 = mt[mti - 1] ^ (mt[mti - 1] >>> 30);
- mt[mti] =
- (((((s0 & 0xffff0000) >>> 16) * INIT_MUL) << 16) +
- (( s0 & 0x0000ffff) * INIT_MUL) +
- mti) >>> 0;
- }
-
- return () => {
- if (mti >= N) {
- let kk = null;
-
- for (kk = 0; kk < N - M; kk++) {
- const y0 =
- (mt[kk] & UPPER_MASK) |
- (mt[kk + 1] & LOWER_MASK);
- mt[kk] = mt[kk + M] ^ (y0 >>> 1) ^ mag01[y0 & 0x1];
- }
-
- for (; kk < N - 1; kk++) {
- const y1 =
- (mt[kk] & UPPER_MASK) |
- (mt[kk + 1] & LOWER_MASK);
- mt[kk] = mt[kk + (M - N)] ^ (y1 >>> 1) ^ mag01[y1 & 0x1];
- }
-
- const y2 =
- (mt[N - 1] & UPPER_MASK) |
- (mt[0] & LOWER_MASK);
- mt[N - 1] = mt[M - 1] ^ (y2 >>> 1) ^ mag01[y2 & 0x1];
- mti = 0;
- }
-
- let y = mt[mti++];
- y ^= (y >>> 11);
- y ^= (y << 7) & 0x9d2c5680;
- y ^= (y << 15) & 0xefc60000;
- y ^= (y >>> 18);
- return y >>> 0;
- };
-};
diff --git a/tests/runner.mjs b/tests/runner.mjs
deleted file mode 100644
index c17c0d0..0000000
--- a/tests/runner.mjs
+++ /dev/null
@@ -1,31 +0,0 @@
-import process from "node:process";
-
-const red = s => `\x1b[31m${s}\x1b[0m`;
-const green = s => `\x1b[32m${s}\x1b[0m`;
-const yellow = s => `\x1b[33m${s}\x1b[0m`;
-
-const t = {
- tap: x => {
- console.error("tap:", x);
- return x;
- },
- start: msg => {
- console.error(`${msg}:`);
- },
- test: async (msg, fn) => {
- process.stderr.write(`${yellow("testing")}: ${msg}... `);
- try {
- await fn();
- } catch (e) {
- process.stderr.write(`${red("FAIL\n")}`);
- throw e;
- }
- process.stderr.write(`${green("OK\n")}`);
- },
-};
-
-export const runTests = async tests => {
- for (const testFn of tests) {
- await testFn(t);
- }
-};