1 // SExp - A S-Expression Parser for C++
2 // Copyright (C) 2015 Ingo Ruhnke <grumbel@gmail.com>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 #include <gtest/gtest.h>
18 
19 #include <sstream>
20 #include <stdint.h>
21 
22 #include "sexp/value.hpp"
23 #include "sexp/parser.hpp"
24 #include "sexp/io.hpp"
25 
TEST(ValueTest,construct_boolean)26 TEST(ValueTest, construct_boolean)
27 {
28   auto sx_bool = sexp::Value::boolean(true);
29   ASSERT_EQ(true, sx_bool.as_bool());
30 }
31 
TEST(ValueTest,construct_integer)32 TEST(ValueTest, construct_integer)
33 {
34   auto sx = sexp::Value::integer(12345789);
35   ASSERT_EQ(12345789, sx.as_int());
36 }
37 
TEST(ValueTest,construct_real)38 TEST(ValueTest, construct_real)
39 {
40   auto sx = sexp::Value::real(12345.0f);
41   ASSERT_EQ(12345.0f, sx.as_float());
42 }
43 
TEST(ValueTest,construct_symbol)44 TEST(ValueTest, construct_symbol)
45 {
46   auto sx = sexp::Value::symbol("Symbol");
47   ASSERT_EQ("Symbol", sx.as_string());
48 }
49 
TEST(ValueTest,construct_string)50 TEST(ValueTest, construct_string)
51 {
52   auto sx = sexp::Value::string("HelloWorld");
53   ASSERT_EQ("HelloWorld", sx.as_string());
54 }
55 
TEST(ValueTest,construct_array)56 TEST(ValueTest, construct_array)
57 {
58   auto sx = sexp::Value::array(sexp::Value::integer(1),
59                                sexp::Value::integer(2),
60                                sexp::Value::integer(3),
61                                sexp::Value::integer(4));
62   ASSERT_EQ("#(1 2 3 4)", sx.str());
63   sx.append(sexp::Value::integer(5));
64   ASSERT_EQ("#(1 2 3 4 5)", sx.str());
65 }
66 
TEST(ValueTest,construct_cons)67 TEST(ValueTest, construct_cons)
68 {
69   auto sx_integer = sexp::Value::integer(12345789);
70   auto sx_cons = sexp::Value::cons(sexp::Value::integer(5), sexp::Value::nil());
71   auto sx_cons2 = sexp::Value::cons(std::move(sx_integer), sexp::Value::nil());
72 
73   ASSERT_EQ(12345789, sx_cons2.get_car().as_int());
74   ASSERT_EQ(sexp::Value::nil(), sx_cons2.get_cdr());
75 }
76 
TEST(ValueTest,copy)77 TEST(ValueTest, copy)
78 {
79   sexp::Value sx = sexp::Parser::from_string("(a-symbol #f #t 1 2 3 (4 5 (6 7 8) (9 . 10) \"Hello world\"))");
80   sexp::Value sx_copy = sexp::Value(sx);
81   ASSERT_EQ(sx.str(), sx_copy.str());
82 }
83 
TEST(ValueTest,equal)84 TEST(ValueTest, equal)
85 {
86   sexp::Value lhs = sexp::Parser::from_string("(a-symbol #f #t 1 2 3 (4 5 (6 7 8) (9 . 10) \"Hello world\"))");
87   sexp::Value rhs = sexp::Parser::from_string("(a-symbol #f #t 1 2 3 (4 5 (6 7 8) (9 . 10) \"Hello world\"))");
88   ASSERT_TRUE(lhs == rhs);
89 }
90 
TEST(ValueTest,assignment)91 TEST(ValueTest, assignment)
92 {
93   sexp::Value lhs = sexp::Parser::from_string("(a-symbol #f #t 1 2 3 (4 5 (6 7 8) (9 . 10) \"Hello world\"))");
94   sexp::Value rhs = sexp::Parser::from_string("(a-symbol #f #t 1 2 3 (4 5 (6 7 8) (9 . 10) \"Hello world\"))");
95   ASSERT_EQ(lhs, rhs);
96   sexp::Value tmp = lhs;
97   lhs = rhs;
98   rhs = tmp;
99   ASSERT_EQ(lhs, rhs);
100 }
101 
TEST(ValueTest,type_errors_boolean)102 TEST(ValueTest, type_errors_boolean)
103 {
104   sexp::Value sx = sexp::Value::boolean(true);
105   ASSERT_THROW(sx.append(sexp::Value::nil()), sexp::TypeError);
106   ASSERT_THROW(sx.set_car(sexp::Value::nil()), sexp::TypeError);
107   ASSERT_THROW(sx.set_cdr(sexp::Value::nil()), sexp::TypeError);
108   ASSERT_THROW(sx.get_car(), sexp::TypeError);
109   ASSERT_THROW(sx.get_cdr(), sexp::TypeError);
110 
111   ASSERT_THROW(sx.as_int(), sexp::TypeError);
112   ASSERT_THROW(sx.as_float(), sexp::TypeError);
113   ASSERT_THROW(sx.as_string(), sexp::TypeError);
114 }
115 
TEST(ValueTest,type_errors_integer)116 TEST(ValueTest, type_errors_integer)
117 {
118   sexp::Value sx = sexp::Value::integer(5);
119   ASSERT_THROW(sx.append(sexp::Value::nil()), sexp::TypeError);
120   ASSERT_THROW(sx.set_car(sexp::Value::nil()), sexp::TypeError);
121   ASSERT_THROW(sx.set_cdr(sexp::Value::nil()), sexp::TypeError);
122   ASSERT_THROW(sx.get_car(), sexp::TypeError);
123   ASSERT_THROW(sx.get_cdr(), sexp::TypeError);
124 
125   ASSERT_THROW(sx.as_bool(), sexp::TypeError);
126   ASSERT_THROW(sx.as_string(), sexp::TypeError);
127 }
128 
TEST(ValueTest,type_errors_real)129 TEST(ValueTest, type_errors_real)
130 {
131   sexp::Value sx = sexp::Value::real(1.125f);
132   ASSERT_THROW(sx.append(sexp::Value::nil()), sexp::TypeError);
133   ASSERT_THROW(sx.set_car(sexp::Value::nil()), sexp::TypeError);
134   ASSERT_THROW(sx.set_cdr(sexp::Value::nil()), sexp::TypeError);
135   ASSERT_THROW(sx.get_car(), sexp::TypeError);
136   ASSERT_THROW(sx.get_cdr(), sexp::TypeError);
137 
138   ASSERT_THROW(sx.as_bool(), sexp::TypeError);
139   ASSERT_THROW(sx.as_string(), sexp::TypeError);
140 }
141 
TEST(ValueTest,type_errors_symbol)142 TEST(ValueTest, type_errors_symbol)
143 {
144   sexp::Value sx = sexp::Value::symbol("HelloWorld");
145   ASSERT_THROW(sx.append(sexp::Value::nil()), sexp::TypeError);
146   ASSERT_THROW(sx.set_car(sexp::Value::nil()), sexp::TypeError);
147   ASSERT_THROW(sx.set_cdr(sexp::Value::nil()), sexp::TypeError);
148   ASSERT_THROW(sx.get_car(), sexp::TypeError);
149   ASSERT_THROW(sx.get_cdr(), sexp::TypeError);
150 
151   ASSERT_THROW(sx.as_bool(), sexp::TypeError);
152   ASSERT_THROW(sx.as_int(), sexp::TypeError);
153   ASSERT_THROW(sx.as_float(), sexp::TypeError);
154 }
155 
TEST(ValueTest,type_errors_string)156 TEST(ValueTest, type_errors_string)
157 {
158   sexp::Value sx = sexp::Value::string("HelloWorld");
159   ASSERT_THROW(sx.append(sexp::Value::nil()), sexp::TypeError);
160   ASSERT_THROW(sx.set_car(sexp::Value::nil()), sexp::TypeError);
161   ASSERT_THROW(sx.set_cdr(sexp::Value::nil()), sexp::TypeError);
162   ASSERT_THROW(sx.get_car(), sexp::TypeError);
163   ASSERT_THROW(sx.get_cdr(), sexp::TypeError);
164 
165   ASSERT_THROW(sx.as_bool(), sexp::TypeError);
166   ASSERT_THROW(sx.as_int(), sexp::TypeError);
167   ASSERT_THROW(sx.as_float(), sexp::TypeError);
168 }
169 
TEST(ValueTest,type_errors_cons)170 TEST(ValueTest, type_errors_cons)
171 {
172   sexp::Value sx = sexp::Value::cons(sexp::Value::integer(5), sexp::Value::integer(5));
173   ASSERT_THROW(sx.as_bool(), sexp::TypeError);
174   ASSERT_THROW(sx.as_int(), sexp::TypeError);
175   ASSERT_THROW(sx.as_float(), sexp::TypeError);
176   ASSERT_THROW(sx.as_string(), sexp::TypeError);
177 }
178 
TEST(ValueTest,object_size)179 TEST(ValueTest, object_size)
180 {
181 #if INTPTR_MAX == INT32_MAX
182   // on 32bit systems
183 #  ifdef _MSC_VER
184   ASSERT_EQ(12, sizeof(sexp::Value));
185 #  else
186   ASSERT_EQ(8, sizeof(sexp::Value));
187 #  endif
188 #elif INTPTR_MAX == INT64_MAX
189   // on 64bit systems
190   ASSERT_EQ(16, sizeof(sexp::Value));
191 #else
192 #  error "environment is neither 32 nor 64-bit"
193 #endif
194 }
195 
196 /* EOF */
197