org.sonar.plugins.kt.advance.batch.DirScanTest.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.plugins.kt.advance.batch.DirScanTest.java

Source

/*
 * KT Advance
 * Copyright (c) 2016 Kestrel Technology LLC
 * http://www.kestreltechnology.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package org.sonar.plugins.kt.advance.batch;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.rule.ActiveRule;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issuable.IssueBuilder;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.plugins.kt.advance.model.ApiFile;
import org.sonar.plugins.kt.advance.model.ApiFile.ApiAssumption;
import org.sonar.plugins.kt.advance.model.ApiFile.Caller;
import org.sonar.plugins.kt.advance.model.ApiFile.PoRef;
import org.sonar.plugins.kt.advance.model.PevFile;
import org.sonar.plugins.kt.advance.model.PpoFile;
import org.sonar.plugins.kt.advance.model.PpoFile.PrimaryProofObligation;
import org.sonar.plugins.kt.advance.model.SevFile;
import org.sonar.plugins.kt.advance.model.SpoFile;
import org.sonar.plugins.kt.advance.model.SpoFile.CallSiteObligation;
import org.sonar.plugins.kt.advance.model.SpoFile.SecondaryProofObligation;
import org.sonar.plugins.kt.advance.util.StringTools;

public class DirScanTest {

    private static final String SRC_MEMTEST_C = "src/memtest.c";
    private static File BASEDIR;
    private static File MODULE_BASEDIR;
    private static final String FILE_NAME_STEM = "memtest_memtest_test";
    private static File ppoFile;

    private static KtAdvanceSensor session;
    private static final String TEST_PPO_FILE = "/ch_analysis/src/memtest/" + FILE_NAME_STEM + "_ppo.xml";

    private static final Logger LOG = Loggers.get(DirScanTest.class.getName());

    static ResourcePerspectives resourcePerspectives;
    static DefaultFileSystem fileSystem;
    static ActiveRules activeRules;
    static Settings settings;
    private int counter = 0;

    public static InputFile getResource(final String file) {

        final FilePredicate filePredicate = fileSystem.predicates().hasRelativePath(file);
        return fileSystem.inputFile(filePredicate);

    }

    @BeforeClass
    public static void setup() throws JAXBException {
        final URL url = DirScanTest.class.getResource("/test_project");
        BASEDIR = new File(url.getFile());
        MODULE_BASEDIR = new File(BASEDIR, "redis/");

        fileSystem = new DefaultFileSystem(MODULE_BASEDIR.toPath());

        fileSystem.add(Factory.makeDefaultInputFile(MODULE_BASEDIR, SRC_MEMTEST_C, 282));
        {
            final Iterator<File> iter = FileUtils.iterateFiles(MODULE_BASEDIR,
                    new String[] { FsAbstraction.XML_EXT }, true);

            while (iter.hasNext()) {
                final File file = iter.next();

                if (file.isFile() && FsAbstraction.ppoFileFilter.accept(file)) {
                    fileSystem.add(Factory.makeDefaultInputFile(MODULE_BASEDIR, file.getAbsolutePath(), 282));
                }
            }
        }
        resourcePerspectives = mock(ResourcePerspectives.class);
        final Issuable issuable = mock(Issuable.class);
        final IssueBuilder issueBuilderMock = mock(IssueBuilder.class);
        when(issueBuilderMock.ruleKey(any())).thenReturn(issueBuilderMock);
        when(issueBuilderMock.effortToFix(any())).thenReturn(issueBuilderMock);
        when(issueBuilderMock.severity(any())).thenReturn(issueBuilderMock);
        when(issueBuilderMock.at(any())).thenReturn(issueBuilderMock);
        when(issueBuilderMock.build()).thenReturn(mock(Issue.class));
        when(issueBuilderMock.newLocation()).thenAnswer(invocation -> new DefaultIssueLocation());

        when(issuable.newIssueBuilder()).thenReturn(issueBuilderMock);
        when(resourcePerspectives.as(any(), any(InputPath.class))).thenReturn(issuable);

        activeRules = mock(ActiveRules.class);
        final ActiveRule ruleMock = mock(ActiveRule.class);
        when(ruleMock.param(any())).thenReturn("1.0");
        when(activeRules.find(any(RuleKey.class))).thenReturn(ruleMock);

        settings = mock(Settings.class);
        when(settings.getFloat(any())).thenReturn(1f);
        session = new KtAdvanceSensor(settings, fileSystem, activeRules, resourcePerspectives);
        ppoFile = new File(MODULE_BASEDIR, TEST_PPO_FILE);
    }

    @Before
    public void setupSensor() throws JAXBException {
        session = new KtAdvanceSensor(settings, fileSystem, activeRules, resourcePerspectives);
    }

    @Test
    public void testAnalyseFile() throws JAXBException, IOException {
        final File baseDir = new File(BASEDIR, "itc-benchmarks/01.w_Defects");
        final DefaultFileSystem fs = new DefaultFileSystem(baseDir);

        final DefaultInputFile uninit_pointer = Factory.makeDefaultInputFile(baseDir, "uninit_pointer.c", 10000);
        fs.add(uninit_pointer);
        fs.add(Factory.makeDefaultInputFile(baseDir,
                "ch_analysis/uninit_pointer/uninit_pointer_uninit_pointer_015_func_001_api.xml", 10000));

        final FilePredicate filePredicate = fs.predicates().all();

        System.err.println("listing FS");
        for (final File f : fs.files(filePredicate)) {
            System.err.println(f);
        }

        final File ppoFileL = new File(BASEDIR, "/itc-benchmarks/01.w_Defects/ch_analysis/uninit_pointer/"
                + "uninit_pointer_uninit_pointer_015_ppo.xml");

        session = new KtAdvanceSensor(settings, fs, activeRules, resourcePerspectives);
        session.getFsContext().doInCache(() -> session.analysePpoSpoXml(ppoFileL));

    }

    @Test

    public void testCache() throws JAXBException, IOException {
        final PpoFile ppo = FsAbstraction.readPpoXml(ppoFile);

        final FsAbstraction fsContext = session.getFsContext();
        fsContext.doInCache(() -> {

            final List<IssuableProofObligation> processPPOs = session.processPPOs(ppo);

            for (final IssuableProofObligation ipo : processPPOs) {

                final IssuableProofObligation fromCache = fsContext.get(ipo.getKey());
                assertNotNull(StringTools.quote(ipo.getKey().toString()) + " not found in cache", fromCache);
                assertEquals(ipo.getKey(), fromCache.getKey());
            }

        });
    }

    @Test
    public void testComplexityLoaded() throws JAXBException {

        final PpoFile ppo = FsAbstraction.readPpoXml(ppoFile);

        double totalComplexityC = 0;
        double totalComplexityP = 0;
        double totalComplexityG = 0;
        final InputFile resourceMock = mock(InputFile.class);
        when(resourceMock.absolutePath()).thenReturn("");
        when(resourceMock.file()).thenReturn(new File(""));
        for (final PrimaryProofObligation pp : ppo.function.proofObligations) {

            final IssuableProofObligation ipo = IssuableProofObligation.newBuilder(ppo, pp)
                    .setInputFile(resourceMock).build();

            totalComplexityC += ipo.getComplexityC();
            totalComplexityP += ipo.getComplexityP();
            totalComplexityG += ipo.getComplexityG();

        }
        assertTrue(totalComplexityC > 0);
        assertTrue(totalComplexityP > 0);
        //assertTrue(totalComplexityG > 0);
    }

    @Test
    public void testListPPOs() throws JAXBException {

        final FsAbstraction fs = new FsAbstraction(fileSystem);
        counter = 0;
        fs.forEachPpoFile(file -> {
            counter++;
            System.out.println("testListPPOs:" + file.getAbsolutePath());
            assertTrue(file.getAbsolutePath().endsWith("_ppo.xml"));
        });
        assertEquals(13, counter);
    }

    @Test
    public void testProcessPPOs() throws JAXBException, IOException {

        session.getFsContext().doInCache(() -> {
            final PpoFile ppo = FsAbstraction.readPpoXml(ppoFile);
            final List<IssuableProofObligation> processPPOs = session.processPPOs(ppo);
            assertEquals(103, processPPOs.size());

        });

    }

    @Test
    public void testReadApi() throws JAXBException {
        final ApiFile api = readApi();
        final PpoFile ppo = readPpo();

        final List<ApiAssumption> assumptions = api.function.apiAssumptions;
        final List<Caller> callers = api.function.callers;

        assertEquals(1, assumptions.size());
        final ApiAssumption apiAssumption = assumptions.get(0);
        assertEquals(1, apiAssumption.dependentPPOs.size());
        final PoRef poRef = apiAssumption.dependentPPOs.get(0);
        assertEquals("2", poRef.getId());

        //

        assertEquals(1, callers.size());
        final Caller caller = callers.get(0);
        assertEquals(136760, caller.callSite.byteNo);
        assertEquals("uninit_pointer.c", caller.callSite.file);
        assertEquals(158, caller.callSite.line);

        //
        final Map<String, PrimaryProofObligation> ppOsAsMap = ppo.getPPOsAsMap();
        for (final ApiAssumption a : assumptions) {
            LOG.info("" + a);
            for (final PoRef ref : a.dependentPPOs) {
                LOG.info("dependentPPO: " + ref.getId() + " " + ppOsAsMap.get(ref.getId()));
                assertNotNull(ppOsAsMap.get(ref.getId()));
            }
        }

    }

    @Test
    public void testReadPev() throws JAXBException {

        final PpoFile ppo = FsAbstraction.readPpoXml(ppoFile);
        final PevFile pev = FsAbstraction.readPevXml(
                FsAbstraction.replaceSuffix(ppoFile, FsAbstraction.PPO_SUFFIX, FsAbstraction.PEV_SUFFIX));

        assertEquals(ppo.function.proofObligations.size(), pev.function.statistics.total);
        assertEquals(pev.function.statistics.total - pev.function.statistics.totalProven,
                pev.function.openProofObligations.size());

        assertEquals(92, pev.function.statistics.totalProven);
        assertEquals(pev.function.statistics.totalProven, pev.function.dischargedProofObligations.size());

    }

    @Test
    public void testReadPpo() throws JAXBException {

        final File ppoFile = new File(MODULE_BASEDIR, TEST_PPO_FILE);

        final PpoFile ppo = FsAbstraction.readPpoXml(ppoFile);

        assertEquals(103, ppo.function.proofObligations.size());
        assertEquals(103, ppo.function.statistics.size);
        assertEquals(ppo.function.proofObligations.size(), ppo.function.statistics.size);

        assertEquals("int-underflow (megabytes * 1024)", ppo.function.proofObligations.get(1).predicate.toString());

    }

    @Test
    public void testReadSev() throws JAXBException {

        final SevFile sev = FsAbstraction
                .readSevXml(new File(BASEDIR, "invalid_memory_access_invalid_memory_access_main_sev.xml"));

        assertEquals(sev.function.statistics.total - sev.function.statistics.totalProven,
                sev.function.openProofObligations.size());

        assertEquals(66, sev.function.statistics.total);
        assertEquals(64, sev.function.statistics.totalProven);
        assertEquals(42, sev.function.statistics.invariant);
        assertEquals(0, sev.function.statistics.invariantWithApi);

        assertEquals(sev.function.statistics.totalProven, sev.function.dischargedProofObligations.size());

    }

    @Test
    public void testReadSev2() throws JAXBException {
        final File sevFile = new File(BASEDIR, "/itc-benchmarks/01.w_Defects/ch_analysis/uninit_pointer/"
                + "uninit_pointer_uninit_pointer_005_sev.xml");
        final SevFile sev = FsAbstraction.readSevXml(sevFile);

        assertEquals(5, sev.getDischargedPOsAsMap().size());

    }

    @Test
    public void testReadSpo() throws JAXBException {
        final SpoFile spo = readSpo();

        assertTrue(spo.function.spoWrapper.proofObligations.size() > 0);
        for (final CallSiteObligation co : spo.function.spoWrapper.proofObligations) {
            assertNotNull(co.location);
            assertNotNull(co.location.file);
            assertNotNull(co.fvid);

            assertTrue(co.proofObligations.size() > 0);

            for (final SecondaryProofObligation sspo : co.proofObligations) {
                assertNotNull(sspo.predicate);
                assertNotNull(sspo.predicate.tag);
            }
        }

    }

    @Test
    public void testReadWrongPev() throws JAXBException {
        final File nonExistentFile = FsAbstraction.replaceSuffix(ppoFile, FsAbstraction.PPO_SUFFIX, "NOISE");
        final PevFile pev = FsAbstraction.readPevXml(nonExistentFile);
        assertNull(pev);
    }

    @Test
    public void testReplaceSuffix() {
        final File apiFile = FsAbstraction.replaceSuffix(ppoFile, "ppo", "api");
        assertEquals(apiFile.getName(), FILE_NAME_STEM + "_api.xml");
        System.out.println("filename change:");
        System.out.println(ppoFile);
        System.out.println(apiFile);
    }

    private ApiFile readApi() throws JAXBException {
        final File apiFile = new File(BASEDIR, "/itc-benchmarks/01.w_Defects/ch_analysis/uninit_pointer/"
                + "uninit_pointer_uninit_pointer_008_func_001_api.xml");

        return FsAbstraction.readApiXml(apiFile);

    }

    private PpoFile readPpo() throws JAXBException {
        final File ppoFile = new File(BASEDIR, "/itc-benchmarks/01.w_Defects/ch_analysis/uninit_pointer/"
                + "uninit_pointer_uninit_pointer_008_func_001_ppo.xml");

        return FsAbstraction.readPpoXml(ppoFile);

    }

    private SpoFile readSpo() throws JAXBException {
        final File spoFile = new File(BASEDIR, "/itc-benchmarks/01.w_Defects/ch_analysis/uninit_pointer/"
                + "uninit_pointer_uninit_pointer_005_spo.xml");

        final SpoFile spo = FsAbstraction.readSpoXml(spoFile);
        return spo;
    }

}