1 /*
2 * test_engine_ngspice.c
3 *
4 *
5 * Authors:
6 * Michi <st101564@stud.uni-stuttgart.de>
7 *
8 * Web page: https://ahoi.io/project/oregano
9 *
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this program; if not, write to the
23 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
25 */
26
27 #include "../src/engines/ngspice-watcher.h"
28 #include <glib.h>
29 #include <glib/gstdio.h>
30 #include <glib/gprintf.h>
31
32 static void test_engine_ngspice_basic();
33 static void test_engine_ngspice_error_no_such_file_or_directory();
34 static void test_engine_ngspice_error_step_zero();
35
36 void
add_funcs_test_engine_ngspice()37 add_funcs_test_engine_ngspice() {
38 g_test_add_func ("/core/engine/ngspice/watcher/basic", test_engine_ngspice_basic);
39 g_test_add_func ("/core/engine/ngspice/watcher/error/no_such_file_or_directory", test_engine_ngspice_error_no_such_file_or_directory);
40 g_test_add_func ("/core/engine/ngspice/watcher/error/step_zero", test_engine_ngspice_error_step_zero);
41 }
42
test_engine_ngspice_log_append_error(GList ** list,const gchar * string)43 static void test_engine_ngspice_log_append_error(GList **list, const gchar *string) {
44 *list = g_list_append(*list, g_strdup(string));
45 }
46
print_log(const GList * list)47 static void print_log(const GList *list) {
48 for (const GList *walker = list; walker; walker = walker->next)
49 g_printf("%s", (char *)walker->data);
50 }
51
52 typedef struct {
53 NgspiceWatcherBuildAndLaunchResources *resources;
54 OreganoNgSpice *ngspice;
55 GMainLoop *loop;
56 GList *log_list;
57 SimSettings *sim_settings;
58 } TestEngineNgspiceResources;
59
test_engine_ngspice_resources_new()60 static TestEngineNgspiceResources *test_engine_ngspice_resources_new() {
61 TestEngineNgspiceResources *test_resources = g_new0(TestEngineNgspiceResources, 1);
62
63
64 test_resources->resources = g_new0(NgspiceWatcherBuildAndLaunchResources, 1);
65 NgspiceWatcherBuildAndLaunchResources *resources = test_resources->resources;
66 test_resources->ngspice = OREGANO_NGSPICE(oregano_spice_new(NULL, FALSE));
67 OreganoNgSpice *ngspice = test_resources->ngspice;
68 GMainLoop *loop = g_main_loop_new(NULL, FALSE);
69 test_resources->loop = loop;
70 g_signal_connect_swapped(G_OBJECT(ngspice), "done", G_CALLBACK(g_main_loop_quit), loop);
71 g_signal_connect_swapped(G_OBJECT(ngspice), "aborted", G_CALLBACK(g_main_loop_quit), loop);
72
73 resources->aborted = &ngspice->priv->aborted;
74 resources->analysis = &ngspice->priv->analysis;
75 resources->child_pid = &ngspice->priv->child_pid;
76 resources->current = &ngspice->priv->current;
77 resources->emit_instance = ngspice;
78
79 resources->log.log = (gpointer)&test_resources->log_list;
80 resources->log.log_append = NULL;
81 resources->log.log_append_error = (LogFunction)test_engine_ngspice_log_append_error;
82
83 resources->num_analysis = &ngspice->priv->num_analysis;
84 resources->progress_ngspice = &ngspice->priv->progress_ngspice;
85 resources->progress_reader = &ngspice->priv->progress_reader;
86 test_resources->sim_settings = sim_settings_new(NULL);
87 resources->sim_settings = test_resources->sim_settings;
88 resources->netlist_file = g_strdup("/tmp/netlist.tmp");
89 resources->ngspice_result_file = g_strdup("/tmp/netlist.lst");
90
91 resources->cancel_info = ngspice->priv->cancel_info;
92 cancel_info_subscribe(resources->cancel_info);
93
94 return test_resources;
95 }
96
test_engine_ngspice_resources_finalize(TestEngineNgspiceResources * test_resources)97 static void test_engine_ngspice_resources_finalize(TestEngineNgspiceResources *test_resources) {
98 NgspiceWatcherBuildAndLaunchResources *resources = test_resources->resources;
99
100 g_main_loop_unref(test_resources->loop);
101
102 sim_settings_finalize(test_resources->sim_settings);
103 g_object_unref(test_resources->ngspice);
104
105 g_list_free_full(test_resources->log_list, g_free);
106
107 ngspice_watcher_build_and_launch_resources_finalize(resources);
108 }
109
test_engine_ngspice_basic()110 static void test_engine_ngspice_basic() {
111
112 TestEngineNgspiceResources *test_resources = test_engine_ngspice_resources_new();
113
114 g_autofree gchar *test_dir = get_test_base_dir();
115
116 g_free(test_resources->resources->netlist_file);
117 test_resources->resources->netlist_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/basic/input.netlist", test_dir);
118
119 g_free(test_resources->resources->ngspice_result_file);
120 test_resources->resources->ngspice_result_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/basic/result/actual.txt", test_dir);
121
122 g_autofree gchar *actual_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/basic/result/actual.txt", test_dir);
123 g_autofree gchar *expected_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/basic/result/expected.txt", test_dir);
124
125 ngspice_watcher_build_and_launch(test_resources->resources);
126 g_main_loop_run(test_resources->loop);
127 print_log(test_resources->log_list);
128
129 test_engine_ngspice_resources_finalize(test_resources);
130
131 g_autofree gchar *actual_content = NULL;
132 gsize actual_size;
133 g_file_get_contents(actual_file, &actual_content, &actual_size, NULL);
134
135 g_autofree gchar *expected_content = NULL;
136 gsize expected_size;
137 g_file_get_contents(expected_file, &expected_content, &expected_size, NULL);
138
139 // FIXME this comparision is too cumbersome and error prone
140 // any kind of change in the ngspice output will brake this
141 // we should only compare the lines which are considered
142 // number output of the simulation
143 // g_assert_true(expected_size > 350);
144 // g_assert_true(actual_size > expected_size - 350);
145 // double distance = 0;
146 // for (gsize i = 0; i < expected_size - 350; i++) {
147 // distance += ABS(actual_content[i] - expected_content[i]);
148 // }
149 // FIXME this will never work reliably
150 // g_assert_true(distance < 3*16*20);
151 }
152
test_engine_ngspice_error_no_such_file_or_directory()153 static void test_engine_ngspice_error_no_such_file_or_directory() {
154 TestEngineNgspiceResources *test_resources = test_engine_ngspice_resources_new();
155
156 // make sure that the given file does not exist
157 g_free(test_resources->resources->netlist_file);
158 gint fd = g_file_open_tmp(NULL, &test_resources->resources->netlist_file, NULL);
159 g_close(fd, NULL);
160 g_remove(test_resources->resources->netlist_file);
161
162 ngspice_watcher_build_and_launch(test_resources->resources);
163 g_main_loop_run(test_resources->loop);
164
165 g_assert_nonnull(test_resources->log_list);
166 g_assert_true(g_str_has_suffix(test_resources->log_list->data, " No such file or directory\n"));
167
168 test_engine_ngspice_resources_finalize(test_resources);
169 }
170
test_engine_ngspice_error_step_zero()171 static void test_engine_ngspice_error_step_zero() {
172 TestEngineNgspiceResources *test_resources = test_engine_ngspice_resources_new();
173
174
175 g_autofree gchar *test_dir = get_test_base_dir();
176
177 g_free(test_resources->resources->netlist_file);
178 test_resources->resources->netlist_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/error/step_zero/input.netlist", test_dir);
179
180 g_free(test_resources->resources->ngspice_result_file);
181 test_resources->resources->ngspice_result_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/error/step_zero/result/actual.txt", test_dir);
182
183 g_autofree gchar *actual_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/error/step_zero/result/actual.txt", test_dir);
184 g_autofree gchar *expected_file = g_strdup_printf("%s/test-files/test_engine_ngspice_watcher/error/step_zero/result/expected.txt", test_dir);
185
186
187 ngspice_watcher_build_and_launch(test_resources->resources);
188 g_main_loop_run(test_resources->loop);
189
190 g_autofree gchar *actual_content = NULL;
191 gsize actual_size;
192 g_file_get_contents(actual_file, &actual_content, &actual_size, NULL);
193
194 g_autofree gchar *expected_content = NULL;
195 gsize expected_size;
196 g_file_get_contents(expected_file, &expected_content, &expected_size, NULL);
197
198 //
199 // g_assert_cmpstr(actual_content, ==, expected_content);
200 //
201 // const gchar *array[] = {
202 // "\n",
203 // "ngspice stopped due to error, no simulation run!\n",
204 // "\n",
205 // "ERROR: fatal error in ngspice, exit(1)\n",
206 // "### ngspice exited abnormally ###\n",
207 // "### netlist error detected ###\n",
208 // "You made a mistake in the simulation settings or part properties.\n",
209 // "The following information will help you to analyze the error.\n",
210 // NULL
211 // };
212 //
213 // GList *walker = test_resources->log_list;
214 //
215 // for (int i = 0; array[i] != NULL; i++) {
216 // g_assert_nonnull(walker);
217 // g_assert_nonnull(walker->data);
218 // g_assert_cmpstr(walker->data, ==, array[i]);
219 // walker = walker->next;
220 // }
221
222 test_engine_ngspice_resources_finalize(test_resources);
223 }
224