KiCad PCB EDA Suite
test_sexpr_parser.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
30
31// Code under test
32#include <sexpr/sexpr_parser.h>
33
34#include "sexpr_test_utils.h"
35
37{
38public:
42 std::unique_ptr<SEXPR::SEXPR> Parse( const std::string& aIn )
43 {
44 return std::unique_ptr<SEXPR::SEXPR>( m_parser.Parse( aIn ) );
45 }
46
48};
49
50
56{
57 std::string m_case_name;
58 std::string m_sexpr_data;
59};
60
61
65BOOST_FIXTURE_TEST_SUITE( SexprParser, TEST_SEXPR_PARSER_FIXTURE )
66
67
71{
72 const std::vector<TEST_SEXPR_CASE> cases = {
73 {
74 "Empty string",
75 "",
76 },
77 {
78 "whitespace",
79 " ",
80 },
81 };
82
83 for( const auto& c : cases )
84 {
85 BOOST_TEST_CONTEXT( c.m_case_name )
86 {
87 const auto data = Parse( c.m_sexpr_data );
88 BOOST_CHECK_EQUAL( data.get(), nullptr );
89 }
90 }
91}
92
97{
98 const std::string content{ "this is just writing" };
99 const auto sexp = Parse( content );
100
101 BOOST_REQUIRE_NE( sexp.get(), nullptr );
102 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsSymbolWithValue, ( *sexp )( "this" ) );
103}
104
108BOOST_AUTO_TEST_CASE( ParseExceptions )
109{
110 const std::vector<TEST_SEXPR_CASE> cases = {
111 {
112 "Unclosed (symbol",
113 "(symbol",
114 },
115 {
116 "Comma",
117 ",",
118 },
119 {
120 "Int only",
121 "1",
122 },
123 {
124 "Double only",
125 "3.14",
126 },
127 {
128 "Symbol only",
129 "symbol",
130 },
131 // { // this is OK for some reason
132 // "String only",
133 // "\"string\"",
134 // },
135 };
136
137 for( const auto& c : cases )
138 {
139 BOOST_TEST_CONTEXT( c.m_case_name )
140 {
141 BOOST_CHECK_THROW( Parse( c.m_sexpr_data ), SEXPR::PARSE_EXCEPTION );
142 }
143 }
144}
145
150{
151 const std::string content{ "()" };
152 const auto sexp = Parse( content );
153
154 BOOST_REQUIRE_NE( sexp.get(), nullptr );
155 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsListOfLength, ( *sexp )( 0 ) );
156}
157
161BOOST_AUTO_TEST_CASE( SimpleSymbol )
162{
163 const std::string content{ "(symbol)" };
164 const auto sexp = Parse( content );
165
166 BOOST_REQUIRE_NE( sexp.get(), nullptr );
167 BOOST_REQUIRE_PREDICATE( KI_TEST::SexprIsListOfLength, ( *sexp )( 1 ) );
168
169 const SEXPR::SEXPR& child = *sexp->GetChild( 0 );
170 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsSymbolWithValue, ( child )( "symbol" ) );
171}
172
176BOOST_AUTO_TEST_CASE( SymbolString )
177{
178 const std::string content{ "(symbol \"string\" 42 3.14 (nested 4 ()))" };
179 const auto sexp = Parse( content );
180
181 BOOST_REQUIRE_NE( sexp.get(), nullptr );
182 BOOST_REQUIRE_PREDICATE( KI_TEST::SexprIsListOfLength, ( *sexp )( 5 ) );
183
184 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsSymbolWithValue, ( *sexp->GetChild( 0 ) )( "symbol" ) );
185 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsStringWithValue, ( *sexp->GetChild( 1 ) )( "string" ) );
186 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsIntegerWithValue, ( *sexp->GetChild( 2 ) )( 42 ) );
187 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsDoubleWithValue, ( *sexp->GetChild( 3 ) )( 3.14 ) );
188
189 // and child list
190 const SEXPR::SEXPR& sublist = *sexp->GetChild( 4 );
191 BOOST_REQUIRE_PREDICATE( KI_TEST::SexprIsListOfLength, ( sublist )( 3 ) );
192 BOOST_CHECK_PREDICATE(
193 KI_TEST::SexprIsSymbolWithValue, ( *sublist.GetChild( 0 ) )( "nested" ) );
194 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsIntegerWithValue, ( *sublist.GetChild( 1 ) )( 4 ) );
195 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsListOfLength, ( *sublist.GetChild( 2 ) )( 0 ) );
196}
197
198
205{
206 std::string m_case_name;
207 std::string m_input;
208};
209
210BOOST_AUTO_TEST_CASE( StringRoundtrip )
211{
212 const std::vector<TEST_SEXPR_ROUNDTRIPPING> cases = {
213 {
214 "empty list",
215 "()",
216 },
217 {
218 "simple list",
219 "(42 3.14 \"string\")",
220 },
221 {
222 "nested list", // REVIEW space after 42?
223 "(42 \n (1 2))",
224 },
225 };
226
227 for( const auto& c : cases )
228 {
229 BOOST_TEST_CONTEXT( c.m_case_name )
230 {
231 const auto sexp = Parse( c.m_input );
232
233 const std::string as_str = sexp->AsString();
234
235 BOOST_CHECK_PREDICATE( KI_TEST::SexprConvertsToString, ( *sexp )( c.m_input ) );
236 }
237 }
238}
239
240BOOST_AUTO_TEST_SUITE_END()
std::unique_ptr< SEXPR > Parse(const std::string &aString)
SEXPR * GetChild(size_t aIndex) const
Definition: sexpr.cpp:48
std::unique_ptr< SEXPR::SEXPR > Parse(const std::string &aIn)
Wrap the parser function with a unique_ptr.
bool SexprIsSymbolWithValue(const SEXPR::SEXPR &aSexpr, const std::string &aVal)
Test predicate: is the s-expression a symbol with the given value?
bool SexprIsDoubleWithValue(const SEXPR::SEXPR &aSexpr, double aVal)
Test predicate: is the s-expression a double with the given value?
bool SexprIsListOfLength(const SEXPR::SEXPR &aSexpr, size_t aExpectedLength)
Test predicate: is the s-expression a list with the given length?
bool SexprIsIntegerWithValue(const SEXPR::SEXPR &aSexpr, std::int64_t aVal)
Test predicate: is the s-expression an integer with the given value?
bool SexprIsStringWithValue(const SEXPR::SEXPR &aSexpr, const std::string &aVal)
Test predicate: is the s-expression a string with the given value?
bool SexprConvertsToString(const SEXPR::SEXPR &aSexpr, const std::string &aExpStr)
Predicate to check an SEXPR object converts to the expected string.
PARSE_RESULT Parse(const wxString &aString, NOTATION aNotation=NOTATION::SI, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT)
Definition: sim_value.cpp:189
Collection of test cases for use when multiple cases can be handled in the same test case.
std::string m_sexpr_data
std::string m_case_name
Test for roundtripping (valid) s-expression back to strings.
BOOST_AUTO_TEST_CASE(Empty)
Declare the test suite.
#define BOOST_TEST_CONTEXT(A)