diff --git a/src/practices/Java/JavaLoggerUsedPractice.spec.ts b/src/practices/Java/JavaLoggerUsedPractice.spec.ts new file mode 100644 index 000000000..a438e586a --- /dev/null +++ b/src/practices/Java/JavaLoggerUsedPractice.spec.ts @@ -0,0 +1,50 @@ +import { JavaLoggerUsedPractice } from './JavaLoggerUsedPractice'; +import { PracticeEvaluationResult, ProgrammingLanguage } from '../../model'; +import { TestContainerContext, createTestContainer } from '../../inversify.config'; +import { IPackageInspector } from '../../inspectors/IPackageInspector'; + +describe('JavaLoggerUsedPractice', () => { + let practice: JavaLoggerUsedPractice; + let containerCtx: TestContainerContext; + let packageInspector: IPackageInspector; + + beforeAll(() => { + containerCtx = createTestContainer(); + containerCtx.container.bind('JavaLoggerUsedPractice').to(JavaLoggerUsedPractice); + practice = containerCtx.container.get('JavaLoggerUsedPractice'); + packageInspector = containerCtx.practiceContext.packageInspector; + }); + + it('Detects a Java logger dependency', async () => { + packageInspector.hasOneOfPackages = () => true; + + const result = await practice.evaluate(containerCtx.practiceContext); + expect(result).toEqual(PracticeEvaluationResult.practicing); + }); + + it('Did not detect a Java logger dependency', async () => { + packageInspector.hasOneOfPackages = () => false; + + const result = await practice.evaluate(containerCtx.practiceContext); + expect(result).toEqual(PracticeEvaluationResult.notPracticing); + }); + + it('Did not recognize packageInspector', async () => { + const result = await practice.evaluate({ ...containerCtx.practiceContext, packageInspector: undefined }); + expect(result).toEqual(PracticeEvaluationResult.unknown); + }); + + it('Is applicable if it is Java', async () => { + containerCtx.practiceContext.projectComponent.language = ProgrammingLanguage.Java; + + const result = await practice.isApplicable(containerCtx.practiceContext); + expect(result).toEqual(true); + }); + + it('Is applicable if it is not Java', async () => { + containerCtx.practiceContext.projectComponent.language = ProgrammingLanguage.Haskell; + + const result = await practice.isApplicable(containerCtx.practiceContext); + expect(result).toEqual(false); + }); +}); diff --git a/src/practices/Java/JavaLoggerUsedPractice.ts b/src/practices/Java/JavaLoggerUsedPractice.ts new file mode 100644 index 000000000..648c81923 --- /dev/null +++ b/src/practices/Java/JavaLoggerUsedPractice.ts @@ -0,0 +1,38 @@ +import { IPractice } from '../IPractice'; +import { PracticeEvaluationResult, PracticeImpact, ProgrammingLanguage } from '../../model'; +import { DxPractice } from '../DxPracticeDecorator'; +import { PracticeContext } from '../../contexts/practice/PracticeContext'; + +@DxPractice({ + id: 'Java.LoggerUsedPractice', + name: 'Use a Java Logging Dependency', + impact: PracticeImpact.small, + suggestion: + 'Use a logging library to avoid errors and even cyber attacks. The most widely used logging library in the Java community is Log4j 2.', + reportOnlyOnce: true, + url: 'https://logging.apache.org/log4j/2.x/', +}) +export class JavaLoggerUsedPractice implements IPractice { + async isApplicable(ctx: PracticeContext): Promise { + return ctx.projectComponent.language === ProgrammingLanguage.Java; + } + + async evaluate(ctx: PracticeContext): Promise { + if (!ctx.packageInspector) { + return PracticeEvaluationResult.unknown; + } + + if ( + ctx.packageInspector.hasOneOfPackages([ + 'org.apache.logging.log4j:log4j', + 'org.apache.logging.log4j:log4j-api', + 'org.apache.logging.log4j:log4j-core', + 'ch.qos.logback:logback-classic', + 'org.slf4j:slf4j-api', + ]) + ) { + return PracticeEvaluationResult.practicing; + } + return PracticeEvaluationResult.notPracticing; + } +} diff --git a/src/practices/index.ts b/src/practices/index.ts index 4d03d0f73..c5b8e0ee0 100644 --- a/src/practices/index.ts +++ b/src/practices/index.ts @@ -31,6 +31,7 @@ import { ThinPullRequestsPractice } from './LanguageIndependent/ThinPullRequests import { SecurityVulnerabilitiesPractice } from './JavaScript/SecurityVulnerabilitiesPractice'; import { FirstTestPractice, SecondTestPractice, InvalidTestPractice } from '../scanner'; import { JavaPackageManagementUsedPractice } from './Java/JavaPackageManagementUsed'; +import { JavaLoggerUsedPractice } from './Java/JavaLoggerUsedPractice'; import { JavaTestingFrameworkUsedPractice } from './Java/JavaTestingFrameworkUsedPractice'; import { JavaMockingFrameworkUsedPractice } from './Java/JavaMockingFrameworkUsed'; @@ -68,6 +69,7 @@ export const practices = [ ThinPullRequestsPractice, SecurityVulnerabilitiesPractice, JavaPackageManagementUsedPractice, + JavaLoggerUsedPractice, JavaTestingFrameworkUsedPractice, JavaMockingFrameworkUsedPractice, ];