Skip to content

Commit

Permalink
Bump code coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
hansott committed Feb 27, 2024
1 parent 890c4ec commit 6f0ad88
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 81 deletions.
25 changes: 25 additions & 0 deletions library/src/agent/Wrapper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as t from "tap";
import { Hooks } from "./Wrapper";

t.test("package throws error if name is empty", async (t) => {
const hooks = new Hooks();

t.throws(() => hooks.package(""));
});

t.test("withVersion throws error if version is empty", async (t) => {
const hooks = new Hooks();
const subject = hooks.package("package");

t.throws(() => subject.withVersion(""));
});

t.test("method throws error if name is empty", async (t) => {
const hooks = new Hooks();
const subject = hooks
.package("package")
.withVersion("^1.0.0")
.subject((exports) => exports);

t.throws(() => subject.method("", () => {}));
});
74 changes: 1 addition & 73 deletions library/src/agent/Wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { Hook } from "require-in-the-middle";
import { wrap } from "shimmer";
import { getPackageVersion } from "../helpers/getPackageVersion";
import { satisfiesVersion } from "../helpers/satisfiesVersion";

type Interceptor = (args: unknown[], subject: unknown) => void | unknown[];

class Method {
export class Method {
constructor(
private readonly name: string,
private readonly interceptor: Interceptor
Expand Down Expand Up @@ -110,73 +105,6 @@ export class Hooks {
}
}

function wrapMethod(subject: unknown, method: Method) {
// @ts-expect-error We don't now the type of the subject
wrap(subject, method.getName(), function wrap(original: Function) {
return function wrap() {
// eslint-disable-next-line prefer-rest-params
const args = Array.from(arguments);
// @ts-expect-error We don't now the type of this
const updatedArgs = method.getInterceptor()(args, this);

return original.apply(
// @ts-expect-error We don't now the type of this
this,
// eslint-disable-next-line prefer-rest-params
Array.isArray(updatedArgs) ? updatedArgs : arguments
);
};
});
}

export function wrapPackages(hooks: Hooks) {
const wrapped: Record<string, { version: string; supported: boolean }> = {};

hooks.getPackages().forEach((pkg) => {
const version = getPackageVersion(pkg.getName());

if (!version) {
return;
}

const selectors = pkg
.getVersions()
.map((versioned) => {
if (!satisfiesVersion(versioned.getRange(), version)) {
return [];
}

return versioned.getSelectors();
})
.flat();

if (selectors.length === 0) {
return;
}

wrapped[pkg.getName()] = {
version,
supported: true,
};

new Hook([pkg.getName()], (exports) => {
selectors.forEach((selector) => {
const subject = selector.getSelector()(exports);

if (!subject) {
return;
}

selector.getMethods().forEach((method) => wrapMethod(subject, method));
});

return exports;
});
});

return wrapped;
}

export interface Wrapper {
wrap(hooks: Hooks): void;
}
5 changes: 3 additions & 2 deletions library/src/agent/protect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { MongoDB } from "../sinks/MongoDB";
import { Postgres } from "../sinks/Postgres";
import * as shimmer from "shimmer";
import { Logger, LoggerConsole, LoggerNoop } from "./Logger";
import { Hooks, wrapPackages } from "./Wrapper";
import { wrap } from "./wrap";
import { Hooks } from "./Wrapper";
import { Options, getOptions } from "../helpers/getOptions";

function wrapInstalledPackages() {
Expand All @@ -19,7 +20,7 @@ function wrapInstalledPackages() {
wrapper.wrap(hooks);
});

return wrapPackages(hooks);
return wrap(hooks);
}

function getLogger(options: Options): Logger {
Expand Down
30 changes: 30 additions & 0 deletions library/src/agent/wrap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as t from "tap";
import { wrap } from "./wrap";
import { Hooks } from "./Wrapper";

t.test("it ignores if package is not installed", async (t) => {
const hooks = new Hooks();
hooks.package("unknown").withVersion("^1.0.0");
t.same(wrap(hooks), {});
});

t.test("it ignores if packages have empty selectors", async (t) => {
const hooks = new Hooks();
hooks.package("shimmer").withVersion("^1.0.0");
t.same(wrap(hooks), {});
});

t.test("it ignores unknown selectors", async (t) => {
const hooks = new Hooks();
hooks
.package("shimmer")
.withVersion("^1.0.0")
.subject((exports) => exports.doesNotExist)
.method("method", () => {});
t.same(wrap(hooks), {
shimmer: {
version: "1.2.1",
supported: true,
},
});
});
72 changes: 72 additions & 0 deletions library/src/agent/wrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Hook } from "require-in-the-middle";
import { wrap as shim } from "shimmer";
import { getPackageVersion } from "../helpers/getPackageVersion";
import { satisfiesVersion } from "../helpers/satisfiesVersion";
import { Hooks, Method } from "./Wrapper";

function wrapMethod(subject: unknown, method: Method) {
// @ts-expect-error We don't now the type of the subject
shim(subject, method.getName(), function wrap(original: Function) {
return function wrap() {
// eslint-disable-next-line prefer-rest-params
const args = Array.from(arguments);
// @ts-expect-error We don't now the type of this
const updatedArgs = method.getInterceptor()(args, this);

return original.apply(
// @ts-expect-error We don't now the type of this
this,
// eslint-disable-next-line prefer-rest-params
Array.isArray(updatedArgs) ? updatedArgs : arguments
);
};
});
}

export function wrap(hooks: Hooks) {
const wrapped: Record<string, { version: string; supported: boolean }> = {};

hooks.getPackages().forEach((pkg) => {
const version = getPackageVersion(pkg.getName());

if (!version) {
return;
}

const selectors = pkg
.getVersions()
.map((versioned) => {
if (!satisfiesVersion(versioned.getRange(), version)) {
return [];
}

Check warning on line 41 in library/src/agent/wrap.ts

View check run for this annotation

Codecov / codecov/patch

library/src/agent/wrap.ts#L40-L41

Added lines #L40 - L41 were not covered by tests

return versioned.getSelectors();
})
.flat();

if (selectors.length === 0) {
return;
}

wrapped[pkg.getName()] = {
version,
supported: true,
};

new Hook([pkg.getName()], (exports) => {
selectors.forEach((selector) => {
const subject = selector.getSelector()(exports);

if (!subject) {
return;
}

Check warning on line 62 in library/src/agent/wrap.ts

View check run for this annotation

Codecov / codecov/patch

library/src/agent/wrap.ts#L61-L62

Added lines #L61 - L62 were not covered by tests

selector.getMethods().forEach((method) => wrapMethod(subject, method));
});

return exports;
});
});

return wrapped;
}
5 changes: 3 additions & 2 deletions library/src/sinks/MongoDB.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { setInstance } from "../agent/AgentSingleton";
import { APIForTesting, Token } from "../agent/API";
import { LoggerNoop } from "../agent/Logger";
import { Context, runWithContext } from "../agent/Context";
import { Hooks, wrapPackages } from "../agent/Wrapper";
import { wrap } from "../agent/wrap";
import { Hooks } from "../agent/Wrapper";
import { MongoDB } from "./MongoDB";

const context: Context = {
Expand All @@ -24,7 +25,7 @@ const context: Context = {
t.test("we can highjack the MongoDB library", async (t) => {
const hooks = new Hooks();
new MongoDB().wrap(hooks);
wrapPackages(hooks);
wrap(hooks);

const agent = new Agent(
true,
Expand Down
5 changes: 3 additions & 2 deletions library/src/sinks/Postgres.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { setInstance } from "../agent/AgentSingleton";
import { APIForTesting, Token } from "../agent/API";
import { LoggerNoop } from "../agent/Logger";
import { runWithContext, type Context } from "../agent/Context";
import { Hooks, wrapPackages } from "../agent/Wrapper";
import { wrap } from "../agent/wrap";
import { Hooks } from "../agent/Wrapper";
import { Postgres } from "./Postgres";
import type { Client } from "pg";

Expand All @@ -31,7 +32,7 @@ const context: Context = {
t.test("We can hijack Postgres class", async () => {
const hooks = new Hooks();
new Postgres().wrap(hooks);
wrapPackages(hooks);
wrap(hooks);

const agent = new Agent(
true,
Expand Down
5 changes: 3 additions & 2 deletions library/src/sources/Express.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import * as t from "tap";
import { Hooks, wrapPackages } from "../agent/Wrapper";
import { wrap } from "../agent/wrap";
import { Hooks } from "../agent/Wrapper";
import { Express } from "./Express";

// Before express is required!
const hooks = new Hooks();
new Express().wrap(hooks);
wrapPackages(hooks);
wrap(hooks);

import * as express from "express";
import * as request from "supertest";
Expand Down

0 comments on commit 6f0ad88

Please sign in to comment.