org.sosy_lab.cpachecker.cmdline.CPASelfCheck.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.cmdline.CPASelfCheck.java

Source

/*
 *  CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2014  Dirk Beyer
 *  All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 *  CPAchecker web page:
 *    http://cpachecker.sosy-lab.org
 */
package org.sosy_lab.cpachecker.cmdline;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import org.sosy_lab.common.configuration.Configuration;
import org.sosy_lab.common.configuration.InvalidConfigurationException;
import org.sosy_lab.common.log.BasicLogManager;
import org.sosy_lab.common.log.LogManager;
import org.sosy_lab.cpachecker.cfa.CFA;
import org.sosy_lab.cpachecker.cfa.CParser;
import org.sosy_lab.cpachecker.cfa.CSourceOriginMapping;
import org.sosy_lab.cpachecker.cfa.Language;
import org.sosy_lab.cpachecker.cfa.MutableCFA;
import org.sosy_lab.cpachecker.cfa.ParseResult;
import org.sosy_lab.cpachecker.cfa.model.FunctionEntryNode;
import org.sosy_lab.cpachecker.cfa.types.MachineModel;
import org.sosy_lab.cpachecker.core.interfaces.AbstractDomain;
import org.sosy_lab.cpachecker.core.interfaces.AbstractState;
import org.sosy_lab.cpachecker.core.interfaces.CPAFactory;
import org.sosy_lab.cpachecker.core.interfaces.ConfigurableProgramAnalysis;
import org.sosy_lab.cpachecker.core.interfaces.MergeOperator;
import org.sosy_lab.cpachecker.core.interfaces.Precision;
import org.sosy_lab.cpachecker.core.interfaces.StopOperator;
import org.sosy_lab.cpachecker.exceptions.CPAException;
import org.sosy_lab.cpachecker.exceptions.ParserException;
import org.sosy_lab.cpachecker.util.VariableClassification;

import com.google.common.base.Optional;
import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ClassInfo;

public class CPASelfCheck {

    private static LogManager logManager;
    private static Configuration config;

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        config = Configuration.defaultConfiguration();
        logManager = new BasicLogManager(config);

        CFA cfa = createCFA();
        FunctionEntryNode main = cfa.getMainFunction();

        logManager.log(Level.INFO, "Searching for CPAs");
        List<Class<ConfigurableProgramAnalysis>> cpas = getCPAs();

        for (Class<ConfigurableProgramAnalysis> cpa : cpas) {
            logManager.log(Level.INFO, "Checking " + cpa.getCanonicalName() + " ...");
            ConfigurableProgramAnalysis cpaInst;
            try {
                cpaInst = tryToInstantiate(cpa, cfa);
            } catch (InvocationTargetException e) {
                logManager.logException(Level.WARNING, e,
                        "Getting factory instance for " + cpa.getCanonicalName() + " failed!");
                continue;
            } catch (NoSuchMethodException e) {
                logManager.logException(Level.WARNING, e,
                        "Getting factory instance for " + cpa.getCanonicalName() + " failed: no factory method!");
                continue;
            } catch (Exception e) {
                logManager.logException(Level.WARNING, e, "Could not instantiate " + cpa.getCanonicalName());
                continue;
            } catch (UnsatisfiedLinkError e) {
                logManager.logException(Level.WARNING, e, "Could not instantiate " + cpa.getCanonicalName());
                continue;
            }
            assert cpaInst != null;

            try {
                cpaInst.getInitialState(main);

                boolean ok = true;
                // check domain and lattice
                ok &= checkJoin(cpa, cpaInst, main);
                /// TODO checking the invariantes of the transfer relation is a bit more work ...
                // check merge
                ok &= checkMergeSoundness(cpa, cpaInst, main);
                // check stop
                ok &= checkStopEmptyReached(cpa, cpaInst, main);
                ok &= checkStopReached(cpa, cpaInst, main);
                /// TODO check invariants of precision adjustment
                logManager.log(Level.INFO, ok ? " OK" : " ERROR");
            } catch (Exception e) {
                logManager.logException(Level.WARNING, e, "");
            }
        }
    }

    private static CFA createCFA() throws IOException, ParserException, InvalidConfigurationException {
        String code = "int main() {\n" + "  int a;\n" + "  a = 1;\n" + "  return (a);\n" + "}\n";

        CParser parser = CParser.Factory.getParser(config, logManager, CParser.Factory.getDefaultOptions(),
                MachineModel.LINUX32);
        CSourceOriginMapping sourceOriginMapping = new CSourceOriginMapping();
        ParseResult cfas = parser.parseString("", code, sourceOriginMapping);
        MutableCFA cfa = new MutableCFA(MachineModel.LINUX32, cfas.getFunctions(), cfas.getCFANodes(),
                cfas.getFunctions().get("main"), Language.C);
        return cfa.makeImmutableCFA(Optional.<VariableClassification>absent());
    }

    private static ConfigurableProgramAnalysis tryToInstantiate(Class<ConfigurableProgramAnalysis> pCpa, CFA cfa)
            throws NoSuchMethodException, InvocationTargetException, InvalidConfigurationException, CPAException,
            IllegalAccessException {
        Method factoryMethod = pCpa.getMethod("factory", new Class<?>[0]);

        CPAFactory factory = (CPAFactory) factoryMethod.invoke(null, new Object[0]);
        return factory.setLogger(logManager).setConfiguration(config).set(cfa, CFA.class).createInstance();
    }

    private static boolean ensure(boolean pB, String pString) {
        if (!pB) {
            logManager.log(Level.WARNING, pString);
            return false;
        }
        return true;
    }

    private static boolean checkJoin(Class<ConfigurableProgramAnalysis> pCpa, ConfigurableProgramAnalysis pCpaInst,
            FunctionEntryNode pMain) throws CPAException, InterruptedException {
        AbstractDomain d = pCpaInst.getAbstractDomain();
        AbstractState initial = pCpaInst.getInitialState(pMain);

        return ensure(d.isLessOrEqual(initial, d.join(initial, initial)), "Join of same elements is unsound!");
    }

    private static boolean checkMergeSoundness(Class<ConfigurableProgramAnalysis> pCpa,
            ConfigurableProgramAnalysis pCpaInst, FunctionEntryNode pMain)
            throws CPAException, InterruptedException {
        AbstractDomain d = pCpaInst.getAbstractDomain();
        MergeOperator merge = pCpaInst.getMergeOperator();
        AbstractState initial = pCpaInst.getInitialState(pMain);
        Precision initialPrec = pCpaInst.getInitialPrecision(pMain);

        return ensure(d.isLessOrEqual(initial, merge.merge(initial, initial, initialPrec)),
                "Merging same elements was unsound!");
    }

    private static boolean checkStopEmptyReached(Class<ConfigurableProgramAnalysis> pCpa,
            ConfigurableProgramAnalysis pCpaInst, FunctionEntryNode pMain)
            throws CPAException, InterruptedException {
        StopOperator stop = pCpaInst.getStopOperator();
        HashSet<AbstractState> reached = new HashSet<>();
        AbstractState initial = pCpaInst.getInitialState(pMain);
        Precision initialPrec = pCpaInst.getInitialPrecision(pMain);

        return ensure(!stop.stop(initial, reached, initialPrec), "Stopped on empty set!");
    }

    private static boolean checkStopReached(Class<ConfigurableProgramAnalysis> pCpa,
            ConfigurableProgramAnalysis pCpaInst, FunctionEntryNode pMain)
            throws CPAException, InterruptedException {
        StopOperator stop = pCpaInst.getStopOperator();
        HashSet<AbstractState> reached = new HashSet<>();
        AbstractState initial = pCpaInst.getInitialState(pMain);
        reached.add(initial);
        Precision initialPrec = pCpaInst.getInitialPrecision(pMain);

        return ensure(stop.stop(initial, reached, initialPrec), "Did not stop on same element!");
    }

    private static List<Class<ConfigurableProgramAnalysis>> getCPAs() throws ClassNotFoundException, IOException {
        Set<ClassInfo> cpaCandidates = ClassPath.from(Thread.currentThread().getContextClassLoader())
                .getTopLevelClasses("org.sosy_lab.cpachecker.cpa");

        List<Class<ConfigurableProgramAnalysis>> cpas = new ArrayList<>();

        Class<ConfigurableProgramAnalysis> targetType = null;

        for (ClassInfo candidateInfo : cpaCandidates) {
            Class<?> candidate = candidateInfo.load();
            if (!Modifier.isAbstract(candidate.getModifiers()) && !Modifier.isInterface(candidate.getModifiers())
                    && ConfigurableProgramAnalysis.class.isAssignableFrom(candidate)) {

                // candidate is non-abstract implementation of CPA interface
                cpas.add(uncheckedGenericCast(candidate, targetType));
            }
        }

        return cpas;
    }

    @SuppressWarnings("unchecked")
    private static <T> Class<T> uncheckedGenericCast(Class<?> classObj, Class<T> targetType) {
        return (Class<T>) classObj;
    }
}