add basic test for database

This commit is contained in:
SikongJueluo 2025-03-24 15:07:06 +08:00
parent f368638f6e
commit 8fa594159f
No known key found for this signature in database
3 changed files with 121 additions and 69 deletions

View File

@ -9,7 +9,8 @@ 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 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 const int32 = z.number().lt(Math.pow(2, 31)).gte(-Math.pow(2, 32))
export function numberToBytes(num: number, bytesLength: number): Uint8Array { export namespace fun {
export function numberToBytes(num: number, bytesLength: number): Uint8Array {
var array = new Uint8Array(bytesLength) var array = new Uint8Array(bytesLength)
for (let i = 0; i < bytesLength; i++) { for (let i = 0; i < bytesLength; i++) {
@ -17,9 +18,11 @@ export function numberToBytes(num: number, bytesLength: number): Uint8Array {
} }
return array return array
} }
export function randomFromArray(array: Array<any>) { export function randomFromArray(array: Array<any>) {
return array[_.random(0, array.length - 1, false)] return array[_.random(0, array.length - 1, false)]
}
} }

View File

@ -1,39 +1,58 @@
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 _ from "lodash"
import { randomFromArray } from "./common.ts" import { None, Ok, Option, Some } from "ts-results-es"
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.BoardTable.count()).toBe(0) expect(db.BoardTable.countAll()).toBe(0)
expect(db.UserTable.count()).toBe(0) expect(db.UserTable.countAll()).toBe(0)
}) })
test("Board Table", () => { test("Board Table", () => {
const boardsNumber = 10 const boardsNumber = 10
const rooms = ["A1", "A2"] const rooms = ["A1", "A1", "A1", "A1", "A1", "A2", "A2", "A2", "A2", "A2"]
// Try to find something empty // Try to find something empty
const findEmptyByID = db.BoardTable.find(_.random(0, boardsNumber)) const findEmptyByID = db.BoardTable.find(_.random(0, boardsNumber))
expect(findEmptyByID).toEqual(Ok(None)) expect(findEmptyByID).toEqual(Ok(None))
const findEmptyByName = db.BoardTable.find("Hello") const findEmptyByName = db.BoardTable.find("Hello", "World")
expect(findEmptyByName).toEqual(Ok(None)) expect(findEmptyByName).toEqual(Ok(None))
const boardsArray: Array<db.Board> = [] const boardsArray: Array<db.Board> = []
for (let i = 0; i < boardsNumber; i++) { for (let i = 0; i < boardsNumber; i++) {
boardsArray.push({ boardsArray.push({
id: _.random(0, 100), id: i,
name: `Board ${i}`, name: `Board ${i}`,
room: randomFromArray(rooms), room: rooms[i],
ipv4: `192.168.172.${i}`, ipv4: `192.168.172.${i}`,
port: _.random(0, 665535), port: i,
}) })
} }
db.BoardTable.addFromArray(boardsArray)
// Test Find
expect(db.BoardTable.find(1)).toEqual(Ok(Some({
id: 1,
name: `Board ${1}`,
room: rooms[1],
ipv4: `192.168.172.${1}`,
port: 1,
} as db.Board)))
expect(db.BoardTable.find("Board 3", "A1")).toEqual(Ok(Some({
id: 3,
name: `Board ${3}`,
room: rooms[3],
ipv4: `192.168.172.${3}`,
port: 3,
} as db.Board)))
// Test Count
expect(db.BoardTable.countByName("Board 1")).toBe(1)
expect(db.BoardTable.countByRoom("A1")).toBe(5)
}) })

View File

@ -93,18 +93,35 @@ export function tableColumnName(table: string): Array<string> {
export namespace BoardTable { export namespace BoardTable {
export function add(board: Board): Result<Changes, "Wrong type" | "ID conflict"> { export function add(board: Board): Result<Changes, "Wrong type" | "ID conflict" | "Name conflict in one room"> {
if (!isBoard(board)) { if (!isBoard(board)) {
return new Err("Wrong type") return new Err("Wrong type")
} }
// Ensure no id conflict
if (board.id == 0) { if (board.id == 0) {
const cnt = count() const cnt = countAll()
board.id = cnt + 1 board.id = cnt + 1
} else if (includes(board.id)) { } else {
return new Err("ID conflict") const retID = includes(board.id)
if (retID.isOk()) {
if (retID.value) return new Err("ID conflict")
} else {
return new Err("Wrong type")
}
} }
// Ensure no name conflict in the same room
{
const retName = includes(board.name, board.room)
if (retName.isOk()) {
if (retName.value) {
return new Err("Name conflict in one room")
}
} else {
return new Err("Wrong type")
}
}
const query = db.query(` const query = db.query(`
INSERT INTO Boards VALUES INSERT INTO Boards VALUES
@ -112,53 +129,74 @@ export namespace BoardTable {
'${board.name}, '${board.name},
'${board.room}', '${board.room}',
'${board.ipv4}', '${board.ipv4}',
'${typeof board.ipv6 === "undefined" ? "NULL" : board.ipv6}', '${_.isUndefined(board.ipv6) ? "NULL" : board.ipv6}',
${board.port}); ${board.port});
`) `)
return Ok(query.run()) return Ok(query.run())
} }
export function addFromArray(array: Array<Board>): Result<Board, "Wrong type"> { export function addFromArray(array: Array<Board>): Result<Array<Changes>, "Wrong type"> {
let arrayChanges: Array<Changes> = []
for (const item of array) { for (const item of array) {
const ret = add(item) const ret = add(item)
if (ret.isErr()) { if (ret.isErr()) {
return new Err("Wrong type") return new Err("Wrong type")
} else {
arrayChanges.push(ret.value)
} }
} }
return new Ok() return new Ok(arrayChanges)
} }
export function count(): number { export function all() {
const query = db.query(`SELECT * FROM Boards`)
const boards = query.all()
query.finalize()
return boards
}
export function countAll(): 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 remove(name?: string): Result<Board, "Wrong Type" | "No such Board"> export function countByName(name: string): number {
export function remove(id?: number): Result<Board, "Wrong Type" | "No such Board"> const query = db.query(`SELECT * FROM Boards WHERE name=${name}`)
export function remove(board?: Board): Result<Board, "Wrong Type" | "No such Board"> return query.values()[0][0] as number
export function remove(arg: any): Result<Board, "Wrong Type" | "No such Board"> { }
export function countByRoom(room: string): number {
const query = db.query(`SELECT * FROM Boards WHERE room=${room}`)
return query.values()[0][0] as number
}
export function remove(name: string, room: string): Result<Board, "Wrong Type" | "No such Board">
export function remove(id: number): Result<Board, "Wrong Type" | "No such Board">
export function remove(board: Board): Result<Board, "Wrong Type" | "No such Board">
export function remove(arg1: any, arg2?: any): Result<Board, "Wrong Type" | "No such Board"> {
let retBoard let retBoard
let condition: string let condition: string
if (isBoard(arg)) { if (isBoard(arg1)) {
retBoard = _.cloneDeep(arg) retBoard = _.cloneDeep(arg1)
condition = `id=${arg.id}` condition = `id=${arg1.id}`
} else if (_.isNumber(arg)) { } else if (_.isNumber(arg1)) {
retBoard = find(arg) retBoard = find(arg1)
if (retBoard.isOk() && retBoard.value.isSome()) { if (retBoard.isOk() && retBoard.value.isSome()) {
retBoard = _.cloneDeep(retBoard.value.value) retBoard = _.cloneDeep(retBoard.value.value)
condition = `id=${arg}` condition = `id=${arg1}`
} else { } else {
return new Err("No such Board") return new Err("No such Board")
} }
} else if (_.isString(arg)) { } else if (_.isString(arg1) && _.isString(arg2)) {
retBoard = find(arg) retBoard = find(arg1, arg2)
if (retBoard.isOk() && retBoard.value.isSome()) { if (retBoard.isOk() && retBoard.value.isSome()) {
retBoard = _.cloneDeep(retBoard.value.value) retBoard = _.cloneDeep(retBoard.value.value)
condition = `name=${arg}` condition = `name=${arg1}`
} else { } else {
return new Err("No such Board") return new Err("No such Board")
} }
@ -173,28 +211,18 @@ export namespace BoardTable {
return new Ok(retBoard) return new Ok(retBoard)
} }
export function all() {
const query = db.query(`SELECT * FROM Boards`)
const boards = query.all()
query.finalize()
return boards
}
export function find(name: string, room: string): Result<Option<Board>, "Wrong type"> export function find(name: string, room: string): Result<Option<Board>, "Wrong type">
export function find(id: number): Result<Option<Board>, "Wrong type"> export function find(id: number): Result<Option<Board>, "Wrong type">
export function find(arg1: any, arg2: any): Result<Option<Board>, "Wrong type"> { export function find(arg1: any, arg2?: any): Result<Option<Board>, "Wrong type"> {
let condition: string let condition: string
if (_.isNumber(arg1)) { if (_.isNumber(arg1)) {
condition = `id=${arg1}` condition = `id=${arg1}`
} else if (_.isString(arg1)) { } else if (_.isString(arg1) && _.isString(arg2)) {
condition = `name='${arg1}'` condition = `name='${arg1}' AND room='${arg2}'`
} else { } else {
return new Err("Wrong type") return new Err("Wrong type")
} }
const query = db.query(`SELECT * FROM Boards WHERE ${condition}`) const query = db.query(`SELECT * FROM Boards WHERE ${condition}`)
@ -208,37 +236,39 @@ export namespace BoardTable {
} }
} }
export function includes(name?: string): Result<boolean, "Wrong type"> export function includes(name: string, room?: string): Result<boolean, "Wrong type">
export function includes(id?: number): Result<boolean, "Wrong type"> export function includes(id: number): Result<boolean, "Wrong type">
export function includes(arg: any): Result<boolean, "Wrong type"> { export function includes(arg1: any, arg2?: any): Result<boolean, "Wrong type"> {
let condition: string let condition: string
if (_.isNumber(arg)) { if (_.isUndefined(arg2)) {
condition = `id=${arg}` if (_.isNumber(arg1)) {
condition = `id=${arg1}`
} else if (_.isString(arg)) { } else if (_.isString(arg1)) {
condition = `name='${arg}'` condition = `name='${arg1}'`
} else { } else {
return new Err("Wrong type") 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(true)
} else { } else {
return new Ok(false) if (_.isString(arg1) && _.isString(arg2)) {
condition = `name='${arg1} AND room=${arg2}'`
} else {
return new Err("Wrong type")
} }
} }
const query = db.query(`SELECT COUNT(*) FROM Boards WHERE ${condition}`)
const num = query.values()[0][0] as number
return new Ok(num > 0 ? true : false)
}
} }
export namespace UserTable { export namespace UserTable {
export function count(): number { export function countAll(): number {
const query = db.query(`SELECT COUNT(*) FROM Users`) const query = db.query(`SELECT COUNT(*) FROM Users`)
return query.values()[0][0] as number return query.values()[0][0] as number
} }