add some test files

This commit is contained in:
SikongJueluo 2025-03-23 21:50:49 +08:00
parent 482d359c98
commit f368638f6e
No known key found for this signature in database
5 changed files with 212 additions and 87 deletions

View File

@ -7,6 +7,7 @@
"@trpc/client": "^10.45.2", "@trpc/client": "^10.45.2",
"@trpc/server": "^10.45.2", "@trpc/server": "^10.45.2",
"@types/lodash": "^4.17.16", "@types/lodash": "^4.17.16",
"lodash": "^4.17.21",
"log-symbols": "^7.0.0", "log-symbols": "^7.0.0",
"pinia": "^3.0.1", "pinia": "^3.0.1",
"trpc-bun-adapter": "^1.2.2", "trpc-bun-adapter": "^1.2.2",
@ -434,6 +435,8 @@
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA=="], "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA=="],
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"log-symbols": ["log-symbols@7.0.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-zrc91EDk2M+2AXo/9BTvK91pqb7qrPg2nX/Hy+u8a5qQlbaOflCKO+6SqgZ+M+xUFxGdKTgwnGiL96b1W3ikRA=="], "log-symbols": ["log-symbols@7.0.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-zrc91EDk2M+2AXo/9BTvK91pqb7qrPg2nX/Hy+u8a5qQlbaOflCKO+6SqgZ+M+xUFxGdKTgwnGiL96b1W3ikRA=="],
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],

View File

@ -16,6 +16,7 @@
"@trpc/client": "^10.45.2", "@trpc/client": "^10.45.2",
"@trpc/server": "^10.45.2", "@trpc/server": "^10.45.2",
"@types/lodash": "^4.17.16", "@types/lodash": "^4.17.16",
"lodash": "^4.17.21",
"log-symbols": "^7.0.0", "log-symbols": "^7.0.0",
"pinia": "^3.0.1", "pinia": "^3.0.1",
"trpc-bun-adapter": "^1.2.2", "trpc-bun-adapter": "^1.2.2",

View File

@ -1,11 +1,25 @@
import _ from "lodash"
import { z } from "zod";
export const uint8 = z.number().nonnegative().lt(Math.pow(2, 8))
export const uint16 = z.number().nonnegative().lt(Math.pow(2, 16))
export const uint32 = z.number().nonnegative().lt(Math.pow(2, 32))
export const int8 = z.number().lt(Math.pow(2, 7)).gte(-Math.pow(2, 8))
export const int16 = z.number().lt(Math.pow(2, 15)).gte(-Math.pow(2, 16))
export const int32 = z.number().lt(Math.pow(2, 31)).gte(-Math.pow(2, 32))
export function numberToBytes(num: number, bytesLength: number): Uint8Array { export function numberToBytes(num: number, bytesLength: number): Uint8Array {
var array = new Uint8Array(bytesLength) var array = new Uint8Array(bytesLength)
var i; for (let i = 0; i < bytesLength; i++) {
for (i = 0; i < bytesLength; i++) {
array[i] = num & (0xFF << (i << 3)) array[i] = num & (0xFF << (i << 3))
} }
return array return array
} }
export function randomFromArray(array: Array<any>) {
return array[_.random(0, array.length - 1, false)]
}

View File

@ -1,10 +1,39 @@
import { test, expect } from "bun:test" import { test, expect } from "bun:test"
import * as db from "./database.ts" import * as db from "./database.ts"
import _ from "lodash"
import { randomFromArray } from "./common.ts"
import { None, Ok } from "ts-results-es"
test("DataBase", () => { test("DataBase", () => {
const allTables = db.allTables() const allTables = db.allTables()
expect(allTables).toBeArray() expect(allTables).toBeArray()
expect(allTables).toEqual(["Users", "Boards"]) expect(allTables).toEqual(["Users", "Boards"])
expect(db.boardsNum()).toBe(0) expect(db.BoardTable.count()).toBe(0)
expect(db.UserTable.count()).toBe(0)
})
test("Board Table", () => {
const boardsNumber = 10
const rooms = ["A1", "A2"]
// Try to find something empty
const findEmptyByID = db.BoardTable.find(_.random(0, boardsNumber))
expect(findEmptyByID).toEqual(Ok(None))
const findEmptyByName = db.BoardTable.find("Hello")
expect(findEmptyByName).toEqual(Ok(None))
const boardsArray: Array<db.Board> = []
for (let i = 0; i < boardsNumber; i++) {
boardsArray.push({
id: _.random(0, 100),
name: `Board ${i}`,
room: randomFromArray(rooms),
ipv4: `192.168.172.${i}`,
port: _.random(0, 665535),
})
}
}) })

View File

@ -1,10 +1,10 @@
import { Database } from "bun:sqlite"; import { Database, type Changes } from "bun:sqlite";
import _ from "lodash"; import _ from "lodash";
import { Ok, Err, Result, None, Some, Option } from "ts-results-es"; import { Ok, Err, Result, None, Some, Option } from "ts-results-es";
import { z } from "zod"; import { z } from "zod";
const db = new Database("lab.sqlite", { strict: true }) const db = new Database("lab.sqlite", { strict: true })
initDB(); initDB(db);
const boardSchema = z.object({ const boardSchema = z.object({
@ -13,7 +13,7 @@ const boardSchema = z.object({
room: z.string(), room: z.string(),
ipv4: z.string().ip({ version: "v4" }), ipv4: z.string().ip({ version: "v4" }),
ipv6: z.string().ip({ version: "v6" }), ipv6: z.string().ip({ version: "v6" }),
port: z.number().nonnegative(), port: z.number().nonnegative().lte(65535),
cmdID: z.number().nonnegative() cmdID: z.number().nonnegative()
}).partial({ }).partial({
ipv6: true, ipv6: true,
@ -42,7 +42,7 @@ export function isUser(obj: any): obj is User {
} }
function initDB() { function initDB(db: Database) {
const tables = allTables() const tables = allTables()
if (!tables.includes("Users")) { if (!tables.includes("Users")) {
@ -91,18 +91,21 @@ export function tableColumnName(table: string): Array<string> {
return columnName return columnName
} }
export function addBoard(board: Board): Result<Board, "Wrong params type"> { export namespace BoardTable {
export function add(board: Board): Result<Changes, "Wrong type" | "ID conflict"> {
if (!isBoard(board)) { if (!isBoard(board)) {
return new Err("Wrong params type") return new Err("Wrong type")
} }
if (board.id == 0) { if (board.id == 0) {
const idNum = boardsNum() const cnt = count()
board.id = idNum board.id = cnt + 1
} else { } else if (includes(board.id)) {
return new Err("ID conflict")
} }
const query = db.query(` const query = db.query(`
INSERT INTO Boards VALUES INSERT INTO Boards VALUES
(${board.id}, (${board.id},
@ -112,55 +115,105 @@ export function addBoard(board: Board): Result<Board, "Wrong params type"> {
'${typeof board.ipv6 === "undefined" ? "NULL" : board.ipv6}', '${typeof board.ipv6 === "undefined" ? "NULL" : board.ipv6}',
${board.port}); ${board.port});
`) `)
query.run()
return Ok(board) return Ok(query.run())
} }
export function boardsNum(): number { export function addFromArray(array: Array<Board>): Result<Board, "Wrong type"> {
for (const item of array) {
const ret = add(item)
if (ret.isErr()) {
return new Err("Wrong type")
}
}
return new Ok()
}
export function count(): number {
const query = db.query(`SELECT COUNT(*) FROM Boards`) const query = db.query(`SELECT COUNT(*) FROM Boards`)
return query.values()[0][0] as number return query.values()[0][0] as number
} }
export function deleteBoard(name?: string): Result<Board, "Wrong Type" | "No such Board"> export function remove(name?: string): Result<Board, "Wrong Type" | "No such Board">
export function deleteBoard(id?: number): Result<Board, "Wrong Type" | "No such Board"> export function remove(id?: number): Result<Board, "Wrong Type" | "No such Board">
export function deleteBoard(board?: Board): Result<Board, "Wrong Type" | "No such Board"> export function remove(board?: Board): Result<Board, "Wrong Type" | "No such Board">
export function deleteBoard(arg: any): Result<Board, "Wrong Type" | "No such Board"> { export function remove(arg: any): Result<Board, "Wrong Type" | "No such Board"> {
let retBoard let retBoard
let condition: string let condition: string
if (isBoard(arg)) { if (isBoard(arg)) {
retBoard = arg retBoard = _.cloneDeep(arg)
condition = `id=${arg.id}`
} else if (_.isNumber(arg)) { } else if (_.isNumber(arg)) {
retBoard = findBoard(arg) retBoard = find(arg)
if (retBoard.isOk() && retBoard.value.isSome()) {
retBoard = _.cloneDeep(retBoard.value.value)
condition = `id=${arg}`
} else {
return new Err("No such Board")
}
} else if (_.isString(arg)) { } else if (_.isString(arg)) {
retBoard = findBoard(arg) retBoard = find(arg)
if (retBoard.isOk() && retBoard.value.isSome()) {
retBoard = _.cloneDeep(retBoard.value.value)
condition = `name=${arg}`
} else {
return new Err("No such Board")
}
} else { } else {
return new Err("Wrong Type") return new Err("Wrong Type")
} }
const query = db.query(`DELETE FROM Boards WHERE id=${arg.id}`) const query = db.query(`DELETE FROM Boards WHERE ${condition}`)
query.run()
return new Ok(retBoard) return new Ok(retBoard)
} }
export function allBoards() { export function all() {
const query = db.query(`SELECT * FROM Boards`) const query = db.query(`SELECT * FROM Boards`)
const boards = query.all() const boards = query.all()
query.finalize() query.finalize()
return boards return boards
} }
export function findBoard(name?: string): Result<Option<Board>, "Wrong type"> export function find(name: string, room: string): Result<Option<Board>, "Wrong type">
export function findBoard(id?: number): Result<Option<Board>, "Wrong type"> export function find(id: number): Result<Option<Board>, "Wrong type">
export function findBoard(arg: any): Result<Option<Board>, "Wrong type"> { export function find(arg1: any, arg2: any): Result<Option<Board>, "Wrong type"> {
let condition: string
if (_.isNumber(arg1)) {
condition = `id=${arg1}`
} else if (_.isString(arg1)) {
condition = `name='${arg1}'`
} else {
return new Err("Wrong type")
}
const query = db.query(`SELECT * FROM Boards WHERE ${condition}`)
const spRet = boardSchema.safeParse(query.get())
if (spRet.success) {
return new Ok(Some(spRet.data))
} else {
return new Ok(None)
}
}
export function includes(name?: string): Result<boolean, "Wrong type">
export function includes(id?: number): Result<boolean, "Wrong type">
export function includes(arg: any): Result<boolean, "Wrong type"> {
let condition: string let condition: string
if (_.isNumber(arg)) { if (_.isNumber(arg)) {
condition = `arg=${arg}` condition = `id=${arg}`
} else if (_.isString(arg)) { } else if (_.isString(arg)) {
condition = `name='${arg}'` condition = `name='${arg}'`
@ -173,22 +226,47 @@ export function findBoard(arg: any): Result<Option<Board>, "Wrong type"> {
const query = db.query(`SELECT * FROM Boards WHERE ${condition}`) const query = db.query(`SELECT * FROM Boards WHERE ${condition}`)
const spRet = boardSchema.safeParse(query.get()) const spRet = boardSchema.safeParse(query.get())
if (spRet.success) {
return new Ok(true)
} else {
return new Ok(false)
}
}
}
export namespace UserTable {
export function count(): number {
const query = db.query(`SELECT COUNT(*) FROM Users`)
return query.values()[0][0] as number
}
export function find(id: number): Result<Option<User>, "Wrong Type">
export function find(name: string): Result<Option<User>, "Wrong Type">
export function find(arg: any): Result<Option<User>, "Wrong Type"> {
let condition: string
if (_.isNumber(arg)) {
condition = `id=${arg}`
} else if (_.isString(arg)) {
condition = `name=${arg}`
} else {
return new Err("Wrong Type")
}
const query = db.query(`SELECT * FROM Users WHERE name='${arg}'`)
const spRet = userSchema.safeParse(query.get())
if (spRet.success) { if (spRet.success) {
return new Ok(Some(spRet.data)) return new Ok(Some(spRet.data))
} else { } else {
return new Ok(None) return new Ok(None)
} }
}
export function findUser(name: string): User {
const query = db.query(`SELECT * FROM Users WHERE name='${name}'`)
const spRet = userSchema.safeParse(query.get())
if (spRet.success) {
return spRet.data
} else {
throw new Error(`Failure: Not found ${name} User`)
} }
} }