1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
2 // Copyright (c) Lawrence Livermore National Security, LLC and other Ascent
3 // Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
4 // other details. No copyright assignment is required to contribute to Ascent.
5 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
6 
7 //-----------------------------------------------------------------------------
8 ///
9 /// file: t_flow_python_script_filter.cpp
10 ///
11 //-----------------------------------------------------------------------------
12 
13 #include "gtest/gtest.h"
14 
15 #include <flow.hpp>
16 #include <flow_python_script_filter.hpp>
17 
18 #include <iostream>
19 #include <math.h>
20 
21 #include "t_config.hpp"
22 #include "t_utils.hpp"
23 
24 
25 
26 using namespace std;
27 using namespace conduit;
28 using namespace ascent;
29 using namespace flow;
30 
31 
32 //-----------------------------------------------------------------------------
33 class SrcFilter: public Filter
34 {
35 public:
SrcFilter()36     SrcFilter()
37     : Filter()
38     {}
39 
~SrcFilter()40     virtual ~SrcFilter()
41     {}
42 
43 
declare_interface(Node & i)44     virtual void declare_interface(Node &i)
45     {
46         i["type_name"]   = "src";
47         i["output_port"] = "true";
48         i["port_names"] = DataType::empty();
49         i["default_params"]["value"].set((int)0);
50     }
51 
52 
execute()53     virtual void execute()
54     {
55         int val = params()["value"].value();
56 
57         // set output
58         Node *res = new Node();
59         res->set(val);
60         set_output<Node>(res);
61 
62         // the registry will take care of deleting the data
63         // when all consuming filters have executed.
64         ASCENT_INFO("SrcFilter::execute: " << name()
65                     << " source filter result = "
66                     << res->to_json());
67     }
68 };
69 
70 
71 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,simple_execute)72 TEST(flow_python_script_filter, simple_execute)
73 {
74     flow::filters::register_builtin();
75 
76     Workspace::register_filter_type<SrcFilter>();
77 
78     Workspace w;
79 
80     Node src_params;
81     src_params["value"] = 21;
82 
83     w.graph().add_filter("src","v",src_params);
84 
85     Node py_params;
86     py_params["source"] = "val = flow_input().value() * 2\n"
87                           "print(val)\n"
88                           "assert val == 42\n"
89                           "flow_set_output(val)\n";
90 
91     w.graph().add_filter("python_script","py", py_params);
92 
93     // // src, dest, port
94     w.graph().connect("v","py","in");
95     //
96     w.print();
97     //
98     w.execute();
99 
100     Workspace::clear_supported_filter_types();
101 }
102 
103 
104 
105 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,simple_execute_mock_file_source)106 TEST(flow_python_script_filter, simple_execute_mock_file_source)
107 {
108     flow::filters::register_builtin();
109 
110     Workspace::register_filter_type<SrcFilter>();
111 
112     Workspace w;
113 
114     Node src_params;
115     src_params["value"] = 21;
116 
117     w.graph().add_filter("src","v",src_params);
118 
119     Node py_params;
120     py_params["source"] = "val = flow_input().value() * 2\n"
121                           "print(val)\n"
122                           "assert val == 42\n"
123                           "print(__file__)\n"
124                           "assert __file__ == 'my_mock_script.py'\n"
125                           "flow_set_output(val)\n";
126 
127     py_params["source_file"] = "my_mock_script.py";
128     w.graph().add_filter("python_script","py", py_params);
129 
130     // // src, dest, port
131     w.graph().connect("v","py","in");
132     //
133     w.print();
134     //
135     w.execute();
136 
137     Workspace::clear_supported_filter_types();
138 }
139 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,simple_execute_echo)140 TEST(flow_python_script_filter, simple_execute_echo)
141 {
142     flow::filters::register_builtin();
143 
144     Workspace::register_filter_type<SrcFilter>();
145 
146     Workspace w;
147 
148     Node src_params;
149     src_params["value"] = 21;
150 
151     w.graph().add_filter("src","v",src_params);
152 
153     Node py_params;
154     py_params["source"] = "val = flow_input().value() * 2\n"
155                           "print(val)\n"
156                           "assert val == 42\n"
157                           "flow_set_output(val)\n";
158     py_params["echo"] = "true";
159 
160     w.graph().add_filter("python_script","py", py_params);
161 
162     // // src, dest, port
163     w.graph().connect("v","py","in");
164     //
165     w.print();
166     //
167     w.execute();
168 
169     Workspace::clear_supported_filter_types();
170 }
171 
172 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,simple_execute_file)173 TEST(flow_python_script_filter, simple_execute_file)
174 {
175     flow::filters::register_builtin();
176 
177     Workspace::register_filter_type<SrcFilter>();
178 
179     Workspace w;
180 
181     Node src_params;
182     src_params["value"] = 21;
183 
184     string output_path = prepare_output_dir();
185 
186     string script_fname = conduit::utils::join_file_path(output_path,
187                                                          "tout_test_flow_filter_script.py");
188 
189     ofstream ofs;
190     ofs.open(script_fname);
191     ofs << "val = flow_input().value() * 2\n"
192         << "print(val)\n"
193         << "assert val == 42\n"
194         << "print(__file__)\n"
195         << "assert __file__ == '" << script_fname << "'\n"
196         << "flow_set_output(val)\n";
197     ofs.close();
198 
199 
200     w.graph().add_filter("src","v",src_params);
201 
202     Node py_params;
203     py_params["interpreter/reset"] = "true";
204     py_params["file"] = script_fname;
205 
206     w.graph().add_filter("python_script","py", py_params);
207 
208     // // src, dest, port
209     w.graph().connect("v","py","in");
210     //
211     w.print();
212     //
213     w.execute();
214     //
215     w.print();
216     Workspace::clear_supported_filter_types();
217 }
218 
219 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,simple_execute_bad_file)220 TEST(flow_python_script_filter, simple_execute_bad_file)
221 {
222     flow::filters::register_builtin();
223 
224     Workspace::register_filter_type<SrcFilter>();
225 
226     Workspace w;
227 
228     Node src_params;
229     src_params["value"] = 21;
230 
231     string output_path = prepare_output_dir();
232 
233     string script_fname = "/blargh/path/to/bad/script.py";
234 
235     w.graph().add_filter("src","v",src_params);
236 
237     Node py_params;
238 
239     py_params["file"] = script_fname;
240 
241     w.graph().add_filter("python_script","py", py_params);
242 
243     // // src, dest, port
244     w.graph().connect("v","py","in");
245     //
246     w.print();
247 
248     EXPECT_THROW(w.execute(),
249                  conduit::Error);
250 
251     Workspace::clear_supported_filter_types();
252 }
253 
254 
255 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,exe_override_interface_func_names)256 TEST(flow_python_script_filter, exe_override_interface_func_names)
257 {
258     flow::filters::register_builtin();
259 
260     Workspace::register_filter_type<SrcFilter>();
261 
262     Workspace w;
263 
264     Node src_params;
265     src_params["value"] = 21;
266 
267     w.graph().add_filter("src","v",src_params);
268 
269     Node py_params;
270     // test customized input() and set_output() names
271     py_params["interface/input"] = "give_me_data";
272     py_params["interface/set_output"] = "here_is_some_data";
273     py_params["interpreter/reset"] = "true";
274     py_params["source"] = "val = give_me_data().value() * 2\nprint(val)\nhere_is_some_data(val)";
275 
276     py_params["source"] = "val = give_me_data().value() * 2\n"
277                           "print(val)\n"
278                           "here_is_some_data(val)";
279 
280     w.graph().add_filter("python_script","py", py_params);
281 
282     // // src, dest, port
283     w.graph().connect("v","py","in");
284 
285     w.print();
286     w.execute();
287 
288     Workspace::clear_supported_filter_types();
289 }
290 
291 
292 //-----------------------------------------------------------------------------
TEST(flow_python_script_filter,exe_override_interface_mod_and_func_names)293 TEST(flow_python_script_filter, exe_override_interface_mod_and_func_names)
294 {
295     flow::filters::register_builtin();
296 
297     Workspace::register_filter_type<SrcFilter>();
298 
299     Workspace w;
300 
301     Node src_params;
302     src_params["value"] = 42;
303 
304     w.graph().add_filter("src","v",src_params);
305 
306     // we will change the name of the binding module to be called mine
307 
308     std::ostringstream py_src_oss;
309     py_src_oss << "import mine\n"
310                << "val = mine.give_me_data().value() * 2\n"
311                << "print(val)\n"
312                << "mine.here_is_some_data(val)\n";
313 
314     Node py_params;
315     // test customized mod name, and input() and set_output() names
316     py_params["interface/module"] = "mine";
317     py_params["interface/input"] = "give_me_data";
318     py_params["interface/set_output"] = "here_is_some_data";
319     py_params["interpreter/reset"] = "true";
320     py_params["source"] = py_src_oss.str();
321 
322 
323     w.graph().add_filter("python_script","py", py_params);
324 
325     // // src, dest, port
326     w.graph().connect("v","py","in");
327 
328     w.print();
329     w.execute();
330 
331     Workspace::clear_supported_filter_types();
332 }
333 
334 
335 
336 
337 
338 
339 
340