/src/plugins/clang/test-daemon.c

https://gitlab.com/tchaik/gnome-builder · C · 500 lines · 405 code · 95 blank · 0 comment · 16 complexity · 8a20694a87f75ce3c8b447cf81fb0551 MD5 · raw file

  1. #include "config.h"
  2. #include <gio/gio.h>
  3. #include <jsonrpc-glib.h>
  4. #include <stdlib.h>
  5. typedef void (*TestFunc) (JsonrpcClient *client,
  6. GTask *task);
  7. static void tick_tests (JsonrpcClient *client);
  8. static void test_initialize (JsonrpcClient *client,
  9. GTask *task);
  10. static void test_complete (JsonrpcClient *client,
  11. GTask *task);
  12. static void test_find_scope (JsonrpcClient *client,
  13. GTask *task);
  14. static void test_diagnose (JsonrpcClient *client,
  15. GTask *task);
  16. static void test_locate (JsonrpcClient *client,
  17. GTask *task);
  18. static void test_index_file (JsonrpcClient *client,
  19. GTask *task);
  20. static void test_symtree (JsonrpcClient *client,
  21. GTask *task);
  22. static void test_highlight (JsonrpcClient *client,
  23. GTask *task);
  24. static void test_index_key (JsonrpcClient *client,
  25. GTask *task);
  26. static gchar **flags;
  27. static const gchar *path;
  28. static GMainLoop *main_loop;
  29. static TestFunc test_funcs[] = {
  30. test_initialize,
  31. test_complete,
  32. test_diagnose,
  33. test_find_scope,
  34. test_index_file,
  35. test_locate,
  36. test_symtree,
  37. test_highlight,
  38. test_index_key,
  39. };
  40. static void
  41. test_index_key_cb (GObject *object,
  42. GAsyncResult *result,
  43. gpointer user_data)
  44. {
  45. JsonrpcClient *client = (JsonrpcClient *)object;
  46. g_autoptr(GTask) task = user_data;
  47. g_autoptr(GVariant) reply = NULL;
  48. g_autoptr(GError) error = NULL;
  49. g_assert (G_IS_TASK (task));
  50. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  51. g_printerr ("getIndexKey: %s\n", error->message);
  52. else
  53. g_printerr ("getIndexKey: %s\n", g_variant_print (reply, TRUE));
  54. g_task_return_boolean (task, TRUE);
  55. }
  56. static void
  57. test_index_key (JsonrpcClient *client,
  58. GTask *task)
  59. {
  60. g_autoptr(GVariant) params = NULL;
  61. params = JSONRPC_MESSAGE_NEW (
  62. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  63. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags),
  64. "line", JSONRPC_MESSAGE_PUT_INT64 (5),
  65. "column", JSONRPC_MESSAGE_PUT_INT64 (5)
  66. );
  67. jsonrpc_client_call_async (client,
  68. "clang/getIndexKey",
  69. params,
  70. NULL,
  71. test_index_key_cb,
  72. g_object_ref (task));
  73. }
  74. static void
  75. test_highlight_cb (GObject *object,
  76. GAsyncResult *result,
  77. gpointer user_data)
  78. {
  79. JsonrpcClient *client = (JsonrpcClient *)object;
  80. g_autoptr(GTask) task = user_data;
  81. g_autoptr(GVariant) reply = NULL;
  82. g_autoptr(GError) error = NULL;
  83. g_assert (G_IS_TASK (task));
  84. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  85. g_error ("getHighlightIndex: %s", error->message);
  86. g_printerr ("getHighlightIndex: %s\n", g_variant_print (reply, TRUE));
  87. g_task_return_boolean (task, TRUE);
  88. }
  89. static void
  90. test_highlight (JsonrpcClient *client,
  91. GTask *task)
  92. {
  93. g_autoptr(GVariant) params = NULL;
  94. params = JSONRPC_MESSAGE_NEW (
  95. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  96. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags)
  97. );
  98. jsonrpc_client_call_async (client,
  99. "clang/getHighlightIndex",
  100. params,
  101. NULL,
  102. test_highlight_cb,
  103. g_object_ref (task));
  104. }
  105. static void
  106. test_symtree_cb (GObject *object,
  107. GAsyncResult *result,
  108. gpointer user_data)
  109. {
  110. JsonrpcClient *client = (JsonrpcClient *)object;
  111. g_autoptr(GTask) task = user_data;
  112. g_autoptr(GVariant) reply = NULL;
  113. g_autoptr(GError) error = NULL;
  114. g_assert (G_IS_TASK (task));
  115. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  116. g_error ("getSymbolTree: %s", error->message);
  117. g_printerr ("getSymbolTree: %s\n", g_variant_print (reply, TRUE));
  118. g_task_return_boolean (task, TRUE);
  119. }
  120. static void
  121. test_symtree (JsonrpcClient *client,
  122. GTask *task)
  123. {
  124. g_autoptr(GVariant) params = NULL;
  125. params = JSONRPC_MESSAGE_NEW (
  126. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  127. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags)
  128. );
  129. jsonrpc_client_call_async (client,
  130. "clang/getSymbolTree",
  131. params,
  132. NULL,
  133. test_symtree_cb,
  134. g_object_ref (task));
  135. }
  136. static void
  137. test_locate_cb (GObject *object,
  138. GAsyncResult *result,
  139. gpointer user_data)
  140. {
  141. JsonrpcClient *client = (JsonrpcClient *)object;
  142. g_autoptr(GTask) task = user_data;
  143. g_autoptr(GVariant) reply = NULL;
  144. g_autoptr(GError) error = NULL;
  145. g_assert (G_IS_TASK (task));
  146. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  147. g_error ("locate-symbol: %s", error->message);
  148. g_printerr ("locate-symbol: %s\n", g_variant_print (reply, TRUE));
  149. g_task_return_boolean (task, TRUE);
  150. }
  151. static void
  152. test_locate (JsonrpcClient *client,
  153. GTask *task)
  154. {
  155. g_autoptr(GVariant) params = NULL;
  156. params = JSONRPC_MESSAGE_NEW (
  157. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  158. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags),
  159. "line", JSONRPC_MESSAGE_PUT_INT64 (5),
  160. "column", JSONRPC_MESSAGE_PUT_INT64 (5)
  161. );
  162. jsonrpc_client_call_async (client,
  163. "clang/locateSymbol",
  164. params,
  165. NULL,
  166. test_locate_cb,
  167. g_object_ref (task));
  168. }
  169. static void
  170. test_index_file_cb (GObject *object,
  171. GAsyncResult *result,
  172. gpointer user_data)
  173. {
  174. JsonrpcClient *client = (JsonrpcClient *)object;
  175. g_autoptr(GTask) task = user_data;
  176. g_autoptr(GVariant) reply = NULL;
  177. g_autoptr(GError) error = NULL;
  178. g_assert (G_IS_TASK (task));
  179. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  180. g_error ("index-file: %s", error->message);
  181. g_printerr ("index-file: %s\n", g_variant_print (reply, TRUE));
  182. g_task_return_boolean (task, TRUE);
  183. }
  184. static void
  185. test_index_file (JsonrpcClient *client,
  186. GTask *task)
  187. {
  188. g_autoptr(GVariant) params = NULL;
  189. params = JSONRPC_MESSAGE_NEW (
  190. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  191. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags)
  192. );
  193. jsonrpc_client_call_async (client,
  194. "clang/indexFile",
  195. params,
  196. NULL,
  197. test_index_file_cb,
  198. g_object_ref (task));
  199. }
  200. static void
  201. test_diagnose_cb (GObject *object,
  202. GAsyncResult *result,
  203. gpointer user_data)
  204. {
  205. JsonrpcClient *client = (JsonrpcClient *)object;
  206. g_autoptr(GTask) task = user_data;
  207. g_autoptr(GVariant) reply = NULL;
  208. g_autoptr(GError) error = NULL;
  209. g_assert (G_IS_TASK (task));
  210. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  211. g_error ("diagnose: %s", error->message);
  212. g_printerr ("diagnose: %s\n", g_variant_print (reply, TRUE));
  213. g_task_return_boolean (task, TRUE);
  214. }
  215. static void
  216. test_diagnose (JsonrpcClient *client,
  217. GTask *task)
  218. {
  219. g_autoptr(GVariant) params = NULL;
  220. params = JSONRPC_MESSAGE_NEW (
  221. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  222. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags)
  223. );
  224. jsonrpc_client_call_async (client,
  225. "clang/diagnose",
  226. params,
  227. NULL,
  228. test_diagnose_cb,
  229. g_object_ref (task));
  230. }
  231. static void
  232. test_find_scope_cb (GObject *object,
  233. GAsyncResult *result,
  234. gpointer user_data)
  235. {
  236. JsonrpcClient *client = (JsonrpcClient *)object;
  237. g_autoptr(GTask) task = user_data;
  238. g_autoptr(GVariant) reply = NULL;
  239. g_autoptr(GError) error = NULL;
  240. g_assert (G_IS_TASK (task));
  241. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  242. g_printerr ("find-nearest-scope: %s\n", error->message);
  243. else
  244. g_printerr ("find-nearest-scope: %s\n", g_variant_print (reply, TRUE));
  245. g_task_return_boolean (task, TRUE);
  246. }
  247. static void
  248. test_find_scope (JsonrpcClient *client,
  249. GTask *task)
  250. {
  251. g_autoptr(GVariant) params = NULL;
  252. params = JSONRPC_MESSAGE_NEW (
  253. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  254. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags),
  255. "line", JSONRPC_MESSAGE_PUT_INT64 (5),
  256. "column", JSONRPC_MESSAGE_PUT_INT64 (3)
  257. );
  258. jsonrpc_client_call_async (client,
  259. "clang/findNearestScope",
  260. params,
  261. NULL,
  262. test_find_scope_cb,
  263. g_object_ref (task));
  264. }
  265. static void
  266. test_complete_cb (GObject *object,
  267. GAsyncResult *result,
  268. gpointer user_data)
  269. {
  270. JsonrpcClient *client = (JsonrpcClient *)object;
  271. g_autoptr(GTask) task = user_data;
  272. g_autoptr(GVariant) reply = NULL;
  273. g_autoptr(GError) error = NULL;
  274. g_assert (G_IS_TASK (task));
  275. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  276. g_error ("complete: %s", error->message);
  277. g_printerr ("complete: %s\n", g_variant_print (reply, TRUE));
  278. g_task_return_boolean (task, TRUE);
  279. }
  280. static void
  281. test_complete (JsonrpcClient *client,
  282. GTask *task)
  283. {
  284. g_autoptr(GVariant) params = NULL;
  285. guint line = 0;
  286. guint column = 0;
  287. params = JSONRPC_MESSAGE_NEW (
  288. "path", JSONRPC_MESSAGE_PUT_STRING (path),
  289. "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags),
  290. "line", JSONRPC_MESSAGE_PUT_INT64 (line),
  291. "column", JSONRPC_MESSAGE_PUT_INT64 (column)
  292. );
  293. jsonrpc_client_call_async (client,
  294. "clang/complete",
  295. params,
  296. NULL,
  297. test_complete_cb,
  298. g_object_ref (task));
  299. }
  300. static void
  301. test_initialize_cb (GObject *object,
  302. GAsyncResult *result,
  303. gpointer user_data)
  304. {
  305. JsonrpcClient *client = (JsonrpcClient *)object;
  306. g_autoptr(GTask) task = user_data;
  307. g_autoptr(GVariant) reply = NULL;
  308. g_autoptr(GError) error = NULL;
  309. g_assert (G_IS_TASK (task));
  310. if (!jsonrpc_client_call_finish (client, result, &reply, &error))
  311. g_error ("initialize: %s", error->message);
  312. g_printerr ("initialize: %s\n", g_variant_print (reply, TRUE));
  313. g_task_return_boolean (task, TRUE);
  314. }
  315. static void
  316. test_initialize (JsonrpcClient *client,
  317. GTask *task)
  318. {
  319. g_autoptr(GVariant) params = NULL;
  320. g_autofree gchar *root = NULL;
  321. g_autofree gchar *uri = NULL;
  322. root = g_path_get_dirname (path);
  323. uri = g_strdup_printf ("file://%s", root);
  324. params = JSONRPC_MESSAGE_NEW (
  325. "rootUri", JSONRPC_MESSAGE_PUT_STRING (uri),
  326. "rootPath", JSONRPC_MESSAGE_PUT_STRING (root),
  327. "processId", JSONRPC_MESSAGE_PUT_INT64 (getpid ()),
  328. "capabilities", "{", "}"
  329. );
  330. jsonrpc_client_call_async (client,
  331. "initialize",
  332. params,
  333. NULL,
  334. test_initialize_cb,
  335. g_object_ref (task));
  336. }
  337. static void
  338. finished_cb (GObject *object,
  339. GAsyncResult *result,
  340. gpointer user_data)
  341. {
  342. JsonrpcClient *client = (JsonrpcClient *)object;
  343. g_autoptr(GError) error = NULL;
  344. g_assert (JSONRPC_IS_CLIENT (client));
  345. g_assert (G_IS_TASK (result));
  346. if (!g_task_propagate_boolean (G_TASK (result), &error))
  347. g_error ("%s", error->message);
  348. tick_tests (client);
  349. }
  350. static void
  351. tick_tests (JsonrpcClient *client)
  352. {
  353. g_autoptr(GTask) task = NULL;
  354. static guint test_pos = 0;
  355. if (test_pos >= G_N_ELEMENTS (test_funcs))
  356. {
  357. g_main_loop_quit (main_loop);
  358. return;
  359. }
  360. task = g_task_new (client, NULL, finished_cb, NULL);
  361. test_funcs[test_pos++] (client, task);
  362. }
  363. gint
  364. main (gint argc,
  365. gchar *argv[])
  366. {
  367. g_autoptr(JsonrpcClient) client = NULL;
  368. g_autoptr(GSubprocess) subprocess = NULL;
  369. g_autoptr(GIOStream) stream = NULL;
  370. g_autoptr(GError) error = NULL;
  371. if (argc != 4)
  372. {
  373. g_printerr ("usage: %s path-to-daemon source-file build-flags\n", argv[0]);
  374. return EXIT_FAILURE;
  375. }
  376. subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
  377. &error,
  378. #if 0
  379. "gdbserver",
  380. "localhost:8888",
  381. #endif
  382. #if 0
  383. "valgrind",
  384. "--suppressions=glib.supp",
  385. "--leak-check=full",
  386. #endif
  387. argv[1],
  388. NULL);
  389. if (subprocess == NULL)
  390. {
  391. g_printerr ("Failed to spawn daemon: %s\n", error->message);
  392. return EXIT_FAILURE;
  393. }
  394. path = argv[2];
  395. if (!g_shell_parse_argv (argv[3], NULL, &flags, NULL))
  396. flags = NULL;
  397. main_loop = g_main_loop_new (NULL, FALSE);
  398. stream = g_simple_io_stream_new (g_subprocess_get_stdout_pipe (subprocess),
  399. g_subprocess_get_stdin_pipe (subprocess));
  400. client = jsonrpc_client_new (stream);
  401. tick_tests (client);
  402. g_subprocess_wait_async (subprocess, NULL, NULL, NULL);
  403. g_main_loop_run (main_loop);
  404. return EXIT_SUCCESS;
  405. }