fix remote libraries listing backend and frontend (#7688)

This commit is contained in:
Patrick Quist
2025-05-16 16:53:40 +02:00
committed by GitHub
parent c157507f72
commit bd9e2d4cbc
8 changed files with 135 additions and 14 deletions

View File

@@ -0,0 +1,9 @@
import {runFrontendTest} from '../support/utils';
describe('RemoteId testing', () => {
before(() => {
cy.visit('/');
});
runFrontendTest('remoteId');
});

View File

@@ -37,6 +37,7 @@ import type {Source} from '../types/source.interfaces.js';
import type {ToolTypeKey} from '../types/tool.interfaces.js';
import {AppArguments} from './app.interfaces.js';
import {getRemoteId} from '../shared/remote-utils.js';
import {logger} from './logger.js';
import type {PropertyGetter, PropertyValue} from './properties.interfaces.js';
import {CompilerProps} from './properties.js';
@@ -376,11 +377,6 @@ export class ClientOptionsHandler {
return libraries;
}
getRemoteId(remoteUrl: string, language: LanguageKey) {
const url = new URL(remoteUrl);
return url.host.replaceAll('.', '_') + '_' + language;
}
libArrayToObject(libsArr: any[]) {
const libs: Record<string, any> = {};
for (const lib of libsArr) {
@@ -397,9 +393,9 @@ export class ClientOptionsHandler {
}
async getRemoteLibraries(language: LanguageKey, remoteUrl: string) {
const remoteId = this.getRemoteId(remoteUrl, language);
const remoteId = getRemoteId(remoteUrl, language);
if (!this.remoteLibs[remoteId]) {
return new Promise(resolve => {
return await new Promise(resolve => {
const url = ClientOptionsHandler.getRemoteUrlForLibraries(remoteUrl, language);
logger.info(`Fetching remote libraries from ${url}`);
let fullData = '';

28
shared/remote-utils.ts Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (c) 2025, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
export function getRemoteId(remoteUrl: string, language: string): string {
const url: URL = new URL(remoteUrl);
return url.host.replace(/\./g, '_') + url.pathname.replace(/\//g, '_') + '_' + language;
}

32
shared/url-testcases.ts Normal file
View File

@@ -0,0 +1,32 @@
export const UrlTestCases = [
{
remoteUrl: 'https://example.com/path/to/resource',
language: 'cpp',
expectedId: 'example_com_path_to_resource_cpp',
},
{
remoteUrl: 'https://example.com',
language: 'java',
expectedId: 'example_com__java',
},
{
remoteUrl: 'https://sub.domain.com/a/b/c/',
language: 'rust',
expectedId: 'sub_domain_com_a_b_c__rust',
},
{
remoteUrl: 'https://godbolt.org:443/gpu',
language: 'c++',
expectedId: 'godbolt_org_gpu_c++',
},
{
remoteUrl: 'https://godbolt.org:443/winprod',
language: 'c++',
expectedId: 'godbolt_org_winprod_c++',
},
{
remoteUrl: 'https://godbolt.org:443',
language: 'c++',
expectedId: 'godbolt_org__c++',
},
];

View File

@@ -22,19 +22,15 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
import {getRemoteId} from '../shared/remote-utils.js';
import {Remote} from './compiler.interfaces.js';
import {LanguageLibs, Library} from './options.interfaces.js';
import {options} from './options.js';
const LIB_MATCH_RE = /([\w-]*)\.([\w-]*)/i;
function getRemoteId(language: string, remoteUrl: string): string {
const url: URL = new URL(remoteUrl);
return url.host.replace(/\./g, '_') + '_' + language;
}
function getRemoteLibraries(language: string, remoteUrl: string): LanguageLibs {
const remoteId = getRemoteId(language, remoteUrl);
const remoteId = getRemoteId(remoteUrl, language);
return options.remoteLibs[remoteId];
}
@@ -78,7 +74,7 @@ export function getSupportedLibraries(
}
return allLibs;
}
const allLibs = getRemoteLibraries(langId, remote.target);
const allLibs = getRemoteLibraries(langId, remote.target + remote.basePath);
if (supportedLibrariesArr && supportedLibrariesArr.length > 0) {
return copyAndFilterLibraries(allLibs, supportedLibrariesArr);
}

View File

@@ -25,3 +25,4 @@
import './frontend-testing';
import './hello-world';
import './motd';
import './remote-id';

47
static/tests/remote-id.ts Normal file
View File

@@ -0,0 +1,47 @@
// Copyright (c) 2025, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
/// <reference path="../../node_modules/cypress/types/cypress-global-vars.d.ts" />
import {getRemoteId} from '../../shared/remote-utils.js';
import {UrlTestCases} from '../../shared/url-testcases.js';
import {ITestable} from './frontend-testing.interfaces.js';
class RemoteIdTests implements ITestable {
public readonly description: string = 'remoteId';
public async run() {
UrlTestCases.forEach(testCase => {
if (getRemoteId(testCase.remoteUrl, testCase.language) !== testCase.expectedId) {
throw new Error(
`Test case failed for language: ${testCase.language}, remoteUrl: ${testCase.remoteUrl}, expectedId: ${testCase.expectedId}`,
);
}
});
}
}
window.compilerExplorerFrontendTesting.add(new RemoteIdTests());

View File

@@ -37,6 +37,9 @@ import {BaseTool} from '../lib/tooling/base-tool.js';
import {CompilerInfo} from '../types/compiler.interfaces.js';
import {LanguageKey} from '../types/languages.interfaces.js';
import {getRemoteId} from '../shared/remote-utils.js';
import {UrlTestCases} from '../shared/url-testcases.js';
import {makeFakeCompilerInfo} from './utils.js';
const languages = {
@@ -593,4 +596,13 @@ describe('Options handler', () => {
expect(librariesUrl).toEqual('https://godbolt.org:443/gpu/api/libraries/c++');
});
describe('getRemoteId', () => {
UrlTestCases.forEach(testCase => {
it(`should generate remote ID for URL "${testCase.remoteUrl}" with language "${testCase.language}"`, () => {
const result = getRemoteId(testCase.remoteUrl, testCase.language);
expect(result).toBe(testCase.expectedId);
});
});
});
});