diff options
author | EuAndreh <eu@euandre.org> | 2024-03-25 06:42:35 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-03-25 06:44:18 -0300 |
commit | 077b81b2bd2c0d418635b265b35f582d68cec16a (patch) | |
tree | ed3c928ea3b1d5df539b6e1902ab418caa937672 | |
parent | src/hero.mjs: Retire code (diff) | |
download | papod-077b81b2bd2c0d418635b265b35f582d68cec16a.tar.gz papod-077b81b2bd2c0d418635b265b35f582d68cec16a.tar.xz |
Node.js -> Go
-rw-r--r-- | .gitignore | 7 | ||||
-rw-r--r-- | Makefile | 56 | ||||
-rw-r--r-- | deps.mk | 26 | ||||
-rw-r--r-- | doc/papo.en.3go.in (renamed from doc/papo.en.3js.in) | 0 | ||||
-rw-r--r-- | go.mod | 5 | ||||
-rw-r--r-- | go.sum | 2 | ||||
-rwxr-xr-x | mkdeps.sh | 8 | ||||
-rw-r--r-- | src/accretion.mjs | 42 | ||||
-rw-r--r-- | src/api.mjs | 20 | ||||
-rwxr-xr-x | src/bin.mjs | 4 | ||||
-rw-r--r-- | src/cmd/papo.go | 28 | ||||
-rw-r--r-- | src/db.mjs | 57 | ||||
-rw-r--r-- | src/escape.mjs | 14 | ||||
-rw-r--r-- | src/ircd.mjs | 19 | ||||
-rw-r--r-- | src/package.json | 3 | ||||
-rw-r--r-- | src/papo.go | 8 | ||||
-rw-r--r-- | src/sqlite.cjs | 1 | ||||
-rw-r--r-- | src/utils.mjs | 105 | ||||
-rw-r--r-- | src/web.mjs | 38 | ||||
-rw-r--r-- | tests/js/accretion.mjs | 48 | ||||
-rw-r--r-- | tests/js/db.mjs | 110 | ||||
-rw-r--r-- | tests/js/escape.mjs | 65 | ||||
-rw-r--r-- | tests/js/ircd.mjs | 6 | ||||
-rw-r--r-- | tests/js/rand.mjs | 96 | ||||
-rw-r--r-- | tests/js/utils.mjs | 474 | ||||
-rw-r--r-- | tests/js/web.mjs | 6 | ||||
-rw-r--r-- | tests/lighttpd.conf | 35 | ||||
-rw-r--r-- | tests/papo_test.go | 14 | ||||
-rw-r--r-- | tests/rand.c | 83 | ||||
-rw-r--r-- | tests/rand.mjs | 55 | ||||
-rw-r--r-- | tests/runner.mjs | 31 |
31 files changed, 99 insertions, 1367 deletions
@@ -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 @@ -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: @@ -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 @@ -0,0 +1,5 @@ +module euandre.org/papo + +go 1.21.5 + +require github.com/mattn/go-sqlite3 v1.14.22 // indirect @@ -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= @@ -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 = { - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' -}; - -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(`"`), """); - assert.strictEqual(escape(`"bar`), ""bar"); - assert.strictEqual(escape(`foo"`), "foo""); - assert.strictEqual(escape(`foo"bar`), "foo"bar"); - assert.strictEqual(escape(`foo""bar`), "foo""bar"); - - assert.strictEqual(escape("&"), "&"); - assert.strictEqual(escape("&bar"), "&bar"); - assert.strictEqual(escape("foo&"), "foo&"); - assert.strictEqual(escape("foo&bar"), "foo&bar"); - assert.strictEqual(escape("foo&&bar"), "foo&&bar"); - - assert.strictEqual(escape("'"), "'"); - assert.strictEqual(escape("'bar"), "'bar"); - assert.strictEqual(escape("foo'"), "foo'"); - assert.strictEqual(escape("foo'bar"), "foo'bar"); - assert.strictEqual(escape("foo''bar"), "foo''bar"); - - assert.strictEqual(escape("<"), "<"); - assert.strictEqual(escape("<bar"), "<bar"); - assert.strictEqual(escape("foo<"), "foo<"); - assert.strictEqual(escape("foo<bar"), "foo<bar"); - assert.strictEqual(escape("foo<<bar"), "foo<<bar"); - - assert.strictEqual(escape(">"), ">"); - assert.strictEqual(escape(">bar"), ">bar"); - assert.strictEqual(escape("foo>"), "foo>"); - assert.strictEqual(escape("foo>bar"), "foo>bar"); - assert.strictEqual(escape("foo>>bar"), "foo>>bar"); - }); - - await t.test("the combination of all special characters", () => { - assert.strictEqual( - escape(`foo, "bar", 'baz' & <quux>`), - "foo, "bar", 'baz' & <quux>", - ); - }); -}; - - -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); - } -}; |