diff options
Diffstat (limited to 'gcc/testsuite/libgdiagnostics.dg')
6 files changed, 367 insertions, 3 deletions
diff --git a/gcc/testsuite/libgdiagnostics.dg/test-logical-location-c.py b/gcc/testsuite/libgdiagnostics.dg/test-logical-location-c.py index 7448a1e..55f338b 100644 --- a/gcc/testsuite/libgdiagnostics.dg/test-logical-location-c.py +++ b/gcc/testsuite/libgdiagnostics.dg/test-logical-location-c.py @@ -31,7 +31,16 @@ def test_sarif_output_with_logical_location(sarif): assert len(location['logicalLocations']) == 1 logical_loc = location['logicalLocations'][0] + assert logical_loc['index'] == 0 + assert logical_loc['fullyQualifiedName'] == 'test_qualified_name' + + # Check theRun.logicalLocations + assert 'logicalLocations' in run + assert len(run['logicalLocations']) == 1 + logical_loc = run['logicalLocations'][0] assert logical_loc['name'] == 'test_short_name' assert logical_loc['fullyQualifiedName'] == 'test_qualified_name' assert logical_loc['decoratedName'] == 'test_decorated_name' assert logical_loc['kind'] == 'function' + assert logical_loc['index'] == 0 + diff --git a/gcc/testsuite/libgdiagnostics.dg/test-logical-location.c b/gcc/testsuite/libgdiagnostics.dg/test-logical-location.c index 1408919..b59ece4 100644 --- a/gcc/testsuite/libgdiagnostics.dg/test-logical-location.c +++ b/gcc/testsuite/libgdiagnostics.dg/test-logical-location.c @@ -20,6 +20,7 @@ PRINT "hello world!"; const int line_num = __LINE__ - 2; #include <assert.h> +#include <string.h> int main () @@ -62,6 +63,17 @@ main () diagnostic_finish (d, "can't find %qs", "foo"); /* end quoted source */ + /* Verify that the accessors work. */ + assert (diagnostic_logical_location_get_kind (logical_loc) + == DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION); + assert (!diagnostic_logical_location_get_parent (logical_loc)); + assert (!strcmp (diagnostic_logical_location_get_short_name (logical_loc), + "test_short_name")); + assert (!strcmp (diagnostic_logical_location_get_fully_qualified_name (logical_loc), + "test_qualified_name")); + assert (!strcmp (diagnostic_logical_location_get_decorated_name (logical_loc), + "test_decorated_name")); + /* Verify that creating a diagnostic_logical_location with equal values yields the same instance. */ const diagnostic_logical_location *dup diff --git a/gcc/testsuite/libgdiagnostics.dg/test-logical-location.cc b/gcc/testsuite/libgdiagnostics.dg/test-logical-location.cc new file mode 100644 index 0000000..3080ade --- /dev/null +++ b/gcc/testsuite/libgdiagnostics.dg/test-logical-location.cc @@ -0,0 +1,91 @@ +/* C++ example of using a logical location. + + Intended output is similar to: + +In function 'test_qualified_name': +PATH/test-error-with-note.cc:17:8: error: can't find 'foo' + 17 | PRINT "hello world!"; + | ^~~~~~~~~~~~ + + along with the equivalent in SARIF. */ + +#include "libgdiagnostics++.h" + +/* Placeholder source: +_________111111111122 +123456789012345678901 +PRINT "hello world!"; +*/ +const int line_num = __LINE__ - 2; + +#include <assert.h> +#include <string.h> + +int +main () +{ + libgdiagnostics::manager mgr; + + auto file = mgr.new_file (__FILE__, "c"); + + mgr.add_text_sink (stderr, DIAGNOSTIC_COLORIZE_IF_TTY); + + auto loc_start = mgr.new_location_from_file_line_column (file, line_num, 8); + auto loc_end = mgr.new_location_from_file_line_column (file, line_num, 19); + auto loc_range = mgr.new_location_from_range (loc_start, loc_start, loc_end); + + auto err (mgr.begin_diagnostic (DIAGNOSTIC_LEVEL_ERROR)); + err.set_location (loc_range); + + libgdiagnostics::logical_location logical_loc + = mgr.new_logical_location (DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, + NULL, /* parent */ + "test_short_name", + "test_qualified_name", + "test_decorated_name"); + err.set_logical_location (logical_loc); + + err.finish ("can't find %qs", "foo"); + + /* Verify that the accessors work. */ + assert (logical_loc.get_kind () + == DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION); + assert (logical_loc.get_parent ().m_inner == nullptr); + assert (!strcmp (logical_loc.get_short_name (), + "test_short_name")); + assert (!strcmp (logical_loc.get_fully_qualified_name (), + "test_qualified_name")); + assert (!strcmp (logical_loc.get_decorated_name (), + "test_decorated_name")); + + /* Verify that libgdiagnostic::logical_location instances created with + equal values compare as equal. */ + libgdiagnostics::logical_location dup + = mgr.new_logical_location (DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, + NULL, /* parent */ + "test_short_name", + "test_qualified_name", + "test_decorated_name"); + assert (dup == logical_loc); + + /* Verify that libgdiagnostic::logical_location instances created with + differing values compare as non-equal. */ + libgdiagnostics::logical_location other + = mgr.new_logical_location (DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, + NULL, /* parent */ + "something_else", + NULL, NULL); + assert (other != logical_loc); + + return 0; +} + +/* Check the output from the text sink. */ +/* { dg-begin-multiline-output "" } +In function 'test_qualified_name': + { dg-end-multiline-output "" } */ +/* { dg-regexp "\[^\n\r\]+test-logical-location.cc:17:8: error: can't find 'foo'" } */ +/* { dg-begin-multiline-output "" } + 17 | PRINT "hello world!"; + | ^~~~~~~~~~~~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py new file mode 100644 index 0000000..39cc1a9 --- /dev/null +++ b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json-c.py @@ -0,0 +1,79 @@ +from sarif import * + +import pytest + +@pytest.fixture(scope='function', autouse=True) +def sarif(): + return sarif_from_env() + +def test_sarif_output_with_logical_location(sarif): + schema = sarif['$schema'] + assert schema == 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json' + + version = sarif['version'] + assert version == '2.1.0' + + runs = sarif['runs'] + run = runs[0] + + tool = run['tool'] + assert tool['driver']['name'] == 'test-nested-logical-locations-json.c.exe' + + results = run['results'] + assert len(results) == 2 + + result = results[0] + assert result['ruleId'] == 'warning' + assert result['level'] == 'warning' + assert result['message']['text'] == "product ID is blank" + assert len(result['locations']) == 1 + location = result['locations'][0] + assert len(location['logicalLocations']) == 1 + logical_loc = location['logicalLocations'][0] + assert logical_loc['index'] == 3 + assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds/1' + + result = results[1] + assert result['ruleId'] == 'warning' + assert result['level'] == 'warning' + assert result['message']['text'] == "value is negative" + assert len(result['locations']) == 1 + location = result['locations'][0] + assert len(location['logicalLocations']) == 1 + logical_loc = location['logicalLocations'][0] + assert logical_loc['index'] == 4 + assert logical_loc['fullyQualifiedName'] == '/orders/0/total' + + # Check theRun.logicalLocations + assert 'logicalLocations' in run + assert len(run['logicalLocations']) == 5 + logical_loc = run['logicalLocations'][0] + assert logical_loc['name'] == 'orders' + assert logical_loc['fullyQualifiedName'] == '/orders' + assert logical_loc['kind'] == 'array' + assert logical_loc['index'] == 0 + logical_loc = run['logicalLocations'][1] + assert logical_loc['name'] == '0' + assert logical_loc['fullyQualifiedName'] == '/orders/0' + assert logical_loc['kind'] == 'object' + assert logical_loc['parentIndex'] == 0 + assert logical_loc['index'] == 1 + logical_loc = run['logicalLocations'][2] + assert logical_loc['name'] == 'productIds' + assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds' + assert logical_loc['kind'] == 'array' + assert logical_loc['parentIndex'] == 1 + assert logical_loc['index'] == 2 + logical_loc = run['logicalLocations'][3] + assert logical_loc['name'] == '1' + assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds/1' + assert logical_loc['kind'] == 'value' + assert logical_loc['parentIndex'] == 2 + assert logical_loc['index'] == 3 + logical_loc = run['logicalLocations'][4] + assert logical_loc['name'] == 'total' + assert logical_loc['fullyQualifiedName'] == '/orders/0/total' + assert logical_loc['kind'] == 'property' + assert logical_loc['parentIndex'] == 1 + assert logical_loc['index'] == 4 + diff --git a/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c new file mode 100644 index 0000000..d06450e --- /dev/null +++ b/gcc/testsuite/libgdiagnostics.dg/test-nested-logical-locations-json.c @@ -0,0 +1,165 @@ +/* Example of nested logical locations, based on the JSON example in + SARIF v2.1.0, 3.33.7 "kind" property; + though see https://github.com/oasis-tcs/sarif-spec/issues/670 + + Intended output is similar to: + +In JSON value '/orders/0/productIds/1': +PATH/test-nested-logical-locations-json.c:28:32: warning: product ID is blank + 28 | "productIds": [ "A-101", "", "A-223" ], + | ^~ +In JSON property '/orders/0/total': +PATH/test-nested-logical-locations-json.c:29:16: warning: value is negative + 29 | "total": "-3.25" + | ^~~~~~~ + + along with the equivalent in SARIF, capturing JSON structure + as nested logical locations. */ + +#include "libgdiagnostics.h" +#include "test-helpers.h" + +/* Placeholder source: +_________1111111111222222222233333333334444444444 +1234567890123456789012345678901234567890123456789 +{ + "orders": [ + { + "productIds": [ "A-101", "", "A-223" ], + "total": "-3.25" + } + ] +} +*/ +const int start_line_num = __LINE__ - 9; +const int line_num_of_product_ids = start_line_num + 3; +const int line_num_of_total = line_num_of_product_ids + 1; + +#include <assert.h> + +int +main () +{ + begin_test ("test-nested-logical-locations-json.c.exe", + "test-nested-logical-locations-json.c.sarif", + __FILE__, "c"); + + /* Create tree of logical locations. */ + /* begin quoted source */ + const diagnostic_logical_location *logical_loc_orders_arr + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, + NULL, /* parent */ + "orders", + "/orders", + NULL); + const diagnostic_logical_location *logical_loc_order_0 + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT, + logical_loc_orders_arr, /* parent */ + "0", + "/orders/0", + NULL); + const diagnostic_logical_location *logical_loc_product_ids + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, + logical_loc_order_0, /* parent */ + "productIds", + "/orders/0/productIds", + NULL); + const diagnostic_logical_location *logical_loc_element_1 + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE, + logical_loc_product_ids, /* parent */ + "1", + "/orders/0/productIds/1", + NULL); + const diagnostic_logical_location *logical_loc_total + = diagnostic_manager_new_logical_location (diag_mgr, + DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY, + logical_loc_order_0, /* parent */ + "total", + "/orders/0/total", + NULL); + /* end quoted source */ + + { + const int line_num = line_num_of_product_ids; + const diagnostic_physical_location *loc_start + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 32); + const diagnostic_physical_location *loc_end + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 33); + const diagnostic_physical_location *loc_range + = diagnostic_manager_new_location_from_range (diag_mgr, + loc_start, + loc_start, + loc_end); + + diagnostic *d = diagnostic_begin (diag_mgr, + DIAGNOSTIC_LEVEL_WARNING); + diagnostic_set_location (d, loc_range); + + diagnostic_set_logical_location (d, logical_loc_element_1); + + diagnostic_finish (d, "product ID is blank"); + } + { + const int line_num = line_num_of_total; + const diagnostic_physical_location *loc_start + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 16); + const diagnostic_physical_location *loc_end + = diagnostic_manager_new_location_from_file_line_column (diag_mgr, + main_file, + line_num, + 22); + const diagnostic_physical_location *loc_range + = diagnostic_manager_new_location_from_range (diag_mgr, + loc_start, + loc_start, + loc_end); + + diagnostic *d = diagnostic_begin (diag_mgr, + DIAGNOSTIC_LEVEL_WARNING); + diagnostic_set_location (d, loc_range); + + diagnostic_set_logical_location (d, logical_loc_total); + + diagnostic_finish (d, "value is negative"); + } + + return end_test (); +} + +/* Check the output from the text sink. */ +/* { dg-begin-multiline-output "" } +In JSON value '/orders/0/productIds/1': + { dg-end-multiline-output "" } */ +/* { dg-regexp "\[^\n\r\]+test-nested-logical-locations-json.c:28:32: warning: product ID is blank" } */ +/* { dg-begin-multiline-output "" } + 28 | "productIds": [ "A-101", "", "A-223" ], + | ^~ + { dg-end-multiline-output "" } */ +/* { dg-begin-multiline-output "" } +In JSON property '/orders/0/total': + { dg-end-multiline-output "" } */ +/* { dg-regexp "\[^\n\r\]+test-nested-logical-locations-json.c:29:16: warning: value is negative" } */ +/* { dg-begin-multiline-output "" } + 29 | "total": "-3.25" + | ^~~~~~~ + { dg-end-multiline-output "" } */ + +/* Verify that some JSON was written to a file with the expected name: + { dg-final { verify-sarif-file } } */ + +/* Use a Python script to verify various properties about the generated + .sarif file: + { dg-final { run-sarif-pytest test-nested-logical-locations-json.c "test-nested-logical-locations-json-c.py" } } */ diff --git a/gcc/testsuite/libgdiagnostics.dg/test-warning-with-path-c.py b/gcc/testsuite/libgdiagnostics.dg/test-warning-with-path-c.py index 5d3bbc4..af1e7b9 100644 --- a/gcc/testsuite/libgdiagnostics.dg/test-warning-with-path-c.py +++ b/gcc/testsuite/libgdiagnostics.dg/test-warning-with-path-c.py @@ -51,10 +51,8 @@ def test_sarif_output_for_warning_with_path(sarif): assert len(location['logicalLocations']) == 1 logical_loc = location['logicalLocations'][0] - assert logical_loc['name'] == 'make_a_list_of_random_ints_badly' + assert logical_loc['index'] == 0 assert logical_loc['fullyQualifiedName'] == 'make_a_list_of_random_ints_badly' - assert logical_loc['decoratedName'] == 'make_a_list_of_random_ints_badly' - assert logical_loc['kind'] == 'function' assert len(result['codeFlows']) == 1 assert len(result['codeFlows'][0]['threadFlows']) == 1 @@ -106,3 +104,13 @@ def test_sarif_output_for_warning_with_path(sarif): == "when calling 'PyList_Append', passing NULL from (1) as argument 1" assert tfl_2['nestingLevel'] == 0 assert tfl_2['executionOrder'] == 3 + + # Check theRun.logicalLocations + assert 'logicalLocations' in run + assert len(run['logicalLocations']) == 1 + logical_loc = run['logicalLocations'][0] + assert logical_loc['name'] == 'make_a_list_of_random_ints_badly' + assert logical_loc['fullyQualifiedName'] == 'make_a_list_of_random_ints_badly' + assert logical_loc['decoratedName'] == 'make_a_list_of_random_ints_badly' + assert logical_loc['kind'] == 'function' + assert logical_loc['index'] == 0 |