Skip to content

Commit

Permalink
added tests for http server and web api
Browse files Browse the repository at this point in the history
  • Loading branch information
pk910 committed Jun 26, 2023
1 parent 0b3b5bc commit 99edbb3
Show file tree
Hide file tree
Showing 6 changed files with 676 additions and 8 deletions.
10 changes: 10 additions & 0 deletions .nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"reporter": ["text", "lcov"],
"include": [
"src/**"
],
"exclude": [
"libs/*.js",
"tests/**"
]
}
6 changes: 0 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@
],
"outputPath": "dist"
},
"nyc": {
"exclude": [
"libs/*.js",
"tests/**"
]
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.4",
"@types/chai": "^4.3.5",
Expand Down
3 changes: 3 additions & 0 deletions src/session/FaucetSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ export class FaucetSession {
throw ex;
}

if(this.status as FaucetSessionStatus === FaucetSessionStatus.FAILED)
return;

this.status = FaucetSessionStatus.RUNNING;
this.isDirty = true;
this.manager.notifySessionUpdate(this);
Expand Down
4 changes: 2 additions & 2 deletions src/webserv/FaucetHttpServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface FaucetWssEndpoint {
handler: (req: IncomingMessage, ws: WebSocket, remoteIp: string) => void;
}

const MAX_BODY_SITE = 1024 * 1024 * 10; // 10MB
const MAX_BODY_SIZE = 1024 * 1024 * 10; // 10MB

export class FaucetHttpServer {
private initialized: boolean;
Expand Down Expand Up @@ -92,7 +92,7 @@ export class FaucetHttpServer {
req.on("data", (chunk: Buffer) => {
bodyParts.push(chunk);
bodySize += chunk.length;
if(bodySize > MAX_BODY_SITE) {
if(bodySize > MAX_BODY_SIZE) {
req.destroy(new Error("body too big"));
}
});
Expand Down
203 changes: 203 additions & 0 deletions tests/FaucetHttpServer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import 'mocha';
import { expect } from 'chai';
import * as fs from 'fs';
import * as path from 'path';
import fetch from 'node-fetch';
import { WebSocket } from 'ws';
import { bindTestStubs, loadDefaultTestConfig, unbindTestStubs } from './common';
import { ServiceManager } from '../src/common/ServiceManager';
import { FaucetWebApi } from '../src/webserv/FaucetWebApi';
import { IncomingHttpHeaders, IncomingMessage } from 'http';
import { Socket } from 'net';
import { sleepPromise } from '../src/utils/SleepPromise';
import { PromiseDfd } from '../src/utils/PromiseDfd';
import { FaucetDatabase } from '../src/db/FaucetDatabase';
import { ModuleManager } from '../src/modules/ModuleManager';
import { faucetConfig } from '../src/config/FaucetConfig';
import { FaucetHttpResponse, FaucetHttpServer } from '../src/webserv/FaucetHttpServer';
import { EthClaimManager } from '../src/eth/EthClaimManager';
import { sha256 } from '../src/utils/CryptoUtils';

describe("Faucet Web Server", () => {
let globalStubs;

beforeEach(async () => {
globalStubs = bindTestStubs({});
loadDefaultTestConfig();
await ServiceManager.GetService(FaucetDatabase).initialize();
await ServiceManager.GetService(ModuleManager).initialize();
});
afterEach(async () => {
let dbService = ServiceManager.GetService(FaucetDatabase);
await ServiceManager.DisposeAllServices();
await dbService.closeDatabase();
await unbindTestStubs(globalStubs);
});

it("generate SEO index.html", async () => {
faucetConfig.faucetTitle = "test_title_" + Math.floor(Math.random() * 99999999).toString();
faucetConfig.buildSeoIndex = true;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
let seoFile = path.join(faucetConfig.staticPath, "index.seo.html");
expect(fs.existsSync(seoFile), "seo file not found");
let seoContent = fs.readFileSync(seoFile, "utf8");
expect(seoContent).contains(faucetConfig.faucetTitle, "uncustomized seo index");
});

it("check basic http call", async () => {
faucetConfig.faucetTitle = "test_title_" + Math.floor(Math.random() * 99999999).toString();
faucetConfig.buildSeoIndex = true;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
let listenPort = webServer.getListenPort();
let indexData = await fetch("http://localhost:" + listenPort).then((rsp) => rsp.text());
expect(indexData).contains(faucetConfig.faucetTitle, "not index contents");
});

it("check api call (GET)", async () => {
faucetConfig.faucetTitle = "test_title_" + Math.floor(Math.random() * 99999999).toString();
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
let listenPort = webServer.getListenPort();
let configData = await fetch("http://localhost:" + listenPort + "/api/getFaucetConfig").then((rsp) => rsp.json());
expect(!!configData).equals(true, "no api response");
expect(configData.faucetTitle).equals(faucetConfig.faucetTitle, "api response mismatch");
});

it("check api call (POST)", async () => {
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
let reqMsg: IncomingMessage;
ServiceManager.GetService(FaucetWebApi).registerApiEndpoint("testEndpoint", async (req, url, body) => {
reqMsg = req;
return sha256(body.toString());
});
let listenPort = webServer.getListenPort();
let responseData = await fetch("http://localhost:" + listenPort + "/api/testEndpoint", {
method: 'POST',
body: JSON.stringify({test: 1}),
headers: {'Content-Type': 'application/json'}
}).then((rsp) => rsp.text());

expect(responseData).equals('"1da06016289bd76a5ada4f52fc805ae0c394612f17ec6d0f0c29b636473c8a9d"', "unexpected api response");
expect(reqMsg.method).equals("POST", "unexpected method");
});

it("check api call (POST, body size limit)", async () => {
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
ServiceManager.GetService(FaucetWebApi).registerApiEndpoint("testEndpoint", async (req, url, body) => {
return "test";
});
let listenPort = webServer.getListenPort();
let error: Error;
try {
let testData = "0123456789".repeat(1024 * 1024);
await fetch("http://localhost:" + listenPort + "/api/testEndpoint", {
method: 'POST',
body: JSON.stringify({test: testData}),
headers: {'Content-Type': 'application/json'}
});
} catch(ex) {
error = ex;
}
expect(!!error).to.equals(true, "no error thrown");
expect(error.toString()).to.matches(/socket hang up/, "unexpected error message");
});

it("check api call (custom response)", async () => {
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
ServiceManager.GetService(FaucetWebApi).registerApiEndpoint("testEndpoint", async (req, url, body) => {
return new FaucetHttpResponse(500, "Test Error 4135");
});
let listenPort = webServer.getListenPort();
let testRsp = await fetch("http://localhost:" + listenPort + "/api/testEndpoint");
expect(testRsp.status).to.equal(500, "unexpected http response code");
expect(testRsp.statusText).to.matches(/Test Error 4135/, "unexpected http response code");
});

it("check api call (rejection)", async () => {
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
ServiceManager.GetService(FaucetWebApi).registerApiEndpoint("testEndpoint", (req, url, body) => {
return Promise.reject("Test Error 3672");
});
let listenPort = webServer.getListenPort();
let testRsp = await fetch("http://localhost:" + listenPort + "/api/testEndpoint");
let testRspText = await testRsp.text();
expect(testRsp.status).to.equal(500, "unexpected http response code");
expect(testRspText).to.matches(/Test Error 3672/, "unexpected http response code");
});

it("check api call (rejection with custom response)", async () => {
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
ServiceManager.GetService(FaucetWebApi).registerApiEndpoint("testEndpoint", async (req, url, body) => {
throw new FaucetHttpResponse(500, "Test Error 4267");
});
let listenPort = webServer.getListenPort();
let testRsp = await fetch("http://localhost:" + listenPort + "/api/testEndpoint");
expect(testRsp.status).to.equal(500, "unexpected http response code");
expect(testRsp.statusText).to.matches(/Test Error 4267/, "unexpected http response code");
});

it("check ws call", async () => {
faucetConfig.faucetTitle = "test_title_" + Math.floor(Math.random() * 99999999).toString();
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
await ServiceManager.GetService(EthClaimManager).initialize();
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
let listenPort = webServer.getListenPort();
let webSocket = new WebSocket("ws://127.0.0.1:" + listenPort + "/ws/claim");
let errorDfd = new PromiseDfd<any>();
webSocket.onmessage = (evt) => {
let data = JSON.parse(evt.data.toString());
if(data && data.action === "error")
errorDfd.resolve(data);
};
await new Promise<void>((resolve) => {
webSocket.onopen = (evt) => {
resolve();
};
});
let errorResponse = await errorDfd.promise;
expect(!!errorResponse).equals(true, "no websocket response");
expect(errorResponse.data.reason).to.matches(/session not found/, "api response mismatch");
webSocket.close();
});

it("check ws call (invalid endpoint)", async () => {
faucetConfig.faucetTitle = "test_title_" + Math.floor(Math.random() * 99999999).toString();
faucetConfig.buildSeoIndex = false;
faucetConfig.serverPort = 0;
await ServiceManager.GetService(EthClaimManager).initialize();
let webServer = ServiceManager.GetService(FaucetHttpServer);
webServer.initialize();
let listenPort = webServer.getListenPort();
let webSocket = new WebSocket("ws://127.0.0.1:" + listenPort + "/api/test");
let errorResponse = await new Promise<any>((resolve) => {
webSocket.onerror = (evt) => {
resolve(evt);
};
});
expect(!!errorResponse).equals(true, "no websocket error");
});

});
Loading

0 comments on commit 99edbb3

Please sign in to comment.