Skip to content

Commit a3f38e7

Browse files
committed
Add unit test to check symbol table JSON input and output format consistency
The unit test first outputs a symbol table to JSON via show_symbol_table() and then reads it back in again via symbol_table_from_json(). Then, it checks that the initial symbol table and the symbol table read back in again are equal.
1 parent 13dac86 commit a3f38e7

File tree

3 files changed

+152
-2
lines changed

3 files changed

+152
-2
lines changed

src/util/ui_message.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ class ui_message_handlert : public message_handlert
2727

2828
virtual ~ui_message_handlert();
2929

30-
uit get_ui() const
30+
virtual uit get_ui() const
3131
{
3232
return _ui;
3333
}
3434

3535
virtual void flush(unsigned level) override;
3636

37-
json_stream_arrayt &get_json_stream()
37+
virtual json_stream_arrayt &get_json_stream()
3838
{
3939
PRECONDITION(json_stream!=nullptr);
4040
return *json_stream;

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ SRC += analyses/ai/ai.cpp \
2828
goto-symex/ssa_equation.cpp \
2929
interpreter/interpreter.cpp \
3030
json/json_parser.cpp \
31+
json_symbol_table.cpp \
3132
path_strategies.cpp \
3233
pointer-analysis/value_set.cpp \
3334
solvers/floatbv/float_utils.cpp \

unit/json_symbol_table.cpp

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/// Author: Daniel Poetzl
2+
3+
/// \file json symbol table read/write consistency
4+
5+
#include <ansi-c/ansi_c_language.h>
6+
7+
#include <cbmc/cbmc_parse_options.h>
8+
9+
#include <goto-programs/goto_convert_functions.h>
10+
#include <goto-programs/goto_model.h>
11+
#include <goto-programs/initialize_goto_model.h>
12+
#include <goto-programs/show_symbol_table.h>
13+
14+
#include <json-symtab-language/json_symbol_table.h>
15+
#include <json/json_parser.h>
16+
17+
#include <langapi/language_file.h>
18+
#include <langapi/mode.h>
19+
20+
#include <util/cmdline.h>
21+
#include <util/config.h>
22+
#include <util/message.h>
23+
#include <util/options.h>
24+
#include <util/symbol_table.h>
25+
26+
#include <testing-utils/catch.hpp>
27+
#include <testing-utils/message.h>
28+
29+
#include <iosfwd>
30+
31+
class test_ui_message_handlert : public ui_message_handlert
32+
{
33+
public:
34+
explicit test_ui_message_handlert(std::ostream &out)
35+
: ui_message_handlert(cmdlinet(), ""), json_stream_array(out, 0)
36+
{
37+
}
38+
39+
uit get_ui() const
40+
{
41+
return uit::JSON_UI;
42+
}
43+
44+
json_stream_arrayt &get_json_stream()
45+
{
46+
return json_stream_array;
47+
}
48+
49+
json_stream_arrayt json_stream_array;
50+
};
51+
52+
void get_goto_model(std::istream &in, goto_modelt &goto_model)
53+
{
54+
optionst options;
55+
cbmc_parse_optionst::set_default_options(options);
56+
57+
messaget null_message(null_message_handler);
58+
59+
language_filest language_files;
60+
language_files.set_message_handler(null_message_handler);
61+
62+
std::string filename("");
63+
64+
language_filet &language_file = language_files.add_file(filename);
65+
66+
language_file.language = get_default_language();
67+
68+
languaget &language = *language_file.language;
69+
language.set_message_handler(null_message_handler);
70+
language.set_language_options(options);
71+
72+
{
73+
bool r = language.parse(in, filename);
74+
REQUIRE(!r);
75+
}
76+
77+
language_file.get_modules();
78+
79+
{
80+
bool r = language_files.typecheck(goto_model.symbol_table);
81+
REQUIRE(!r);
82+
}
83+
84+
REQUIRE(!goto_model.symbol_table.has_symbol(goto_functionst::entry_point()));
85+
86+
{
87+
bool r = language_files.generate_support_functions(goto_model.symbol_table);
88+
REQUIRE(!r);
89+
}
90+
91+
goto_convert(
92+
goto_model.symbol_table, goto_model.goto_functions, null_message_handler);
93+
}
94+
95+
TEST_CASE("json symbol table read/write consistency")
96+
{
97+
register_language(new_ansi_c_language);
98+
99+
cmdlinet cmdline;
100+
config.main = "main";
101+
config.set(cmdline);
102+
103+
goto_modelt goto_model;
104+
105+
// Get symbol table associated with goto program
106+
107+
{
108+
std::string program = "int main() { return 0; }\n";
109+
110+
std::istringstream in(program);
111+
get_goto_model(in, goto_model);
112+
}
113+
114+
const symbol_tablet &symbol_table1 = goto_model.symbol_table;
115+
116+
// Convert symbol table to json string
117+
118+
std::ostringstream out;
119+
120+
{
121+
test_ui_message_handlert ui_message_handler(out);
122+
REQUIRE(ui_message_handler.get_ui() == ui_message_handlert::uit::JSON_UI);
123+
124+
show_symbol_table(symbol_table1, ui_message_handler);
125+
}
126+
127+
// Convert json string to symbol table
128+
129+
symbol_tablet symbol_table2;
130+
131+
{
132+
std::istringstream in(out.str());
133+
jsont json;
134+
135+
bool r = parse_json(in, "", null_message_handler, json);
136+
REQUIRE(!r);
137+
138+
REQUIRE(json.is_array());
139+
140+
const json_arrayt &json_array = to_json_array(json);
141+
const jsont &json_symbol_table = *json_array.begin();
142+
143+
symbol_table_from_json(json_symbol_table, symbol_table2);
144+
}
145+
146+
// Finally check if symbol tables are consistent
147+
148+
REQUIRE(symbol_table1 == symbol_table2);
149+
}

0 commit comments

Comments
 (0)