Skip to content

Commit

Permalink
[client] Store support configuration file
Browse files Browse the repository at this point in the history
  • Loading branch information
csordasmarton committed May 7, 2020
1 parent 132eb46 commit fafa224
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 14 deletions.
4 changes: 1 addition & 3 deletions analyzer/codechecker_analyzer/cmd/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ def add_arguments_to_parser(parser):
"line arguments. The format of "
"configuration file is: "
"{"
" \"enabled\": true,"
" \"analyzer\": ["
" \"--enable=core.DivideZero\","
" \"--enable=core.CallAndMessage\","
Expand Down Expand Up @@ -603,8 +602,7 @@ def process_config_file(args):
"""
if args.config_file and os.path.exists(args.config_file):
cfg = load_json_or_empty(args.config_file, default={})
if cfg.get("enabled"):
return cfg.get('analyzer', [])
return cfg.get('analyzer', [])


def check_config_file(args):
Expand Down
1 change: 0 additions & 1 deletion analyzer/tests/functional/config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ def test_only_clangsa_config(self):
with open(self.config_file, 'w+',
encoding="utf-8", errors="ignore") as config_f:
json.dump({
'enabled': True,
'analyzer': ['--analyzers', 'clangsa']}, config_f)

out, returncode = self.__run_analyze()
Expand Down
1 change: 0 additions & 1 deletion docs/analyzer/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,6 @@ Lets assume you have a configuration file
[`codechecker.json`](#config/codechecker.json) with the following content:
```json
{
"enabled": true,
"analyzer": [
"--enable=core.DivideZero",
"--enable=core.CallAndMessage",
Expand Down
16 changes: 14 additions & 2 deletions docs/web/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ a database.
to the database.

```
usage: CodeChecker store [-h] [-t {plist}] [-n NAME] [--tag TAG] [-f]
[--url PRODUCT_URL]
usage: CodeChecker store [-h] [-t {plist}] [-n NAME] [--tag TAG]
[--trim-path-prefix [TRIM_PATH_PREFIX [TRIM_PATH_PREFIX ...]]]
[--config CONFIG_FILE] [-f] [--url PRODUCT_URL]
[--verbose {info,debug,debug_analyzer}]
[file/folder [file/folder ...]]
Expand Down Expand Up @@ -194,6 +195,17 @@ optional arguments:
removing "/a/b/" prefix will store files like c/x.cpp
and c/y.cpp. If multiple prefix is given, the longest
match will be removed.
--config CONFIG_FILE Allow the configuration from an explicit JSON based
configuration file. The values configured in the
config file will overwrite the values set in the
command line. The format of configuration file is:
{
"store": [
"--name=run_name",
"--tag=my_tag"
"--url=http://codechecker.my/MyProduct"
]
}. (default: None)
-f, --force Delete analysis results stored in the database for the
current analysis run's name and store only the results
reported in the 'input' files. (By default,
Expand Down
34 changes: 31 additions & 3 deletions web/client/codechecker_client/cmd/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ def get_argparser_ctor_args():
'formatter_class': arg.RawDescriptionDefaultHelpFormatter,

# Description is shown when the command's help is queried directly
'description': "Store the results from one or more 'codechecker-"
"analyze' result files in a database.",
'description': """
Store the results from one or more 'codechecker-analyze' result files in a
database.""",

# Epilogue is shown after the arguments when the help is queried
# directly.
Expand All @@ -86,6 +87,7 @@ def get_argparser_ctor_args():
It can also be used to setup different credential files to
login to the same server with a different user.
The results can be viewed by connecting to such a server in a Web browser or
via 'CodeChecker cmd'.""",

Expand Down Expand Up @@ -151,6 +153,22 @@ def add_arguments_to_parser(parser):
"If multiple prefix is given, the longest match "
"will be removed.")

parser.add_argument('--config',
dest='config_file',
required=False,
help="R|Allow the configuration from an explicit JSON "
"based configuration file. The values configured "
"in the config file will overwrite the values "
"set in the command line. The format of "
"configuration file is:\n"
"{\n"
" \"store\": [\n"
" \"--name=run_name\",\n"
" \"--tag=my_tag\"\n"
" \"--url=http://codechecker.my/MyProduct\"\n"
" ]\n"
"}.")

parser.add_argument('-f', '--force',
dest="force",
default=argparse.SUPPRESS,
Expand Down Expand Up @@ -181,7 +199,17 @@ def add_arguments_to_parser(parser):
"'[http[s]://]host:port/Endpoint'.")

logger.add_verbose_arguments(parser)
parser.set_defaults(func=main)
parser.set_defaults(func=main,
func_process_config_file=process_config_file)


def process_config_file(args):
"""
Handler to get config file options.
"""
if args.config_file and os.path.exists(args.config_file):
cfg = util.load_json_or_empty(args.config_file, default={})
return cfg.get('store', [])


def __get_run_name(input_list):
Expand Down
26 changes: 22 additions & 4 deletions web/tests/functional/cli_config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# coding=utf-8
# -----------------------------------------------------------------------------
# The CodeChecker Infrastructure
# This file is distributed under the University of Illinois Open Source
Expand All @@ -10,8 +9,11 @@

import os
import shutil
import sys

from libtest import codechecker
from libtest import env
from libtest import project


# Test workspace should be initialized in this module.
Expand All @@ -33,11 +35,23 @@ def setup_package():
codechecker_cfg = {
'workspace': TEST_WORKSPACE,
'check_env': env.test_env(TEST_WORKSPACE),
'viewer_host': 'localhost',
'viewer_product': 'db_cleanup'
'reportdir': os.path.join(TEST_WORKSPACE, 'reports')
}

env.export_test_cfg(TEST_WORKSPACE, {'codechecker_cfg': codechecker_cfg})
# Start or connect to the running CodeChecker server and get connection
# details.
print("This test uses a CodeChecker server... connecting...")
server_access = codechecker.start_or_get_server()
server_access['viewer_product'] = 'config'
codechecker.add_test_package_product(server_access, TEST_WORKSPACE)

# Extend the checker configuration with the server access.
codechecker_cfg.update(server_access)

test_config = {
'codechecker_cfg': codechecker_cfg}

env.export_test_cfg(TEST_WORKSPACE, test_config)


def teardown_package():
Expand All @@ -47,5 +61,9 @@ def teardown_package():
# and print out the path.
global TEST_WORKSPACE

check_env = env.import_test_cfg(TEST_WORKSPACE)[
'codechecker_cfg']['check_env']
codechecker.remove_test_package_product(TEST_WORKSPACE, check_env)

print("Removing: " + TEST_WORKSPACE)
shutil.rmtree(TEST_WORKSPACE)
90 changes: 90 additions & 0 deletions web/tests/functional/cli_config/test_store_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#
# -----------------------------------------------------------------------------
# The CodeChecker Infrastructure
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
# -----------------------------------------------------------------------------

"""
Test store configuration file.
"""


import json
import os
import subprocess
import unittest

from libtest import env


class TestStoreConfig(unittest.TestCase):
_ccClient = None

def setUp(self):

# TEST_WORKSPACE is automatically set by test package __init__.py .
self.test_workspace = os.environ['TEST_WORKSPACE']
self.codechecker_cfg = env.import_codechecker_cfg(self.test_workspace)

test_class = self.__class__.__name__
print('Running ' + test_class + ' tests in ' + self.test_workspace)

# Get the CodeChecker cmd if needed for the tests.
self._codechecker_cmd = env.codechecker_cmd()

self.config_file = os.path.join(self.test_workspace,
"codechecker.json")

# Create an empty report directory which will be used to check store
# command.
if not os.path.exists(self.codechecker_cfg['reportdir']):
os.mkdir(self.codechecker_cfg['reportdir'])

def test_valid_config(self):
""" Store with a valid configuration file. """
with open(self.config_file, 'w+',
encoding="utf-8", errors="ignore") as config_f:
json.dump({
'store': [
'--name=' + 'store_config',
'--url=' + env.parts_to_url(self.codechecker_cfg),
self.codechecker_cfg['reportdir']]}, config_f)

store_cmd = [env.codechecker_cmd(), 'store', '--config',
self.config_file]

subprocess.check_output(
store_cmd, encoding="utf-8", errors="ignore")

def test_invalid_config(self):
""" Store with an invalid configuration file. """
with open(self.config_file, 'w+',
encoding="utf-8", errors="ignore") as config_f:
json.dump({
'store': ['--dummy-option']}, config_f)

store_cmd = [env.codechecker_cmd(), 'store',
'--name', 'store_config',
'--config', self.config_file,
'--url', env.parts_to_url(self.codechecker_cfg),
self.codechecker_cfg['reportdir']]

with self.assertRaises(subprocess.CalledProcessError):
subprocess.check_output(
store_cmd, encoding="utf-8", errors="ignore")

def test_empty_config(self):
""" Store with an empty configuration file. """
with open(self.config_file, 'w+',
encoding="utf-8", errors="ignore") as config_f:
config_f.write("")

store_cmd = [env.codechecker_cmd(), 'store',
'--name', 'store_config',
'--config', self.config_file,
'--url', env.parts_to_url(self.codechecker_cfg),
self.codechecker_cfg['reportdir']]

subprocess.check_output(
store_cmd, encoding="utf-8", errors="ignore")

0 comments on commit fafa224

Please sign in to comment.