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