Skip to content

Commit

Permalink
chore:SP-1924 Adds copyleft policy unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
agustingroh committed Dec 10, 2024
1 parent 4cbecae commit f22e879
Show file tree
Hide file tree
Showing 11 changed files with 697 additions and 81 deletions.
4 changes: 2 additions & 2 deletions .github/linters/.eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ rules:
'@typescript-eslint/func-call-spacing': ['error', 'never'],
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-extraneous-class': 'error',
'@typescript-eslint/no-for-in-array': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
Expand All @@ -82,5 +82,5 @@ rules:
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/unbound-method': 'error',
'github/array-foreach' : 'off',
'eslint-comments/no-unlimited-disable': 'off'
'eslint-comments/no-unlimited-disable': 'off',
}
129 changes: 129 additions & 0 deletions __tests__/copyleft-argument-builder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import {
COPYLEFT_LICENSE_EXCLUDE,
COPYLEFT_LICENSE_EXPLICIT,
COPYLEFT_LICENSE_INCLUDE,
OUTPUT_FILEPATH,
REPO_DIR,
RUNTIME_CONTAINER
} from '../src/app.input';
import { CopyLeftArgumentBuilder } from '../src/policies/argument_builders/copyleft-argument-builder';

describe('CopyleftArgumentBuilder', () => {
const defaultCopyleftLicenseExplicit = COPYLEFT_LICENSE_EXPLICIT;
const defaultCopyleftLicenseExclude = COPYLEFT_LICENSE_EXCLUDE;
const defaultCopyleftLicenseInclude = COPYLEFT_LICENSE_INCLUDE;

afterEach(() => {
// Restore all mocks
jest.restoreAllMocks();
(COPYLEFT_LICENSE_EXPLICIT as any) = defaultCopyleftLicenseExplicit;
(COPYLEFT_LICENSE_EXCLUDE as any) = defaultCopyleftLicenseExclude;
(COPYLEFT_LICENSE_INCLUDE as any) = defaultCopyleftLicenseInclude;
});

test('Copyleft explicit test', async () => {
(COPYLEFT_LICENSE_EXPLICIT as any) = 'MIT,Apache-2.0';
(COPYLEFT_LICENSE_EXCLUDE as any) = 'MIT,Apache-2.0';
(REPO_DIR as any) = 'scanoss';
(OUTPUT_FILEPATH as any) = 'results.json';

const builder = new CopyLeftArgumentBuilder();
const cmd = await builder.build();
expect(cmd).toEqual([
'run',
'-v',
'scanoss:/scanoss',
'ghcr.io/scanoss/scanoss-py:v1.18.0',
'inspect',
'copyleft',
'--input',
'results.json',
'--format',
'md',
'--explicit',
'MIT,Apache-2.0'
]);
});

test('Copyleft exclude test', async () => {
(COPYLEFT_LICENSE_EXCLUDE as any) = 'MIT,Apache-2.0';
(REPO_DIR as any) = 'scanoss';
(OUTPUT_FILEPATH as any) = 'results.json';
const builder = new CopyLeftArgumentBuilder();
const cmd = await builder.build();
expect(cmd).toEqual([
'run',
'-v',
'scanoss:/scanoss',
'ghcr.io/scanoss/scanoss-py:v1.18.0',
'inspect',
'copyleft',
'--input',
'results.json',
'--format',
'md',
'--exclude',
'MIT,Apache-2.0'
]);
});

test('Copyleft include test', async () => {
(COPYLEFT_LICENSE_INCLUDE as any) = 'MIT,Apache-2.0,LGPL-3.0-only';
(REPO_DIR as any) = 'scanoss';
(OUTPUT_FILEPATH as any) = 'results.json';
const builder = new CopyLeftArgumentBuilder();
const cmd = await builder.build();
expect(cmd).toEqual([
'run',
'-v',
'scanoss:/scanoss',
'ghcr.io/scanoss/scanoss-py:v1.18.0',
'inspect',
'copyleft',
'--input',
'results.json',
'--format',
'md',
'--include',
'MIT,Apache-2.0,LGPL-3.0-only'
]);
});

test('Copyleft empty parameters test', async () => {
(REPO_DIR as any) = 'scanoss';
(OUTPUT_FILEPATH as any) = 'results.json';
const builder = new CopyLeftArgumentBuilder();
const cmd = await builder.build();
expect(cmd).toEqual([
'run',
'-v',
'scanoss:/scanoss',
RUNTIME_CONTAINER,
'inspect',
'copyleft',
'--input',
'results.json',
'--format',
'md'
]);
});

test('Build Command test', async () => {
(REPO_DIR as any) = 'scanoss';
(OUTPUT_FILEPATH as any) = 'results.json';
const builder = new CopyLeftArgumentBuilder();
const cmd = await builder.build();
expect(cmd).toEqual([
'run',
'-v',
'scanoss:/scanoss',
RUNTIME_CONTAINER,
'inspect',
'copyleft',
'--input',
'results.json',
'--format',
'md'
]);
});
});
112 changes: 79 additions & 33 deletions __tests__/copyleft-policy-check.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import path from 'path';
import {
COPYLEFT_LICENSE_EXCLUDE,
COPYLEFT_LICENSE_EXPLICIT,
COPYLEFT_LICENSE_INCLUDE,
OUTPUT_FILEPATH,
REPO_DIR
} from '../src/app.input';
import { CopyleftPolicyCheck } from '../src/policies/copyleft-policy-check';
import { CONCLUSION, PolicyCheck } from '../src/policies/policy-check';
import { ScannerResults } from '../src/services/result.interfaces';
import { resultsMock } from './results.mock';

// Mock the @actions/github module
jest.mock('@actions/github', () => ({
Expand All @@ -14,49 +20,89 @@ jest.mock('@actions/github', () => ({
getOctokit: jest.fn().mockReturnValue({
rest: {
checks: {
update: jest.fn().mockResolvedValue({})
update: jest.fn().mockResolvedValue({}),
create: jest.fn().mockReturnValue({
data: {
id: 1
}
})
}
}
})
}));

describe('CopyleftPolicyCheck', () => {
let scannerResults: ScannerResults;
let policyCheck: CopyleftPolicyCheck;
const defaultCopyleftLicenseExplicit = COPYLEFT_LICENSE_EXPLICIT;
const defaultCopyleftLicenseExclude = COPYLEFT_LICENSE_EXCLUDE;
const defaultCopyleftLicenseInclude = COPYLEFT_LICENSE_INCLUDE;

beforeEach(() => {
jest.clearAllMocks();
afterEach(() => {
// Restore all mocks
jest.restoreAllMocks();
(COPYLEFT_LICENSE_EXPLICIT as any) = defaultCopyleftLicenseExplicit;
(COPYLEFT_LICENSE_EXCLUDE as any) = defaultCopyleftLicenseExclude;
(COPYLEFT_LICENSE_INCLUDE as any) = defaultCopyleftLicenseInclude;
});

test('Copyleft policy check fail', async () => {
const TEST_DIR = __dirname;
const TEST_REPO_DIR = path.join(TEST_DIR, 'data');
const TEST_RESULTS_FILE = 'results.json';

policyCheck = new CopyleftPolicyCheck();
jest.spyOn(PolicyCheck.prototype, 'uploadArtifact').mockImplementation(async () => {
(REPO_DIR as any) = TEST_REPO_DIR;
(OUTPUT_FILEPATH as any) = TEST_RESULTS_FILE;

jest.spyOn(CopyleftPolicyCheck.prototype, 'uploadArtifact').mockImplementation(async () => {
return Promise.resolve({ id: 123456 });
});
jest.spyOn(PolicyCheck.prototype, 'initStatus').mockImplementation();
jest.spyOn(PolicyCheck.prototype, 'finish').mockImplementation();
});
jest.spyOn(CopyleftPolicyCheck.prototype, 'initStatus').mockImplementation();
jest.spyOn(CopyleftPolicyCheck.prototype, 'updateCheck').mockImplementation();
const copyleftPolicyCheck = new CopyleftPolicyCheck();
await copyleftPolicyCheck.start(1);
await copyleftPolicyCheck.run();
//neutral cause policy policy halt on failure is not set
expect(copyleftPolicyCheck.conclusion).toEqual(CONCLUSION.Neutral);
}, 30000);

it('should pass the policy check when no copyleft components are found', async () => {
scannerResults = JSON.parse(resultsMock[0].content);
await policyCheck.run(scannerResults);
expect(policyCheck.conclusion).toEqual(CONCLUSION.Success);
});
test('Copyleft policy empty results', async () => {
const TEST_DIR = __dirname;
const TEST_REPO_DIR = path.join(TEST_DIR, 'data');
const TEST_RESULTS_FILE = 'results.json';

it('should fail the policy check when copyleft components are found', async () => {
scannerResults = JSON.parse(resultsMock[2].content);
await policyCheck.run(scannerResults);
expect(policyCheck.conclusion).toEqual(CONCLUSION.Neutral);
});
(REPO_DIR as any) = TEST_REPO_DIR;
(OUTPUT_FILEPATH as any) = TEST_RESULTS_FILE;
(COPYLEFT_LICENSE_EXCLUDE as any) = 'GPL-2.0-only';

it('should fail the policy check when copyleft dependencies are found', async () => {
scannerResults = JSON.parse(resultsMock[4].content);
await policyCheck.run(scannerResults);
// NEUTRAL is the same as failure in this context. See inputs.POLICIES_HALT_ON_FAILURE. (Default FALSE)
expect(policyCheck.conclusion).toEqual(CONCLUSION.Neutral);
});
jest.spyOn(CopyleftPolicyCheck.prototype, 'uploadArtifact').mockImplementation(async () => {
return Promise.resolve({ id: 123456 });
});
jest.spyOn(CopyleftPolicyCheck.prototype, 'initStatus').mockImplementation();
jest.spyOn(CopyleftPolicyCheck.prototype, 'updateCheck').mockImplementation();
const copyleftPolicyCheck = new CopyleftPolicyCheck();
await copyleftPolicyCheck.start(1);
await copyleftPolicyCheck.run();
//neutral cause policy policy halt on failure is not set
expect(copyleftPolicyCheck.conclusion).toEqual(CONCLUSION.Success);
}, 30000);

it('should pass the copyleft policy check', async () => {
scannerResults = JSON.parse(resultsMock[5].content);
await policyCheck.run(scannerResults);
expect(policyCheck.conclusion).toEqual(CONCLUSION.Success);
});
test('Copyleft policy explicit licenses', async () => {
const TEST_DIR = __dirname;
const TEST_REPO_DIR = path.join(TEST_DIR, 'data');
const TEST_RESULTS_FILE = 'results.json';

(REPO_DIR as any) = TEST_REPO_DIR;
(OUTPUT_FILEPATH as any) = TEST_RESULTS_FILE;
(COPYLEFT_LICENSE_EXPLICIT as any) = 'MIT,Apache-2.0';

jest.spyOn(CopyleftPolicyCheck.prototype, 'uploadArtifact').mockImplementation(async () => {
return Promise.resolve({ id: 123456 });
});
jest.spyOn(CopyleftPolicyCheck.prototype, 'initStatus').mockImplementation();
jest.spyOn(CopyleftPolicyCheck.prototype, 'updateCheck').mockImplementation();
const copyleftPolicyCheck = new CopyleftPolicyCheck();
await copyleftPolicyCheck.start(1);
await copyleftPolicyCheck.run();
//neutral cause policy policy halt on failure is not set
expect(copyleftPolicyCheck.conclusion).toEqual(CONCLUSION.Neutral);
}, 30000);
});
50 changes: 50 additions & 0 deletions __tests__/data/empty-results.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"crc32c.c": [
{
"id": "none",
"server": {
"kb_version": {
"daily": "24.11.12",
"monthly": "24.10"
},
"version": "5.4.8"
}
}
],
"json.c": [
{
"id": "none",
"server": {
"kb_version": {
"daily": "24.11.12",
"monthly": "24.10"
},
"version": "5.4.8"
}
}
],
"log.c": [
{
"id": "none",
"server": {
"kb_version": {
"daily": "24.11.12",
"monthly": "24.10"
},
"version": "5.4.8"
}
}
],
"package.json": [
{
"id": "none",
"server": {
"kb_version": {
"daily": "24.11.12",
"monthly": "24.10"
},
"version": "5.4.8"
}
}
]
}
28 changes: 28 additions & 0 deletions __tests__/data/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "scanoss",
"version": "0.15.3",
"description": "The SCANOSS JS package provides a simple, easy to consume module for interacting with SCANOSS APIs/Engine.",
"main": "build/main/index.js",
"typings": "build/main/index.d.ts",
"module": "build/module/index.js",
"repository": "https://github.com/scanoss/scanoss.js",
"license": "MIT",
"keywords": [],
"bin": {
"scanoss-js": "build/main/cli/bin/cli-bin.js"
},
"scripts": {
"build": "run-p build:*",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"test": "nyc mocha -r ts-node/register 'tests/**/*.ts' 'src/**/*.spec.ts'",
"install-dev": "npm run build && npm run test && npm install -g ."
},
"engines": {
"node": ">=10"
},
"dependencies": {
"@grpc/grpc-js": "^1.5.5",
"abort-controller": "^3.0.0"
}
}
Loading

0 comments on commit f22e879

Please sign in to comment.