1 /*
2  * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19 #include <stdio.h>
20 #include <glib.h>
21 #include <glib-object.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <gmodule.h>
26 #include <libgda/libgda.h>
27 #include <sql-parser/gda-sql-parser.h>
28 
29 #include <libxml/parser.h>
30 #include <libxml/tree.h>
31 
32 static GdaSqlParser *create_parser_for_provider (const gchar *prov_name);
33 static gint do_test (GdaSqlParser *parser, const xmlChar *id, const xmlChar *file, xmlNodePtr test_node);
34 
35 int
main(int argc,char ** argv)36 main (int argc, char** argv)
37 {
38 	xmlDocPtr doc;
39         xmlNodePtr root, node;
40 	GdaSqlParser *parser;
41 	gint failures = 0;
42 	gint ntests = 0;
43 	gchar *fname;
44 	GHashTable *parsers_hash;
45 	GdaDataModel *providers_model;
46 	gint i;
47 
48 	gda_init ();
49 
50 	/* load file */
51 	fname = g_build_filename (ROOT_DIR, "tests", "parser", "testscripts.xml", NULL);
52 	if (! g_file_test (fname, G_FILE_TEST_EXISTS)) {
53                 g_print ("File '%s' does not exist\n", fname);
54                 exit (1);
55         }
56 
57 	/* create parsers */
58 	parsers_hash = g_hash_table_new (g_str_hash, g_str_equal);
59 	providers_model = gda_config_list_providers ();
60 	for (i = 0; i < gda_data_model_get_n_rows (providers_model); i++) {
61 		const GValue *pname;
62 		GError *lerror = NULL;
63 		pname = gda_data_model_get_value_at (providers_model, 0, i, &lerror);
64 		if (!pname) {
65 			g_print ("Can't get data model's value: %s",
66 				 lerror && lerror->message ? lerror->message : "No detail");
67 			exit (1);
68 		}
69 		parser = create_parser_for_provider (g_value_get_string (pname));
70 		g_hash_table_insert (parsers_hash, g_strdup (g_value_get_string (pname)), parser);
71 		g_print ("Created parser for provider %s\n", g_value_get_string (pname));
72 	}
73 	g_object_unref (providers_model);
74 	g_hash_table_insert (parsers_hash, "", gda_sql_parser_new ());
75 
76 	/* use test data */
77 	doc = xmlParseFile (fname);
78 	g_free (fname);
79 	g_assert (doc);
80 	root = xmlDocGetRootElement (doc);
81 	g_assert (!strcmp ((gchar*) root->name, "testdata"));
82 	for (node = root->children; node; node = node->next) {
83 		if (strcmp ((gchar*) node->name, "test"))
84 			continue;
85 		xmlChar *id;
86 		xmlChar *file;
87 		xmlChar *prov_name;
88 
89 		prov_name = xmlGetProp (node, BAD_CAST "provider");
90 		if (prov_name) {
91 			parser = g_hash_table_lookup (parsers_hash, (gchar *) prov_name);
92 			xmlFree (prov_name);
93 		}
94 		else
95 			parser = g_hash_table_lookup (parsers_hash, "");
96 		if (!parser)
97 			continue;
98 
99 		id = xmlGetProp (node, BAD_CAST "id");
100 		file = xmlGetProp (node, BAD_CAST "file");
101 
102 		if (id && file) {
103 			failures += do_test (parser, id, file, node);
104 			ntests++;
105 		}
106 
107 		/* mem free */
108 		if (id)	xmlFree (id);
109 		if (file) xmlFree (file);
110 	}
111 	xmlFreeDoc (doc);
112 
113 	g_print ("TESTS COUNT: %d\n", ntests);
114 	g_print ("FAILURES: %d\n", failures);
115 
116 	return failures != 0 ? 1 : 0;
117 }
118 
119 /*
120  * Returns: the number of failures
121  */
122 static gint
do_test(GdaSqlParser * parser,const xmlChar * id,const xmlChar * file,xmlNodePtr test_node)123 do_test (GdaSqlParser *parser, const xmlChar *id, const xmlChar *file, xmlNodePtr test_node)
124 {
125 	gboolean failures = 0;
126 	GdaBatch *batch;
127 	GError *error = NULL;
128 	gchar *full_file;
129 
130 	full_file = g_build_filename (ROOT_DIR, "tests", "parser", "scripts", file, NULL);
131 
132 #ifdef GDA_DEBUG
133 	g_print ("===== TEST %s FILE: %s\n", id, full_file);
134 #endif
135 
136 	batch = gda_sql_parser_parse_file_as_batch (parser, full_file, &error);
137 	g_free (full_file);
138 
139 	if (!batch) {
140 		g_print ("ERROR for test '%s':\n   *got error while parsing: %s\n", id,
141 			 error && error->message ? error->message: "No detail");
142 		if (error)
143 			g_error_free (error);
144 		failures ++;
145 	}
146 	else {
147 		const GSList *stmt_list;
148 		xmlNodePtr snode;
149 		guint nb_stmt = 0;
150 
151 		stmt_list = gda_batch_get_statements (batch);
152 
153 		/* number of statements */
154 		for (snode = test_node->children; snode; snode = snode->next) {
155 			if (!strcmp ((gchar*) snode->name, "stmt"))
156 				nb_stmt++;
157 		}
158 		if (nb_stmt != g_slist_length ((GSList*) stmt_list)) {
159 			g_print ("ERROR for test '%s':\n   *expected %d statements and got %d\n", id,
160 				 nb_stmt, g_slist_length ((GSList*) stmt_list));
161 			failures ++;
162 		}
163 
164 		/* each statement */
165 		GSList *list;
166 		for (snode = test_node->children, list = (GSList*) stmt_list;
167 		     list;
168 		     list = list->next) {
169 			gchar *sql;
170 			sql = gda_statement_to_sql (GDA_STATEMENT (list->data), NULL, &error);
171 			if (!sql) {
172 				g_print ("ERROR for test '%s':\n   *can't convert statement at position %d to SQL: %s\n", id,
173 					 g_slist_position ((GSList*) stmt_list, list),
174 					 error && error->message ? error->message: "No detail");
175 				if (error)
176 					g_error_free (error);
177 				failures ++;
178 			}
179 			else {
180 				/* find the next <stmt> node */
181 				xmlChar *expected = NULL;
182 				for (; snode; snode = snode->next) {
183 					if (strcmp ((gchar*) snode->name, "stmt"))
184 						continue;
185 					expected = xmlNodeGetContent (snode);
186 					snode = snode->next;
187 					break;
188 				}
189 				if (!expected) {
190 					g_print ("ERROR for test '%s':\n   *missing <stmt> tag for statement at position %d\n", id,
191 						 g_slist_position ((GSList*) stmt_list, list));
192 					failures ++;
193 				}
194 
195 				gchar *ptr;
196 				for (ptr = sql; *ptr; ptr++) {
197 					if ((*ptr == '\n') || (*ptr == '\t') || (*ptr == '\r'))
198 						*ptr = ' ';
199 				}
200 				g_strstrip (sql);
201 				if (expected) {
202 					if (strcmp (sql, expected)) {
203 						g_print ("ERROR for test '%s', statement at position %d:\n   *exp:%s\n   *got:%s\n", id,
204 							 g_slist_position ((GSList*) stmt_list, list), expected, sql);
205 						failures ++;
206 						break;
207 					}
208 				}
209 				else
210 					g_print ("% 2d: %s\n", g_slist_position ((GSList*) stmt_list, list), sql);
211 				g_free (sql);
212 			}
213 		}
214 		g_object_unref (batch);
215 	}
216 
217 	return failures;
218 }
219 
220 static GdaSqlParser *
create_parser_for_provider(const gchar * prov_name)221 create_parser_for_provider (const gchar *prov_name)
222 {
223 	GdaServerProvider *prov;
224 	GdaSqlParser *parser;
225 	GError *error = NULL;
226 
227 	prov = gda_config_get_provider (prov_name, &error);
228 	if (!prov)
229 		g_error ("Could not create provider for '%s': %s\n", prov_name,
230 			 error && error->message ? error->message : "No detail");
231 
232 	parser = gda_server_provider_create_parser (prov, NULL);
233 	if (!parser)
234 		parser = gda_sql_parser_new ();
235 
236 	return parser;
237 }
238