Add library versions to data extensions editor

This commit is contained in:
Koen Vlaswinkel
2023-06-29 15:24:06 +02:00
parent 10d9213dbe
commit f91da95081
14 changed files with 339 additions and 62 deletions

View File

@@ -5,6 +5,7 @@ import {
ExternalApiUsage,
} from "./external-api-usage";
import { ModeledMethodType } from "./modeled-method";
import { parseLibraryFilename } from "./library";
export function decodeBqrsToExternalApiUsages(
chunk: DecodedBqrsChunk,
@@ -15,7 +16,8 @@ export function decodeBqrsToExternalApiUsages(
const usage = tuple[0] as Call;
const signature = tuple[1] as string;
const supported = (tuple[2] as string) === "true";
const library = tuple[4] as string;
let library = tuple[4] as string;
let libraryVersion: string | undefined = tuple[5] as string;
const type = tuple[6] as ModeledMethodType;
const classification = tuple[8] as CallClassification;
@@ -37,9 +39,25 @@ export function decodeBqrsToExternalApiUsages(
methodDeclaration.indexOf("("),
);
// For Java, we'll always get back a .jar file, and the library version may be bad because not all library authors
// properly specify the version. Therefore, we'll always try to parse the name and version from the library filename
// for Java.
if (library.endsWith(".jar") || libraryVersion === "") {
const { name, version } = parseLibraryFilename(library);
library = name;
if (version) {
libraryVersion = version;
}
}
if (libraryVersion === "") {
libraryVersion = undefined;
}
if (!methodsByApiName.has(signature)) {
methodsByApiName.set(signature, {
library,
libraryVersion,
signature,
packageName,
typeName,

View File

@@ -22,6 +22,10 @@ export type ExternalApiUsage = {
* Contains the name of the library containing the method declaration, e.g. `sql2o-1.6.0.jar` or `System.Runtime.dll`
*/
library: string;
/**
* Contains the version of the library if it can be determined by CodeQL, e.g. `4.2.2.2`
*/
libraryVersion?: string;
/**
* A unique signature that can be used to identify this external API usage.
*

View File

@@ -0,0 +1,55 @@
import { basename, extname } from "../common/path";
// From the semver package using
// const { re, t } = require("semver/internal/re");
// console.log(re[t.LOOSE]);
// Modifications:
// - Added version named group which does not capture the v prefix
// - Removed the ^ and $ anchors
// - Made the minor and patch versions optional
// This will match any semver string at the end of a larger string
const semverRegex =
/[v=\s]*(?<version>([0-9]+)(\.([0-9]+)(?:\.([0-9]+)(?:-?((?:[0-9]+|\d*[a-zA-Z-][a-zA-Z0-9-]*)(?:\.(?:[0-9]+|\d*[a-zA-Z-][a-zA-Z0-9-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?)?)?)/g;
export interface Library {
name: string;
version?: string;
}
export function parseLibraryFilename(filename: string): Library {
let libraryName = basename(filename);
const extension = extname(libraryName);
libraryName = libraryName.slice(0, -extension.length);
let libraryVersion: string | undefined;
let match: RegExpMatchArray | null = null;
// Reset the regex
semverRegex.lastIndex = 0;
// Find the last occurence of the regex within the library name
// eslint-disable-next-line no-constant-condition
while (true) {
const currentMatch = semverRegex.exec(libraryName);
if (currentMatch === null) {
break;
}
match = currentMatch;
}
if (match?.groups) {
libraryVersion = match.groups?.version;
// Remove everything after the start of the match
libraryName = libraryName.slice(0, match.index);
}
// Remove any leading or trailing hyphens or dots
libraryName = libraryName.replaceAll(/^[.-]+|[.-]+$/g, "");
return {
name: libraryName,
version: libraryVersion,
};
}

View File

@@ -30,8 +30,8 @@ where
usage = aUsage(api) and
type = supportedType(api) and
classification = methodClassification(usage)
select usage, apiName, supported.toString(), "supported", api.getFile().getBaseName(), "library",
type, "type", classification, "classification"
select usage, apiName, supported.toString(), "supported", api.dllName(), api.dllVersion(), type,
"type", classification, "classification"
`,
frameworkModeQuery: `/**
* @name Public methods
@@ -111,7 +111,7 @@ class CallableMethod extends DotNet::Declaration {
bindingset[this]
private string getSignature() {
result =
nestedName(this.getDeclaringType().getUnboundDeclaration()) + "." + this.getName() + "(" +
nestedName(this.getDeclaringType().getUnboundDeclaration()) + "#" + this.getName() + "(" +
parameterQualifiedTypeNamesToString(this) + ")"
}
@@ -125,7 +125,23 @@ class CallableMethod extends DotNet::Declaration {
* Gets the namespace and signature of this API.
*/
bindingset[this]
string getApiName() { result = this.getNamespace() + "#" + this.getSignature() }
string getApiName() { result = this.getNamespace() + "." + this.getSignature() }
private string getDllName() { result = this.getLocation().(Assembly).getName() }
private string getDllVersion() { result = this.getLocation().(Assembly).getVersion().toString() }
string dllName() {
result = this.getDllName()
or
not exists(this.getDllName()) and result = this.getFile().getBaseName()
}
string dllVersion() {
result = this.getDllVersion()
or
not exists(this.getDllVersion()) and result = ""
}
/** Gets a node that is an input to a call to this API. */
private ArgumentNode getAnInput() {
@@ -195,7 +211,7 @@ string supportedType(CallableMethod method) {
or
method.isNeutral() and result = "neutral"
or
not method.isSupported() and result = "none"
not method.isSupported() and result = ""
}
string methodClassification(Call method) {

View File

@@ -27,8 +27,8 @@ where
usage = aUsage(externalApi) and
type = supportedType(externalApi) and
classification = methodClassification(usage)
select usage, apiName, supported.toString(), "supported", externalApi.jarContainer(), "library",
type, "type", classification, "classification"
select usage, apiName, supported.toString(), "supported", externalApi.jarContainer(),
externalApi.jarVersion(), type, "type", classification, "classification"
`,
frameworkModeQuery: `/**
* @name Public methods
@@ -75,7 +75,7 @@ private predicate isUninteresting(Callable c) {
/**
* A callable method from either the Standard Library, a 3rd party library or from the source.
*/
class CallableMethod extends Method {
class CallableMethod extends Callable {
CallableMethod() { not isUninteresting(this) }
/**
@@ -91,6 +91,10 @@ class CallableMethod extends Method {
result = this.getCompilationUnit().getParentContainer*().(JarFile).getBaseName()
}
private string getJarVersion() {
result = this.getCompilationUnit().getParentContainer*().(JarFile).getSpecificationVersion()
}
/**
* Gets the jar file containing this API. Normalizes the Java Runtime to "rt.jar" despite the presence of modules.
*/
@@ -100,6 +104,15 @@ class CallableMethod extends Method {
not exists(this.getJarName()) and result = "rt.jar"
}
/**
* Gets the version of the JAR file containing this API. Empty if no version is found in the JAR.
*/
string jarVersion() {
result = this.getJarVersion()
or
not exists(this.getJarVersion()) and result = ""
}
/** Gets a node that is an input to a call to this API. */
private DataFlow::Node getAnInput() {
exists(Call call | call.getCallee().getSourceDeclaration() = this |
@@ -160,7 +173,7 @@ string supportedType(CallableMethod method) {
or
method.isNeutral() and result = "neutral"
or
not method.isSupported() and result = "none"
not method.isSupported() and result = ""
}
string methodClassification(Call method) {

View File

@@ -8,7 +8,7 @@ export type Query = {
* - supported: whether the external API is modeled. This should be a string representation of a boolean to satify the result pattern for a problem query.
* - "supported": a string literal. This is required to make the query a valid problem query.
* - libraryName: the name of the library that contains the external API. This is a string and usually the basename of a file.
* - "library": a string literal. This is required to make the query a valid problem query.
* - libraryVersion: the version of the library that contains the external API. This is a string and can be empty if the version cannot be determined.
* - type: the modeled kind of the method, either "sink", "source", "summary", or "neutral"
* - "type": a string literal. This is required to make the query a valid problem query.
* - classification: the classification of the use of the method, either "source", "test", "generated", or "unknown"
@@ -25,7 +25,7 @@ export type Query = {
* - supported: whether this method is modeled. This should be a string representation of a boolean to satify the result pattern for a problem query.
* - "supported": a string literal. This is required to make the query a valid problem query.
* - libraryName: an arbitrary string. This is required to make it match the structure of the application query.
* - "library": a string literal. This is required to make the query a valid problem query.
* - libraryVersion: an arbitrary string. This is required to make it match the structure of the application query.
* - type: the modeled kind of the method, either "sink", "source", "summary", or "neutral"
* - "type": a string literal. This is required to make the query a valid problem query.
* - "unknown": a string literal. This is required to make it match the structure of the application query.

View File

@@ -1,6 +1,5 @@
import Ajv from "ajv";
import { basename, extname } from "../common/path";
import { ExternalApiUsage } from "./external-api-usage";
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
import {
@@ -144,29 +143,12 @@ export function createDataExtensionYamlsForFrameworkMode(
};
}
// From the semver package using
// const { re, t } = require("semver/internal/re");
// console.log(re[t.LOOSE]);
// Modified to remove the ^ and $ anchors
// This will match any semver string at the end of a larger string
const semverRegex =
/[v=\s]*([0-9]+)\.([0-9]+)\.([0-9]+)(?:-?((?:[0-9]+|\d*[a-zA-Z-][a-zA-Z0-9-]*)(?:\.(?:[0-9]+|\d*[a-zA-Z-][a-zA-Z0-9-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?/;
export function createFilenameForLibrary(
library: string,
prefix = "models/",
suffix = ".model",
) {
let libraryName = basename(library);
const extension = extname(libraryName);
libraryName = libraryName.slice(0, -extension.length);
const match = semverRegex.exec(libraryName);
if (match !== null) {
// Remove everything after the start of the match
libraryName = libraryName.slice(0, match.index);
}
let libraryName = library;
// Lowercase everything
libraryName = libraryName.toLowerCase();

View File

@@ -33,7 +33,8 @@ DataExtensionsEditor.args = {
},
initialExternalApiUsages: [
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Connection#createQuery(String)",
packageName: "org.sql2o",
typeName: "Connection",
@@ -54,7 +55,8 @@ DataExtensionsEditor.args = {
}),
},
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Query#executeScalar(Class)",
packageName: "org.sql2o",
typeName: "Query",
@@ -75,7 +77,8 @@ DataExtensionsEditor.args = {
}),
},
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Sql2o#open()",
packageName: "org.sql2o",
typeName: "Sql2o",
@@ -96,7 +99,7 @@ DataExtensionsEditor.args = {
}),
},
{
library: "rt.jar",
library: "rt",
signature: "java.io.PrintStream#println(String)",
packageName: "java.io",
typeName: "PrintStream",
@@ -130,7 +133,8 @@ DataExtensionsEditor.args = {
],
},
{
library: "spring-boot-3.0.2.jar",
library: "spring-boot",
libraryVersion: "3.0.2",
signature:
"org.springframework.boot.SpringApplication#run(Class,String[])",
packageName: "org.springframework.boot",
@@ -152,7 +156,8 @@ DataExtensionsEditor.args = {
}),
},
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
packageName: "org.sql2o",
typeName: "Sql2o",
@@ -173,7 +178,8 @@ DataExtensionsEditor.args = {
}),
},
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Sql2o#Sql2o(String)",
packageName: "org.sql2o",
typeName: "Sql2o",

View File

@@ -68,6 +68,7 @@ const ButtonsContainer = styled.div`
type Props = {
title: string;
libraryVersion?: string;
externalApiUsages: ExternalApiUsage[];
modeledMethods: Record<string, ModeledMethod>;
viewState: DataExtensionEditorViewState;
@@ -91,6 +92,7 @@ type Props = {
export const LibraryRow = ({
title,
libraryVersion,
externalApiUsages,
modeledMethods,
viewState,
@@ -158,7 +160,10 @@ export const LibraryRow = ({
<Codicon name="chevron-right" label="Expand" />
)}
<NameContainer>
<DependencyName>{title}</DependencyName>
<DependencyName>
{title}
{libraryVersion && <>@{libraryVersion}</>}
</DependencyName>
<ModeledPercentage>
{percentFormatter.format(modeledPercentage / 100)} modeled
</ModeledPercentage>

View File

@@ -266,8 +266,10 @@ function UnmodelableMethodRow(props: Props) {
function ExternalApiUsageName(props: { externalApiUsage: ExternalApiUsage }) {
return (
<span>
{props.externalApiUsage.packageName}.{props.externalApiUsage.typeName}.
{props.externalApiUsage.methodName}
{props.externalApiUsage.packageName && (
<>{props.externalApiUsage.packageName}.</>
)}
{props.externalApiUsage.typeName}.{props.externalApiUsage.methodName}
{props.externalApiUsage.methodParameters}
</span>
);

View File

@@ -3,6 +3,7 @@ import { useMemo } from "react";
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
import { ModeledMethod } from "../../data-extensions-editor/modeled-method";
import { LibraryRow } from "./LibraryRow";
import { Mode } from "../../data-extensions-editor/shared/mode";
import {
groupMethods,
sortGroupNames,
@@ -31,6 +32,10 @@ type Props = {
onGenerateFromSourceClick: () => void;
};
const libraryNameOverrides: Record<string, string> = {
rt: "Java Runtime",
};
export const ModeledMethodsList = ({
externalApiUsages,
unsavedModels,
@@ -46,6 +51,24 @@ export const ModeledMethodsList = ({
[externalApiUsages, viewState.mode],
);
const libraryVersions = useMemo(() => {
if (viewState.mode !== Mode.Application) {
return {};
}
const libraryVersions: Record<string, string> = {};
for (const externalApiUsage of externalApiUsages) {
const { library, libraryVersion } = externalApiUsage;
if (library && libraryVersion) {
libraryVersions[library] = libraryVersion;
}
}
return libraryVersions;
}, [externalApiUsages, viewState.mode]);
const sortedGroupNames = useMemo(() => sortGroupNames(grouped), [grouped]);
return (
@@ -53,7 +76,8 @@ export const ModeledMethodsList = ({
{sortedGroupNames.map((libraryName) => (
<LibraryRow
key={libraryName}
title={libraryName}
title={libraryNameOverrides[libraryName] ?? libraryName}
libraryVersion={libraryVersions[libraryName]}
externalApiUsages={grouped[libraryName]}
hasUnsavedChanges={unsavedModels.has(libraryName)}
modeledMethods={modeledMethods}

View File

@@ -1,5 +1,6 @@
import { decodeBqrsToExternalApiUsages } from "../../../src/data-extensions-editor/bqrs";
import { DecodedBqrsChunk } from "../../../src/common/bqrs-cli-types";
import { CallClassification } from "../../../src/data-extensions-editor/external-api-usage";
describe("decodeBqrsToExternalApiUsages", () => {
const chunk: DecodedBqrsChunk = {
@@ -8,6 +9,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
{ name: "apiName", kind: "String" },
{ kind: "String" },
{ kind: "String" },
{ kind: "String" },
{ kind: "String" },
{ name: "type", kind: "String" },
{ kind: "String" },
{ name: "classification", kind: "String" },
{ kind: "String" },
],
tuples: [
[
@@ -24,6 +31,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"java.io.PrintStream#println(String)",
"true",
"supported",
"rt.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -39,6 +52,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.springframework.boot.SpringApplication#run(Class,String[])",
"false",
"supported",
"spring-boot-3.0.2.jar",
"",
"none",
"type",
"source",
"classification",
],
[
{
@@ -54,6 +73,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Connection#createQuery(String)",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -69,6 +94,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Connection#createQuery(String)",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -84,6 +115,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Query#executeScalar(Class)",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -99,6 +136,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Query#executeScalar(Class)",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -114,6 +157,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Sql2o#open()",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -129,6 +178,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Sql2o#open()",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -144,6 +199,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Sql2o#Sql2o(String,String,String)",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
[
{
@@ -159,6 +220,12 @@ describe("decodeBqrsToExternalApiUsages", () => {
"org.sql2o.Sql2o#Sql2o(String)",
"true",
"supported",
"sql2o-1.6.0.jar",
"",
"sink",
"type",
"source",
"classification",
],
],
};
@@ -169,12 +236,15 @@ describe("decodeBqrsToExternalApiUsages", () => {
// - Sorting the array of usages is guaranteed to be a stable sort
expect(decodeBqrsToExternalApiUsages(chunk)).toEqual([
{
library: "rt",
libraryVersion: undefined,
signature: "java.io.PrintStream#println(String)",
packageName: "java.io",
typeName: "PrintStream",
methodName: "println",
methodParameters: "(String)",
supported: true,
supportedType: "sink",
usages: [
{
label: "println(...)",
@@ -185,10 +255,13 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 29,
endColumn: 49,
},
classification: CallClassification.Source,
},
],
},
{
library: "spring-boot",
libraryVersion: "3.0.2",
signature:
"org.springframework.boot.SpringApplication#run(Class,String[])",
packageName: "org.springframework.boot",
@@ -196,6 +269,7 @@ describe("decodeBqrsToExternalApiUsages", () => {
methodName: "run",
methodParameters: "(Class,String[])",
supported: false,
supportedType: "none",
usages: [
{
label: "run(...)",
@@ -206,16 +280,20 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 9,
endColumn: 66,
},
classification: CallClassification.Source,
},
],
},
{
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Connection#createQuery(String)",
packageName: "org.sql2o",
typeName: "Connection",
methodName: "createQuery",
methodParameters: "(String)",
supported: true,
supportedType: "sink",
usages: [
{
label: "createQuery(...)",
@@ -226,6 +304,7 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 15,
endColumn: 56,
},
classification: CallClassification.Source,
},
{
label: "createQuery(...)",
@@ -236,16 +315,20 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 26,
endColumn: 39,
},
classification: CallClassification.Source,
},
],
},
{
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Query#executeScalar(Class)",
packageName: "org.sql2o",
typeName: "Query",
methodName: "executeScalar",
methodParameters: "(Class)",
supported: true,
supportedType: "sink",
usages: [
{
label: "executeScalar(...)",
@@ -256,6 +339,7 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 15,
endColumn: 85,
},
classification: CallClassification.Source,
},
{
label: "executeScalar(...)",
@@ -266,16 +350,20 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 26,
endColumn: 68,
},
classification: CallClassification.Source,
},
],
},
{
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Sql2o#open()",
packageName: "org.sql2o",
typeName: "Sql2o",
methodName: "open",
methodParameters: "()",
supported: true,
supportedType: "sink",
usages: [
{
label: "open(...)",
@@ -286,6 +374,7 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 14,
endColumn: 35,
},
classification: CallClassification.Source,
},
{
label: "open(...)",
@@ -296,16 +385,20 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 25,
endColumn: 35,
},
classification: CallClassification.Source,
},
],
},
{
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
packageName: "org.sql2o",
typeName: "Sql2o",
methodName: "Sql2o",
methodParameters: "(String,String,String)",
supported: true,
supportedType: "sink",
usages: [
{
label: "new Sql2o(...)",
@@ -316,16 +409,20 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 10,
endColumn: 88,
},
classification: CallClassification.Source,
},
],
},
{
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Sql2o#Sql2o(String)",
packageName: "org.sql2o",
typeName: "Sql2o",
methodName: "Sql2o",
methodParameters: "(String)",
supported: true,
supportedType: "sink",
usages: [
{
label: "new Sql2o(...)",
@@ -336,6 +433,7 @@ describe("decodeBqrsToExternalApiUsages", () => {
endLine: 23,
endColumn: 36,
},
classification: CallClassification.Source,
},
],
},

View File

@@ -0,0 +1,59 @@
import { parseLibraryFilename } from "../../../src/data-extensions-editor/library";
describe("parseLibraryFilename", () => {
const testCases = [
{ filename: "sql2o-1.6.0.jar", name: "sql2o", version: "1.6.0" },
{
filename: "spring-boot-3.0.2.jar",
name: "spring-boot",
version: "3.0.2",
},
{ filename: "rt.jar", name: "rt", version: undefined },
{ filename: "guava-15.0.jar", name: "guava", version: "15.0" },
{
filename: "embedded-db-junit-1.0.0.jar",
name: "embedded-db-junit",
version: "1.0.0",
},
{
filename: "h2-1.3.160.jar",
name: "h2",
version: "1.3.160",
},
{
filename: "joda-time-2.0.jar",
name: "joda-time",
version: "2.0",
},
{
filename: "System.Runtime.dll",
name: "System.Runtime",
version: undefined,
},
{
filename: "System.Linq.Expressions.dll",
name: "System.Linq.Expressions",
version: undefined,
},
{
filename: "System.Diagnostics.Debug.dll",
name: "System.Diagnostics.Debug",
version: undefined,
},
{
filename: "spring-boot-3.1.0-rc2.jar",
name: "spring-boot",
version: "3.1.0-rc2",
},
];
test.each(testCases)(
"$filename is $name@$version",
({ filename, name, version }) => {
expect(parseLibraryFilename(filename)).toEqual({
name,
version,
});
},
);
});

View File

@@ -148,7 +148,8 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
"java",
[
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Connection#createQuery(String)",
packageName: "org.sql2o",
typeName: "Connection",
@@ -182,7 +183,8 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
],
},
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
libraryVersion: "1.6.0",
signature: "org.sql2o.Query#executeScalar(Class)",
packageName: "org.sql2o",
typeName: "Query",
@@ -216,7 +218,8 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
],
},
{
library: "sql2o-2.5.0-alpha1.jar",
library: "sql2o",
libraryVersion: "2.5.0-alpha1",
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
packageName: "org.sql2o",
typeName: "Sql2o",
@@ -239,7 +242,8 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
],
},
{
library: "spring-boot-3.0.2.jar",
library: "spring-boot",
libraryVersion: "3.0.2",
signature:
"org.springframework.boot.SpringApplication#run(Class,String[])",
packageName: "org.springframework.boot",
@@ -263,7 +267,7 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
],
},
{
library: "rt.jar",
library: "rt",
signature: "java.io.PrintStream#println(String)",
packageName: "java.io",
typeName: "PrintStream",
@@ -566,37 +570,28 @@ describe("loadDataExtensionYaml", () => {
describe("createFilenameForLibrary", () => {
const testCases = [
{ library: "sql2o.jar", filename: "models/sql2o.model.yml" },
{
library: "sql2o-1.6.0.jar",
library: "sql2o",
filename: "models/sql2o.model.yml",
},
{
library: "spring-boot-3.0.2.jar",
library: "spring-boot",
filename: "models/spring-boot.model.yml",
},
{
library: "spring-boot-v3.0.2.jar",
library: "spring--boot",
filename: "models/spring-boot.model.yml",
},
{
library: "spring-boot-3.0.2-alpha1.jar",
filename: "models/spring-boot.model.yml",
},
{
library: "spring-boot-3.0.2beta2.jar",
filename: "models/spring-boot.model.yml",
},
{
library: "rt.jar",
library: "rt",
filename: "models/rt.model.yml",
},
{
library: "System.Runtime.dll",
library: "System.Runtime",
filename: "models/system.runtime.model.yml",
},
{
library: "System.Runtime.1.5.0.dll",
library: "System..Runtime",
filename: "models/system.runtime.model.yml",
},
];