|  | // Copyright (c) 2016, 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. | 
|  |  | 
|  | import path from 'path'; | 
|  |  | 
|  | import approvals from 'approvals'; | 
|  |  | 
|  | import {AsmParser} from '../lib/parsers/asm-parser'; | 
|  | import {SassAsmParser} from '../lib/parsers/asm-parser-sass'; | 
|  | import {VcAsmParser} from '../lib/parsers/asm-parser-vc'; | 
|  |  | 
|  | import {fs, resolvePathFromTestRoot} from './utils'; | 
|  |  | 
|  | approvals.mocha(); | 
|  |  | 
|  | function processAsm(filename, filters) { | 
|  | const file = fs.readFileSync(filename, 'utf-8'); | 
|  | let parser; | 
|  | if (file.includes('Microsoft')) parser = new VcAsmParser(); | 
|  | else if (filename.includes('sass-')) parser = new SassAsmParser(); | 
|  | else { | 
|  | parser = new AsmParser(); | 
|  | parser.binaryHideFuncRe = | 
|  | /^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|\.plt.*|_dl_relocate_static_pie)$/; | 
|  | } | 
|  | return parser.process(file, filters); | 
|  | } | 
|  |  | 
|  | const casesRoot = resolvePathFromTestRoot('filters-cases'); | 
|  | const files = fs.readdirSync(casesRoot); | 
|  | const filesInCaseDir = files.map(x => resolvePathFromTestRoot('filters-cases', x)); | 
|  |  | 
|  | const cases = filesInCaseDir.filter(x => x.endsWith('.asm')); | 
|  |  | 
|  | const optionsOverride = { | 
|  | forceApproveAll: false, // set to true to automatically regenerate all the cases. | 
|  | blockUntilReporterExits: false, | 
|  | maxLaunches: 1, | 
|  | normalizeLineEndingsTo: process.platform === 'win32' ? '\r\n' : '\n', | 
|  | errorOnStaleApprovedFiles: process.platform !== 'win32', | 
|  | }; | 
|  |  | 
|  | function testFilter(filename, suffix, filters) { | 
|  | const testName = path.basename(filename + suffix); | 
|  | it(testName, () => { | 
|  | const result = processAsm(filename, filters); | 
|  | delete result.parsingTime; | 
|  | delete result.filteredCount; | 
|  | approvals.verifyAsJSON(casesRoot, testName, result, optionsOverride); | 
|  | }).timeout(5000); // Bump the timeout a bit so that we don't fail for slow cases | 
|  | } | 
|  |  | 
|  | /* | 
|  | The before() hooks on mocha are for it()s - They don't execute before the describes! | 
|  | That's sad because then we can't have cases be loaded in a before() for every describe child to see. | 
|  | */ | 
|  | describe('Filter test cases', function () { | 
|  | describe('No filters', function () { | 
|  | for (const x of cases) testFilter(x, '.none', {}); | 
|  | }); | 
|  | describe('Directive filters', function () { | 
|  | for (const x of cases) testFilter(x, '.directives', {directives: true}); | 
|  | }); | 
|  | describe('Directives and labels together', function () { | 
|  | for (const x of cases) testFilter(x, '.directives.labels', {directives: true, labels: true}); | 
|  | }); | 
|  | describe('Directives, labels and comments', function () { | 
|  | for (const x of cases) { | 
|  | testFilter(x, '.directives.labels.comments', {directives: true, labels: true, commentOnly: true}); | 
|  | } | 
|  | }); | 
|  | describe('Binary, directives, labels and comments', function () { | 
|  | if (process.platform !== 'win32') { | 
|  | for (const x of cases) { | 
|  | testFilter(x, '.binary.directives.labels.comments', { | 
|  | binary: true, | 
|  | directives: true, | 
|  | labels: true, | 
|  | commentOnly: true, | 
|  | }); | 
|  | } | 
|  | } | 
|  | }); | 
|  | describe('Binary, directives, labels, comments and library code', function () { | 
|  | if (process.platform !== 'win32') { | 
|  | for (const x of cases) { | 
|  | if (!x.endsWith('-bin.asm')) continue; | 
|  |  | 
|  | testFilter(x, '.binary.directives.labels.comments.library', { | 
|  | binary: true, | 
|  | directives: true, | 
|  | labels: true, | 
|  | commentOnly: true, | 
|  | libraryCode: true, | 
|  | }); | 
|  | } | 
|  | } | 
|  | }); | 
|  | describe('Binary, directives, labels, comments and library code with dontMaskFilenames', function () { | 
|  | if (process.platform !== 'win32') { | 
|  | for (const x of cases) { | 
|  | if (!x.endsWith('-bin.asm')) continue; | 
|  |  | 
|  | testFilter(x, '.binary.directives.labels.comments.library.dontMaskFilenames', { | 
|  | binary: true, | 
|  | directives: true, | 
|  | labels: true, | 
|  | commentOnly: true, | 
|  | libraryCode: true, | 
|  | dontMaskFilenames: true, | 
|  | }); | 
|  | } | 
|  | } | 
|  | }); | 
|  | describe('Directives and comments', function () { | 
|  | for (const x of cases) testFilter(x, '.directives.comments', {directives: true, commentOnly: true}); | 
|  | }); | 
|  | describe('Directives and library code', function () { | 
|  | for (const x of cases) testFilter(x, '.directives.library', {directives: true, libraryCode: true}); | 
|  | }); | 
|  | describe('Directives, labels, comments and library code', function () { | 
|  | for (const x of cases) { | 
|  | testFilter(x, '.directives.labels.comments.library', { | 
|  | directives: true, | 
|  | labels: true, | 
|  | commentOnly: true, | 
|  | libraryCode: true, | 
|  | }); | 
|  | } | 
|  | }); | 
|  | describe('Directives, labels, comments and library code with dontMaskFilenames', function () { | 
|  | for (const x of cases) { | 
|  | testFilter(x, '.directives.labels.comments.library.dontMaskFilenames', { | 
|  | directives: true, | 
|  | labels: true, | 
|  | commentOnly: true, | 
|  | libraryCode: true, | 
|  | dontMaskFilenames: true, | 
|  | }); | 
|  | } | 
|  | }); | 
|  | }); | 
|  |  | 
|  | describe('AsmParser tests', () => { | 
|  | const parser = new AsmParser(); | 
|  | it('should identify generic opcodes', () => { | 
|  | parser.hasOpcode('  mov r0, #1').should.be.true; | 
|  | parser.hasOpcode('  ROL A').should.be.true; | 
|  | }); | 
|  | it('should not identify non-opcodes as opcodes', () => { | 
|  | parser.hasOpcode('  ;mov r0, #1').should.be.false; | 
|  | parser.hasOpcode('').should.be.false; | 
|  | parser.hasOpcode('# moose').should.be.false; | 
|  | }); | 
|  | it('should identify llvm opcodes', () => { | 
|  | parser.hasOpcode('  %i1 = phi i32 [ %i2, %.preheader ], [ 0, %bb ]').should.be.true; | 
|  | }); | 
|  | }); | 
|  |  | 
|  | describe('forceApproveAll should be false', () => { | 
|  | it('should have forceApproveAll false', () => { | 
|  | optionsOverride.forceApproveAll.should.be.false; | 
|  | }); | 
|  | }); |