Skip to content

Commit

Permalink
[feat] Introduce chronological order for dynamic reports
Browse files Browse the repository at this point in the history
Reports' can be assigned some labels. It is useful especially for
dynamic analyzer reports for storing their timestamps or test cases
during which they appeared.
Now it is possible to store a "chronological-order" annotation which is
a simple integer counter.
  • Loading branch information
bruntib committed Feb 6, 2025
1 parent c20461c commit 03bb2c5
Show file tree
Hide file tree
Showing 15 changed files with 81 additions and 37 deletions.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/js/codechecker-api-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codechecker-api",
"version": "6.60.0",
"version": "6.61.0",
"description": "Generated node.js compatible API stubs for CodeChecker server.",
"main": "lib",
"homepage": "https://github.com/Ericsson/codechecker",
Expand Down
Binary file modified web/api/py/codechecker_api/dist/codechecker_api.tar.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.60.0'
api_version = '6.61.0'

setup(
name='codechecker_api',
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api_shared/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.60.0'
api_version = '6.61.0'

setup(
name='codechecker_api_shared',
Expand Down
3 changes: 2 additions & 1 deletion web/api/report_server.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ enum SortType {
DETECTION_STATUS,
BUG_PATH_LENGTH,
TIMESTAMP,
TESTCASE
TESTCASE,
CHRONOLOGICAL_ORDER
}

enum RunSortType {
Expand Down
2 changes: 1 addition & 1 deletion web/codechecker_web/shared/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# The newest supported minor version (value) for each supported major version
# (key) in this particular build.
SUPPORTED_VERSIONS = {
6: 60
6: 61
}

# Used by the client to automatically identify the latest major and minor
Expand Down
24 changes: 4 additions & 20 deletions web/server/codechecker_server/api/mass_store_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
Run, RunLock, RunHistory
from ..metadata import checker_is_unavailable, MetadataInfoParser

from .report_annotations import report_annotation_types
from .report_server import ThriftRequestHandler
from .thrift_enum_helper import report_extended_data_type_str

Expand Down Expand Up @@ -1160,39 +1161,22 @@ def __validate_and_add_report_annotations(
doesn't match then an exception is thrown. In case of proper format the
annotation is added to the database.
"""
allowed_types = {
"datetime": {
"func": datetime.fromisoformat,
"display": "date-time in ISO format"
},
"string": {
"func": str,
"display": "string"
}
}

allowed_annotations = {
"timestamp": allowed_types["datetime"],
"testsuite": allowed_types["string"],
"testcase": allowed_types["string"]
}

for key, value in report_annotation.items():
try:
allowed_annotations[key]["func"](value)
report_annotation_types[key]["func"](value)
session.add(ReportAnnotations(report_id, key, value))
except KeyError:
# pylint: disable=raise-missing-from
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.REPORT_FORMAT,
f"'{key}' is not an allowed report annotation.",
allowed_annotations.keys())
report_annotation_types.keys())
except ValueError:
# pylint: disable=raise-missing-from
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.REPORT_FORMAT,
f"'{value}' has wrong format. '{key}' annotations must be "
f"'{allowed_annotations[key]['display']}'.")
f"'{report_annotation_types[key]['display']}'.")

def __get_report_limit_for_product(self):
with DBSession(self.__config_database) as session:
Expand Down
37 changes: 37 additions & 0 deletions web/server/codechecker_server/api/report_annotations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -------------------------------------------------------------------------
#
# Part of the CodeChecker project, under the Apache License v2.0 with
# LLVM Exceptions. See LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# -------------------------------------------------------------------------

from datetime import datetime
import sqlalchemy


__allowed_types = {
"datetime": {
"func": datetime.fromisoformat,
"display": "date-time in ISO format",
"db": sqlalchemy.types.DateTime
},
"string": {
"func": str,
"display": "string",
"db": sqlalchemy.types.String
},
"integer": {
"func": int,
"display": "integer",
"db": sqlalchemy.types.Integer
}
}


report_annotation_types = {
"timestamp": __allowed_types["datetime"],
"testsuite": __allowed_types["string"],
"testcase": __allowed_types["string"],
"chronological-order": __allowed_types["integer"]
}
11 changes: 8 additions & 3 deletions web/server/codechecker_server/api/report_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
from .thrift_enum_helper import detection_status_enum, \
detection_status_str, report_status_enum, \
review_status_enum, review_status_str, report_extended_data_type_enum
from .report_annotations import report_annotation_types

# These names are inherited from Thrift stubs.
# pylint: disable=invalid-name
Expand Down Expand Up @@ -1024,7 +1025,9 @@ def get_sort_map(sort_types, is_unique=False):
SortType.REVIEW_STATUS: [(Report.review_status, 'rw_status')],
SortType.DETECTION_STATUS: [(Report.detection_status, 'dt_status')],
SortType.TIMESTAMP: [('annotation_timestamp', 'annotation_timestamp')],
SortType.TESTCASE: [('annotation_testcase', 'annotation_testcase')]}
SortType.TESTCASE: [('annotation_testcase', 'annotation_testcase')],
SortType.CHRONOLOGICAL_ORDER: [('annotation_chronological-order',
'annotation_chronological-order')]}

if is_unique:
sort_type_map[SortType.FILENAME] = [(File.filename, 'filename')]
Expand Down Expand Up @@ -1959,7 +1962,9 @@ def getRunResults(self, run_ids, limit, offset, sort_types,
for col in annotation_keys:
annotation_cols[col] = func.max(sqlalchemy.case([(
ReportAnnotations.key == col,
ReportAnnotations.value)])).label(f"annotation_{col}")
cast(ReportAnnotations.value,
report_annotation_types[col]["db"]))])) \
.label(f"annotation_{col}")

if report_filter.isUnique:
# A report annotation filter cannot be set in WHERE clause if
Expand Down Expand Up @@ -2143,7 +2148,7 @@ def getRunResults(self, run_ids, limit, offset, sort_types,
for row in query_result:
report, filepath = row[0], row[1]
annotations = {
k: v for k, v in zip(annotation_keys, row[2:])
k: str(v) for k, v in zip(annotation_keys, row[2:])
if v is not None}

review_data = create_review_data(
Expand Down
13 changes: 6 additions & 7 deletions web/server/vue-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/server/vue-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@mdi/font": "^6.5.95",
"codechecker-api": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.60.0.tgz",
"codechecker-api": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.61.0.tgz",
"chart.js": "^2.9.4",
"chartjs-plugin-datalabels": "^0.7.0",
"codemirror": "^5.65.0",
Expand Down
20 changes: 19 additions & 1 deletion web/server/vue-cli/src/views/Reports.vue
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ export default {
align: "center",
sortable: true
},
{
text: "Chronological order",
value: "chronological-order",
align: "center",
sortable: true
},
{
text: "Testcase",
value: "testcase",
Expand All @@ -287,6 +293,7 @@ export default {
sameReports: {},
hasTimeStamp: true,
hasTestCase : true,
hasChronologicalOrder: true,
selected: [],
namespace: namespace,
pagination: {
Expand Down Expand Up @@ -337,6 +344,10 @@ export default {
return this.hasTestCase;
}
if (header.value === "chronological-order") {
return this.hasChronologicalOrder;
}
return true;
});
},
Expand Down Expand Up @@ -365,7 +376,8 @@ export default {
"$id": id,
"sameReports": report.sameReports,
"timestamp": report.annotations["timestamp"],
"testcase": report.annotations["testcase"]
"testcase": report.annotations["testcase"],
"chronological-order": report.annotations["chronological-order"]
};
});
}
Expand All @@ -388,6 +400,9 @@ export default {
this.hasTestCase =
this.formattedReports.some(report => report.testcase);
this.hasChronologicalOrder =
this.formattedReports.some(report => report["chronological-order"]);
}
}
},
Expand Down Expand Up @@ -426,6 +441,9 @@ export default {
case "testcase":
type = SortType.TESTCASE;
break;
case "chronological-order":
type = SortType.CHRONOLOGICAL_ORDER;
break;
default:
type = SortType.SEVERITY;
}
Expand Down

0 comments on commit 03bb2c5

Please sign in to comment.