diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CMakeLists.txt | 2 | ||||
-rwxr-xr-x | tools/InterfaceGenerator/Generator.py | 9 | ||||
-rw-r--r-- | tools/InterfaceGenerator/MsgVersionGenerate.py | 85 | ||||
-rwxr-xr-x | tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py | 4 | ||||
-rwxr-xr-x | tools/InterfaceGenerator/generator/parsers/RPCBase.py | 3 | ||||
-rwxr-xr-x | tools/Utils/generate_test_certificates.py | 279 | ||||
-rwxr-xr-x | tools/infrastructure/check_style.sh | 47 | ||||
-rwxr-xr-x | tools/infrastructure/collect_coverage.sh | 27 | ||||
-rw-r--r-- | tools/infrastructure/format_src.py | 37 | ||||
-rwxr-xr-x | tools/infrastructure/git-hooks/pre-commit | 102 | ||||
-rw-r--r-- | tools/infrastructure/install_hooks.py | 40 | ||||
-rw-r--r-- | tools/infrastructure/utils.py | 43 | ||||
-rw-r--r-- | tools/policy_table_validator/CMakeLists.txt | 9 | ||||
-rw-r--r-- | tools/policy_table_validator/main.cpp | 2 |
14 files changed, 678 insertions, 11 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 557c23f4e7..cf3e2c692c 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -5,7 +5,7 @@ include(ExternalProject) set(intergen_SOURCES "${CMAKE_CURRENT_LIST_DIR}/intergen") set(intergen_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/intergen") set(intergen_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/intergen") -set(intergen_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${intergen_INSTALL_DIR}) +set(intergen_CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_INSTALL_PREFIX=${intergen_INSTALL_DIR}) ExternalProject_Add(intergen SOURCE_DIR ${intergen_SOURCES} diff --git a/tools/InterfaceGenerator/Generator.py b/tools/InterfaceGenerator/Generator.py index 5b5894bc00..932620c153 100755 --- a/tools/InterfaceGenerator/Generator.py +++ b/tools/InterfaceGenerator/Generator.py @@ -26,6 +26,7 @@ import generator.parsers.SDLRPCV2 import generator.parsers.JSONRPC import generator.generators.SmartFactorySDLRPC import generator.generators.SmartFactoryJSONRPC +import MsgVersionGenerate from generator.parsers.RPCBase import ParseError from generator.generators.SmartFactoryBase import GenerateError @@ -71,7 +72,6 @@ def _handle_fatal_error(error): print sys.exit(errno.EINVAL) - def main(): """Main function of the generator that does actual work.""" @@ -101,6 +101,13 @@ Generating interface source code with following parameters: except ParseError as error: _handle_fatal_error(error) + # Parse sdl version from MOBILE_API.xml and create source file with this version + if src_xml_name == "MOBILE_API": + try: + MsgVersionGenerate.generate_msg_version(src_xml, output_dir) + except ParseError as error: + _handle_fatal_error(error) + # Generate SmartFactory source code from internal model try: code_generator.generate(interface, diff --git a/tools/InterfaceGenerator/MsgVersionGenerate.py b/tools/InterfaceGenerator/MsgVersionGenerate.py new file mode 100644 index 0000000000..7ff6c384d3 --- /dev/null +++ b/tools/InterfaceGenerator/MsgVersionGenerate.py @@ -0,0 +1,85 @@ +""" +Generate file with major and minor msg_version. +""" +import xml.etree.ElementTree +from string import Template +import re +from generator.parsers import RPCBase + +def generate_msg_version(file_name, path_to_storage): + """Parses MOBILE_API.xml in order to + receive major_version and minor_version + """ + tree = xml.etree.ElementTree.parse(file_name) + root = tree.getroot() + if (root.tag == "interface" and "version" in root.attrib): + check_version_format(root.attrib["version"]) + array = (root.attrib["version"]).split(".") + major_version = array[0] + minor_version = array[1] + if (major_version.isdigit() and minor_version.isdigit()): + data_for_storage = prepare_data_for_storage(major_version, minor_version) + store_data_to_file(path_to_storage, data_for_storage) + else: + raise RPCBase.ParseError("Attribute version has incorect value in MOBILE_API.xml") + else: + raise RPCBase.ParseError("Check MOBILE_API.xml file, parser can not find first element " + " with tag interface or atribute version") + +def store_data_to_file(path_to_storage, data_for_storage): + """Stores data with major and minor version + to file generated_msg_version.h + """ + path_to_storage = path_to_storage + "/generated_msg_version.h" + fh = open(path_to_storage, 'w') + fh.write(data_for_storage) + fh.close() + +def check_version_format(version): + """Checks correctness of format of version + """ + p = re.compile('\d+\\.\d+') + result = p.match(version) + if result == None or (result.end() != len(version)): + raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " + "Need format of version major_version.minor_version") + +def prepare_data_for_storage(major_version, minor_version): + """Prepares data to store to file. + """ + temp = Template( + u'''/*Copyright (c) 2016, Ford Motor Company\n''' + u'''All rights reserved.\n''' + u'''Redistribution and use in source and binary forms, with or without\n''' + u'''modification, are permitted provided that the following conditions are met:\n''' + u'''Redistributions of source code must retain the above copyright notice, this\n''' + u'''list of conditions and the following disclaimer.\n''' + u'''Redistributions in binary form must reproduce the above copyright notice,\n''' + u'''this list of conditions and the following\n''' + u'''disclaimer in the documentation and/or other materials provided with the\n''' + u'''distribution.\n''' + u'''Neither the name of the Ford Motor Company nor the names of its contributors\n''' + u'''may be used to endorse or promote products derived from this software\n''' + u'''without specific prior written permission.\n''' + u'''THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n''' + u'''AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n''' + u'''IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n''' + u'''ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n''' + u'''LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n''' + u'''CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n''' + u'''SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n''' + u'''INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n''' + u'''CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n''' + u'''ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n''' + u'''POSSIBILITY OF SUCH DAMAGE.\n''' + u'''*/\n''' + u'''#ifndef GENERATED_MSG_VERSION_H\n''' + u'''#define GENERATED_MSG_VERSION_H\n\n''' + u'''namespace application_manager {\n\n''' + u'''const uint16_t major_version = $m_version;\n''' + u'''const uint16_t minor_version = $min_version;\n''' + u'''} // namespace application_manager\n''' + u'''#endif // GENERATED_MSG_VERSION_H''') + data_to_file = temp.substitute(m_version = major_version, min_version = minor_version) + return data_to_file + diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py index 2b372021c2..d13ac29c9b 100755 --- a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py +++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py @@ -1223,7 +1223,7 @@ class CodeGenerator(object): _hpp_schema_file_tempalte = string.Template( u'''/**\n''' - u''' * @file ${class_name}.hpp\n''' + u''' * @file ${class_name}.h\n''' u''' * @brief Generated class ${class_name} header file.\n''' u''' *\n''' u''' * This class is a part of SmartObjects solution. It provides\n''' @@ -1280,7 +1280,7 @@ class CodeGenerator(object): u'''#ifndef $guard\n''' u'''#define $guard\n''' u'''\n''' - u'''#include "formatters/CSmartFactory.hpp"\n''' + u'''#include "formatters/CSmartFactory.h"\n''' u'''#include "smart_objects/smart_schema.h"\n''' u'''#include "smart_objects/schema_item.h"\n''' u'''#include "utils/shared_ptr.h"\n''' diff --git a/tools/InterfaceGenerator/generator/parsers/RPCBase.py b/tools/InterfaceGenerator/generator/parsers/RPCBase.py index 2b3db62d56..22f3fd2c2d 100755 --- a/tools/InterfaceGenerator/generator/parsers/RPCBase.py +++ b/tools/InterfaceGenerator/generator/parsers/RPCBase.py @@ -568,7 +568,8 @@ class Parser(object): default_value = self._get_bool_from_string(default_value); param_type = Model.Boolean(default_value=default_value) elif type_name == "Integer" or \ - type_name == "Float": + type_name == "Float" or \ + type_name == "Double" : min_value = self._extract_optional_number_attrib( attrib, "minvalue", int if type_name == "Integer" else float) max_value = self._extract_optional_number_attrib( diff --git a/tools/Utils/generate_test_certificates.py b/tools/Utils/generate_test_certificates.py new file mode 100755 index 0000000000..73b6f53cc8 --- /dev/null +++ b/tools/Utils/generate_test_certificates.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +"""Generate certificates for testing + Usage: + generate_test_certificate.py --dir=<name of directory> +""" + +import os +import subprocess +import tempfile +from argparse import ArgumentParser +from subprocess import check_call + +def run(command, *args): + """Application caller + wrap console call 'command args' + """ + args_str = " " + " ".join(str(s) for s in list(args[0])) + if len(args_str) > 0 : + command += " " + args_str + print "Running", command + retcode = check_call(command, shell=True) + if retcode < 0: + raise RuntimeError("Child was terminated by signal") + +def openssl(*args): + """OpenSSL caller + wrap console call 'openssl args' + """ + run("openssl", args) + +def gen_rsa_key(out_key_file, key_size): + """Private key generator + wrap console call 'openssl genrsa -out $out_key_file $key_size' + """ + openssl("genrsa", "-out", out_key_file, key_size) + +def gen_root_cert(out_cert_file, key_file, days, answer): + """Root certificate generator + wrap console call 'openssl req -x509 -new -key $key_file -days $days -out $out_cert_file -subj $answer' + """ + openssl("req -x509 -new -key", key_file, "-days", days, "-out", out_cert_file, "-subj", answer) + +def gen_cert(out_cert_file, key_file, ca_cert_file, ca_key_file, days, answer): + """Certificate generator + wrap console call + 'openssl req -new -key $key_file -days $days -out $out_cert_file -subj $answer' + 'openssl x509 -req -in $out_cert_file -CA $ca_cert_file -CAkey ca_key_file -CAcreateserial -out $out_cert_file -days 5000' + """ + request_file = out_cert_file + ".req" + openssl("req -new -key", key_file, "-days", days, "-out", request_file, "-subj", answer) + + openssl("x509 -hash -req -in", request_file, "-CA", ca_cert_file, "-CAkey", ca_key_file, \ + "-CAcreateserial -out", out_cert_file, "-days", days) + +def gen_expire_cert(out_cert_file, key_file, ca_cert_file, ca_key_file, days, answer): + """Expired certificate generator + wrap console call + 'openssl req -new -key $key_file -days $days -out $out_cert_file -subj $answer' + 'openssl ca -batch -config $config_file_path -in $request_file -out $out_cert_file, + "-cert", ca_cert_file, "-keyfile", ca_key_file, "-startdate 150101000000Z -enddate 150314092653Z' + """ + request_file = out_cert_file + ".req" + openssl("req -new -key", key_file, "-days", days, "-out", request_file, "-subj", answer) + + # Create temporary files needed for expired certificate generation + temp_dir = tempfile.mkdtemp() + config_file_path = os.path.join(temp_dir, "database.conf") + database_file_path = os.path.join(temp_dir, "database") + serial_file_path = os.path.join(temp_dir, "serial") + # create file + open(database_file_path, 'w').close() + + serial_file = open(serial_file_path, 'w') + serial_file.write("01") + serial_file.close(); + + current_dir = os.getcwd() + config_file = open(config_file_path, 'w') + config_file.write( + """[ ca ] + default_ca = ca_default + + [ ca_default ] + dir = %s""" % (temp_dir, ) + """ + certs = %s""" % (current_dir, ) + """ + new_certs_dir = %s""" % (current_dir, ) + """ + database = %s""" % (database_file_path, ) + """ + serial = %s""" % (serial_file_path, ) + """ + RANDFILE = $dir/ca.db.rand + certificate = %s""" % (os.path.abspath(ca_cert_file), ) + """ + private_key = %s""" % (os.path.abspath(ca_key_file), ) + """ + default_days = 365 + default_crl_days = 30 + default_md = md5 + preserve = no + policy = generic_policy + [ generic_policy ] + countryName = optional + stateOrProvinceName = optional + localityName = optional + organizationName = optional + organizationalUnitName = optional + commonName = supplied + emailAddress = optional\n""") + config_file.close(); + + openssl("ca -batch -config", config_file_path, "-in", request_file, "-out", out_cert_file, + "-startdate 150101000000Z -enddate 150314092653Z") + +def gen_pkcs12(out, key_file, cert_file, verification_certificate) : + """Pem to PKCS#12 standard + wrap console call + 'openssl pkcs12 -export -out $out -inkey $key_file -in $cert_file -name 'SPT key and certificates' -certfile $certs' + """ + openssl("pkcs12 -export -out", out, "-inkey", key_file, "-in", cert_file, \ + "-name 'SPT key and certificates'", "-CAfile ", verification_certificate, \ + " -passout pass:") + + """ + Encode certificate $out to base 64 + """ + with open(out, "rb") as cert: + with open(out + ".enc", "wb") as enc_cert: + enc_cert.write(cert.read().encode("base64")) + +def answers(name, app_id, country, state, locality, organization, unit, email) : + """Answer string generator + Generate answer for certificate creation with openssl + Country argument need to be 2 symbol size + """ + if len(country) != 2 : + raise ValueError("Country argument need to be 2 symbol size") + answer ="'/C={0}/ST={1}/L={2}/O={3}".format(country, state, locality, organization) + answer +="/OU={0}/CN={1}/emailAddress={2}'".format(unit, name, email) + if len(app_id) > 0: + answer += "/serialNumber={0}".format(app_id) + return answer + +def concat_files(out_file_name, *args) : + print "Concatenate text files", args, "into", out_file_name + with open(out_file_name, 'w') as outfile: + for fname in args : + with open(fname) as infile : + outfile.write(infile.read()) + + +def main(): + soft_verify_file = os.path.join("server", "server_root.key") + arg_parser = ArgumentParser(description='Welcome to SDL test certificate generator.') + arg_parser.add_argument('-d', '--dir', help="directory for certificate generating") + arg_parser.add_argument('-s', '--soft', help="do not override existing certificates if '%s' exists" % soft_verify_file, action='store_true' ) + args = arg_parser.parse_args() + if args.dir: + if not os.path.exists(args.dir): + raise OSError("Input directory does not exist") + os.chdir(args.dir) + if args.soft: + if os.path.exists(soft_verify_file): + print "Root key file '%s' exists. Generation skipped according to soft mode." % (soft_verify_file, ) + return + + server_root_answer = answers("server_root", "", "US", "California", "Silicon Valley", "CAcert.org", "CAcert", "sample@cacert.org") + client_root_answer = answers("client_root", "", "US", "California", "Silicon Valley", "CAcert.org", "CAcert", "sample@cacert.org") + ford_server_answer = answers("FORD", "", "US", "Michigan", "Detroit", "FORD_SERVER", "FORD_SDL_SERVER" ,"sample@ford.com") + ford_client_answer = answers("FORD_CLIENT", "", "US", "Michigan", "Detroit", "FORD_CLIENT", "FORD_SDL_CLIENT" ,"sample@ford.com") + client_answer = answers("client", "SPT", "RU", "Russia", "St. Petersburg", "Luxoft", "HeadUnit" ,"sample@luxoft.com") + server_answer = answers("server", "SPT", "RU", "Russia", "St. Petersburg", "Luxoft", "Mobile" ,"sample@luxoft.com") + server_unsigned_answer = answers("server", "SPT", "RU", "Russia", "St. Petersburg", "Luxoft", "Mobile_unsigned" ,"sample@luxoft.com") + server_expired_answer = answers("server", "SPT", "RU", "Russia", "St. Petersburg", "Luxoft", "Mobile_expired" ,"sample@luxoft.com") + client_unsigned_answer = answers("client", "SPT", "RU", "Russia", "St. Petersburg", "Luxoft", "Mobile_unsigned" ,"sample@luxoft.com") + client_expired_answer = answers("client", "SPT", "RU", "Russia", "St. Petersburg", "Luxoft", "Mobile_expired" ,"sample@luxoft.com") + days = 10000 + + server_dir = "server" + client_dir = "client" + if not os.path.exists(server_dir): + os.mkdir(server_dir) + if not os.path.exists(client_dir): + os.mkdir(client_dir) + + print " --== Root certificate generating SERVER==-- " + server_root_key_file = os.path.join(server_dir, "server_root.key") + assert soft_verify_file == server_root_key_file, 'Update soft key file path' + server_root_cert_file = os.path.join(server_dir, "server_root.crt") + gen_rsa_key(server_root_key_file, 2048) + gen_root_cert(server_root_cert_file, server_root_key_file, days, server_root_answer) + + print " --== Root certificate generating CLIENT==-- " + client_root_key_file = os.path.join(client_dir, "client_root.key") + client_root_cert_file = os.path.join(client_dir, "client_root.crt") + gen_rsa_key(client_root_key_file, 2048) + gen_root_cert(client_root_cert_file, client_root_key_file, days, client_root_answer) + + print + print " --== Ford server CA certificate generating ==-- " + ford_server_key_file = os.path.join(server_dir, "ford_server.key") + ford_server_cert_file = os.path.join(server_dir, "ford_server.crt") + gen_rsa_key(ford_server_key_file, 2048) + gen_cert(ford_server_cert_file, ford_server_key_file, server_root_cert_file, server_root_key_file, days, ford_server_answer) + + print + print " --== Ford client CA certificate generating ==-- " + ford_client_key_file = os.path.join(client_dir, "ford_client.key") + ford_client_cert_file = os.path.join(client_dir, "ford_client.crt") + gen_rsa_key(ford_client_key_file, 2048) + gen_cert(ford_client_cert_file, ford_client_key_file, client_root_cert_file, client_root_key_file, days, ford_client_answer) + + print + print " --== SDL and SPT adjustment ==-- " + server_verification_ca_cert_file = os.path.join(server_dir, "server_verification_ca_cetrificates.crt") + client_verification_ca_cert_file = os.path.join(client_dir, "client_verification_ca_cetrificates.crt") + concat_files(server_verification_ca_cert_file, server_root_cert_file, ford_server_cert_file) + concat_files(client_verification_ca_cert_file, client_root_cert_file, ford_client_cert_file) + + + print + print " --== Client certificate generating ==-- " + client_key_file = os.path.join(client_dir, "client.key") + client_cert_file = os.path.join(client_dir, "client.crt") + gen_rsa_key(client_key_file, 2048) + gen_cert(client_cert_file, client_key_file, ford_client_cert_file, ford_client_key_file, days, client_answer) + + + print + print " --== Server certificate generating ==-- " + server_key_file = os.path.join(server_dir, "server.key") + server_cert_file = os.path.join(server_dir, "server.crt") + server_pkcs12_file = os.path.join(server_dir, "spt_credential.p12") + gen_rsa_key(server_key_file, 2048) + gen_cert(server_cert_file, server_key_file, ford_server_cert_file, ford_server_key_file, days, server_answer) + gen_pkcs12(server_pkcs12_file, server_key_file, server_cert_file, client_verification_ca_cert_file) + + print + print " --== Server unsigned certificate generating ==-- " + server_unsigned_cert_file = os.path.join(server_dir, "server_unsigned.crt") + server_pkcs12_unsigned_file = os.path.join(server_dir, "spt_credential_unsigned.p12") + gen_root_cert(server_unsigned_cert_file, server_key_file, days, server_unsigned_answer) + gen_pkcs12(server_pkcs12_unsigned_file, server_key_file, server_unsigned_cert_file, client_verification_ca_cert_file) + + print + print " --== Server expired certificate generating ==-- " + server_expired_cert_file = os.path.join(server_dir, "server_expired.crt") + server_pkcs12_expired_file = os.path.join(server_dir, "spt_credential_expired.p12") + gen_expire_cert(server_expired_cert_file, server_key_file, ford_server_cert_file, ford_server_key_file, days, server_expired_answer) + gen_pkcs12(server_pkcs12_expired_file, server_key_file, server_expired_cert_file, client_verification_ca_cert_file) + + + print + print " --== Client pkcs12 certificate generating ==-- " + client_key_file = os.path.join(client_dir, "client.key") + client_cert_file = os.path.join(client_dir, "client.crt") + client_pkcs12_file = os.path.join(client_dir, "client_credential.p12") + gen_rsa_key(client_key_file, 2048) + gen_cert(client_cert_file, client_key_file, ford_client_cert_file, ford_client_key_file, days, client_answer) + gen_pkcs12(client_pkcs12_file, client_key_file, client_cert_file, server_verification_ca_cert_file) + + print + print " --== Client pkcs12 unsigned certificate generating ==-- " + client_unsigned_cert_file = os.path.join(client_dir, "client_unsigned.crt") + client_pkcs12_unsigned_file = os.path.join(client_dir, "client_credential_unsigned.p12") + gen_root_cert(client_unsigned_cert_file, client_key_file, days, client_unsigned_answer) + gen_pkcs12(client_pkcs12_unsigned_file, client_key_file, client_unsigned_cert_file, server_verification_ca_cert_file) + + print + print " --== Client pkcs12 expired certificate generating ==-- " + client_expired_cert_file = os.path.join(client_dir, "client_expired.crt") + client_pkcs12_expired_file = os.path.join(client_dir, "client_credential_expired.p12") + gen_expire_cert(client_expired_cert_file, client_key_file, ford_client_cert_file, ford_client_key_file, days, client_expired_answer) + gen_pkcs12(client_pkcs12_expired_file, client_key_file, client_expired_cert_file, server_verification_ca_cert_file) + + subprocess.call(["c_rehash", server_dir]) + subprocess.call(["c_rehash", client_dir]) + print + print "All certificates have been generated" + +if __name__ == "__main__": + main() diff --git a/tools/infrastructure/check_style.sh b/tools/infrastructure/check_style.sh new file mode 100755 index 0000000000..f42a048b34 --- /dev/null +++ b/tools/infrastructure/check_style.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env sh +# Copyright (c) 2016 Ford Motor Company, +# 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. +# +# * Neither the name of Ford Motor Company nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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. + +FILE_NAMES=$(find src -name \*.h -print -o -name \*.cpp -print -o -name \*.cc -print | grep -v 3rd_party) + + +check_style() { + clang-format-3.6 -style=file $1 | diff $1 - +} + +fix_style() { + clang-format-3.6 -style=file -i $1 +} + +if [ "$1" = "--fix" ] +then + for FILE_NAME in $FILE_NAMES; do fix_style $FILE_NAME; done +else + for FILE_NAME in $FILE_NAMES; do check_style $FILE_NAME; done +fi + diff --git a/tools/infrastructure/collect_coverage.sh b/tools/infrastructure/collect_coverage.sh new file mode 100755 index 0000000000..47559e6c47 --- /dev/null +++ b/tools/infrastructure/collect_coverage.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +BUILD_DIR=$1 +COVERAGE_DIR=$BUILD_DIR/coverage +REPORTS_DIR=$BUILD_DIR/coverage_reports + +if [ "$BUILD_DIR" = "" ] +then + echo "You should specify your build directory as first argument " + echo "Example:" + echo "\t\$ collect_coverage.sh [PATH TO BUILD DIR]" + exit +fi + + +rm -rf $COVERAGE_DIR +rm -rf $REPORTS_DIR - + +mkdir $COVERAGE_DIR +lcov --quiet --capture --directory . --output-file $COVERAGE_DIR/full_report.info +lcov --quiet --remove $COVERAGE_DIR/full_report.info '/usr/*' '*/test/*' '*/src/3rd*' '*/build/src/*' --output-file $COVERAGE_DIR/coverage.info + +mkdir $REPORTS_DIR +genhtml --quiet $COVERAGE_DIR/coverage.info --output-directory $REPORTS_DIR +html2text -width 150 $REPORTS_DIR/index.html +tar -zcf coverage_report.tar.gz $REPORTS_DIR +echo More information avaliable in $REPORTS_DIR/index.html diff --git a/tools/infrastructure/format_src.py b/tools/infrastructure/format_src.py new file mode 100644 index 0000000000..b7927b2708 --- /dev/null +++ b/tools/infrastructure/format_src.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Format all sources with clang-format. All *.cc and *h in the src dir +are affected. Excluded from formatting sources in the "3rd_party" and +in the "3rd_party-static" dirs. For the formatting used ".clang-format" +in the project root. +""" + +import os +from utils import setup_working_dir, walk_dir, run_cmd +import re + + +INCLUDE_PATTERNS = ['^.*\.cc$', '^.*\.h$', '^.*\.cpp$', '^.*\.hpp$'] +EXCLUDE_PATTERNS = ['^.*3rd_party.*$'] +FORMAT_CMD = 'clang-format -i -style=file {}' + + +def main(): + ''' Main logic ''' + setup_working_dir() + print 'Current working dir is {}'.format(os.getcwd()) + + def action(file_path): + if re.match('|'.join(INCLUDE_PATTERNS), file_path, re.M | re.I): + if not re.match('|'.join(EXCLUDE_PATTERNS), + file_path, + re.M | re.I): + print 'Formatting file {}'.format(file_path) + run_cmd(FORMAT_CMD.format(file_path)) + walk_dir('src', action) + + +if __name__ == '__main__': + main() diff --git a/tools/infrastructure/git-hooks/pre-commit b/tools/infrastructure/git-hooks/pre-commit new file mode 100755 index 0000000000..9c46f195f3 --- /dev/null +++ b/tools/infrastructure/git-hooks/pre-commit @@ -0,0 +1,102 @@ +#!/bin/bash + +# Hide all unstaged changes to prevent any influence of the further checks +function POP_STASHED() { + # pop stashed changes if working directory isn't clean + if [ -n "$IS_DIRTY" ]; then + git reset --hard HEAD > /dev/null + skipped=$(git ls-files -t | grep ^S | cut -d' ' -f2-) + git stash pop --index > /dev/null + echo "$skipped" | while read file; do git update-index --skip-worktree "$file"; done + fi +} + +# determine working tree status +IS_DIRTY=`[[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo '*'` + +# stash not staged for commit changes +if [ -n "$IS_DIRTY" ]; then + git stash save --keep-index + trap POP_STASHED EXIT +fi +# End of stashing + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +TEXT_DEFAULT="\\033[0;39m" +TEXT_INFO="\\033[1;32m" +TEXT_ERROR="\\033[1;31m" +TEXT_UNDERLINE="\\0033[4m" +TEXT_BOLD="\\0033[1m" + +# check for odd whitespace +git diff --check --cached --color +if [ "$?" -ne "0" ]; then + echo -e "$TEXT_ERROR" "Your changes introduce whitespace errors" "$TEXT_DEFAULT" + exit 1 +fi + +# Auto update c++ files with clang-format-3.6 +CLANG_FORMAT=clang-format-3.6 +# Verify clang-format +CLANG_FORMAT_REQUIRED_VERSION=3.6 +CLANG_FORMAT_CURRENT_VERSION=$($CLANG_FORMAT -version) +if [[ $CLANG_FORMAT_CURRENT_VERSION != *$CLANG_FORMAT_REQUIRED_VERSION* ]] +then + echo -e "$TEXT_ERROR" "Wrong version of the clang-format. Required: $CLANG_FORMAT_REQUIRED_VERSION. Got: $CLANG_FORMAT_CURRENT_VERSION" "$TEXT_DEFAULT" + exit 1 +fi + +CPP_SRC_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E "(\.cc$|\.cpp$|\.h$|\.hpp$)" | grep -v "3rd_party") +if [ -n "$CPP_SRC_FILES" ]; then + $CLANG_FORMAT -i -style=file $CPP_SRC_FILES + # Add possible changes after formating to the index + git add $CPP_SRC_FILES +fi + +# Auto-check for pep8 in python code +PYTHON_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -e '\.py$') + +if [ -n "$PYTHON_FILES" ]; then + flake8 $PYTHON_FILES + if [ "$?" -ne "0" ]; then + echo -e "$TEXT_ERROR" "Flake8 reports about the issues in the python scripts" "$TEXT_DEFAULT" + exit 2 + fi +fi diff --git a/tools/infrastructure/install_hooks.py b/tools/infrastructure/install_hooks.py new file mode 100644 index 0000000000..6f93e02c41 --- /dev/null +++ b/tools/infrastructure/install_hooks.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Install (copy) git hooks +""" + +import os +import glob +import shutil +from utils import setup_working_dir + + +def uninstall_hooks(hooks_dir): + print 'Deleting existing pre-commit hooks from {}'.format(hooks_dir) + files = glob.glob(os.path.join(hooks_dir, 'pre-commit*')) + for item in files: + os.remove(item) + + +def install_hooks(src_dir, dst_dir): + print 'Installing pre-commit hooks' + src_files = glob.glob(os.path.join(src_dir, 'pre-commit*')) + for item in src_files: + shutil.copy(item, dst_dir) + + +def main(): + ''' Main logic ''' + setup_working_dir() + print 'Current working dir is {}'.format(os.getcwd()) + hooks_src_dir = os.path.join( + os.getcwd(), 'tools', 'infrastructure', 'git-hooks') + hooks_dst_dir = os.path.join(os.getcwd(), '.git', 'hooks') + uninstall_hooks(hooks_dst_dir) + install_hooks(hooks_src_dir, hooks_dst_dir) + + +if __name__ == '__main__': + main() diff --git a/tools/infrastructure/utils.py b/tools/infrastructure/utils.py new file mode 100644 index 0000000000..ec1af42cce --- /dev/null +++ b/tools/infrastructure/utils.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +""" Misc utils used by other modules """ + +import os +import contextlib + + +def setup_working_dir(): + """ Prepare current working dir (in case if script is called from + outside). Set it to the project root. + """ + os.chdir(os.path.join(os.path.dirname( + os.path.realpath(__file__)), os.pardir, os.pardir)) + + +def run_cmd(cmd_line): + import subprocess + + return subprocess.call(cmd_line, shell=True) + + +def walk_dir(directory, action, recursive=True): + """ Walks a directory, and executes the action on each file """ + directory = os.path.abspath(directory) + for file in [file for file in os.listdir(directory) if file not in [os.curdir, os.pardir]]: + file_path = os.path.join(directory, file) + action(file_path) + if recursive and os.path.isdir(file_path): + walk_dir(file_path, action) + + +@contextlib.contextmanager +def working_directory(path): + """ A context manager which changes the working directory to the given + path, and then changes it back to it's previous value on exit. + """ + prev_cwd = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(prev_cwd) diff --git a/tools/policy_table_validator/CMakeLists.txt b/tools/policy_table_validator/CMakeLists.txt index 2a372d7ffa..7d9194e473 100644 --- a/tools/policy_table_validator/CMakeLists.txt +++ b/tools/policy_table_validator/CMakeLists.txt @@ -1,16 +1,15 @@ #set( CMAKE_VERBOSE_MAKEFILE on ) include_directories( - ${CMAKE_SOURCE_DIR}/src/components/policy/src/policy/ - ${CMAKE_SOURCE_DIR}/src/components/rpc_base/include/ - ${CMAKE_SOURCE_DIR}/src/components/utils/include/ + ${CMAKE_SOURCE_DIR}/src/components/policy/include + ${CMAKE_SOURCE_DIR}/src/components/rpc_base/include/ + ${CMAKE_SOURCE_DIR}/src/components/utils/include/ ${JSONCPP_INCLUDE_DIRECTORY} ) link_directories ( - ${CMAKE_BINARY_DIR}/src/components/policy/src/policy/policy_table/table_struct/ - ${CMAKE_BINARY_DIR}/src/components/rpc_base/ + ${CMAKE_BINARY_DIR}/src/components/rpc_base/ ) diff --git a/tools/policy_table_validator/main.cpp b/tools/policy_table_validator/main.cpp index 16454ca128..509182edbf 100644 --- a/tools/policy_table_validator/main.cpp +++ b/tools/policy_table_validator/main.cpp @@ -1,6 +1,6 @@ #include <iostream> #include <cstdlib> -#include "policy_table/table_struct/types.h" +#include "policy/policy_table/types.h" #include "json/reader.h" #include "utils/file_system.h" |