157 lines
5.1 KiB
TypeScript
157 lines
5.1 KiB
TypeScript
|
import {
|
||
|
describe
|
||
|
, expect
|
||
|
, it
|
||
|
, beforeEach
|
||
|
} from 'bun:test'
|
||
|
import {
|
||
|
Elysia
|
||
|
} from 'elysia'
|
||
|
import {
|
||
|
treaty
|
||
|
} from '@elysiajs/eden'
|
||
|
import app from '../app.ts'
|
||
|
import Docker from 'dockerode'
|
||
|
import { mkdir } from "node:fs/promises";
|
||
|
import path from 'node:path'
|
||
|
|
||
|
|
||
|
if (!process.env.TRACKER_HELPER_USERNAME) throw new Error("TRACKER_HELPER_USERNAME is missing in env.");
|
||
|
if (!process.env.TRACKER_HELPER_PASSWORD) throw new Error("TRACKER_HELPER_PASSWORD is missing in env.");
|
||
|
|
||
|
const accesslistFilePath = process.env.TRACKER_HELPER_ACCESSLIST_PATH || "/var/lib/aquatic/accesslist"
|
||
|
const fixture = "3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01" // ubuntustudio-22.04.5-dvd-amd64.iso
|
||
|
const fixture2 = "b22ea43e4c0a7f73fc706b5faf1c35bb078d3722" // Solus-GNOME-Release-2025-01-26.iso
|
||
|
|
||
|
const username = process.env.TRACKER_HELPER_USERNAME!
|
||
|
const password = process.env.TRACKER_HELPER_PASSWORD!
|
||
|
const opts = {
|
||
|
headers: {
|
||
|
authorization: "Basic " + btoa(username + ':' + password)
|
||
|
}
|
||
|
}
|
||
|
const api = treaty(app)
|
||
|
|
||
|
|
||
|
|
||
|
describe
|
||
|
('tracker-helper', () => {
|
||
|
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
console.log(`Asserting existence of accesslist at ${accesslistFilePath}`);
|
||
|
|
||
|
const assertAccesslistExists = async function (accesslistFilePath: string) {
|
||
|
const wlFile = Bun.file(accesslistFilePath);
|
||
|
const exists = await wlFile.exists();
|
||
|
|
||
|
if (!exists) {
|
||
|
console.log(`Creating accesslist file at ${accesslistFilePath}`);
|
||
|
|
||
|
// Ensure the parent directory exists
|
||
|
await mkdir(path.dirname(accesslistFilePath), { recursive: true });
|
||
|
|
||
|
await wlFile.write(`${fixture2}\n${fixture}\n`);
|
||
|
|
||
|
|
||
|
}
|
||
|
};
|
||
|
|
||
|
await assertAccesslistExists(accesslistFilePath);
|
||
|
});
|
||
|
|
||
|
it('return a health response', async () => {
|
||
|
const { data, status } = await api.health.get()
|
||
|
expect(status).toBe(200)
|
||
|
expect(data).toBe("OK")
|
||
|
})
|
||
|
|
||
|
it('return a version', async () => {
|
||
|
const { data, status } = await api.version.get(opts)
|
||
|
expect(status).toBe(200)
|
||
|
expect(data).toContain("version")
|
||
|
})
|
||
|
|
||
|
it('return a accesslist', async () => {
|
||
|
const { data, status } = await api.accesslist.get(opts)
|
||
|
expect(status).toBe(200)
|
||
|
expect(data).toContain(fixture)
|
||
|
})
|
||
|
|
||
|
it('expects the accesslist to already exist', async () => {
|
||
|
const accesslist = Bun.file(accesslistFilePath)
|
||
|
const accesslistExists = await accesslist.exists()
|
||
|
expect(accesslistExists).toBe(true)
|
||
|
})
|
||
|
|
||
|
it('appends a new info_hash to the accesslist file', async () => {
|
||
|
|
||
|
|
||
|
// make an api call which is supposed to add an entry to the accesslist
|
||
|
const { data, status } = await api.accesslist.post(fixture, opts)
|
||
|
|
||
|
// assert that the entry has been added to the accesslist
|
||
|
|
||
|
|
||
|
const w = Bun.file(accesslistFilePath)
|
||
|
const accesslistAfter = await w.text()
|
||
|
console.log('accesslistAfter as follows')
|
||
|
console.log(accesslistAfter)
|
||
|
|
||
|
expect(status).toBe(201)
|
||
|
expect(data).toMatch(fixture)
|
||
|
expect(accesslistAfter).toMatch(fixture)
|
||
|
|
||
|
})
|
||
|
|
||
|
// it('sends a SIGHUP to opentracker', async () => {
|
||
|
|
||
|
// const { data, status } = await api.accesslist.post(fixture, opts)
|
||
|
// const containerId = "act-ci-Tests-Checks-6e6f12196682961041a41a25b9d0dcf00e4d0f8e58f-7cb37eebfe9e1670328d58ad1f7c7bdf0fa078298ca6dd299e67d0141a4b9579"
|
||
|
// // await docker.getContainer(containerId).kill({ signal: 'SIGHUP' })
|
||
|
// let container = await docker.getContainer(containerId)
|
||
|
// container.inspect
|
||
|
|
||
|
// })
|
||
|
|
||
|
|
||
|
// // This is skipped because I couldn't figure out opentracker's accesslist add/delete via FIFO functionality.
|
||
|
// // I got as far as writing to the FIFO, and seeing opentracker acknowledge the line in it's logs.
|
||
|
// // Despite this, requests from qbittorrent to opentracker responded with,
|
||
|
// // "Requested download is not authorized for use with this tracker"
|
||
|
// // About a week on this problem, and I give up! Using the accesslist reloading strat instead.
|
||
|
// it.skip('writes a new info_hash to a fifo', async () => {
|
||
|
// const fifoFilePath = process.env.TRACKER_HELPER_FIFO_PATH!
|
||
|
// const fifo = Bun.file(fifoFilePath)
|
||
|
// const fifoExists = await fifo.exists();
|
||
|
|
||
|
|
||
|
// // create fifo if it doesn't exist
|
||
|
// if (!fifoExists) {
|
||
|
// await Bun.spawn(["mkfifo", fifoFilePath]).exited;
|
||
|
// }
|
||
|
|
||
|
// // Start a process to read from the FIFO
|
||
|
// const reader = Bun.spawn(["cat", fifoFilePath], { stdout: "pipe" });
|
||
|
|
||
|
// const { data, status } = await api.accesslist.post("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01", opts)
|
||
|
|
||
|
// const text = await new Response(reader.stdout).text();
|
||
|
|
||
|
// expect(text).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01\n")
|
||
|
// expect(status).toBe(200)
|
||
|
// expect(data).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01")
|
||
|
// })
|
||
|
|
||
|
it('returns 401 when username/password is missing from GET /accesslist ', async () => {
|
||
|
const { status } = await api.accesslist.get()
|
||
|
expect(status).toBe(401)
|
||
|
})
|
||
|
|
||
|
it('returns 401 when username/password is missing from POST /accesslist ', async () => {
|
||
|
const { status } = await api.accesslist.post()
|
||
|
expect(status).toBe(401)
|
||
|
})
|
||
|
|
||
|
})
|