KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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, see <https://www.gnu.org/licenses/>.
18 */
19
24
26
27// Code under test
28#include <sexpr/sexpr_parser.h>
29
30#include "sexpr_test_utils.h"
31
33{
34public:
38 std::unique_ptr<SEXPR::SEXPR> Parse( const std::string& aIn )
39 {
40 return std::unique_ptr<SEXPR::SEXPR>( m_parser.Parse( aIn ) );
41 }
42
44};
45
46
52{
53 std::string m_case_name;
54 std::string m_sexpr_data;
55};
56
57
61BOOST_FIXTURE_TEST_SUITE( SexprParser, TEST_SEXPR_PARSER_FIXTURE )
62
63
67{
68 const std::vector<TEST_SEXPR_CASE> cases = {
69 {
70 "Empty string",
71 "",
72 },
73 {
74 "whitespace",
75 " ",
76 },
77 };
78
79 for( const auto& c : cases )
80 {
81 BOOST_TEST_CONTEXT( c.m_case_name )
82 {
83 const auto data = Parse( c.m_sexpr_data );
84 BOOST_CHECK_EQUAL( data.get(), nullptr );
85 }
86 }
87}
88
93{
94 const std::string content{ "this is just writing" };
95 const auto sexp = Parse( content );
96
97 BOOST_REQUIRE_NE( sexp.get(), nullptr );
99}
100
104BOOST_AUTO_TEST_CASE( ParseExceptions )
105{
106 const std::vector<TEST_SEXPR_CASE> cases = {
107 {
108 "Unclosed (symbol",
109 "(symbol",
110 },
111 {
112 "Comma",
113 ",",
114 },
115 {
116 "Int only",
117 "1",
118 },
119 {
120 "Double only",
121 "3.14",
122 },
123 {
124 "Symbol only",
125 "symbol",
126 },
127 // { // this is OK for some reason
128 // "String only",
129 // "\"string\"",
130 // },
131 };
132
133 for( const auto& c : cases )
134 {
135 BOOST_TEST_CONTEXT( c.m_case_name )
136 {
137 BOOST_CHECK_THROW( Parse( c.m_sexpr_data ), SEXPR::PARSE_EXCEPTION );
138 }
139 }
140}
141
146{
147 const std::string content{ "()" };
148 const auto sexp = Parse( content );
149
150 BOOST_REQUIRE_NE( sexp.get(), nullptr );
152}
153
157BOOST_AUTO_TEST_CASE( SimpleSymbol )
158{
159 const std::string content{ "(symbol)" };
160 const auto sexp = Parse( content );
161
162 BOOST_REQUIRE_NE( sexp.get(), nullptr );
163 BOOST_REQUIRE_PREDICATE( KI_TEST::SexprIsListOfLength, ( *sexp )( 1 ) );
164
165 const SEXPR::SEXPR& child = *sexp->GetChild( 0 );
167}
168
172BOOST_AUTO_TEST_CASE( SymbolString )
173{
174 const std::string content{ "(symbol \"string\" 42 3.14 (nested 4 ()))" };
175 const auto sexp = Parse( content );
176
177 BOOST_REQUIRE_NE( sexp.get(), nullptr );
178 BOOST_REQUIRE_PREDICATE( KI_TEST::SexprIsListOfLength, ( *sexp )( 5 ) );
179
180 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsSymbolWithValue, ( *sexp->GetChild( 0 ) )( "symbol" ) );
181 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsStringWithValue, ( *sexp->GetChild( 1 ) )( "string" ) );
182 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsIntegerWithValue, ( *sexp->GetChild( 2 ) )( 42 ) );
183 BOOST_CHECK_PREDICATE( KI_TEST::SexprIsDoubleWithValue, ( *sexp->GetChild( 3 ) )( 3.14 ) );
184
185 // and child list
186 const SEXPR::SEXPR& sublist = *sexp->GetChild( 4 );
187 BOOST_REQUIRE_PREDICATE( KI_TEST::SexprIsListOfLength, ( sublist )( 3 ) );
189 KI_TEST::SexprIsSymbolWithValue, ( *sublist.GetChild( 0 ) )( "nested" ) );
192}
193
194
201{
202 std::string m_case_name;
203 std::string m_input;
204};
205
206BOOST_AUTO_TEST_CASE( StringRoundtrip )
207{
208 const std::vector<TEST_SEXPR_ROUNDTRIPPING> cases = {
209 {
210 "empty list",
211 "()",
212 },
213 {
214 "simple list",
215 "(42 3.14 \"string\")",
216 },
217 {
218 "nested list", // REVIEW space after 42?
219 "(42 \n (1 2))",
220 },
221 };
222
223 for( const auto& c : cases )
224 {
225 BOOST_TEST_CONTEXT( c.m_case_name )
226 {
227 const auto sexp = Parse( c.m_input );
228
229 const std::string as_str = sexp->AsString();
230
231 BOOST_CHECK_PREDICATE( KI_TEST::SexprConvertsToString, ( *sexp )( c.m_input ) );
232 }
233 }
234}
235
SEXPR * GetChild(size_t aIndex) const
Definition sexpr.cpp:50
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.
Collection of test cases for use when multiple cases can be handled in the same test case.
Test for roundtripping (valid) s-expression back to strings.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(Empty)
Declare the test suite.
BOOST_CHECK_PREDICATE(ArePolylineEndPointsNearCircle,(chain)(c.m_geom.m_center_point)(radius)(accuracy+epsilon))
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_CHECK_EQUAL(result, "25.4")