NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
system_test.cpp
Go to the documentation of this file.
1#ifdef BUILD_UNITTEST
2
3#include "warning_push.h"
4#include <gtest/gtest.h>
5#include "warning_pop.h"
6
7#include "jit.h"
8#include "system.h"
9#include "analysis.h"
10
11using namespace newlang;
12using namespace newlang::runtime;
13
14class SystemTest : public ::testing::Test {
15protected:
16
17
18
19 std::vector<std::string> m_postlex;
20
21 Logger::FuncCallback *m_log_callback_save;
22 void *m_log_callback_arg_save;
23 std::string m_output;
24
25 static void LoggerCallback(void *param, Logger::LogLevelType level, const char * str, bool flush) {
26 SystemTest *p = static_cast<SystemTest *> (param);
27 fprintf(stdout, "%s", str);
28 if (flush) {
29 fflush(stdout);
30 }
31 if (p) {
32 p->m_output += str;
33 }
34 }
35
36 void SetUp() {
37 Logger::Instance()->SaveCallback(m_log_callback_save, m_log_callback_arg_save);
38 Logger::Instance()->SetCallback(&LoggerCallback, this);
39 }
40
41 void TearDown() {
42 Logger::Instance()->SetCallback(m_log_callback_save, m_log_callback_arg_save);
43 }
44
45 TermPtr Parse(std::string str, MacroPtr buffer = nullptr, DiagPtr diag = nullptr) {
46 m_postlex.clear();
47 Parser p(buffer, &m_postlex, diag);
48 ast = p.Parse(str);
49 return ast;
50 }
51
52 int Count(TermID token_id) {
53 int result = 0;
54 for (int c = 0; c < ast->size(); c++) {
55 if ((*ast)[c].second->m_id == token_id) {
56 result++;
57 }
58 }
59 return result;
60 }
61
62 std::string LexOut() {
63 std::string result;
64 for (int i = 0; i < m_postlex.size(); i++) {
65 if (!result.empty()) {
66 result += " ";
67 }
68 result += m_postlex[i];
69 }
70 trim(result);
71 return result;
72 }
73
74 TermPtr ast;
75};
76
77
78/*
79
80 :System().run("echo", "Hello from the other side!");
81
82 os := :System();
83
84 home_dir := os.run("cd", "~");
85 printf("`cd ~` ran with exit code %d", os.exitcode());
86
87 unknown_dir := os.run("cd", "doesnotexist");
88 printf("`cd doesnotexis` ran with exit code %d", os.exitcode());
89
90 *
91 `echo Hello from the other side!`;
92
93 *
94 `echo Hello from the other side!`;
95 res := $^;
96 printf("`cd doesnotexis` ran with exit code %d", res.exitcode());
97
98 *
99 */
100
101
102//#include <cstdio>
103//#include <iostream>
104//#include <memory>
105//#include <stdexcept>
106//#include <string>
107//#include <array>
108
109//std::string exec(const char* cmd) {
110// std::array<char, 128> buffer;
111// std::string result;
112// std::unique_ptr<FILE, decltype(&pclose) > pipe(popen(cmd, "r"), pclose);
113// if (!pipe) {
114// throw std::runtime_error("popen() failed!");
115// }
116// while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
117// result += buffer.data();
118// }
119// return result;
120//}
121
122
123// os.system(command) - исполняет системную команду, возвращает код её завершения (в случае успеха 0).
124//
125//
126// os.chdir(path) - смена текущей директории.
127// os.chmod(path, mode, *, dir_fd=None, follow_symlinks=True) - смена прав доступа к объекту (mode - восьмеричное число).
128// os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True) - меняет id владельца и группы (Unix).
129// os.getcwd() - текущая рабочая директория.
130// os.link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True) - создаёт жёсткую ссылку.
131// os.listdir(path=".") - список файлов и директорий в папке.
132// os.mkdir(path, mode=0o777, *, dir_fd=None) - создаёт директорию. OSError, если директория существует.
133// os.makedirs(path, mode=0o777, exist_ok=False) - создаёт директорию, создавая при этом промежуточные директории.
134// os.remove(path, *, dir_fd=None) - удаляет путь к файлу.
135// os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает файл или директорию из src в dst.
136// os.renames(old, new) - переименовывает old в new, создавая промежуточные директории.
137// os.replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает из src в dst с принудительной заменой.
138// os.rmdir(path, *, dir_fd=None) - удаляет пустую директорию.
139// os.removedirs(path) - удаляет директорию, затем пытается удалить родительские директории, и удаляет их рекурсивно, пока они пусты.
140// os.symlink(source, link_name, target_is_directory=False, *, dir_fd=None) - создаёт символическую ссылку на объект.
141// os.sync() - записывает все данные на диск (Unix).
142// os.truncate(path, length) - обрезает файл до длины length.
143// os.utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True) - модификация времени последнего доступа и изменения файла. Либо times - кортеж (время доступа в секундах, время изменения в секундах), либо ns - кортеж (время доступа в наносекундах, время изменения в наносекундах).
144// os.walk(top, topdown=True, onerror=None, followlinks=False) - генерация имён файлов в дереве каталогов, сверху вниз (если topdown равен True), либо снизу вверх (если False). Для каждого каталога функция walk возвращает кортеж (путь к каталогу, список каталогов, список файлов).
145
146TEST_F(SystemTest, MethodExist) {
147
148 struct Method {
149 std::string name;
150 ObjPtr res;
151 };
152
153 std::vector<Method> list;
154
155 list.push_back({"getname", nullptr});
156 // list.push_back("getlogin");
157 // list.push_back("getenv");
158 // list.push_back("getpid");
159 // list.push_back("getuname");
160 std::string callname;
161 for (auto &elem : list) {
162 callname = "System::";
163 callname += elem.name;
164 callname += "()";
165 }
166
167 // CALSS_METHOD(System, getname);
168
169 ObjPtr arg = Obj::CreateDict();
170 arg->push_back(Obj::Arg());
171 arg->push_back(Obj::Arg("ls -l"));
172
173 ObjPtr ret = System::system(nullptr, *arg);
174
175 std::cout << ret->toString().c_str();
176
177}
178
179TEST_F(SystemTest, StaticAssert) {
180
181 JIT * jit = JIT::ReCreate();
182 ASSERT_TRUE(jit);
183
184 ASSERT_TRUE(jit->m_macro);
185 ASSERT_FALSE(jit->m_macro->empty());
186 ASSERT_FALSE(jit->m_macro->find("static_assert") == jit->m_macro->end()) << jit->m_macro->Dump();
187
188
189
190 TermPtr term = jit->GetParser()->Parse("@static_assert(1)");
191 ASSERT_TRUE(term);
192 ASSERT_TRUE(term->getTermID() == TermID::END);
193
194 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(0)"));
195 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(0.0)"));
196 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(0\\1)"));
197 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert('')"));
198 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(\"\")"));
199 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert($local)"));
200 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(::global)"));
201 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(@macro)"));
202
203 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(1)"));
204 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(1.0)"));
205 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(1\\1)"));
206 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(' ')"));
207 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(\" \")"));
208
209 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(%printf)"));
210
211 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(%FAIL_NATIVE_NAME)"));
212 int FAIL_NATIVE_NAME;
213 LLVMAddSymbol("FAIL_NATIVE_NAME", (void *) &FAIL_NATIVE_NAME);
214 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(%FAIL_NATIVE_NAME)"));
215
216 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(1==1)"));
217 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(1.0===1.0)"));
218 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(1\\1 <= 10)"));
219 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(''=='')"));
220 ASSERT_NO_THROW(jit->GetParser()->Parse("@static_assert(\"str\"=='str')"));
221
222 ASSERT_ANY_THROW(jit->GetParser()->Parse("@static_assert(\"str2222\"=='str')"));
223
224}
225
226TEST_F(SystemTest, Assert) {
227
228 JIT * jit = JIT::ReCreate();
229
231 NameLookupStack stack(*jit, external);
232
233
234 ASSERT_TRUE(jit);
235 ASSERT_TRUE(jit->m_assert_enable);
236
237 ASSERT_TRUE(jit->m_macro);
238 ASSERT_FALSE(jit->m_macro->empty());
239 ASSERT_FALSE(jit->m_macro->find("assert") == jit->m_macro->end()) << jit->m_macro->Dump();
240 ASSERT_FALSE(jit->m_macro->find("verify") == jit->m_macro->end()) << jit->m_macro->Dump();
241
243
244 ASSERT_NO_THROW(result = jit->Run("1"));
245 ASSERT_TRUE(result);
246 ASSERT_STREQ("1", result->toString().c_str());
247
248 ASSERT_NO_THROW(result = jit->Run(":Bool(1)"));
249 ASSERT_TRUE(result);
250 ASSERT_STREQ("1", result->toString().c_str());
251
252 ASSERT_NO_THROW(result = jit->Run("1+1"));
253 ASSERT_TRUE(result);
254 ASSERT_STREQ("2", result->toString().c_str());
255
256 ASSERT_NO_THROW(result = jit->Run(":Bool(1+1)"));
257 ASSERT_TRUE(result);
258 ASSERT_STREQ("1", result->toString().c_str());
259
260 TermPtr term;
261 ASSERT_NO_THROW(term = jit->GetParser()->Parse(" :Bool(1)")) << jit->Dump();
262 ASSERT_TRUE(term);
263 ASSERT_STREQ(":Bool(1)", term->toString().c_str());
264
265 ASSERT_NO_THROW(term = jit->GetParser()->Parse(":Bool(1+1)")) << jit->Dump();
266 ASSERT_TRUE(term);
267
268
269 const char * assert1 = "@assert(1+1, 2, 'str')";
270 ASSERT_NO_THROW(
271 term = jit->GetParser()->Parse(assert1);
272 ) << jit->Dump();
273 ASSERT_TRUE(term);
274 ASSERT_TRUE(term->getTermID() == TermID::FOLLOW) << term->toString();
275 ASSERT_STREQ("[:Bool(1 + 1) == 0]-->{::Base::__assert_abort__(\"1+1\", 1 + 1, 2, 'str');};", term->toString().c_str());
276 //[:Bool(@$value)==0]-->{ ::Base::__assert_abort__(@# @$value, @$... ) }
277 AstAnalysis analisys(*jit, jit->m_diag.get());
278 ASSERT_TRUE(analisys.Analyze(term, &stack)) << jit->Dump();
279
280 Obj args;
281 ASSERT_NO_THROW(result = jit->Run(assert1)) << jit->Dump();
282
283 ASSERT_NO_THROW(
284 term = jit->GetParser()->Parse("@verify(1)");
285 ) << jit->Dump();
286 ASSERT_TRUE(term);
287 ASSERT_TRUE(term->getTermID() == TermID::FOLLOW) << term->toString();
288 ASSERT_STREQ("[:Bool(1) == 0]-->{::Base::__assert_abort__(\"1\", 1);};", term->toString().c_str());
289
290 ASSERT_NO_THROW(result = jit->Run(term->toString())) << jit->Dump();
291
292 const char * assert2 = "@verify(0, 3+4, '555')";
293 term = jit->GetParser()->Parse(assert2);
294 ASSERT_TRUE(term);
295 ASSERT_TRUE(term->getTermID() == TermID::FOLLOW) << term->toString();
296 ASSERT_STREQ("[:Bool(0) == 0]-->{::Base::__assert_abort__(\"0\", 0, 3 + 4, '555');};", term->toString().c_str());
297
298 ASSERT_ANY_THROW(result = jit->Run(assert2)) << jit->Dump();
299
300
301 jit = JIT::ReCreate({"--nlc-no-assert"});
302 ASSERT_FALSE(jit->m_assert_enable);
303
304 ASSERT_TRUE(jit->m_macro);
305 ASSERT_FALSE(jit->m_macro->empty());
306 ASSERT_FALSE(jit->m_macro->find("assert") == jit->m_macro->end()) << jit->m_macro->Dump();
307 ASSERT_FALSE(jit->m_macro->find("verify") == jit->m_macro->end()) << jit->m_macro->Dump();
308
309
310
311 const char * assert3 = "@assert(1+1, 2, 'str'); 33+44; 55";
312 ASSERT_NO_THROW(
313 term = jit->GetParser()->Parse(assert3);
314 ) << jit->Dump();
315 ASSERT_TRUE(term);
316 ASSERT_TRUE(term->getTermID() == TermID::SEQUENCE) << toString(term->getTermID()) << " " << term->toString();
317 ASSERT_STREQ("_; 33 + 44; 55;", term->toString().c_str());
318
319 ASSERT_NO_THROW(result = jit->Run(assert3)) << jit->Dump();
320
321 ASSERT_NO_THROW(
322 term = jit->GetParser()->Parse("@verify(1+1, 'message'); 33+44");
323 );
324 ASSERT_TRUE(term);
325 ASSERT_TRUE(term->getTermID() == TermID::SEQUENCE) << term->toString();
326 ASSERT_STREQ("1 + 1; 33 + 44;", term->toString().c_str());
327
328 ASSERT_NO_THROW(result = jit->Run(term->toString()));
329 ASSERT_NO_THROW(
330 term = jit->GetParser()->Parse("@verify(0+0)");
331 );
332 ASSERT_TRUE(term);
333 ASSERT_TRUE(term->getTermID() == TermID::OP_MATH) << term->toString();
334 ASSERT_STREQ("0 + 0", term->toString().c_str());
335
336 ASSERT_NO_THROW(result = jit->Run(term->toString()));
337}
338
339//TEST_F(SystemTest, Base) {
340//
341// // struct Method {
342// // std::string name;
343// // ObjPtr res;
344// // };
345// //
346// // std::vector<Method> list;
347// //
348// // list.push_back({"getname", nullptr});
349// // // list.push_back("getlogin");
350// // // list.push_back("getenv");
351// // // list.push_back("getpid");
352// // // list.push_back("getuname");
353// // std::string callname;
354// // for (auto &elem : list) {
355// // callname = "System::";
356// // callname += elem.name;
357// // callname += "()";
358// // }
359//
360// // CALSS_METHOD(System, getname);
361//
362// ObjPtr arg = Obj::CreateDict();
363// arg->push_back(Obj::Arg());
364// arg->push_back(Obj::Arg("ls -l"));
365//
366// ObjPtr ret = Base::__pragma_assert__(nullptr, *arg);
367//
368// std::cout << ret->toString().c_str();
369//
370// RuntimePtr rt = RunTime::Init();
371//
373//
374//
375//
376//
377//}
378//
379//TEST_F(SystemTest, MethodRun) {
380//
381// ObjPtr sys = std::make_shared<System>();
382//
383//}
384//
385//TEST_F(SystemTest, Runtime) {
386//
387// RuntimePtr rt = RunTime::Init();
388// for (auto &elem : *rt) {
389// ASSERT_TRUE(elem.second) << elem.first;
390// ASSERT_TRUE(elem.second->proto) << elem.first;
391// std::cout << elem.first << " -> " << elem.second->proto->toString() << "\n";
392// }
393//
394// Context ctx(rt);
395//
396// TermPtr term = Parser::ParseString(":System::getlogin()", nullptr);
397// ASSERT_TRUE(term);
398// std::cout << "\nTerm: " << term->toString() << "!!!!!!!!!!!!!!!!!!!!!!!!!!11\n";
399//
400// ObjPtr result = ctx.Run(term, nullptr);
401// ASSERT_TRUE(result);
402//
403// std::cout << result->toString() << "!!!!!!!!!!!!!!!!!!!!!!!!!!11";
404//
405//}
406//
407//TEST_F(SystemTest, Native) {
408//
409// RuntimePtr rt = RunTime::Init();
410// Context ctx(rt);
411//
412// ASSERT_ANY_THROW(ctx.ExecStr("time(:Pointer):Int32 := %time"));
413// ASSERT_ANY_THROW(ctx.ExecStr("time(arg):Int32 := %time"));
414// ASSERT_ANY_THROW(ctx.ExecStr("time(arg:Rational):Int32 := %time"));
415//
416// ObjPtr usleep = ctx.ExecStr("usleep(usec:DWord64):Int32 := %usleep");
417// ASSERT_TRUE(usleep);
418//
419// ObjPtr time = ctx.ExecStr("time(ptr:Pointer):Int32 := %time");
420// ASSERT_TRUE(time);
421//
422// ASSERT_TRUE(time->m_prototype);
423// ASSERT_EQ(1, time->m_prototype->size());
424// ASSERT_STREQ("ptr", (*time->m_prototype)[0].second->m_text.c_str());
425//
426// ASSERT_TRUE((*time->m_prototype)[0].second->m_type);
427// ASSERT_STREQ(":Pointer", (*time->m_prototype)[0].second->m_type->m_text.c_str());
428//
429// ASSERT_TRUE(time->m_prototype->m_type);
430// ASSERT_STREQ(":Int32", time->m_prototype->m_type->m_text.c_str());
431//
433//
434// ObjPtr res;
435//
436// ASSERT_NO_THROW(
437// res = time->Call(&ctx, Obj::ArgNull());
438// ) << time->m_prototype->toString();
439//
440// std::cout << time->toString();
441//
442// usleep->Call(&ctx, Obj::Arg(1000000));
443//
444// ObjPtr res2 = time->Call(&ctx, Obj::ArgNull());
445//
446// std::cout << "\nres1: " << res->toString() << "\n";
447// std::cout << "res2: " << res2->toString() << "\n";
448// (*res2) -= res;
449// std::cout << "res2: " << res2->toString() << "\n";
450//
451// std::cout << "\nusleep: " << res2->toString() << "\n";
452//
453// ObjPtr srand = ctx.ExecStr("srand(val:Int32):None := %srand");
454// ASSERT_TRUE(srand);
455//
456// srand->Call(&ctx, Obj::Arg(time->Call(&ctx, Obj::ArgNull())));
457//
458// ObjPtr rand = ctx.ExecStr("rand():Int32 := %rand");
459// ASSERT_TRUE(rand);
460//
461// std::cout << rand->toString() << " -> " << rand->Call(&ctx) << ", " << rand->Call(&ctx) << "\n";
462//
463//}
464//
466// rand():Int32 := %rand;
467// usleep(usec:DWord64):None := %usleep;
468// printf(format:FmtChar, ...):Int32 := %printf;
469//
470// */
471//
472//TEST_F(SystemTest, Logger) {
473// // std::cout << exec("ls -l");
474// // std::system("ls -l > temp/test.txt"); // executes the UNIX command "ls -l >test.txt"
475// // std::cout << std::ifstream("temp/test.txt").rdbuf();
476//}
477
478
479#endif // UNITTEST
std::string Dump(const std::string_view filter="", const char delim=';')
Definition types.cpp:314
ObjPtr Run(const std::string_view str, Obj *args=nullptr)
Definition jit.cpp:2558
MacroPtr m_macro
Definition jit.h:93
ParserPtr GetParser()
Definition jit.cpp:2535
uint8_t LogLevelType
Definition logger.h:319
DiagPtr m_diag
Definition runtime.h:402
bool m_assert_enable
Definition runtime.h:388
std::map< std::string, StorageTerm > ModuleMapType
Definition term.h:172
int result
Definition lexer.l:367
Definition nlc.h:59
TermID
Definition term.h:119
std::shared_ptr< Term > TermPtr
Definition variable.h:33
std::shared_ptr< Obj > ObjPtr
Definition variable.h:28
std::shared_ptr< Macro > MacroPtr
Definition types.h:244
std::shared_ptr< Diag > DiagPtr
Definition types.h:243
const char * toString(TermID type)
Definition term.h:126
std::string & trim(std::string &s, const char *t=ws)
Definition types.h:111