Skip to content

Commit

Permalink
add failing test case
Browse files Browse the repository at this point in the history
  • Loading branch information
j-white committed May 4, 2024
1 parent 0d61876 commit e6b725e
Show file tree
Hide file tree
Showing 7 changed files with 361 additions and 14 deletions.
39 changes: 39 additions & 0 deletions features/step_definitions/cf_mock_server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import http from "http";
import {AddressInfo} from "net";

export class CloudflareMockServer {
server: http.Server | undefined;

start() {
let self = this;
this.server = http.createServer((req, res) => {
var body = "";
req.on('readable', function() {
let part = req.read();
if (part !== undefined && part !== null) {
body += part;
}
});
req.on('end', function() {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('OK');
});
});
this.server.listen(() => {
console.log('opened server on', self.server?.address());
});
}

url() {
const { port } = this.server?.address() as AddressInfo;
return `http://localhost:${port}/`;
}

async dispose() {
if (this.server != undefined) {
this.server.close();
this.server = undefined;
}
}
}
76 changes: 76 additions & 0 deletions features/step_definitions/mf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {Log, LogLevel, Miniflare} from "miniflare";
import { MockAgent } from "undici";

export class MiniflareDriver {
mockAgent = new MockAgent();
mf: Miniflare | undefined;

start(options?: {metricsUrl?: string, cloudflareApiUrl?: string}): Miniflare {
this.mockAgent
.get("https://cloudflare.com")
.intercept({ path: "/" })
.reply(200, "cloudflare!");

this.mockAgent
.get("https://jsonplaceholder.typicode.com")
.intercept({ path: "/todos/1" })
.reply(
200,
{
userId: 1,
id: 1,
title: "delectus aut autem",
completed: false,
},
{
headers: {
"content-type": "application/json",
},
}
);

let metricsUrl = "";
let cloudflareApiUrl = "";
if (options !== undefined) {
if (options.metricsUrl !== undefined) {
metricsUrl = options.metricsUrl;
}
if (options.cloudflareApiUrl !== undefined) {
cloudflareApiUrl = options.cloudflareApiUrl;
}
}

this.mf = new Miniflare({
log: new Log(LogLevel.DEBUG), // Enable debug messages
cachePersist: false,
d1Persist: false,
kvPersist: false,
r2Persist: false,
workers: [{
scriptPath: "./build/worker/shim.mjs",
compatibilityDate: "2022-04-05",
cache: true,
modules: true,
modulesRules: [
{ type: "CompiledWasm", include: ["**/*.wasm"], fallthrough: true },
],
fetchMock: this.mockAgent,
}]});
return this.mf;
}

dispose() {
if (this.mf === undefined) {
return;
}
let promise = this.mf.dispose();
this.mf = undefined;
return promise;
}

async trigger() {
this.start({});
await this.mf?.dispatchFetch("http://localhost:8787/cdn-cgi/mf/scheduled");
this.dispose();
}
}
34 changes: 20 additions & 14 deletions features/step_definitions/o11y_steps.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
import {Given, When, Then} from '@cucumber/cucumber';
import {After, Given, When, Then} from '@cucumber/cucumber';
import {cloudflareMockServer, mf, mfConfig, otelServer} from "./state";
import {expect} from "chai";

Given('Worker is configured to point to mock Cloudflare API', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
cloudflareMockServer.start();
mfConfig.cloudflareApiUrl = cloudflareMockServer.url();
});

Given('Worker is configured to send metrics to a mock OpenTelemetry collector', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
otelServer.start();
mfConfig.metricsUrl = otelServer.metricsUrl();
});

When('Worker is triggered', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
When('Worker is triggered', async function () {
await mf.trigger();
});

Then('Worker metrics are published', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
let metrics = otelServer.getMetrics();
expect(metrics).to.have.length.gte(1);
});


Then('Meter name should include {string}', function (string) {
// Write code here that turns the phrase above into concrete actions
return 'pending';
Then('Meter name should include {string}', function (metricName: string) {
let metricNames = otelServer.getMetricNames();
expect(metricNames).to.contain(metricName);
});

After(async function () {
await mf.dispose();
await cloudflareMockServer.dispose();
await otelServer.dispose();
})
73 changes: 73 additions & 0 deletions features/step_definitions/otel_server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import http from 'http';
import {IExportMetricsServiceRequest} from "@opentelemetry/otlp-transformer";
import {AddressInfo} from "net";

export class OpenTelemetryServer {
server: http.Server | undefined;
metrics: IExportMetricsServiceRequest[] = [];
metricNames: Map<string, number> = new Map<string, number>();

private reset() {
this.metrics = [];
this.indexMetrics();
}

start() {
let self = this;
self.reset();
this.server = http.createServer((req, res) => {
var body = "";
req.on('readable', function() {
let part = req.read();
if (part !== undefined && part !== null) {
body += part;
}
});
req.on('end', function() {
const metrics = JSON.parse(body) as IExportMetricsServiceRequest;
self.metrics.push(metrics);
self.indexMetrics();
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('OK');
});
});
this.server.listen(() => {
console.log('opened server on', self.server?.address());
});
}

indexMetrics() {
let self = this;
this.metricNames.clear();
for (let metrics of this.metrics) {
for (let resourceMetrics of metrics.resourceMetrics) {
for (let scopeMetrics of resourceMetrics.scopeMetrics) {
for (let metric of scopeMetrics.metrics) {
self.metricNames.set(metric.name, 1);
}
}
}
}
}

metricsUrl() {
const { port } = this.server?.address() as AddressInfo;
return `http://localhost:${port}/v1/metrics`;
}

async dispose() {
if (this.server != undefined) {
this.server.close();
this.server = undefined;
}
}

getMetrics() {
return this.metrics;
}

getMetricNames() {
return this.metricNames.keys();
}
}
19 changes: 19 additions & 0 deletions features/step_definitions/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {MiniflareDriver} from "./mf";
import {OpenTelemetryServer} from "./otel_server";
import {CloudflareMockServer} from "./cf_mock_server";

const mf = new MiniflareDriver();
const otelServer = new OpenTelemetryServer();
const cloudflareMockServer = new CloudflareMockServer();

type MfConfig = {
metricsUrl: string|undefined;
cloudflareApiUrl: string|undefined
};

const mfConfig: MfConfig = {
metricsUrl: undefined,
cloudflareApiUrl: undefined,
}

export { mf, mfConfig, otelServer, cloudflareMockServer };
Loading

0 comments on commit e6b725e

Please sign in to comment.