From d1cd99244f96bd95bbd67cc737248df346dec08b Mon Sep 17 00:00:00 2001 From: egor-tensin Date: Thu, 25 Apr 2024 03:50:51 +0000 Subject: =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20egor-tensin/cimp?= =?UTF-8?q?le@8e652dd2cb69928ea1596aa3e59845fef6854e2c=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ....base64.c.6cc41135837c80527c8f246c27adf87e.html | 603 +++ ...dex.buf.c.ed8381695b8bbc07634acc8fcf3aab27.html | 517 +++ ...ndex.ci.c.aafc6aa1373a4054fe8dceca1e5a2cd2.html | 990 ++++ ....client.c.7eeddcdb2bd1344daca0a340abd305ae.html | 1121 +++++ ...nt_main.c.0ff1a98449e6ae22cf540fe28921fa2d.html | 909 ++++ ...md_line.c.fc55483624faae9ff92546137d095857.html | 680 +++ ...command.c.d26991ef13eb41283f88bf34125ef986.html | 2048 ++++++++ coverage/index.css | 505 ++ ...nt_loop.c.037d09258818a0617a2d29f47e2b5064.html | 2163 +++++++++ ...ex.file.c.0cc24881e570d19e625204519d50254f.html | 1491 ++++++ ...dex.git.c.ecafe65200a95f92fc10a3095d9e5f09.html | 1092 +++++ coverage/index.html | 475 ++ ...ex.json.c.9fe0913c76249e448eec3131d7e8b263.html | 2632 +++++++++++ ...son_rpc.c.2aeccc6679171fb423f72eef95ec01c0.html | 4816 +++++++++++++++++++ ...dex.log.c.47179e5db7ed3f2db741c99372ba24f3.html | 539 +++ ...dex.net.c.37012fce13860cefc5963f57e0f36732.html | 2386 ++++++++++ ...process.c.52f9324f34485af6c2c0f7cc7bbf5f8b.html | 1491 ++++++ ...rotocol.c.4964764a2e677a55c2f4207a995c3ce7.html | 2054 ++++++++ ...n_queue.c.fdfaa39d71447cf1e7d01ff206bd91e5.html | 1816 ++++++++ ....server.c.0235f01a49d01b35e981a41f59a9d2d6.html | 4455 ++++++++++++++++++ ...er_main.c.3ca591a47eaf0cc37ef7579efe6031fe.html | 885 ++++ ....signal.c.71d63611c8a63e0778dd598afad76dfd.html | 826 ++++ ....sqlite.c.13cf77e7262c599539f10e3be0248b3e.html | 2733 +++++++++++ ...storage.c.96d197609feea4b630e7b775fb18af81.html | 1189 +++++ ..._sqlite.c.b44f7f73d467be85cd4227a40c11d12a.html | 4906 ++++++++++++++++++++ ....string.c.2a75186e465ffeac1b306a350f4a56f8.html | 515 ++ ..._server.c.68fbb5aebb39dbc263f5110d228c9b35.html | 2532 ++++++++++ ....worker.c.4cbdfac39be7d0330fdfd94f65ce9ea9.html | 2492 ++++++++++ ...er_main.c.3e96ea0429977547c8b5eee564591fe0.html | 885 ++++ ...r_queue.c.aeb7258cd8f695c41a9aa8634701b38c.html | 755 +++ 30 files changed, 50501 insertions(+) create mode 100644 coverage/index.base64.c.6cc41135837c80527c8f246c27adf87e.html create mode 100644 coverage/index.buf.c.ed8381695b8bbc07634acc8fcf3aab27.html create mode 100644 coverage/index.ci.c.aafc6aa1373a4054fe8dceca1e5a2cd2.html create mode 100644 coverage/index.client.c.7eeddcdb2bd1344daca0a340abd305ae.html create mode 100644 coverage/index.client_main.c.0ff1a98449e6ae22cf540fe28921fa2d.html create mode 100644 coverage/index.cmd_line.c.fc55483624faae9ff92546137d095857.html create mode 100644 coverage/index.command.c.d26991ef13eb41283f88bf34125ef986.html create mode 100644 coverage/index.css create mode 100644 coverage/index.event_loop.c.037d09258818a0617a2d29f47e2b5064.html create mode 100644 coverage/index.file.c.0cc24881e570d19e625204519d50254f.html create mode 100644 coverage/index.git.c.ecafe65200a95f92fc10a3095d9e5f09.html create mode 100644 coverage/index.html create mode 100644 coverage/index.json.c.9fe0913c76249e448eec3131d7e8b263.html create mode 100644 coverage/index.json_rpc.c.2aeccc6679171fb423f72eef95ec01c0.html create mode 100644 coverage/index.log.c.47179e5db7ed3f2db741c99372ba24f3.html create mode 100644 coverage/index.net.c.37012fce13860cefc5963f57e0f36732.html create mode 100644 coverage/index.process.c.52f9324f34485af6c2c0f7cc7bbf5f8b.html create mode 100644 coverage/index.protocol.c.4964764a2e677a55c2f4207a995c3ce7.html create mode 100644 coverage/index.run_queue.c.fdfaa39d71447cf1e7d01ff206bd91e5.html create mode 100644 coverage/index.server.c.0235f01a49d01b35e981a41f59a9d2d6.html create mode 100644 coverage/index.server_main.c.3ca591a47eaf0cc37ef7579efe6031fe.html create mode 100644 coverage/index.signal.c.71d63611c8a63e0778dd598afad76dfd.html create mode 100644 coverage/index.sqlite.c.13cf77e7262c599539f10e3be0248b3e.html create mode 100644 coverage/index.storage.c.96d197609feea4b630e7b775fb18af81.html create mode 100644 coverage/index.storage_sqlite.c.b44f7f73d467be85cd4227a40c11d12a.html create mode 100644 coverage/index.string.c.2a75186e465ffeac1b306a350f4a56f8.html create mode 100644 coverage/index.tcp_server.c.68fbb5aebb39dbc263f5110d228c9b35.html create mode 100644 coverage/index.worker.c.4cbdfac39be7d0330fdfd94f65ce9ea9.html create mode 100644 coverage/index.worker_main.c.3e96ea0429977547c8b5eee564591fe0.html create mode 100644 coverage/index.worker_queue.c.aeb7258cd8f695c41a9aa8634701b38c.html (limited to 'coverage') diff --git a/coverage/index.base64.c.6cc41135837c80527c8f246c27adf87e.html b/coverage/index.base64.c.6cc41135837c80527c8f246c27adf87e.html new file mode 100644 index 0000000..6de630e --- /dev/null +++ b/coverage/index.base64.c.6cc41135837c80527c8f246c27adf87e.html @@ -0,0 +1,603 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/base64.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:182766.7%
Branches:31225.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "base64.h"
9 + #include "log.h"
10 +
11 + #include <sodium.h>
12 +
13 + #include <stddef.h>
14 + #include <stdlib.h>
15 + #include <string.h>
16 +
17 + static const int base64_variant = sodium_base64_VARIANT_ORIGINAL;
18 +
19 + 9180int base64_encode(const unsigned char *src, size_t src_len, char **_dst)
20 + {
21 + 9180 const size_t dst_len = sodium_base64_encoded_len(src_len, base64_variant);
22 +
23 + 9180 char *dst = calloc(dst_len, 1);
24 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!dst) {
25 + log_errno("calloc");
26 + return -1;
27 + }
28 +
29 + 9180 sodium_bin2base64(dst, dst_len, src, src_len, base64_variant);
30 +
31 + 9180 *_dst = dst;
32 + 9180 return 0;
33 + }
34 +
35 + 9180int base64_decode(const char *src, unsigned char **_dst, size_t *_dst_len)
36 + {
37 + 9180 const size_t src_len = strlen(src);
38 + 9180 const size_t dst_max_len = src_len / 4 * 3;
39 + 9180 size_t dst_len = 0;
40 +
41 + 9180 unsigned char *dst = calloc(dst_max_len, 1);
42 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!dst) {
43 + log_errno("calloc");
44 + return -1;
45 + }
46 +
47 + int ret =
48 + 9180 sodium_base642bin(dst, dst_max_len, src, src_len, NULL, &dst_len, NULL, base64_variant);
49 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
50 + log_err("Couldn't parse base64-encoded string\n");
51 + goto free;
52 + }
53 +
54 + 9180 *_dst = dst;
55 + 9180 *_dst_len = dst_len;
56 + 9180 return ret;
57 +
58 + free:
59 + free(dst);
60 +
61 + return ret;
62 + }
63 +
+
+ +
+ + + + diff --git a/coverage/index.buf.c.ed8381695b8bbc07634acc8fcf3aab27.html b/coverage/index.buf.c.ed8381695b8bbc07634acc8fcf3aab27.html new file mode 100644 index 0000000..7988fce --- /dev/null +++ b/coverage/index.buf.c.ed8381695b8bbc07634acc8fcf3aab27.html @@ -0,0 +1,517 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/buf.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:161888.9%
Branches:1425.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "buf.h"
9 + #include "log.h"
10 +
11 + #include <stdint.h>
12 + #include <stdlib.h>
13 + #include <string.h>
14 +
15 + struct buf {
16 + uint32_t size;
17 + const void *data;
18 + };
19 +
20 + 92012int buf_create(struct buf **_buf, const void *data, uint32_t size)
21 + {
22 + 92012 struct buf *buf = malloc(sizeof(struct buf));
23 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 92012 times.
+
+
+
92012 if (!buf) {
24 + log_errno("malloc");
25 + return -1;
26 + }
27 +
28 + 92012 buf->data = data;
29 + 92012 buf->size = size;
30 +
31 + 92012 *_buf = buf;
32 + 92012 return 0;
33 + }
34 +
35 + 46006int buf_create_from_string(struct buf **buf, const char *str)
36 + {
37 + 46006 return buf_create(buf, str, strlen(str) + 1);
38 + }
39 +
40 + 92012void buf_destroy(struct buf *buf)
41 + {
42 + 92012 free(buf);
43 + 92012}
44 +
45 + 92012uint32_t buf_get_size(const struct buf *buf)
46 + {
47 + 92012 return buf->size;
48 + }
49 +
50 + 138018const void *buf_get_data(const struct buf *buf)
51 + {
52 + 138018 return buf->data;
53 + }
54 +
+
+ +
+ + + + diff --git a/coverage/index.ci.c.aafc6aa1373a4054fe8dceca1e5a2cd2.html b/coverage/index.ci.c.aafc6aa1373a4054fe8dceca1e5a2cd2.html new file mode 100644 index 0000000..3bccad8 --- /dev/null +++ b/coverage/index.ci.c.aafc6aa1373a4054fe8dceca1e5a2cd2.html @@ -0,0 +1,990 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/ci.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:374778.7%
Branches:91850.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "ci.h"
9 + #include "file.h"
10 + #include "git.h"
11 + #include "log.h"
12 + #include "process.h"
13 +
14 + #include <git2.h>
15 + #include <stddef.h>
16 + #include <stdlib.h>
17 +
18 + /* clang-format off */
19 + static const char *ci_scripts[] = {
20 + "./.ci.sh",
21 + "./.ci",
22 + "./ci.sh",
23 + "./ci",
24 + NULL,
25 + };
26 +
27 + static const char *ci_env[] = {
28 + "CI=y",
29 + "CIMPLE=y",
30 + NULL,
31 + };
32 + /* clang-format on */
33 +
34 + 9180static int ci_run_script(const char *script, struct proc_output *result)
35 + {
36 + 9180 const char *args[] = {script, NULL};
37 + 9180 return proc_capture(args, ci_env, result);
38 + }
39 +
40 + 9180int ci_run(struct proc_output *result)
41 + {
42 +
+ 1/2 +
+
✓ Branch 0 taken 36720 times.
+
✗ Branch 1 not taken.
+
+
+
36720 for (const char **script = ci_scripts; *script; ++script) {
43 +
+ 2/2 +
+
✓ Branch 1 taken 27540 times.
+
✓ Branch 2 taken 9180 times.
+
+
+
36720 if (!file_exists(*script))
44 + 27540 continue;
45 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Going to run: %s\n", *script);
46 + 9180 return ci_run_script(*script, result);
47 + }
48 +
49 + log("Couldn't find any CI scripts to run\n");
50 + return -1;
51 + }
52 +
53 + 9180static void ci_cleanup_git_repo(git_repository *repo)
54 + {
55 + 9180 rm_rf(git_repository_workdir(repo));
56 + 9180 libgit_repository_free(repo);
57 + 9180}
58 +
59 + 9180static int ci_prepare_git_repo(git_repository **repo, const char *url, const char *rev)
60 + {
61 + 9180 int ret = 0;
62 +
63 + 9180 ret = libgit_clone_to_tmp(repo, url);
64 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
65 + return ret;
66 +
67 + 9180 ret = libgit_checkout(*repo, rev);
68 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
69 + goto cleanup_repo;
70 +
71 + 9180 return ret;
72 +
73 + cleanup_repo:
74 + ci_cleanup_git_repo(*repo);
75 +
76 + return ret;
77 + }
78 +
79 + 9180int ci_run_git_repo(const char *url, const char *rev, struct proc_output *output)
80 + {
81 + 9180 char *oldpwd = NULL;
82 + 9180 git_repository *repo = NULL;
83 + 9180 int ret = 0;
84 +
85 + 9180 ret = ci_prepare_git_repo(&repo, url, rev);
86 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
87 + goto exit;
88 +
89 + 9180 ret = my_chdir(git_repository_workdir(repo), &oldpwd);
90 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
91 + goto free_repo;
92 +
93 + 9180 ret = ci_run(output);
94 +
+ 1/2 +
+
✓ Branch 0 taken 9180 times.
+
✗ Branch 1 not taken.
+
+
+
9180 if (ret < 0)
95 + goto oldpwd;
96 +
97 + 9180oldpwd:
98 + 9180 my_chdir(oldpwd, NULL);
99 + 9180 free(oldpwd);
100 +
101 + 9180free_repo:
102 + 9180 ci_cleanup_git_repo(repo);
103 +
104 + 9180exit:
105 + 9180 return ret;
106 + }
107 +
+
+ +
+ + + + diff --git a/coverage/index.client.c.7eeddcdb2bd1344daca0a340abd305ae.html b/coverage/index.client.c.7eeddcdb2bd1344daca0a340abd305ae.html new file mode 100644 index 0000000..be1da71 --- /dev/null +++ b/coverage/index.client.c.7eeddcdb2bd1344daca0a340abd305ae.html @@ -0,0 +1,1121 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/client.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:506280.6%
Branches:173056.7%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "client.h"
9 + #include "cmd_line.h"
10 + #include "compiler.h"
11 + #include "const.h"
12 + #include "json_rpc.h"
13 + #include "log.h"
14 + #include "net.h"
15 + #include "protocol.h"
16 + #include "run_queue.h"
17 +
18 + #include <stdlib.h>
19 + #include <string.h>
20 +
21 + struct client {
22 + int dummy;
23 + };
24 +
25 + 9208int client_create(struct client **_client)
26 + {
27 + 9208 int ret = 0;
28 +
29 + 9208 struct client *client = malloc(sizeof(struct client));
30 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9208 times.
+
+
+
9208 if (!client) {
31 + log_errno("malloc");
32 + return -1;
33 + }
34 +
35 + 9208 *_client = client;
36 + 9208 return ret;
37 + }
38 +
39 + 9206void client_destroy(struct client *client)
40 + {
41 + 9206 free(client);
42 + 9206}
43 +
44 + 9208static int make_request(struct jsonrpc_request **request, int argc, const char **argv)
45 + {
46 +
+ 2/2 +
+
✓ Branch 0 taken 1 times.
+
✓ Branch 1 taken 9207 times.
+
+
+
9208 if (argc < 1) {
47 + 1 exit_with_usage_err("no action specified");
48 + return -1;
49 + }
50 +
51 +
+ 2/2 +
+
✓ Branch 0 taken 9180 times.
+
✓ Branch 1 taken 27 times.
+
+
+
9207 if (!strcmp(argv[0], CMD_QUEUE_RUN)) {
52 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (argc != 3)
53 + return -1;
54 +
55 + 9180 struct run *run = NULL;
56 + 9180 int ret = run_queued(&run, argv[1], argv[2]);
57 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
58 + return ret;
59 +
60 + 9180 ret = request_create_queue_run(request, run);
61 + 9180 run_destroy(run);
62 + 9180 return ret;
63 +
+ 2/2 +
+
✓ Branch 0 taken 26 times.
+
✓ Branch 1 taken 1 times.
+
+
+
27 } else if (!strcmp(argv[0], CMD_GET_RUNS)) {
64 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (argc != 1)
65 + return -1;
66 + 26 return request_create_get_runs(request);
67 + }
68 +
69 + 1 return -1;
70 + }
71 +
72 + 9208int client_main(UNUSED const struct client *client, const struct settings *settings, int argc,
73 + const char **argv)
74 + {
75 + 9208 int ret = 0;
76 +
77 + 9208 struct jsonrpc_request *request = NULL;
78 + 9208 ret = make_request(&request, argc, argv);
79 +
+ 2/2 +
+
✓ Branch 0 taken 1 times.
+
✓ Branch 1 taken 9206 times.
+
+
+
9207 if (ret < 0) {
80 + 1 exit_with_usage_err("invalid request");
81 + return ret;
82 + }
83 +
84 + 9206 ret = net_connect(settings->host, settings->port);
85 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
86 + goto free_request;
87 + 9206 int fd = ret;
88 +
89 + 9206 ret = jsonrpc_request_send(request, fd);
90 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
91 + goto close;
92 +
93 + 9206 struct jsonrpc_response *response = NULL;
94 + 9206 ret = jsonrpc_response_recv(&response, fd);
95 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
96 + goto close;
97 +
98 + 9206 const char *response_str = jsonrpc_response_to_string(response);
99 +
+ 1/2 +
+
✓ Branch 0 taken 9206 times.
+
✗ Branch 1 not taken.
+
+
+
9206 if (response_str) {
100 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9206 times.
+
+
+
9206 if (jsonrpc_response_is_error(response))
101 + ret = -1;
102 + 9206 printf("%s", response_str);
103 + } else {
104 + log_err("no response\n");
105 + }
106 + 9206 goto free_response;
107 +
108 + 9206free_response:
109 + 9206 jsonrpc_response_destroy(response);
110 +
111 + 9206close:
112 + 9206 net_close(fd);
113 +
114 + 9206free_request:
115 + 9206 jsonrpc_request_destroy(request);
116 +
117 + 9206 return ret;
118 + }
119 +
+
+ +
+ + + + diff --git a/coverage/index.client_main.c.0ff1a98449e6ae22cf540fe28921fa2d.html b/coverage/index.client_main.c.0ff1a98449e6ae22cf540fe28921fa2d.html new file mode 100644 index 0000000..47d3a69 --- /dev/null +++ b/coverage/index.client_main.c.0ff1a98449e6ae22cf540fe28921fa2d.html @@ -0,0 +1,909 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/client_main.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:344379.1%
Branches:101471.4%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "client.h"
9 + #include "cmd_line.h"
10 + #include "const.h"
11 + #include "log.h"
12 +
13 + #include <getopt.h>
14 + #include <unistd.h>
15 +
16 + 9214static struct settings default_settings(void)
17 + {
18 + 9214 struct settings settings = {
19 + .host = default_host,
20 + .port = default_port,
21 + };
22 + 9214 return settings;
23 + }
24 +
25 + 6const char *get_usage_string(void)
26 + {
27 + 6 return "[-h|--help] [-V|--version] [-v|--verbose] [-H|--host HOST] [-p|--port PORT] ACTION [ARG...]\n\
28 + \n\
29 + available actions:\n\
30 + \t" CMD_QUEUE_RUN " URL REV - schedule a CI run of repository at URL, revision REV";
31 + }
32 +
33 + 9214static int parse_settings(struct settings *settings, int argc, char *argv[])
34 + {
35 + int opt, longind;
36 +
37 + 9214 *settings = default_settings();
38 +
39 + /* clang-format off */
40 + static struct option long_options[] = {
41 + {"help", no_argument, 0, 'h'},
42 + {"version", no_argument, 0, 'V'},
43 + {"verbose", no_argument, 0, 'v'},
44 + {"host", required_argument, 0, 'H'},
45 + {"port", required_argument, 0, 'p'},
46 + {0, 0, 0, 0},
47 + };
48 + /* clang-format on */
49 +
50 +
+ 2/2 +
+
✓ Branch 1 taken 18422 times.
+
✓ Branch 2 taken 9208 times.
+
+
+
27630 while ((opt = getopt_long(argc, argv, "hVvH:p:", long_options, &longind)) != -1) {
51 +
+ 5/6 +
+
✓ Branch 0 taken 2 times.
+
✓ Branch 1 taken 2 times.
+
✗ Branch 2 not taken.
+
✓ Branch 3 taken 9208 times.
+
✓ Branch 4 taken 9208 times.
+
✓ Branch 5 taken 2 times.
+
+
+
18422 switch (opt) {
52 + 2 case 'h':
53 + 2 exit_with_usage(0);
54 + break;
55 + 2 case 'V':
56 + 2 exit_with_version();
57 + break;
58 + case 'v':
59 + g_log_lvl = LOG_LVL_DEBUG;
60 + break;
61 + 9208 case 'H':
62 + 9208 settings->host = optarg;
63 + 9208 break;
64 + 9208 case 'p':
65 + 9208 settings->port = optarg;
66 + 9208 break;
67 + 2 default:
68 + 2 exit_with_usage(1);
69 + break;
70 + }
71 + }
72 +
73 + 9208 return 0;
74 + }
75 +
76 + 9214int main(int argc, char *argv[])
77 + {
78 + struct settings settings;
79 + 9214 struct client *client = NULL;
80 + 9214 int ret = 0;
81 +
82 + 9214 ret = parse_settings(&settings, argc, argv);
83 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9208 times.
+
+
+
9208 if (ret < 0)
84 + return ret;
85 +
86 + 9208 ret = client_create(&client);
87 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9208 times.
+
+
+
9208 if (ret < 0)
88 + return ret;
89 +
90 + 9208 ret = client_main(client, &settings, argc - optind, (const char **)argv + optind);
91 +
+ 1/2 +
+
✓ Branch 0 taken 9206 times.
+
✗ Branch 1 not taken.
+
+
+
9206 if (ret < 0)
92 + goto destroy_client;
93 +
94 + 9206destroy_client:
95 + 9206 client_destroy(client);
96 +
97 + 9206 return ret;
98 + }
99 +
+
+ +
+ + + + diff --git a/coverage/index.cmd_line.c.fc55483624faae9ff92546137d095857.html b/coverage/index.cmd_line.c.fc55483624faae9ff92546137d095857.html new file mode 100644 index 0000000..fbaa218 --- /dev/null +++ b/coverage/index.cmd_line.c.fc55483624faae9ff92546137d095857.html @@ -0,0 +1,680 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/cmd_line.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:283190.3%
Branches:71450.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "cmd_line.h"
9 + #include "const.h"
10 + #include "file.h"
11 + #include "log.h"
12 +
13 + #include <stdio.h>
14 + #include <stdlib.h>
15 + #include <string.h>
16 +
17 + 20static char *get_current_binary_path(void)
18 + {
19 + 20 return my_readlink("/proc/self/exe");
20 + }
21 +
22 + 20static char *get_current_binary_name(void)
23 + {
24 + 20 char *path = get_current_binary_path();
25 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 20 times.
+
+
+
20 if (!path)
26 + return NULL;
27 +
28 + 20 char *name = basename(path);
29 +
30 + 20 char *result = strdup(name);
31 +
+ 1/2 +
+
✓ Branch 0 taken 20 times.
+
✗ Branch 1 not taken.
+
+
+
20 if (!result) {
32 + log_errno("strdup");
33 + goto free_path;
34 + }
35 +
36 + 20free_path:
37 + 20 free(path);
38 +
39 + 20 return result;
40 + }
41 +
42 + 14void exit_with_usage(int ec)
43 + {
44 + 14 FILE *dest = stdout;
45 +
+ 2/2 +
+
✓ Branch 0 taken 8 times.
+
✓ Branch 1 taken 6 times.
+
+
+
14 if (ec)
46 + 8 dest = stderr;
47 +
48 + 14 char *binary = get_current_binary_name();
49 +
50 +
+ 1/2 +
+
✓ Branch 1 taken 14 times.
+
✗ Branch 2 not taken.
+
+
+
14 fprintf(dest, "usage: %s %s\n", binary ? binary : "prog", get_usage_string());
51 + 14 free(binary);
52 + 14 exit(ec);
53 + }
54 +
55 + 2void exit_with_usage_err(const char *msg)
56 + {
57 +
+ 1/2 +
+
✓ Branch 0 taken 2 times.
+
✗ Branch 1 not taken.
+
+
+
2 if (msg)
58 + 2 fprintf(stderr, "usage error: %s\n", msg);
59 + 2 exit_with_usage(1);
60 + }
61 +
62 + 6void exit_with_version(void)
63 + {
64 + 6 char *binary = get_current_binary_name();
65 +
66 +
+ 1/2 +
+
✓ Branch 0 taken 6 times.
+
✗ Branch 1 not taken.
+
+
+
6 printf("%s v%s (%s)\n", binary ? binary : "prog", project_version, project_rev);
67 + 6 free(binary);
68 + 6 exit(0);
69 + }
70 +
+
+ +
+ + + + diff --git a/coverage/index.command.c.d26991ef13eb41283f88bf34125ef986.html b/coverage/index.command.c.d26991ef13eb41283f88bf34125ef986.html new file mode 100644 index 0000000..6eca578 --- /dev/null +++ b/coverage/index.command.c.d26991ef13eb41283f88bf34125ef986.html @@ -0,0 +1,2048 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/command.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:8912074.2%
Branches:336650.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "command.h"
9 + #include "compiler.h"
10 + #include "event_loop.h"
11 + #include "json_rpc.h"
12 + #include "log.h"
13 +
14 + #include <poll.h>
15 + #include <stdlib.h>
16 + #include <string.h>
17 +
18 + struct cmd_dispatcher {
19 + struct cmd_desc *cmds;
20 + size_t numof_cmds;
21 + void *ctx;
22 + };
23 +
24 + 170static int copy_cmd(struct cmd_desc *dest, const struct cmd_desc *src)
25 + {
26 + 170 dest->name = strdup(src->name);
27 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 170 times.
+
+
+
170 if (!dest->name) {
28 + log_errno("strdup");
29 + return -1;
30 + }
31 + 170 dest->handler = src->handler;
32 + 170 return 0;
33 + }
34 +
35 + 170static void free_cmd(struct cmd_desc *desc)
36 + {
37 + 170 free(desc->name);
38 + 170}
39 +
40 + 83static int copy_cmds(struct cmd_desc *dest, const struct cmd_desc *src, size_t numof_cmds)
41 + {
42 + 83 size_t numof_copied = 0;
43 + 83 int ret = 0;
44 +
45 +
+ 2/2 +
+
✓ Branch 0 taken 170 times.
+
✓ Branch 1 taken 83 times.
+
+
+
253 for (numof_copied = 0; numof_copied < numof_cmds; ++numof_copied) {
46 + 170 ret = copy_cmd(&dest[numof_copied], &src[numof_copied]);
47 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 170 times.
+
+
+
170 if (ret < 0)
48 + goto free;
49 + }
50 +
51 + 83 return 0;
52 +
53 + free:
54 + for (size_t i = 0; i < numof_copied; ++i)
55 + free_cmd(&dest[numof_copied]);
56 +
57 + return -1;
58 + }
59 +
60 + 83static void free_cmds(struct cmd_desc *cmds, size_t numof_cmds)
61 + {
62 +
+ 2/2 +
+
✓ Branch 0 taken 170 times.
+
✓ Branch 1 taken 83 times.
+
+
+
253 for (size_t i = 0; i < numof_cmds; ++i)
63 + 170 free_cmd(&cmds[i]);
64 + 83}
65 +
66 + 83int cmd_dispatcher_create(struct cmd_dispatcher **_dispatcher, struct cmd_desc *cmds,
67 + size_t numof_cmds, void *ctx)
68 + {
69 + 83 int ret = 0;
70 +
71 + 83 struct cmd_dispatcher *dispatcher = malloc(sizeof(struct cmd_dispatcher));
72 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 83 times.
+
+
+
83 if (!dispatcher) {
73 + log_errno("malloc");
74 + return -1;
75 + }
76 +
77 + 83 dispatcher->ctx = ctx;
78 +
79 + 83 dispatcher->cmds = malloc(sizeof(struct cmd_desc) * numof_cmds);
80 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 83 times.
+
+
+
83 if (!dispatcher->cmds) {
81 + log_errno("malloc");
82 + goto free;
83 + }
84 + 83 dispatcher->numof_cmds = numof_cmds;
85 +
86 + 83 ret = copy_cmds(dispatcher->cmds, cmds, numof_cmds);
87 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 83 times.
+
+
+
83 if (ret < 0)
88 + goto free_cmds;
89 +
90 + 83 *_dispatcher = dispatcher;
91 + 83 return 0;
92 +
93 + free_cmds:
94 + free(dispatcher->cmds);
95 +
96 + free:
97 + free(dispatcher);
98 +
99 + return -1;
100 + }
101 +
102 + 83void cmd_dispatcher_destroy(struct cmd_dispatcher *dispatcher)
103 + {
104 + 83 free_cmds(dispatcher->cmds, dispatcher->numof_cmds);
105 + 83 free(dispatcher->cmds);
106 + 83 free(dispatcher);
107 + 83}
108 +
109 + 36800static int cmd_dispatcher_handle_internal(const struct cmd_dispatcher *dispatcher,
110 + const struct jsonrpc_request *request,
111 + struct jsonrpc_response **result, void *arg)
112 + {
113 + 36800 const char *actual_cmd = jsonrpc_request_get_method(request);
114 +
115 +
+ 1/2 +
+
✓ Branch 0 taken 64418 times.
+
✗ Branch 1 not taken.
+
+
+
64418 for (size_t i = 0; i < dispatcher->numof_cmds; ++i) {
116 + 64418 struct cmd_desc *cmd = &dispatcher->cmds[i];
117 +
118 +
+ 2/2 +
+
✓ Branch 0 taken 27618 times.
+
✓ Branch 1 taken 36800 times.
+
+
+
64418 if (strcmp(cmd->name, actual_cmd))
119 + 27618 continue;
120 +
121 + 36800 return cmd->handler(request, result, arg);
122 + }
123 +
124 + log_err("Received an unknown command: %s\n", actual_cmd);
125 + return -1;
126 + }
127 +
128 + int cmd_dispatcher_handle(const struct cmd_dispatcher *dispatcher,
129 + const struct jsonrpc_request *command, struct jsonrpc_response **result)
130 + {
131 + return cmd_dispatcher_handle_internal(dispatcher, command, result, dispatcher->ctx);
132 + }
133 +
134 + 36800static struct cmd_conn_ctx *make_conn_ctx(int fd, void *arg)
135 + {
136 + 36800 struct cmd_conn_ctx *ctx = malloc(sizeof(struct cmd_conn_ctx));
137 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (!ctx) {
138 + log_errno("malloc");
139 + return NULL;
140 + }
141 +
142 + 36800 ctx->fd = fd;
143 + 36800 ctx->arg = arg;
144 +
145 + 36800 return ctx;
146 + }
147 +
148 + 36800static int cmd_dispatcher_handle_conn_internal(int conn_fd, struct cmd_dispatcher *dispatcher)
149 + {
150 + 36800 int ret = 0;
151 +
152 + 36800 struct cmd_conn_ctx *new_ctx = make_conn_ctx(conn_fd, dispatcher->ctx);
153 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (!new_ctx)
154 + return -1;
155 +
156 + 36800 struct jsonrpc_request *request = NULL;
157 + 36800 ret = jsonrpc_request_recv(&request, conn_fd);
158 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
159 + goto free_ctx;
160 +
161 + 36800 const int requires_response = !jsonrpc_request_is_notification(request);
162 +
163 + 36800 struct jsonrpc_response *default_response = NULL;
164 +
+ 2/2 +
+
✓ Branch 0 taken 9206 times.
+
✓ Branch 1 taken 27594 times.
+
+
+
36800 if (requires_response) {
165 + 9206 ret = jsonrpc_response_create(&default_response, request, NULL);
166 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
167 + goto free_request;
168 + }
169 +
170 + 36800 struct jsonrpc_response *default_error = NULL;
171 +
+ 2/2 +
+
✓ Branch 0 taken 9206 times.
+
✓ Branch 1 taken 27594 times.
+
+
+
36800 if (requires_response) {
172 + 9206 ret = jsonrpc_error_create(&default_error, request, -1, "An error occured");
173 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
174 + goto free_default_response;
175 + }
176 +
177 + 36800 struct jsonrpc_response *response = NULL;
178 + 36800 ret = cmd_dispatcher_handle_internal(dispatcher, request, &response, new_ctx);
179 +
180 +
+ 2/2 +
+
✓ Branch 0 taken 9206 times.
+
✓ Branch 1 taken 27594 times.
+
+
+
36800 if (requires_response) {
181 + 9206 struct jsonrpc_response *actual_response = response;
182 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (!actual_response) {
183 + actual_response = ret < 0 ? default_error : default_response;
184 + }
185 +
+ 1/4 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
✗ Branch 3 not taken.
+
✗ Branch 4 not taken.
+
+
+
9206 if (ret < 0 && !jsonrpc_response_is_error(actual_response)) {
186 + actual_response = default_error;
187 + }
188 +
+ 1/2 +
+
✓ Branch 1 taken 9206 times.
+
✗ Branch 2 not taken.
+
+
+
9206 ret = jsonrpc_response_send(actual_response, conn_fd) < 0 ? -1 : ret;
189 + }
190 +
191 +
+ 2/2 +
+
✓ Branch 0 taken 9206 times.
+
✓ Branch 1 taken 27594 times.
+
+
+
36800 if (response)
192 + 9206 jsonrpc_response_destroy(response);
193 +
194 +
+ 2/2 +
+
✓ Branch 0 taken 27594 times.
+
✓ Branch 1 taken 9206 times.
+
+
+
36800 if (default_error)
195 + 9206 jsonrpc_response_destroy(default_error);
196 +
197 + 27594free_default_response:
198 +
+ 2/2 +
+
✓ Branch 0 taken 27594 times.
+
✓ Branch 1 taken 9206 times.
+
+
+
36800 if (default_response)
199 + 9206 jsonrpc_response_destroy(default_response);
200 +
201 + 27594free_request:
202 + 36800 jsonrpc_request_destroy(request);
203 +
204 + 36800free_ctx:
205 + 36800 free(new_ctx);
206 +
207 + 36800 return ret;
208 + }
209 +
210 + 27620int cmd_dispatcher_handle_conn(int conn_fd, void *_dispatcher)
211 + {
212 + 27620 return cmd_dispatcher_handle_conn_internal(conn_fd, (struct cmd_dispatcher *)_dispatcher);
213 + }
214 +
215 + 9180int cmd_dispatcher_handle_event(UNUSED struct event_loop *loop, int fd, short revents,
216 + void *_dispatcher)
217 + {
218 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!(revents & POLLIN)) {
219 + log_err("Descriptor %d is not readable\n", fd);
220 + return -1;
221 + }
222 +
223 + 9180 return cmd_dispatcher_handle_conn_internal(fd, (struct cmd_dispatcher *)_dispatcher);
224 + }
225 +
+
+ +
+ + + + diff --git a/coverage/index.css b/coverage/index.css new file mode 100644 index 0000000..b51dc2e --- /dev/null +++ b/coverage/index.css @@ -0,0 +1,505 @@ +:root { + font-family: sans-serif; + --unknown_color: LightGray; + --low_color: #FF6666; + --medium_color: #F9FD63; + --high_color: #85E485; + --covered_color: #85E485; + --uncovered_color: #FF8C8C; + --takenBranch_color: Green; + --notTakenBranch_color: Red; +} + +body +{ + color: #000000; + background-color: #FFFFFF; +} + +h1 +{ + text-align: center; + margin: 0; + padding-bottom: 10px; + font-size: 20pt; + font-weight: bold; +} + +hr +{ + background-color: navy; + height: 2px; + border: 0; +} + +/* Link formats: use maroon w/underlines */ +a:link +{ + color: navy; + text-decoration: underline; +} +a:visited +{ + color: maroon; + text-decoration: underline; +} + +/*** Summary formats ***/ + +.summary +{ + display: flex; + flex-flow: row wrap; + max-width: 100%; + justify-content: flex-start; +} + +.summary > table +{ + flex: 1 0 7em; + border: 0; +} + +.summary > :last-child { + margin-left: auto; +} + +table.legend +{ + color: black; + display: flex; + flex-flow: row wrap; + justify-content: flex-start; +} + +table.legend th[scope=row] +{ + font-weight: normal; + text-align: right; + white-space: nowrap; +} + +table.legend td +{ + color: blue; + text-align: left; + white-space: nowrap; + padding-left: 5px; +} + +table.legend td.legend +{ + color: black; + font-size: 80%; +} + +table.coverage td, +table.coverage th +{ + text-align: right; + color: black; + font-weight: normal; + white-space: nowrap; + padding-left: 5px; + padding-right: 4px; +} + +table.coverage td +{ + background-color: LightSteelBlue; +} + +table.coverage th[scope=row] +{ + color: black; + font-weight: normal; + white-space: nowrap; +} + +table.coverage th[scope=col] +{ + color: blue; + font-weight: normal; + white-space: nowrap; +} + +table.legend span +{ + margin-right: 4px; + padding: 2px; +} + +table.legend span.coverage-unknown, +table.legend span.coverage-none, +table.legend span.coverage-low, +table.legend span.coverage-medium, +table.legend span.coverage-high +{ + padding-left: 3px; + padding-right: 3px; +} + +table.legend span.coverage-unknown, +table.coverage td.coverage-unknown +{ + background-color: var(--unknown_color) !important; +} + +table.legend span.coverage-none, +table.legend span.coverage-low, +table.coverage td.coverage-none, +table.coverage td.coverage-low +{ + background-color: var(--low_color) !important; +} + +table.legend span.coverage-medium, +table.coverage td.coverage-medium +{ + background-color: var(--medium_color) !important; +} + +table.legend span.coverage-high, +table.coverage td.coverage-high +{ + background-color: var(--high_color) !important; +} + + +/*** End of Summary formats ***/ +/*** Meter formats ***/ + +/* Common */ +meter { + -moz-appearance: none; + + width: 30vw; + min-width: 4em; + max-width: 15em; + height: 0.75em; + padding: 0; + vertical-align: baseline; + margin-top: 3px; + /* Outer background for Mozilla */ + background: none; + background-color: whitesmoke; +} + +/* Webkit */ + +meter::-webkit-meter-bar { + /* Outer background for Webkit */ + background: none; + background-color: whitesmoke; + height: 0.75em; + border-radius: 0px; +} + +meter::-webkit-meter-optimum-value, +meter::-webkit-meter-suboptimum-value, +meter::-webkit-meter-even-less-good-value +{ + /* Inner shadow for Webkit */ + border: solid 1px black; +} + +meter.coverage-none::-webkit-meter-optimum-value, +meter.coverage-low::-webkit-meter-optimum-value +{ + background: var(--low_color); +} + +meter.coverage-medium::-webkit-meter-optimum-value +{ + background: var(--medium_color); +} + +meter.coverage-high::-webkit-meter-optimum-value +{ + background: var(--high_color); +} + +/* Mozilla */ + +meter::-moz-meter-bar +{ + box-sizing: border-box; +} + +meter:-moz-meter-optimum::-moz-meter-bar, +meter:-moz-meter-sub-optimum::-moz-meter-bar, +meter:-moz-meter-sub-sub-optimum::-moz-meter-bar +{ + /* Inner shadow for Mozilla */ + border: solid 1px black; +} + +meter.coverage-none:-moz-meter-optimum::-moz-meter-bar, +meter.coverage-low:-moz-meter-optimum::-moz-meter-bar +{ + background: var(--low_color); +} + +meter.coverage-medium:-moz-meter-optimum::-moz-meter-bar +{ + background: var(--medium_color); +} + +meter.coverage-high:-moz-meter-optimum::-moz-meter-bar +{ + background: var(--high_color); +} + +/*** End of Meter formats ***/ +.file-list td, .file-list th { + padding: 0 10px; + font-weight: bold; +} + +.file-list th[scope^=col] +{ + text-align: center; + color: white; + background-color: SteelBlue; + font-size: 120%; +} + +.file-list th[scope=row] +{ + text-align: left; + color: black; + font-family: monospace; + font-weight: bold; + font-size: 110%; +} + +.file-list tr > td, +.file-list tr > th { + background: aliceblue; +} + +.file-list tr:nth-child(even) > td, +.file-list tr:nth-child(even) > th { + background: LightSteelBlue +} + +.file-list tr:hover > td, +.file-list tr:hover > th[scope=row] +{ + background-color: #ddd; +} +td.CoverValue +{ + text-align: right; + white-space: nowrap; +} + +td.coveredLine, +span.coveredLine +{ + background-color: var(--covered_color) !important; +} + +td.uncoveredLine, +span.uncoveredLine +{ + background-color: var(--uncovered_color) !important; +} + +.linebranch, .linecount +{ + font-family: monospace; + border-right: 1px gray solid; + background-color: lightgray; + text-align: right; +} + +.linebranchDetails +{ + position: relative; +} +.linebranchSummary +{ + cursor: help; +} +.linebranchContents +{ + font-family: sans-serif; + font-size: small; + text-align: left; + position: absolute; + width: 15em; + padding: 1em; + background: white; + border: solid gray 1px; + box-shadow: 5px 5px 10px gray; + z-index: 1; /* show in front of the table entries */ +} + +.takenBranch +{ + color: var(--takenBranch_color) !important; +} + +.notTakenBranch +{ + color: var(--notTakenBranch_color) !important; +} + +.src +{ + padding-left: 12px; + text-align: left; + + font-family: monospace; + white-space: pre; + + tab-size: var(--tab_size); + -moz-tab-size: var(--tab_size); +} + +span.takenBranch, +span.notTakenBranch +{ + font-family: monospace; + font-weight: bold; +} + +pre +{ + height : 15px; + margin-top: 0; + margin-bottom: 0; +} + +.source-line +{ + height : 15px; + margin-top: 0; + margin-bottom: 0; +} + +.lineno +{ + background-color: #EFE383; + border-right: 1px solid #BBB15F; + text-align: right; + unicode-bidi: embed; + font-family: monospace; + white-space: pre; +} + +.lineno > a +{ + text-decoration: none; + color: inherit; +} + +.file-list +{ + margin: 1em auto; + border: 0; + border-spacing: 1px; +} + +.file-source table +{ + border-spacing: 0; +} + +.file-source table td, +.file-source table th +{ + padding: 1px 10px; +} + +.file-source table th +{ + font-family: monospace; + font-weight: bold; +} + +.file-source table td:last-child +{ + width: 100%; +} +footer +{ + text-align: center; + padding-top: 3px; +} + +/* pygments syntax highlighting */ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.hll { background-color: #ffffcc } +.c { color: #3D7B7B; font-style: italic } /* Comment */ +.err { border: 1px solid #FF0000 } /* Error */ +.k { color: #008000; font-weight: bold } /* Keyword */ +.o { color: #666666 } /* Operator */ +.ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ +.cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ +.cp { color: #9C6500 } /* Comment.Preproc */ +.cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ +.c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ +.cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ +.gd { color: #A00000 } /* Generic.Deleted */ +.ge { font-style: italic } /* Generic.Emph */ +.gr { color: #E40000 } /* Generic.Error */ +.gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.gi { color: #008400 } /* Generic.Inserted */ +.go { color: #717171 } /* Generic.Output */ +.gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.gs { font-weight: bold } /* Generic.Strong */ +.gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.gt { color: #0044DD } /* Generic.Traceback */ +.kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.kp { color: #008000 } /* Keyword.Pseudo */ +.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.kt { color: #B00040 } /* Keyword.Type */ +.m { color: #666666 } /* Literal.Number */ +.s { color: #BA2121 } /* Literal.String */ +.na { color: #687822 } /* Name.Attribute */ +.nb { color: #008000 } /* Name.Builtin */ +.nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.no { color: #880000 } /* Name.Constant */ +.nd { color: #AA22FF } /* Name.Decorator */ +.ni { color: #717171; font-weight: bold } /* Name.Entity */ +.ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ +.nf { color: #0000FF } /* Name.Function */ +.nl { color: #767600 } /* Name.Label */ +.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.nt { color: #008000; font-weight: bold } /* Name.Tag */ +.nv { color: #19177C } /* Name.Variable */ +.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mb { color: #666666 } /* Literal.Number.Bin */ +.mf { color: #666666 } /* Literal.Number.Float */ +.mh { color: #666666 } /* Literal.Number.Hex */ +.mi { color: #666666 } /* Literal.Number.Integer */ +.mo { color: #666666 } /* Literal.Number.Oct */ +.sa { color: #BA2121 } /* Literal.String.Affix */ +.sb { color: #BA2121 } /* Literal.String.Backtick */ +.sc { color: #BA2121 } /* Literal.String.Char */ +.dl { color: #BA2121 } /* Literal.String.Delimiter */ +.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.s2 { color: #BA2121 } /* Literal.String.Double */ +.se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ +.sh { color: #BA2121 } /* Literal.String.Heredoc */ +.si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ +.sx { color: #008000 } /* Literal.String.Other */ +.sr { color: #A45A77 } /* Literal.String.Regex */ +.s1 { color: #BA2121 } /* Literal.String.Single */ +.ss { color: #19177C } /* Literal.String.Symbol */ +.bp { color: #008000 } /* Name.Builtin.Pseudo */ +.fm { color: #0000FF } /* Name.Function.Magic */ +.vc { color: #19177C } /* Name.Variable.Class */ +.vg { color: #19177C } /* Name.Variable.Global */ +.vi { color: #19177C } /* Name.Variable.Instance */ +.vm { color: #19177C } /* Name.Variable.Magic */ +.il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/coverage/index.event_loop.c.037d09258818a0617a2d29f47e2b5064.html b/coverage/index.event_loop.c.037d09258818a0617a2d29f47e2b5064.html new file mode 100644 index 0000000..22de3df --- /dev/null +++ b/coverage/index.event_loop.c.037d09258818a0617a2d29f47e2b5064.html @@ -0,0 +1,2163 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/event_loop.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:11113184.7%
Branches:397651.3%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "event_loop.h"
9 + #include "log.h"
10 + #include "string.h"
11 +
12 + #include <poll.h>
13 + #include <stddef.h>
14 + #include <stdlib.h>
15 + #include <sys/queue.h>
16 +
17 + SIMPLEQ_HEAD(event_fd_queue, event_fd);
18 +
19 + struct event_fd {
20 + int fd;
21 + short events;
22 + event_handler handler;
23 + void *arg;
24 + int once;
25 +
26 + SIMPLEQ_ENTRY(event_fd) entries;
27 + };
28 +
29 + 36966static struct event_fd *event_fd_create(int fd, short events, event_handler handler, void *arg)
30 + {
31 + 36966 struct event_fd *res = calloc(1, sizeof(struct event_fd));
32 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36966 times.
+
+
+
36966 if (!res) {
33 + log_errno("calloc");
34 + return NULL;
35 + }
36 +
37 + 36966 res->fd = fd;
38 + 36966 res->events = events;
39 + 36966 res->handler = handler;
40 + 36966 res->arg = arg;
41 + 36966 res->once = 0;
42 +
43 + 36966 return res;
44 + }
45 +
46 + 36966static void event_fd_destroy(struct event_fd *entry)
47 + {
48 + 36966 free(entry);
49 + 36966}
50 +
51 + 83static void event_fd_queue_create(struct event_fd_queue *queue)
52 + {
53 + 83 SIMPLEQ_INIT(queue);
54 + 83}
55 +
56 + 83static void event_fd_queue_destroy(struct event_fd_queue *queue)
57 + {
58 + 83 struct event_fd *entry1 = SIMPLEQ_FIRST(queue);
59 +
+ 2/2 +
+
✓ Branch 0 taken 166 times.
+
✓ Branch 1 taken 83 times.
+
+
+
249 while (entry1) {
60 + 166 struct event_fd *entry2 = SIMPLEQ_NEXT(entry1, entries);
61 + 166 event_fd_destroy(entry1);
62 + 166 entry1 = entry2;
63 + }
64 + 83 SIMPLEQ_INIT(queue);
65 + 83}
66 +
67 + struct event_loop {
68 + nfds_t nfds;
69 + struct event_fd_queue entries;
70 + };
71 +
72 + 83int event_loop_create(struct event_loop **_loop)
73 + {
74 + 83 int ret = 0;
75 +
76 + 83 struct event_loop *loop = calloc(1, sizeof(struct event_loop));
77 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 83 times.
+
+
+
83 if (!loop) {
78 + log_errno("calloc");
79 + return -1;
80 + }
81 + 83 *_loop = loop;
82 +
83 + 83 event_fd_queue_create(&loop->entries);
84 +
85 + 83 return ret;
86 + }
87 +
88 + 83void event_loop_destroy(struct event_loop *loop)
89 + {
90 + 83 event_fd_queue_destroy(&loop->entries);
91 + 83 free(loop);
92 + 83}
93 +
94 + 36966static void event_loop_add_internal(struct event_loop *loop, struct event_fd *entry)
95 + {
96 +
+ 1/2 +
+
✓ Branch 1 taken 36966 times.
+
✗ Branch 2 not taken.
+
+
+
36966 log_debug("Adding descriptor %d to event loop\n", entry->fd);
97 +
98 + 36966 nfds_t nfds = loop->nfds + 1;
99 + 36966 SIMPLEQ_INSERT_TAIL(&loop->entries, entry, entries);
100 + 36966 loop->nfds = nfds;
101 + 36966}
102 +
103 + 112int event_loop_add(struct event_loop *loop, int fd, short events, event_handler handler, void *arg)
104 + {
105 + 112 struct event_fd *entry = event_fd_create(fd, events, handler, arg);
106 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 112 times.
+
+
+
112 if (!entry)
107 + return -1;
108 + 112 event_loop_add_internal(loop, entry);
109 + 112 return 0;
110 + }
111 +
112 + 36854int event_loop_add_once(struct event_loop *loop, int fd, short events, event_handler handler,
113 + void *arg)
114 + {
115 + 36854 struct event_fd *entry = event_fd_create(fd, events, handler, arg);
116 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36854 times.
+
+
+
36854 if (!entry)
117 + return -1;
118 + 36854 entry->once = 1;
119 + 36854 event_loop_add_internal(loop, entry);
120 + 36854 return 0;
121 + }
122 +
123 + 36800static void event_loop_remove(struct event_loop *loop, struct event_fd *entry)
124 + {
125 +
+ 1/2 +
+
✓ Branch 1 taken 36800 times.
+
✗ Branch 2 not taken.
+
+
+
36800 log_debug("Removing descriptor %d from event loop\n", entry->fd);
126 +
127 +
+ 5/8 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
✗ Branch 2 not taken.
+
✗ Branch 3 not taken.
+
✓ Branch 4 taken 48335 times.
+
✓ Branch 5 taken 36800 times.
+
✓ Branch 6 taken 25199 times.
+
✓ Branch 7 taken 11601 times.
+
+
+
85135 SIMPLEQ_REMOVE(&loop->entries, entry, event_fd, entries);
128 + 36800 event_fd_destroy(entry);
129 + 36800 --loop->nfds;
130 + 36800}
131 +
132 + 305444static char *append_event(char *buf, size_t sz, char *ptr, const char *event)
133 + {
134 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (ptr > buf)
135 + ptr = string_append(ptr, buf + sz, ",");
136 + 305444 return string_append(ptr, buf + sz, event);
137 + }
138 +
139 + 305444static char *events_to_string(short events)
140 + {
141 + 305444 const size_t sz = 128;
142 + 305444 char *buf = calloc(1, sz);
143 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (!buf)
144 + return NULL;
145 +
146 + 305444 char *ptr = buf;
147 +
148 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (events & POLLNVAL)
149 + ptr = append_event(buf, sz, ptr, "POLLNVAL");
150 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (events & POLLERR)
151 + ptr = append_event(buf, sz, ptr, "POLLERR");
152 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (events & POLLHUP)
153 + ptr = append_event(buf, sz, ptr, "POLLHUP");
154 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (events & POLLRDHUP)
155 + ptr = append_event(buf, sz, ptr, "POLLRDHUP");
156 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (events & POLLPRI)
157 + ptr = append_event(buf, sz, ptr, "POLLPRI");
158 +
+ 1/2 +
+
✓ Branch 0 taken 305444 times.
+
✗ Branch 1 not taken.
+
+
+
305444 if (events & POLLIN)
159 + 305444 ptr = append_event(buf, sz, ptr, "POLLIN");
160 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (events & POLLOUT)
161 + ptr = append_event(buf, sz, ptr, "POLLOUT");
162 +
163 + 305444 return buf;
164 + }
165 +
166 + 63268static struct pollfd *make_pollfds(const struct event_loop *loop)
167 + {
168 + 63268 struct pollfd *fds = calloc(loop->nfds, sizeof(struct pollfd));
169 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 63268 times.
+
+
+
63268 if (!fds) {
170 + log_errno("calloc");
171 + return NULL;
172 + }
173 +
174 + 63268 struct event_fd *entry = SIMPLEQ_FIRST(&loop->entries);
175 +
+ 2/2 +
+
✓ Branch 0 taken 240941 times.
+
✓ Branch 1 taken 63268 times.
+
+
+
304209 for (nfds_t i = 0; i < loop->nfds; ++i, entry = SIMPLEQ_NEXT(entry, entries)) {
176 + 240941 fds[i].fd = entry->fd;
177 + 240941 fds[i].events = entry->events;
178 + }
179 +
180 +
+ 1/2 +
+
✓ Branch 1 taken 63268 times.
+
✗ Branch 2 not taken.
+
+
+
63268 log_debug("Descriptors:\n");
181 +
+ 2/2 +
+
✓ Branch 0 taken 240941 times.
+
✓ Branch 1 taken 63268 times.
+
+
+
304209 for (nfds_t i = 0; i < loop->nfds; ++i) {
182 + 240941 char *events = events_to_string(fds[i].events);
183 +
+ 1/4 +
+
✓ Branch 1 taken 240941 times.
+
✗ Branch 2 not taken.
+
✗ Branch 3 not taken.
+
✗ Branch 4 not taken.
+
+
+
240941 log_debug(" %d (%s)\n", fds[i].fd, events ? events : "");
184 + 240941 free(events);
185 + }
186 +
187 + 63268 return fds;
188 + }
189 +
190 + 63268int event_loop_run(struct event_loop *loop)
191 + {
192 + /* Cache the number of event descriptors so that event handlers can
193 + * append new ones. */
194 + 63268 const nfds_t nfds = loop->nfds;
195 +
196 + 63268 struct pollfd *fds = make_pollfds(loop);
197 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 63268 times.
+
+
+
63268 if (!fds)
198 + return -1;
199 +
200 + 63268 int ret = poll(fds, nfds, -1);
201 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 63268 times.
+
+
+
63268 if (ret < 0) {
202 + log_errno("poll");
203 + return ret;
204 + }
205 + 63268 ret = 0;
206 +
207 + 63268 struct event_fd *entry = SIMPLEQ_FIRST(&loop->entries);
208 +
+ 2/2 +
+
✓ Branch 0 taken 240941 times.
+
✓ Branch 1 taken 63268 times.
+
+
+
304209 for (nfds_t i = 0; i < nfds; ++i) {
209 + 240941 struct event_fd *next = SIMPLEQ_NEXT(entry, entries);
210 +
211 +
+ 2/2 +
+
✓ Branch 0 taken 176438 times.
+
✓ Branch 1 taken 64503 times.
+
+
+
240941 if (!fds[i].revents)
212 + 176438 goto next;
213 +
214 + 64503 char *events = events_to_string(fds[i].revents);
215 +
+ 1/4 +
+
✓ Branch 1 taken 64503 times.
+
✗ Branch 2 not taken.
+
✗ Branch 3 not taken.
+
✗ Branch 4 not taken.
+
+
+
64503 log_debug("Descriptor %d is ready: %s\n", fds[i].fd, events ? events : "");
216 + 64503 free(events);
217 +
218 + /* Execute all handlers but notice if any of them fail. */
219 + 64503 const int handler_ret = entry->handler(loop, fds[i].fd, fds[i].revents, entry->arg);
220 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 64503 times.
+
+
+
64503 if (handler_ret < 0)
221 + ret = handler_ret;
222 +
223 +
+ 2/2 +
+
✓ Branch 0 taken 27703 times.
+
✓ Branch 1 taken 36800 times.
+
+
+
64503 if (entry->once)
224 + 36800 event_loop_remove(loop, entry);
225 +
226 + 27703 next:
227 + 240941 entry = next;
228 + 240941 continue;
229 + }
230 +
231 + 63268 free(fds);
232 + 63268 return ret;
233 + }
234 +
+
+ +
+ + + + diff --git a/coverage/index.file.c.0cc24881e570d19e625204519d50254f.html b/coverage/index.file.c.0cc24881e570d19e625204519d50254f.html new file mode 100644 index 0000000..3a3f228 --- /dev/null +++ b/coverage/index.file.c.0cc24881e570d19e625204519d50254f.html @@ -0,0 +1,1491 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/file.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:568466.7%
Branches:205238.5%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "file.h"
9 + #include "compiler.h"
10 + #include "log.h"
11 +
12 + #include <fcntl.h>
13 + #include <ftw.h>
14 + #include <stdio.h>
15 + #include <stdlib.h>
16 + #include <sys/stat.h>
17 + #include <unistd.h>
18 +
19 + 403638static int unlink_cb(const char *fpath, UNUSED const struct stat *sb, UNUSED int typeflag,
20 + UNUSED struct FTW *ftwbuf)
21 + {
22 + 403638 int ret = 0;
23 +
24 + 403638 ret = remove(fpath);
25 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 403638 times.
+
+
+
403638 if (ret < 0) {
26 + log_errno("remove");
27 + return ret;
28 + }
29 +
30 + 403638 return ret;
31 + }
32 +
33 + 9180int rm_rf(const char *dir)
34 + {
35 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Recursively removing directory: %s\n", dir);
36 + 9180 return nftw(dir, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
37 + }
38 +
39 + 18360int my_chdir(const char *dir, char **old)
40 + {
41 + 18360 int ret = 0;
42 +
43 +
+ 2/2 +
+
✓ Branch 0 taken 9180 times.
+
✓ Branch 1 taken 9180 times.
+
+
+
18360 if (old) {
44 + 9180 *old = get_current_dir_name();
45 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!*old) {
46 + log_errno("get_current_dir_name");
47 + return -1;
48 + }
49 + }
50 +
51 + 18360 ret = chdir(dir);
52 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18360 times.
+
+
+
18360 if (ret < 0) {
53 + log_errno("chdir");
54 + goto free_old;
55 + }
56 +
57 + 18360 return ret;
58 +
59 + free_old:
60 + if (old)
61 + free(*old);
62 +
63 + return ret;
64 + }
65 +
66 + 20char *my_readlink(const char *path)
67 + {
68 + 20 size_t current_size = 256;
69 + 20 char *buf = NULL;
70 +
71 + while (1) {
72 + 20 char *tmp_buf = realloc(buf, current_size);
73 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 20 times.
+
+
+
20 if (!tmp_buf) {
74 + log_errno("realloc");
75 + goto free;
76 + }
77 + 20 buf = tmp_buf;
78 +
79 + 20 ssize_t res = readlink(path, buf, current_size);
80 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 20 times.
+
+
+
20 if (res < 0) {
81 + log_errno("readlink");
82 + goto free;
83 + }
84 +
85 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 20 times.
+
+
+
20 if ((size_t)res == current_size) {
86 + current_size *= 2;
87 + continue;
88 + }
89 +
90 + 20 buf[res] = '\0';
91 + 20 break;
92 + }
93 +
94 + 20 return buf;
95 +
96 + free:
97 + free(buf);
98 +
99 + return NULL;
100 + }
101 +
102 + 9234int file_dup(int fd)
103 + {
104 + 9234 int ret = 0;
105 +
106 + 9234 ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
107 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0) {
108 + log_errno("fcntl");
109 + return ret;
110 + }
111 +
112 + 9234 return ret;
113 + }
114 +
115 + 110566void file_close(int fd)
116 + {
117 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 110566 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
110566 log_errno_if(close(fd), "close");
118 + 110566}
119 +
120 + 36720int file_exists(const char *path)
121 + {
122 + struct stat stat;
123 + 36720 int ret = lstat(path, &stat);
124 +
+ 3/4 +
+
✓ Branch 0 taken 9180 times.
+
✓ Branch 1 taken 27540 times.
+
✓ Branch 2 taken 9180 times.
+
✗ Branch 3 not taken.
+
+
+
36720 return !ret && S_ISREG(stat.st_mode);
125 + }
126 +
127 + 9180int file_read(int fd, unsigned char **_contents, size_t *_size)
128 + {
129 + 9180 size_t alloc_size = 256;
130 + 9180 unsigned char *contents = NULL;
131 + 9180 size_t size = 0;
132 +
133 + 261952 while (1) {
134 + 271132 unsigned char *tmp_contents = realloc(contents, alloc_size);
135 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 271132 times.
+
+
+
271132 if (!tmp_contents) {
136 + log_errno("realloc");
137 + free(contents);
138 + return -1;
139 + }
140 + 271132 contents = tmp_contents;
141 +
142 + 271132 ssize_t read_size = read(fd, contents + size, alloc_size - size);
143 +
144 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 271132 times.
+
+
+
271132 if (read_size < 0) {
145 + log_errno("read");
146 + free(contents);
147 + return read_size;
148 + }
149 +
150 +
+ 2/2 +
+
✓ Branch 0 taken 9180 times.
+
✓ Branch 1 taken 261952 times.
+
+
+
271132 if (!read_size) {
151 + 9180 *_contents = contents;
152 + 9180 *_size = size;
153 + 9180 return 0;
154 + }
155 +
156 + 261952 size += read_size;
157 +
158 +
+ 2/2 +
+
✓ Branch 0 taken 49896 times.
+
✓ Branch 1 taken 212056 times.
+
+
+
261952 if (size == alloc_size) {
159 + 49896 alloc_size *= 2;
160 + }
161 + }
162 + }
163 +
+
+ +
+ + + + diff --git a/coverage/index.git.c.ecafe65200a95f92fc10a3095d9e5f09.html b/coverage/index.git.c.ecafe65200a95f92fc10a3095d9e5f09.html new file mode 100644 index 0000000..a82cde7 --- /dev/null +++ b/coverage/index.git.c.ecafe65200a95f92fc10a3095d9e5f09.html @@ -0,0 +1,1092 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/git.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:395570.9%
Branches:106415.6%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "git.h"
9 + #include "log.h"
10 +
11 + #include <git2.h>
12 +
13 + #include <stdlib.h>
14 +
15 + #define git_log_err(fn) \
16 + do { \
17 + const git_error *error = git_error_last(); \
18 + const char *msg = error && error->message ? error->message : "???"; \
19 + log_err("%s: %s\n", fn, msg); \
20 + } while (0)
21 +
22 + 54int libgit_init(void)
23 + {
24 + 54 int ret = 0;
25 +
26 + 54 ret = git_libgit2_init();
27 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0) {
28 + git_log_err("git_libgit2_init");
29 + return ret;
30 + }
31 +
32 + 54 return 0;
33 + }
34 +
35 + 54void libgit_shutdown(void)
36 + {
37 + 54 git_libgit2_shutdown();
38 + 54}
39 +
40 + 9180int libgit_clone(git_repository **repo, const char *url, const char *dir)
41 + {
42 + git_clone_options opts;
43 + 9180 int ret = 0;
44 +
45 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Cloning git repository from %s to %s\n", url, dir);
46 +
47 + 9180 ret = git_clone_options_init(&opts, GIT_CLONE_OPTIONS_VERSION);
48 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
49 + git_log_err("git_clone_options_init");
50 + return ret;
51 + }
52 + 9180 opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
53 +
54 + 9180 ret = git_clone(repo, url, dir, &opts);
55 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
56 + git_log_err("git_clone");
57 + return ret;
58 + }
59 +
60 + 9180 return 0;
61 + }
62 +
63 + 9180int libgit_clone_to_tmp(git_repository **repo, const char *url)
64 + {
65 + 9180 char dir[] = "/tmp/git.XXXXXX";
66 +
67 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 if (!mkdtemp(dir)) {
68 + log_errno("mkdtemp");
69 + return -1;
70 + }
71 +
72 + 9180 return libgit_clone(repo, url, dir);
73 + }
74 +
75 + 9180void libgit_repository_free(git_repository *repo)
76 + {
77 + 9180 git_repository_free(repo);
78 + 9180}
79 +
80 + 9180int libgit_checkout(git_repository *repo, const char *rev)
81 + {
82 + git_checkout_options opts;
83 + git_object *obj;
84 + 9180 int ret = 0;
85 +
86 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Checking out revision %s\n", rev);
87 +
88 + 9180 ret = git_revparse_single(&obj, repo, rev);
89 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
90 + git_log_err("git_revparse_single");
91 + return ret;
92 + }
93 +
94 + 9180 ret = git_checkout_options_init(&opts, GIT_CHECKOUT_OPTIONS_VERSION);
95 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
96 + git_log_err("git_checkout_options_init");
97 + goto free_obj;
98 + }
99 + 9180 opts.checkout_strategy = GIT_CHECKOUT_FORCE;
100 +
101 + 9180 ret = git_checkout_tree(repo, obj, &opts);
102 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
103 + git_log_err("git_checkout_tree");
104 + goto free_obj;
105 + }
106 +
107 + 9180 ret = git_repository_set_head_detached(repo, git_object_id(obj));
108 +
+ 1/2 +
+
✓ Branch 0 taken 9180 times.
+
✗ Branch 1 not taken.
+
+
+
9180 if (ret < 0) {
109 + git_log_err("git_repository_set_head_detached");
110 + goto free_obj;
111 + }
112 +
113 + 9180free_obj:
114 + 9180 git_object_free(obj);
115 +
116 + 9180 return ret;
117 + }
118 +
+
+ +
+ + + + diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 0000000..e252ffb --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,475 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
Date:2024-04-25 03:45:42
Legend: + low: >= 0% + medium: >= 75.0% + high: >= 90.0% +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:2020284171.1%
Branches:560140939.7%
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileLinesBranches
+ base64.c + + 66.7 + 66.7%18 / 2725.0%3 / 12
+ buf.c + + 88.9 + 88.9%16 / 1825.0%1 / 4
+ ci.c + + 78.7 + 78.7%37 / 4750.0%9 / 18
+ client.c + + 80.6 + 80.6%50 / 6256.7%17 / 30
+ client_main.c + + 79.1 + 79.1%34 / 4371.4%10 / 14
+ cmd_line.c + + 90.3 + 90.3%28 / 3150.0%7 / 14
+ command.c + + 74.2 + 74.2%89 / 12050.0%33 / 66
+ event_loop.c + + 84.7 + 84.7%111 / 13151.3%39 / 76
+ file.c + + 66.7 + 66.7%56 / 8438.5%20 / 52
+ git.c + + 70.9 + 70.9%39 / 5515.6%10 / 64
+ json.c + + 73.2 + 73.2%112 / 15331.4%22 / 70
+ json_rpc.c + + 65.7 + 65.7%201 / 30639.7%58 / 146
+ log.c + + 91.7 + 91.7%22 / 2466.7%4 / 6
+ net.c + + 62.6 + 62.6%87 / 13932.6%30 / 92
+ process.c + + 48.8 + 48.8%41 / 8423.1%12 / 52
+ protocol.c + + 68.7 + 68.7%90 / 13150.0%24 / 48
+ run_queue.c + + 73.6 + 73.6%81 / 11047.2%17 / 36
+ server.c + + 71.7 + 71.7%195 / 27241.8%61 / 146
+ server_main.c + + 79.1 + 79.1%34 / 4371.4%10 / 14
+ signal.c + + 81.6 + 81.6%31 / 3850.0%5 / 10
+ sqlite.c + + 62.3 + 62.3%101 / 16222.1%21 / 95
+ storage.c + + 75.5 + 75.5%37 / 4945.0%9 / 20
+ storage_sqlite.c + + 72.5 + 72.5%245 / 33842.3%66 / 156
+ string.c + + 27.3 + 27.3%6 / 2218.8%3 / 16
+ tcp_server.c + + 71.3 + 71.3%87 / 12240.9%27 / 66
+ worker.c + + 70.2 + 70.2%106 / 15143.5%27 / 62
+ worker_main.c + + 79.1 + 79.1%34 / 4371.4%10 / 14
+ worker_queue.c + + 88.9 + 88.9%32 / 3650.0%5 / 10
+ +
+ + + + diff --git a/coverage/index.json.c.9fe0913c76249e448eec3131d7e8b263.html b/coverage/index.json.c.9fe0913c76249e448eec3131d7e8b263.html new file mode 100644 index 0000000..2f4c69d --- /dev/null +++ b/coverage/index.json.c.9fe0913c76249e448eec3131d7e8b263.html @@ -0,0 +1,2632 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/json.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:11215373.2%
Branches:227031.4%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "json.h"
9 + #include "buf.h"
10 + #include "log.h"
11 + #include "net.h"
12 +
13 + #include <json-c/json_object.h>
14 + #include <json-c/json_tokener.h>
15 +
16 + #include <errno.h>
17 + #include <stdint.h>
18 + #include <stdlib.h>
19 + #include <string.h>
20 +
21 + #define libjson_errno(fn) \
22 + do { \
23 + log_err("JSON: %s failed\n", fn); \
24 + } while (0)
25 +
26 + 110424void libjson_free(struct json_object *obj)
27 + {
28 + 110424 json_object_put(obj);
29 + 110424}
30 +
31 + 55212static const char *libjson_to_string_internal(struct json_object *obj, int flags)
32 + {
33 + 55212 const char *result = json_object_to_json_string_ext(obj, flags);
34 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 55212 times.
+
+
+
55212 if (!result) {
35 + libjson_errno("json_object_to_json_string");
36 + return NULL;
37 + }
38 + 55212 return result;
39 + }
40 +
41 + 46006const char *libjson_to_string(struct json_object *obj)
42 + {
43 + 46006 return libjson_to_string_internal(obj, JSON_C_TO_STRING_SPACED);
44 + }
45 +
46 + 9206const char *libjson_to_string_pretty(struct json_object *obj)
47 + {
48 + 9206 return libjson_to_string_internal(obj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
49 + }
50 +
51 + 46006struct json_object *libjson_from_string(const char *src)
52 + {
53 + enum json_tokener_error error;
54 +
55 + 46006 struct json_object *result = json_tokener_parse_verbose(src, &error);
56 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (!result) {
57 + libjson_errno("json_tokener_parse_verbose");
58 + log_err("JSON: parsing failed: %s\n", json_tokener_error_desc(error));
59 + return NULL;
60 + }
61 +
62 + 46006 return result;
63 + }
64 +
65 + 27618int libjson_clone(const struct json_object *obj, const char *key, struct json_object **_value)
66 + {
67 + 27618 int ret = 0;
68 +
69 + 27618 struct json_object *old_value = NULL;
70 + 27618 ret = libjson_get(obj, key, &old_value);
71 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (ret < 0)
72 + return ret;
73 +
74 + 27618 struct json_object *new_value = NULL;
75 + 27618 ret = json_object_deep_copy(old_value, &new_value, NULL);
76 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (ret < 0)
77 + return ret;
78 +
79 + 27618 *_value = new_value;
80 + 27618 return ret;
81 + }
82 +
83 + 46006int libjson_send(struct json_object *obj, int fd)
84 + {
85 + 46006 int ret = 0;
86 +
87 + 46006 const char *str = libjson_to_string(obj);
88 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (!str)
89 + return -1;
90 +
91 + 46006 struct buf *buf = NULL;
92 + 46006 ret = buf_create_from_string(&buf, str);
93 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0)
94 + return ret;
95 +
96 + 46006 ret = net_send_buf(fd, buf);
97 + 46006 buf_destroy(buf);
98 + 46006 return ret;
99 + }
100 +
101 + 46006struct json_object *libjson_recv(int fd)
102 + {
103 + 46006 struct json_object *result = NULL;
104 + 46006 int ret = 0;
105 +
106 + 46006 struct buf *buf = NULL;
107 + 46006 ret = net_recv_buf(fd, &buf);
108 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0)
109 + return NULL;
110 +
111 + 46006 result = libjson_from_string((const char *)buf_get_data(buf));
112 +
+ 1/2 +
+
✓ Branch 0 taken 46006 times.
+
✗ Branch 1 not taken.
+
+
+
46006 if (!result)
113 + goto destroy_buf;
114 +
115 + 46006destroy_buf:
116 + 46006 free((void *)buf_get_data(buf));
117 + 46006 buf_destroy(buf);
118 +
119 + 46006 return result;
120 + }
121 +
122 + 110344int libjson_new_object(struct json_object **_obj)
123 + {
124 + 110344 struct json_object *obj = json_object_new_object();
125 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 110344 times.
+
+
+
110344 if (!obj) {
126 + libjson_errno("json_object_new_object");
127 + return -1;
128 + }
129 + 110344 *_obj = obj;
130 + 110344 return 0;
131 + }
132 +
133 + 26int libjson_new_array(struct json_object **_arr)
134 + {
135 + 26 struct json_object *arr = json_object_new_array();
136 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (!arr) {
137 + libjson_errno("json_object_new_array");
138 + return -1;
139 + }
140 + 26 *_arr = arr;
141 + 26 return 0;
142 + }
143 +
144 + 606620int libjson_has(const struct json_object *obj, const char *key)
145 + {
146 + 606620 return json_object_object_get_ex(obj, key, NULL);
147 + }
148 +
149 + 385956int libjson_get(const struct json_object *obj, const char *key, struct json_object **value)
150 + {
151 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 385956 times.
+
+
+
385956 if (!libjson_has(obj, key)) {
152 + log_err("JSON: key is missing: %s\n", key);
153 + return -1;
154 + }
155 +
156 + 385956 return json_object_object_get_ex(obj, key, value);
157 + }
158 +
159 + 165506int libjson_get_string(const struct json_object *obj, const char *key, const char **_value)
160 + {
161 + 165506 struct json_object *value = NULL;
162 +
163 + 165506 int ret = libjson_get(obj, key, &value);
164 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 165506 times.
+
+
+
165506 if (ret < 0)
165 + return ret;
166 +
167 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 165506 times.
+
+
+
165506 if (!json_object_is_type(value, json_type_string)) {
168 + log_err("JSON: key is not a string: %s\n", key);
169 + return -1;
170 + }
171 +
172 + 165506 *_value = json_object_get_string(value);
173 + 165506 return 0;
174 + }
175 +
176 + 27540int libjson_get_int(const struct json_object *obj, const char *key, int64_t *_value)
177 + {
178 + 27540 struct json_object *value = NULL;
179 +
180 + 27540 int ret = libjson_get(obj, key, &value);
181 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (ret < 0)
182 + return ret;
183 +
184 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 27540 times.
+
+
+
27540 if (!json_object_is_type(value, json_type_int)) {
185 + log_err("JSON: key is not an integer: %s\n", key);
186 + return -1;
187 + }
188 +
189 + 27540 errno = 0;
190 + 27540 int64_t tmp = json_object_get_int64(value);
191 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (errno) {
192 + log_err("JSON: failed to parse integer from key: %s\n", key);
193 + return -1;
194 + }
195 +
196 + 27540 *_value = tmp;
197 + 27540 return 0;
198 + }
199 +
200 + 321772static int libjson_set_internal(struct json_object *obj, const char *key, struct json_object *value,
201 + unsigned flags)
202 + {
203 + 321772 int ret = 0;
204 +
205 + 321772 ret = json_object_object_add_ex(obj, key, value, flags);
206 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 321772 times.
+
+
+
321772 if (ret < 0) {
207 + libjson_errno("json_object_object_add_ex");
208 + return ret;
209 + }
210 +
211 + 321772 return 0;
212 + }
213 +
214 + 174684static int libjson_set_string_internal(struct json_object *obj, const char *key, const char *_value,
215 + unsigned flags)
216 + {
217 + 174684 struct json_object *value = json_object_new_string(_value);
218 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 174684 times.
+
+
+
174684 if (!value) {
219 + libjson_errno("json_object_new_string");
220 + return -1;
221 + }
222 +
223 + 174684 int ret = libjson_set_internal(obj, key, value, flags);
224 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 174684 times.
+
+
+
174684 if (ret < 0)
225 + goto free_value;
226 +
227 + 174684 return ret;
228 +
229 + free_value:
230 + json_object_put(value);
231 +
232 + return ret;
233 + }
234 +
235 + 64312static int libjson_set_int_internal(struct json_object *obj, const char *key, int64_t _value,
236 + unsigned flags)
237 + {
238 + 64312 struct json_object *value = json_object_new_int64(_value);
239 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 64312 times.
+
+
+
64312 if (!value) {
240 + libjson_errno("json_object_new_int");
241 + return -1;
242 + }
243 +
244 + 64312 int ret = libjson_set_internal(obj, key, value, flags);
245 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 64312 times.
+
+
+
64312 if (ret < 0)
246 + goto free_value;
247 +
248 + 64312 return ret;
249 +
250 + free_value:
251 + json_object_put(value);
252 +
253 + return ret;
254 + }
255 +
256 + 55158int libjson_set(struct json_object *obj, const char *key, struct json_object *value)
257 + {
258 + 55158 return libjson_set_internal(obj, key, value, 0);
259 + }
260 +
261 + 45900int libjson_set_string(struct json_object *obj, const char *key, const char *value)
262 + {
263 + 45900 return libjson_set_string_internal(obj, key, value, 0);
264 + }
265 +
266 + 27540int libjson_set_int(struct json_object *obj, const char *key, int64_t value)
267 + {
268 + 27540 return libjson_set_int_internal(obj, key, value, 0);
269 + }
270 +
271 + #ifndef JSON_C_OBJECT_ADD_CONSTANT_KEY
272 + #define JSON_C_OBJECT_ADD_CONSTANT_KEY JSON_C_OBJECT_KEY_IS_CONSTANT
273 + #endif
274 + static const unsigned json_const_key_flags = JSON_C_OBJECT_ADD_CONSTANT_KEY;
275 +
276 + 27618int libjson_set_const_key(struct json_object *obj, const char *key, struct json_object *value)
277 + {
278 + 27618 return libjson_set_internal(obj, key, value, json_const_key_flags);
279 + }
280 +
281 + 128784int libjson_set_string_const_key(struct json_object *obj, const char *key, const char *value)
282 + {
283 + 128784 return libjson_set_string_internal(obj, key, value, json_const_key_flags);
284 + }
285 +
286 + 36772int libjson_set_int_const_key(struct json_object *obj, const char *key, int64_t value)
287 + {
288 + 36772 return libjson_set_int_internal(obj, key, value, json_const_key_flags);
289 + }
290 +
291 + 9180int libjson_append(struct json_object *arr, struct json_object *elem)
292 + {
293 + 9180 int ret = json_object_array_add(arr, elem);
294 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
295 + libjson_errno("json_object_array_add");
296 + return ret;
297 + }
298 + 9180 return ret;
299 + }
300 +
+
+ +
+ + + + diff --git a/coverage/index.json_rpc.c.2aeccc6679171fb423f72eef95ec01c0.html b/coverage/index.json_rpc.c.2aeccc6679171fb423f72eef95ec01c0.html new file mode 100644 index 0000000..dc75407 --- /dev/null +++ b/coverage/index.json_rpc.c.2aeccc6679171fb423f72eef95ec01c0.html @@ -0,0 +1,4816 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/json_rpc.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:20130665.7%
Branches:5814639.7%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "json_rpc.h"
9 + #include "json.h"
10 + #include "log.h"
11 +
12 + #include <json-c/json_object.h>
13 +
14 + #include <stdatomic.h>
15 + #include <stdint.h>
16 + #include <stdlib.h>
17 + #include <string.h>
18 +
19 + struct jsonrpc_request {
20 + struct json_object *impl;
21 + };
22 +
23 + struct jsonrpc_response {
24 + struct json_object *impl;
25 + };
26 +
27 + static const char *const jsonrpc_key_version = "jsonrpc";
28 + static const char *const jsonrpc_key_id = "id";
29 + static const char *const jsonrpc_key_method = "method";
30 + static const char *const jsonrpc_key_params = "params";
31 +
32 + static const char *const jsonrpc_value_version = "2.0";
33 +
34 + 46006static int jsonrpc_check_version(struct json_object *obj)
35 + {
36 + 46006 const char *key = jsonrpc_key_version;
37 + 46006 const char *version = NULL;
38 +
39 + 46006 int ret = libjson_get_string(obj, key, &version);
40 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0)
41 + return ret;
42 +
43 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (strcmp(version, jsonrpc_value_version)) {
44 + log_err("JSON-RPC: invalid '%s' value: %s\n", key, version);
45 + return -1;
46 + }
47 +
48 + 46006 return 0;
49 + }
50 +
51 + 64418static int jsonrpc_set_version(struct json_object *obj)
52 + {
53 + 64418 return libjson_set_string_const_key(obj, jsonrpc_key_version, jsonrpc_value_version);
54 + }
55 +
56 + static _Atomic int jsonrpc_id_counter = 1;
57 +
58 + 9206int jsonrpc_generate_request_id(void)
59 + {
60 + 9206 return jsonrpc_id_counter++;
61 + }
62 +
63 + 18412static int jsonrpc_check_id_type(struct json_object *id)
64 + {
65 +
+ 2/4 +
+
✓ Branch 1 taken 18412 times.
+
✗ Branch 2 not taken.
+
✗ Branch 4 not taken.
+
✓ Branch 5 taken 18412 times.
+
+
+
18412 if (!json_object_is_type(id, json_type_string) && !json_object_is_type(id, json_type_int)) {
66 + log_err("JSON-RPC: key '%s' must be either an integer or a string\n",
67 + jsonrpc_key_id);
68 + return -1;
69 + }
70 + 18412 return 0;
71 + }
72 +
73 + 46006static int jsonrpc_check_id(struct json_object *obj, int required)
74 + {
75 + 46006 const char *key = jsonrpc_key_id;
76 +
77 +
+ 2/2 +
+
✓ Branch 1 taken 27594 times.
+
✓ Branch 2 taken 18412 times.
+
+
+
46006 if (!libjson_has(obj, key)) {
78 +
+ 1/2 +
+
✓ Branch 0 taken 27594 times.
+
✗ Branch 1 not taken.
+
+
+
27594 if (!required)
79 + 27594 return 0;
80 + log_err("JSON-RPC: key is missing: %s\n", key);
81 + return -1;
82 + }
83 +
84 + 18412 struct json_object *id = NULL;
85 +
86 + 18412 int ret = libjson_get(obj, key, &id);
87 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18412 times.
+
+
+
18412 if (ret < 0)
88 + return ret;
89 + 18412 return jsonrpc_check_id_type(id);
90 + }
91 +
92 + 9206static int jsonrpc_set_id(struct json_object *obj, int id)
93 + {
94 + 9206 return libjson_set_int_const_key(obj, jsonrpc_key_id, id);
95 + }
96 +
97 + 36800static int jsonrpc_check_method(struct json_object *obj)
98 + {
99 + 36800 const char *key = jsonrpc_key_method;
100 + 36800 const char *method = NULL;
101 + 36800 return libjson_get_string(obj, key, &method);
102 + }
103 +
104 + 36800static int jsonrpc_set_method(struct json_object *obj, const char *method)
105 + {
106 + 36800 return libjson_set_string_const_key(obj, jsonrpc_key_method, method);
107 + }
108 +
109 + 27540static int jsonrpc_check_params_type(struct json_object *params)
110 + {
111 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 27540 times.
+
✗ Branch 3 not taken.
+
✗ Branch 4 not taken.
+
+
+
27540 if (!json_object_is_type(params, json_type_object) &&
112 + !json_object_is_type(params, json_type_array)) {
113 + log_err("JSON-RPC: key '%s' must be either an object or an array\n",
114 + jsonrpc_key_params);
115 + return -1;
116 + }
117 + 27540 return 0;
118 + }
119 +
120 + 36800static int jsonrpc_check_params(struct json_object *obj)
121 + {
122 + 36800 const char *key = jsonrpc_key_params;
123 +
124 +
+ 2/2 +
+
✓ Branch 1 taken 9260 times.
+
✓ Branch 2 taken 27540 times.
+
+
+
36800 if (!libjson_has(obj, key))
125 + 9260 return 0;
126 +
127 + 27540 struct json_object *params = NULL;
128 +
129 + 27540 int ret = libjson_get(obj, key, &params);
130 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (ret < 0)
131 + return ret;
132 + 27540 return jsonrpc_check_params_type(params);
133 + }
134 +
135 + static int jsonrpc_set_params(struct json_object *obj, struct json_object *params)
136 + {
137 + const char *key = jsonrpc_key_params;
138 +
139 + int ret = jsonrpc_check_params_type(params);
140 + if (ret < 0)
141 + return ret;
142 + return libjson_set_const_key(obj, key, params);
143 + }
144 +
145 + static const char *const jsonrpc_key_result = "result";
146 + static const char *const jsonrpc_key_error = "error";
147 +
148 + static const char *const jsonrpc_key_code = "code";
149 + static const char *const jsonrpc_key_message = "message";
150 +
151 + static int jsonrpc_check_error(struct json_object *obj)
152 + {
153 + const char *key = jsonrpc_key_error;
154 + struct json_object *error = NULL;
155 +
156 + int ret = libjson_get(obj, key, &error);
157 + if (ret < 0)
158 + return ret;
159 +
160 + int64_t code = -1;
161 +
162 + ret = libjson_get_int(error, jsonrpc_key_code, &code);
163 + if (ret < 0) {
164 + log_err("JSON-RPC: key is missing or not an integer: %s\n", jsonrpc_key_code);
165 + return -1;
166 + }
167 +
168 + const char *message = NULL;
169 +
170 + ret = libjson_get_string(error, jsonrpc_key_message, &message);
171 + if (ret < 0) {
172 + log_err("JSON-RPC: key is missing or not a string: %s\n", jsonrpc_key_message);
173 + return -1;
174 + }
175 +
176 + return ret;
177 + }
178 +
179 + 9206static int jsonrpc_check_result_or_error(struct json_object *obj)
180 + {
181 + 9206 const char *key_result = jsonrpc_key_result;
182 + 9206 const char *key_error = jsonrpc_key_error;
183 +
184 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9206 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
9206 if (!libjson_has(obj, key_result) && !libjson_has(obj, key_error)) {
185 + log_err("JSON-RPC: either '%s' or '%s' must be present\n", key_result, key_error);
186 + return -1;
187 + }
188 +
189 +
+ 1/2 +
+
✓ Branch 1 taken 9206 times.
+
✗ Branch 2 not taken.
+
+
+
9206 if (libjson_has(obj, key_result))
190 + 9206 return 0;
191 +
192 + return jsonrpc_check_error(obj);
193 + }
194 +
195 + 36800static int jsonrpc_request_create_internal(struct jsonrpc_request **_request, int *id,
196 + const char *method, struct json_object *params)
197 + {
198 + 36800 int ret = 0;
199 +
200 + 36800 struct jsonrpc_request *request = malloc(sizeof(struct jsonrpc_request));
201 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (!request) {
202 + log_errno("malloc");
203 + ret = -1;
204 + goto exit;
205 + }
206 +
207 + 36800 ret = libjson_new_object(&request->impl);
208 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
209 + goto free;
210 +
211 + 36800 ret = jsonrpc_set_version(request->impl);
212 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
213 + goto free_impl;
214 +
215 +
+ 2/2 +
+
✓ Branch 0 taken 9206 times.
+
✓ Branch 1 taken 27594 times.
+
+
+
36800 if (id) {
216 + 9206 ret = jsonrpc_set_id(request->impl, *id);
217 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
218 + goto free_impl;
219 + }
220 +
221 + 36800 ret = jsonrpc_set_method(request->impl, method);
222 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
223 + goto free_impl;
224 +
225 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (params) {
226 + ret = jsonrpc_set_params(request->impl, params);
227 + if (ret < 0)
228 + goto free_impl;
229 + }
230 +
231 + 36800 *_request = request;
232 + 36800 goto exit;
233 +
234 + free_impl:
235 + libjson_free(request->impl);
236 + free:
237 + free(request);
238 + 36800exit:
239 + 36800 return ret;
240 + }
241 +
242 + 9206int jsonrpc_request_create(struct jsonrpc_request **_request, int id, const char *method,
243 + struct json_object *params)
244 + {
245 + 9206 return jsonrpc_request_create_internal(_request, &id, method, params);
246 + }
247 +
248 + 73600void jsonrpc_request_destroy(struct jsonrpc_request *request)
249 + {
250 + 73600 libjson_free(request->impl);
251 + 73600 free(request);
252 + 73600}
253 +
254 + 27594int jsonrpc_notification_create(struct jsonrpc_request **_request, const char *method,
255 + struct json_object *params)
256 + {
257 + 27594 return jsonrpc_request_create_internal(_request, NULL, method, params);
258 + }
259 +
260 + 36800int jsonrpc_request_is_notification(const struct jsonrpc_request *request)
261 + {
262 + 36800 return !libjson_has(request->impl, jsonrpc_key_id);
263 + }
264 +
265 + 36800static int jsonrpc_request_from_json(struct jsonrpc_request **_request, struct json_object *impl)
266 + {
267 + 36800 int ret = 0;
268 +
269 + 36800 ret = jsonrpc_check_version(impl);
270 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
271 + return ret;
272 + 36800 ret = jsonrpc_check_id(impl, 0);
273 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
274 + return ret;
275 + 36800 ret = jsonrpc_check_method(impl);
276 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
277 + return ret;
278 + 36800 ret = jsonrpc_check_params(impl);
279 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
280 + return ret;
281 +
282 + 36800 struct jsonrpc_request *request = malloc(sizeof(struct jsonrpc_request));
283 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (!request) {
284 + log_errno("malloc");
285 + return -1;
286 + }
287 + 36800 request->impl = impl;
288 +
289 + 36800 *_request = request;
290 + 36800 return ret;
291 + }
292 +
293 + 36800int jsonrpc_request_send(const struct jsonrpc_request *request, int fd)
294 + {
295 + 36800 return libjson_send(request->impl, fd);
296 + }
297 +
298 + 36800int jsonrpc_request_recv(struct jsonrpc_request **request, int fd)
299 + {
300 + 36800 struct json_object *impl = libjson_recv(fd);
301 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (!impl) {
302 + log_err("JSON-RPC: failed to receive request\n");
303 + return -1;
304 + }
305 +
306 + 36800 int ret = jsonrpc_request_from_json(request, impl);
307 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0)
308 + goto free_impl;
309 +
310 + 36800 return ret;
311 +
312 + free_impl:
313 + libjson_free(impl);
314 +
315 + return ret;
316 + }
317 +
318 + 36800const char *jsonrpc_request_get_method(const struct jsonrpc_request *request)
319 + {
320 + 36800 const char *method = NULL;
321 + 36800 int ret = libjson_get_string(request->impl, jsonrpc_key_method, &method);
322 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36800 times.
+
+
+
36800 if (ret < 0) {
323 + /* Should never happen. */
324 + return NULL;
325 + }
326 + 36800 return method;
327 + }
328 +
329 + 73440static struct json_object *jsonrpc_request_create_params(struct jsonrpc_request *request)
330 + {
331 + 73440 int ret = 0;
332 + 73440 const char *const key = jsonrpc_key_params;
333 +
334 +
+ 2/2 +
+
✓ Branch 1 taken 27540 times.
+
✓ Branch 2 taken 45900 times.
+
+
+
73440 if (!libjson_has(request->impl, key)) {
335 + 27540 struct json_object *params = NULL;
336 +
337 + 27540 ret = libjson_new_object(&params);
338 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (ret < 0)
339 + return NULL;
340 +
341 + 27540 ret = libjson_set(request->impl, key, params);
342 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (ret < 0) {
343 + libjson_free(params);
344 + return NULL;
345 + }
346 + 27540 return params;
347 + }
348 +
349 + 45900 struct json_object *params = NULL;
350 + 45900 ret = libjson_get(request->impl, key, &params);
351 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 45900 times.
+
+
+
45900 if (ret < 0)
352 + return NULL;
353 + 45900 return params;
354 + }
355 +
356 + 45900int jsonrpc_request_get_param_string(const struct jsonrpc_request *request, const char *name,
357 + const char **value)
358 + {
359 + 45900 struct json_object *params = NULL;
360 + 45900 int ret = libjson_get(request->impl, jsonrpc_key_params, &params);
361 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 45900 times.
+
+
+
45900 if (ret < 0)
362 + return ret;
363 + 45900 return libjson_get_string(params, name, value);
364 + }
365 +
366 + 45900int jsonrpc_request_set_param_string(struct jsonrpc_request *request, const char *name,
367 + const char *value)
368 + {
369 + 45900 struct json_object *params = jsonrpc_request_create_params(request);
370 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 45900 times.
+
+
+
45900 if (!params)
371 + return -1;
372 + 45900 return libjson_set_string(params, name, value);
373 + }
374 +
375 + 27540int jsonrpc_request_get_param_int(const struct jsonrpc_request *request, const char *name,
376 + int64_t *value)
377 + {
378 + 27540 struct json_object *params = NULL;
379 + 27540 int ret = libjson_get(request->impl, jsonrpc_key_params, &params);
380 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (ret < 0)
381 + return ret;
382 + 27540 return libjson_get_int(params, name, value);
383 + }
384 +
385 + 27540int jsonrpc_request_set_param_int(struct jsonrpc_request *request, const char *name, int64_t value)
386 + {
387 + 27540 struct json_object *params = jsonrpc_request_create_params(request);
388 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (!params)
389 + return -1;
390 + 27540 return libjson_set_int(params, name, value);
391 + }
392 +
393 + 9206const char *jsonrpc_response_to_string(const struct jsonrpc_response *response)
394 + {
395 + 9206 return libjson_to_string_pretty(response->impl);
396 + }
397 +
398 + 27618int jsonrpc_response_create_internal(struct jsonrpc_response **_response,
399 + const struct jsonrpc_request *request,
400 + struct json_object *result, struct json_object *error)
401 + {
402 + 27618 int ret = 0;
403 +
404 + 27618 struct jsonrpc_response *response = malloc(sizeof(struct jsonrpc_response));
405 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (!response) {
406 + log_errno("malloc");
407 + ret = -1;
408 + goto exit;
409 + }
410 +
411 + 27618 ret = libjson_new_object(&response->impl);
412 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (ret < 0)
413 + goto free;
414 +
415 + 27618 ret = jsonrpc_set_version(response->impl);
416 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (ret < 0)
417 + goto free_impl;
418 +
419 + 27618 struct json_object *id = NULL;
420 + 27618 ret = libjson_clone(request->impl, jsonrpc_key_id, &id);
421 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (ret < 0)
422 + goto free_impl;
423 +
424 + 27618 ret = libjson_set(response->impl, jsonrpc_key_id, id);
425 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27618 times.
+
+
+
27618 if (ret < 0) {
426 + libjson_free(id);
427 + goto free_impl;
428 + }
429 +
430 +
+ 2/2 +
+
✓ Branch 0 taken 9206 times.
+
✓ Branch 1 taken 18412 times.
+
+
+
27618 if (error) {
431 + 9206 ret = libjson_set_const_key(response->impl, jsonrpc_key_error, error);
432 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
433 + goto free_impl;
434 + } else {
435 + 18412 ret = libjson_set_const_key(response->impl, jsonrpc_key_result, result);
436 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18412 times.
+
+
+
18412 if (ret < 0)
437 + goto free_impl;
438 + }
439 +
440 + 27618 *_response = response;
441 + 27618 goto exit;
442 +
443 + free_impl:
444 + libjson_free(response->impl);
445 + free:
446 + free(response);
447 + 27618exit:
448 + 27618 return ret;
449 + }
450 +
451 + 18412int jsonrpc_response_create(struct jsonrpc_response **response,
452 + const struct jsonrpc_request *request, struct json_object *result)
453 + {
454 + 18412 return jsonrpc_response_create_internal(response, request, result, NULL);
455 + }
456 +
457 + 36824void jsonrpc_response_destroy(struct jsonrpc_response *response)
458 + {
459 + 36824 libjson_free(response->impl);
460 + 36824 free(response);
461 + 36824}
462 +
463 + 9206int jsonrpc_error_create(struct jsonrpc_response **response, struct jsonrpc_request *request,
464 + int code, const char *message)
465 + {
466 + 9206 int ret = 0;
467 + 9206 struct json_object *error = NULL;
468 +
469 + 9206 ret = libjson_new_object(&error);
470 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
471 + return ret;
472 +
473 + 9206 ret = libjson_set_int_const_key(error, jsonrpc_key_code, code);
474 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
475 + goto free;
476 + 9206 ret = libjson_set_string_const_key(error, jsonrpc_key_message, message);
477 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
478 + goto free;
479 +
480 + 9206 ret = jsonrpc_response_create_internal(response, request, NULL, error);
481 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
482 + goto free;
483 +
484 + 9206 return ret;
485 +
486 + free:
487 + libjson_free(error);
488 +
489 + return ret;
490 + }
491 +
492 + 9206int jsonrpc_response_is_error(const struct jsonrpc_response *response)
493 + {
494 + 9206 return libjson_has(response->impl, jsonrpc_key_error);
495 + }
496 +
497 + 9206static int jsonrpc_response_from_json(struct jsonrpc_response **_response, struct json_object *impl)
498 + {
499 + 9206 int ret = 0;
500 +
501 + 9206 ret = jsonrpc_check_version(impl);
502 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
503 + return ret;
504 + 9206 ret = jsonrpc_check_id(impl, 1);
505 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
506 + return ret;
507 + 9206 ret = jsonrpc_check_result_or_error(impl);
508 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
509 + return ret;
510 +
511 + 9206 struct jsonrpc_response *response = malloc(sizeof(struct jsonrpc_response));
512 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (!response) {
513 + log_errno("malloc");
514 + return -1;
515 + }
516 + 9206 response->impl = impl;
517 +
518 + 9206 *_response = response;
519 + 9206 return ret;
520 + }
521 +
522 + 9206int jsonrpc_response_send(const struct jsonrpc_response *response, int fd)
523 + {
524 + 9206 return libjson_send(response->impl, fd);
525 + }
526 +
527 + 9206int jsonrpc_response_recv(struct jsonrpc_response **response, int fd)
528 + {
529 + 9206 struct json_object *impl = libjson_recv(fd);
530 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (!impl) {
531 + log_err("JSON-RPC: failed to receive response\n");
532 + return -1;
533 + }
534 +
535 + 9206 int ret = jsonrpc_response_from_json(response, impl);
536 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9206 times.
+
+
+
9206 if (ret < 0)
537 + goto free_impl;
538 +
539 + 9206 return ret;
540 +
541 + free_impl:
542 + libjson_free(impl);
543 +
544 + return ret;
545 + }
546 +
+
+ +
+ + + + diff --git a/coverage/index.log.c.47179e5db7ed3f2db741c99372ba24f3.html b/coverage/index.log.c.47179e5db7ed3f2db741c99372ba24f3.html new file mode 100644 index 0000000..0b70801 --- /dev/null +++ b/coverage/index.log.c.47179e5db7ed3f2db741c99372ba24f3.html @@ -0,0 +1,539 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/log.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:222491.7%
Branches:4666.7%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "log.h"
9 +
10 + #include <stdio.h>
11 + #include <sys/time.h>
12 + #include <time.h>
13 + #include <unistd.h>
14 +
15 + int g_log_lvl = LOG_LVL_INFO;
16 +
17 + 182861static inline void log_prefix_timestamp(FILE *dest)
18 + {
19 + struct timeval tv;
20 + struct tm tm;
21 + char buf[64];
22 + 182861 size_t used = 0;
23 +
24 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 182861 times.
+
+
+
182861 if (gettimeofday(&tv, NULL) < 0)
25 + return;
26 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 182861 times.
+
+
+
182861 if (!gmtime_r(&tv.tv_sec, &tm))
27 + return;
28 +
29 + 182861 buf[0] = '\0';
30 + 182861 used += strftime(buf + used, sizeof(buf) - used, "%F %T", &tm);
31 + 182861 long long msec = (long long)tv.tv_usec / 1000;
32 + 182861 used += snprintf(buf + used, sizeof(buf) - used, ".%03lld | ", msec);
33 + 182861 fprintf(dest, "%s", buf);
34 + }
35 +
36 + 182861static inline void log_prefix_thread_id(FILE *dest)
37 + {
38 + 182861 fprintf(dest, "%d | ", gettid());
39 + 182861}
40 +
41 + 708199int log_entry_start(int lvl, FILE *dest)
42 + {
43 +
+ 2/2 +
+
✓ Branch 0 taken 525338 times.
+
✓ Branch 1 taken 182861 times.
+
+
+
708199 if (lvl < g_log_lvl)
44 + 525338 return 0;
45 + 182861 flockfile(dest);
46 + 182861 log_prefix_timestamp(dest);
47 + 182861 log_prefix_thread_id(dest);
48 + 182861 return 1;
49 + }
50 +
51 + 182861void log_entry_end(FILE *dest)
52 + {
53 + 182861 funlockfile(dest);
54 + 182861}
55 +
+
+ +
+ + + + diff --git a/coverage/index.net.c.37012fce13860cefc5963f57e0f36732.html b/coverage/index.net.c.37012fce13860cefc5963f57e0f36732.html new file mode 100644 index 0000000..25c157c --- /dev/null +++ b/coverage/index.net.c.37012fce13860cefc5963f57e0f36732.html @@ -0,0 +1,2386 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/net.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:8713962.6%
Branches:309232.6%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "net.h"
9 + #include "buf.h"
10 + #include "file.h"
11 + #include "log.h"
12 +
13 + #include <netdb.h>
14 + #include <stdint.h>
15 + #include <stdlib.h>
16 + #include <string.h>
17 + #include <sys/socket.h>
18 + #include <sys/types.h>
19 + #include <unistd.h>
20 +
21 + #define gai_log_errno(ec) log_err("getaddrinfo: %s\n", gai_strerror(ec))
22 +
23 + 29int net_bind(const char *port)
24 + {
25 + static const int flags = SOCK_CLOEXEC;
26 + 29 struct addrinfo *result = NULL, *it = NULL;
27 + struct addrinfo hints;
28 + 29 int socket_fd = -1, ret = 0;
29 +
30 + 29 memset(&hints, 0, sizeof(hints));
31 + 29 hints.ai_family = AF_INET6;
32 + 29 hints.ai_socktype = SOCK_STREAM;
33 + 29 hints.ai_flags = AI_PASSIVE;
34 +
35 + 29 ret = getaddrinfo(NULL, port, &hints, &result);
36 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret) {
37 + gai_log_errno(ret);
38 + return -1;
39 + }
40 +
41 +
+ 1/2 +
+
✓ Branch 0 taken 29 times.
+
✗ Branch 1 not taken.
+
+
+
29 for (it = result; it; it = it->ai_next) {
42 + 29 socket_fd = socket(it->ai_family, it->ai_socktype | flags, it->ai_protocol);
43 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (socket_fd < 0) {
44 + log_errno("socket");
45 + continue;
46 + }
47 +
48 + static const int yes = 1;
49 + static const int no = 0;
50 +
51 +
+ 1/2 +
+
✓ Branch 0 taken 29 times.
+
✗ Branch 1 not taken.
+
+
+
29 if (it->ai_family == AF_INET6) {
52 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 if (setsockopt(socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)) < 0) {
53 + log_errno("setsockopt");
54 + goto close_socket;
55 + }
56 + }
57 +
58 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
59 + log_errno("setsockopt");
60 + goto close_socket;
61 + }
62 +
63 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 if (bind(socket_fd, it->ai_addr, it->ai_addrlen) < 0) {
64 + log_errno("bind");
65 + goto close_socket;
66 + }
67 +
68 + 29 break;
69 +
70 + close_socket:
71 + net_close(socket_fd);
72 + }
73 +
74 + 29 freeaddrinfo(result);
75 +
76 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!it) {
77 + log_err("Couldn't bind to port %s\n", port);
78 + return -1;
79 + }
80 +
81 + 29 ret = listen(socket_fd, 4096);
82 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0) {
83 + log_errno("listen");
84 + goto fail;
85 + }
86 +
87 + 29 return socket_fd;
88 +
89 + fail:
90 + net_close(socket_fd);
91 +
92 + return ret;
93 + }
94 +
95 + 27620int net_accept(int fd)
96 + {
97 + static const int flags = SOCK_CLOEXEC;
98 + 27620 int ret = 0;
99 +
100 + 27620 ret = accept4(fd, NULL, NULL, flags);
101 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0) {
102 + log_errno("accept4");
103 + return ret;
104 + }
105 +
106 + 27620 return ret;
107 + }
108 +
109 + 27620int net_connect(const char *host, const char *port)
110 + {
111 + static const int flags = SOCK_CLOEXEC;
112 + 27620 struct addrinfo *result = NULL, *it = NULL;
113 + struct addrinfo hints;
114 + 27620 int socket_fd = -1, ret = 0;
115 +
116 + 27620 memset(&hints, 0, sizeof(hints));
117 + 27620 hints.ai_family = AF_UNSPEC;
118 + 27620 hints.ai_socktype = SOCK_STREAM;
119 +
120 + 27620 ret = getaddrinfo(host, port, &hints, &result);
121 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret) {
122 + gai_log_errno(ret);
123 + return -1;
124 + }
125 +
126 +
+ 1/2 +
+
✓ Branch 0 taken 27620 times.
+
✗ Branch 1 not taken.
+
+
+
27620 for (it = result; it; it = it->ai_next) {
127 + 27620 socket_fd = socket(it->ai_family, it->ai_socktype | flags, it->ai_protocol);
128 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (socket_fd < 0) {
129 + log_errno("socket");
130 + continue;
131 + }
132 +
133 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 27620 times.
+
+
+
27620 if (connect(socket_fd, it->ai_addr, it->ai_addrlen) < 0) {
134 + log_errno("connect");
135 + goto close_socket;
136 + }
137 +
138 + 27620 break;
139 +
140 + close_socket:
141 + net_close(socket_fd);
142 + }
143 +
144 + 27620 freeaddrinfo(result);
145 +
146 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (!it) {
147 + log_err("Couldn't connect to host %s, port %s\n", host, port);
148 + return -1;
149 + }
150 +
151 + 27620 return socket_fd;
152 + }
153 +
154 + 64503void net_close(int fd)
155 + {
156 + 64503 file_close(fd);
157 + 64503}
158 +
159 + 92012static ssize_t net_send_part(int fd, const void *buf, size_t size)
160 + {
161 + static const int flags = MSG_NOSIGNAL;
162 +
163 + 92012 ssize_t ret = send(fd, buf, size, flags);
164 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 92012 times.
+
+
+
92012 if (ret < 0) {
165 + log_errno("send");
166 + return -1;
167 + }
168 +
169 + 92012 return ret;
170 + }
171 +
172 + 92012int net_send(int fd, const void *buf, size_t size)
173 + {
174 + 92012 size_t sent_total = 0;
175 +
176 +
+ 2/2 +
+
✓ Branch 0 taken 92012 times.
+
✓ Branch 1 taken 92012 times.
+
+
+
184024 while (sent_total < size) {
177 + ssize_t sent_now =
178 + 92012 net_send_part(fd, (const char *)buf + sent_total, size - sent_total);
179 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 92012 times.
+
+
+
92012 if (sent_now < 0)
180 + return -1;
181 + 92012 sent_total += sent_now;
182 + }
183 +
184 + 92012 return 0;
185 + }
186 +
187 + 92012int net_recv(int fd, void *buf, size_t size)
188 + {
189 + 92012 ssize_t read_total = 0;
190 +
191 +
+ 2/2 +
+
✓ Branch 0 taken 109165 times.
+
✓ Branch 1 taken 92012 times.
+
+
+
201177 while ((size_t)read_total < size) {
192 + 109165 ssize_t read_now = read(fd, (unsigned char *)buf + read_total, size - read_total);
193 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 109165 times.
+
+
+
109165 if (!read_now)
194 + break;
195 +
196 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 109165 times.
+
+
+
109165 if (read_now < 0) {
197 + log_errno("read");
198 + return -1;
199 + }
200 +
201 + 109165 read_total += read_now;
202 + }
203 +
204 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 92012 times.
+
+
+
92012 if ((size_t)read_total < size) {
205 + log_err("Received only %zd bytes out of %zu\n", read_total, size);
206 + return -1;
207 + }
208 +
209 + 92012 return 0;
210 + }
211 +
212 + 46006int net_send_buf(int fd, const struct buf *buf)
213 + {
214 + 46006 int ret = 0;
215 +
216 + 46006 uint32_t size = htonl(buf_get_size(buf));
217 + 46006 ret = net_send(fd, &size, sizeof(size));
218 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0)
219 + return ret;
220 +
221 + 46006 ret = net_send(fd, buf_get_data(buf), buf_get_size(buf));
222 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0)
223 + return ret;
224 +
225 + 46006 return ret;
226 + }
227 +
228 + 46006int net_recv_buf(int fd, struct buf **buf)
229 + {
230 + 46006 uint32_t size = 0;
231 + 46006 int ret = 0;
232 +
233 + 46006 ret = net_recv(fd, &size, sizeof(size));
234 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0) {
235 + log_err("Couldn't read buffer size\n");
236 + goto fail;
237 + }
238 + 46006 size = ntohl(size);
239 +
240 + 46006 void *data = malloc(size);
241 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (!data) {
242 + log_errno("malloc");
243 + goto fail;
244 + }
245 +
246 + 46006 ret = net_recv(fd, data, size);
247 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0) {
248 + log_err("Couldn't read buffer\n");
249 + goto free_data;
250 + }
251 +
252 + 46006 ret = buf_create(buf, data, size);
253 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 46006 times.
+
+
+
46006 if (ret < 0)
254 + goto free_data;
255 +
256 + 46006 return ret;
257 +
258 + free_data:
259 + free(data);
260 +
261 + fail:
262 + return -1;
263 + }
264 +
+
+ +
+ + + + diff --git a/coverage/index.process.c.52f9324f34485af6c2c0f7cc7bbf5f8b.html b/coverage/index.process.c.52f9324f34485af6c2c0f7cc7bbf5f8b.html new file mode 100644 index 0000000..d724686 --- /dev/null +++ b/coverage/index.process.c.52f9324f34485af6c2c0f7cc7bbf5f8b.html @@ -0,0 +1,1491 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/process.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:418448.8%
Branches:125223.1%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "process.h"
9 + #include "file.h"
10 + #include "log.h"
11 +
12 + #include <fcntl.h>
13 + #include <stdlib.h>
14 + #include <sys/wait.h>
15 + #include <unistd.h>
16 +
17 + static int exec_child(const char *args[], const char *envp[])
18 + {
19 + static const char *default_envp[] = {NULL};
20 +
21 + if (!envp)
22 + envp = default_envp;
23 +
24 + int ret = execvpe(args[0], (char *const *)args, (char *const *)envp);
25 + if (ret < 0) {
26 + log_errno("execvpe");
27 + return ret;
28 + }
29 +
30 + return ret;
31 + }
32 +
33 + 9180static int wait_for_child(pid_t pid, int *ec)
34 + {
35 + int status;
36 +
37 + 9180 pid_t ret = waitpid(pid, &status, __WNOTHREAD);
38 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
39 + log_errno("waitpid");
40 + return ret;
41 + }
42 +
43 + /* The child process reports the lowest 8 bits of its exit code, which
44 + * are treated as an unsigned integer on Linux.
45 + *
46 + * If it was killed by a signal, indicate that by negating the signal
47 + * number. */
48 +
49 +
+ 2/2 +
+
✓ Branch 0 taken 9144 times.
+
✓ Branch 1 taken 36 times.
+
+
+
9180 if (WIFEXITED(status)) {
50 + 9144 *ec = WEXITSTATUS(status);
51 +
+ 1/2 +
+
✓ Branch 0 taken 36 times.
+
✗ Branch 1 not taken.
+
+
+
36 } else if (WIFSIGNALED(status)) {
52 + 36 *ec = -WTERMSIG(status);
53 + } else {
54 + log_err("This shouldn't happen: %d\n", status);
55 + *ec = 1;
56 + }
57 +
58 + 9180 return 0;
59 + }
60 +
61 + int proc_spawn(const char *args[], const char *envp[], int *ec)
62 + {
63 + pid_t child_pid = fork();
64 + if (child_pid < 0) {
65 + log_errno("fork");
66 + return child_pid;
67 + }
68 +
69 + if (!child_pid)
70 + exit(exec_child(args, envp));
71 +
72 + return wait_for_child(child_pid, ec);
73 + }
74 +
75 + static int redirect_and_exec_child(int pipe_fds[2], const char *args[], const char *envp[])
76 + {
77 + int ret = 0;
78 +
79 + file_close(pipe_fds[0]);
80 +
81 + ret = dup2(pipe_fds[1], STDOUT_FILENO);
82 + if (ret < 0) {
83 + log_errno("dup2");
84 + return ret;
85 + }
86 +
87 + ret = dup2(pipe_fds[1], STDERR_FILENO);
88 + if (ret < 0) {
89 + log_errno("dup2");
90 + return ret;
91 + }
92 +
93 + return exec_child(args, envp);
94 + }
95 +
96 + 9180int proc_capture(const char *args[], const char *envp[], struct proc_output *result)
97 + {
98 + static const int flags = O_CLOEXEC;
99 + int pipe_fds[2];
100 + 9180 int ret = 0;
101 +
102 + 9180 ret = pipe2(pipe_fds, flags);
103 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
104 + log_errno("pipe2");
105 + return -1;
106 + }
107 +
108 + 9180 pid_t child_pid = fork();
109 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (child_pid < 0) {
110 + log_errno("fork");
111 + goto close_pipe;
112 + }
113 +
114 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!child_pid)
115 + exit(redirect_and_exec_child(pipe_fds, args, envp));
116 +
117 + 9180 file_close(pipe_fds[1]);
118 +
119 + 9180 ret = file_read(pipe_fds[0], &result->data, &result->data_size);
120 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
121 + goto close_pipe;
122 +
123 + 9180 ret = wait_for_child(child_pid, &result->ec);
124 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
125 + goto free_data;
126 +
127 + 9180 goto close_pipe;
128 +
129 + free_data:
130 + free(result->data);
131 +
132 + 9180close_pipe:
133 + 9180 file_close(pipe_fds[0]);
134 + /* No errno checking here, we might've already closed the write end. */
135 + 9180 close(pipe_fds[1]);
136 +
137 + 9180 return ret;
138 + }
139 +
140 + 18360int proc_output_create(struct proc_output **_output)
141 + {
142 + 18360 struct proc_output *output = calloc(1, sizeof(struct proc_output));
143 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18360 times.
+
+
+
18360 if (!output) {
144 + log_errno("calloc");
145 + return -1;
146 + }
147 +
148 + 18360 output->ec = 0;
149 + 18360 output->data = NULL;
150 + 18360 output->data_size = 0;
151 +
152 + 18360 *_output = output;
153 + 18360 return 0;
154 + }
155 +
156 + 18360void proc_output_destroy(struct proc_output *output)
157 + {
158 + 18360 free(output->data);
159 + 18360 free(output);
160 + 18360}
161 +
162 + 9180void proc_output_dump(const struct proc_output *output)
163 + {
164 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Process exit code: %d\n", output->ec);
165 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Process output: %zu bytes\n", output->data_size);
166 + 9180}
167 +
+
+ +
+ + + + diff --git a/coverage/index.protocol.c.4964764a2e677a55c2f4207a995c3ce7.html b/coverage/index.protocol.c.4964764a2e677a55c2f4207a995c3ce7.html new file mode 100644 index 0000000..e07baf3 --- /dev/null +++ b/coverage/index.protocol.c.4964764a2e677a55c2f4207a995c3ce7.html @@ -0,0 +1,2054 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/protocol.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:9013168.7%
Branches:244850.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "protocol.h"
9 + #include "base64.h"
10 + #include "compiler.h"
11 + #include "const.h"
12 + #include "json.h"
13 + #include "json_rpc.h"
14 + #include "process.h"
15 + #include "run_queue.h"
16 +
17 + #include <stddef.h>
18 + #include <stdint.h>
19 + #include <stdlib.h>
20 +
21 + static const char *const run_key_id = "id";
22 + static const char *const run_key_url = "url";
23 + static const char *const run_key_rev = "rev";
24 +
25 + 9180int request_create_queue_run(struct jsonrpc_request **request, const struct run *run)
26 + {
27 + 9180 int ret = 0;
28 +
29 + 9180 ret = jsonrpc_request_create(request, jsonrpc_generate_request_id(), CMD_QUEUE_RUN, NULL);
30 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
31 + return ret;
32 + 9180 ret = jsonrpc_request_set_param_string(*request, run_key_url, run_get_repo_url(run));
33 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
34 + goto free_request;
35 + 9180 ret = jsonrpc_request_set_param_string(*request, run_key_rev, run_get_repo_rev(run));
36 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
37 + goto free_request;
38 +
39 + 9180 return ret;
40 +
41 + free_request:
42 + jsonrpc_request_destroy(*request);
43 +
44 + return ret;
45 + }
46 +
47 + 9180int request_parse_queue_run(const struct jsonrpc_request *request, struct run **run)
48 + {
49 + 9180 int ret = 0;
50 +
51 + 9180 const char *url = NULL;
52 + 9180 ret = jsonrpc_request_get_param_string(request, run_key_url, &url);
53 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
54 + return ret;
55 + 9180 const char *rev = NULL;
56 + 9180 ret = jsonrpc_request_get_param_string(request, run_key_rev, &rev);
57 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
58 + return ret;
59 +
60 + 9180 return run_queued(run, url, rev);
61 + }
62 +
63 + 9234int request_create_new_worker(struct jsonrpc_request **request)
64 + {
65 + 9234 return jsonrpc_notification_create(request, CMD_NEW_WORKER, NULL);
66 + }
67 +
68 + int request_parse_new_worker(UNUSED const struct jsonrpc_request *request)
69 + {
70 + return 0;
71 + }
72 +
73 + 9180int request_create_start_run(struct jsonrpc_request **request, const struct run *run)
74 + {
75 + 9180 int ret = 0;
76 +
77 + 9180 ret = jsonrpc_notification_create(request, CMD_START_RUN, NULL);
78 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
79 + return ret;
80 + 9180 ret = jsonrpc_request_set_param_int(*request, run_key_id, run_get_id(run));
81 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
82 + goto free_request;
83 + 9180 ret = jsonrpc_request_set_param_string(*request, run_key_url, run_get_repo_url(run));
84 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
85 + goto free_request;
86 + 9180 ret = jsonrpc_request_set_param_string(*request, run_key_rev, run_get_repo_rev(run));
87 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
88 + goto free_request;
89 +
90 + 9180 return ret;
91 +
92 + free_request:
93 + jsonrpc_request_destroy(*request);
94 +
95 + return ret;
96 + }
97 +
98 + 9180int request_parse_start_run(const struct jsonrpc_request *request, struct run **run)
99 + {
100 + 9180 int ret = 0;
101 +
102 + 9180 int64_t id = 0;
103 + 9180 ret = jsonrpc_request_get_param_int(request, run_key_id, &id);
104 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
105 + return ret;
106 + 9180 const char *url = NULL;
107 + 9180 ret = jsonrpc_request_get_param_string(request, run_key_url, &url);
108 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
109 + return ret;
110 + 9180 const char *rev = NULL;
111 + 9180 ret = jsonrpc_request_get_param_string(request, run_key_rev, &rev);
112 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
113 + return ret;
114 +
115 + 9180 return run_created(run, (int)id, url, rev);
116 + }
117 +
118 + static const char *const finished_key_run_id = "run_id";
119 + static const char *const finished_key_ec = "exit_code";
120 + static const char *const finished_key_data = "output";
121 +
122 + 9180int request_create_finished_run(struct jsonrpc_request **request, int run_id,
123 + const struct proc_output *output)
124 + {
125 + 9180 int ret = 0;
126 +
127 + 9180 ret = jsonrpc_notification_create(request, CMD_FINISHED_RUN, NULL);
128 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
129 + return ret;
130 + 9180 ret = jsonrpc_request_set_param_int(*request, finished_key_run_id, run_id);
131 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
132 + goto free_request;
133 + 9180 ret = jsonrpc_request_set_param_int(*request, finished_key_ec, output->ec);
134 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
135 + goto free_request;
136 +
137 + 9180 char *b64data = NULL;
138 + 9180 ret = base64_encode(output->data, output->data_size, &b64data);
139 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
140 + goto free_request;
141 +
142 + 9180 ret = jsonrpc_request_set_param_string(*request, finished_key_data, b64data);
143 + 9180 free(b64data);
144 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
145 + goto free_request;
146 +
147 + 9180 return ret;
148 +
149 + free_request:
150 + jsonrpc_request_destroy(*request);
151 +
152 + return ret;
153 + }
154 +
155 + 9180int request_parse_finished_run(const struct jsonrpc_request *request, int *_run_id,
156 + struct proc_output **_output)
157 + {
158 + 9180 int ret = 0;
159 +
160 + 9180 struct proc_output *output = NULL;
161 + 9180 ret = proc_output_create(&output);
162 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
163 + return ret;
164 +
165 + 9180 int64_t run_id = 0;
166 + 9180 ret = jsonrpc_request_get_param_int(request, finished_key_run_id, &run_id);
167 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
168 + goto free_output;
169 +
170 + 9180 int64_t ec = -1;
171 + 9180 ret = jsonrpc_request_get_param_int(request, finished_key_ec, &ec);
172 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
173 + goto free_output;
174 + 9180 output->ec = (int)ec;
175 +
176 + 9180 const char *b64data = NULL;
177 + 9180 ret = jsonrpc_request_get_param_string(request, finished_key_data, &b64data);
178 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
179 + goto free_output;
180 +
181 + 9180 ret = base64_decode(b64data, &output->data, &output->data_size);
182 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
183 + goto free_output;
184 +
185 + 9180 *_run_id = (int)run_id;
186 + 9180 *_output = output;
187 + 9180 return ret;
188 +
189 + free_output:
190 + proc_output_destroy(output);
191 +
192 + return ret;
193 + }
194 +
195 + 26int request_create_get_runs(struct jsonrpc_request **request)
196 + {
197 + 26 return jsonrpc_request_create(request, jsonrpc_generate_request_id(), CMD_GET_RUNS, NULL);
198 + }
199 +
200 + 26int request_parse_get_runs(UNUSED const struct jsonrpc_request *request)
201 + {
202 + 26 return 0;
203 + }
204 +
205 + 26int response_create_get_runs(struct jsonrpc_response **response,
206 + const struct jsonrpc_request *request, const struct run_queue *runs)
207 + {
208 + 26 struct json_object *runs_json = NULL;
209 + 26 int ret = 0;
210 +
211 + 26 ret = run_queue_to_json(runs, &runs_json);
212 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (ret < 0)
213 + return ret;
214 +
215 + 26 ret = jsonrpc_response_create(response, request, runs_json);
216 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (ret < 0)
217 + goto free_json;
218 +
219 + 26 return ret;
220 +
221 + free_json:
222 + libjson_free(runs_json);
223 +
224 + return ret;
225 + }
226 +
+
+ +
+ + + + diff --git a/coverage/index.run_queue.c.fdfaa39d71447cf1e7d01ff206bd91e5.html b/coverage/index.run_queue.c.fdfaa39d71447cf1e7d01ff206bd91e5.html new file mode 100644 index 0000000..3b4a19b --- /dev/null +++ b/coverage/index.run_queue.c.fdfaa39d71447cf1e7d01ff206bd91e5.html @@ -0,0 +1,1816 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/run_queue.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:8111073.6%
Branches:173647.2%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "run_queue.h"
9 + #include "json.h"
10 + #include "log.h"
11 +
12 + #include <json-c/json_object.h>
13 +
14 + #include <stdlib.h>
15 + #include <string.h>
16 + #include <sys/queue.h>
17 +
18 + struct run {
19 + int id;
20 + char *repo_url;
21 + char *repo_rev;
22 + int status;
23 + int exit_code;
24 +
25 + SIMPLEQ_ENTRY(run) entries;
26 + };
27 +
28 + 36720int run_new(struct run **_entry, int id, const char *_repo_url, const char *_repo_rev,
29 + enum run_status status, int exit_code)
30 + {
31 + 36720 struct run *entry = malloc(sizeof(struct run));
32 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36720 times.
+
+
+
36720 if (!entry) {
33 + log_errno("malloc");
34 + goto fail;
35 + }
36 +
37 + 36720 char *repo_url = strdup(_repo_url);
38 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36720 times.
+
+
+
36720 if (!repo_url) {
39 + log_errno("strdup");
40 + goto free_entry;
41 + }
42 +
43 + 36720 char *repo_rev = strdup(_repo_rev);
44 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36720 times.
+
+
+
36720 if (!repo_rev) {
45 + log_errno("strdup");
46 + goto free_repo_url;
47 + }
48 +
49 + 36720 entry->id = id;
50 + 36720 entry->repo_url = repo_url;
51 + 36720 entry->repo_rev = repo_rev;
52 + 36720 entry->status = status;
53 + 36720 entry->exit_code = exit_code;
54 +
55 + 36720 *_entry = entry;
56 + 36720 return 0;
57 +
58 + free_repo_url:
59 + free(repo_url);
60 +
61 + free_entry:
62 + free(entry);
63 +
64 + fail:
65 + return -1;
66 + }
67 +
68 + 36720void run_destroy(struct run *entry)
69 + {
70 + 36720 free(entry->repo_rev);
71 + 36720 free(entry->repo_url);
72 + 36720 free(entry);
73 + 36720}
74 +
75 + 18360int run_queued(struct run **entry, const char *repo_url, const char *repo_rev)
76 + {
77 + 18360 return run_new(entry, -1, repo_url, repo_rev, RUN_STATUS_CREATED, -1);
78 + }
79 +
80 + 9180int run_created(struct run **entry, int id, const char *repo_url, const char *repo_rev)
81 + {
82 + 9180 return run_new(entry, id, repo_url, repo_rev, RUN_STATUS_CREATED, -1);
83 + }
84 +
85 + 9180int run_to_json(const struct run *entry, struct json_object **_json)
86 + {
87 + 9180 struct json_object *json = NULL;
88 + 9180 int ret = 0;
89 +
90 + 9180 ret = libjson_new_object(&json);
91 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
92 + return -1;
93 + 9180 ret = libjson_set_int_const_key(json, "id", entry->id);
94 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
95 + goto free;
96 + 9180 ret = libjson_set_int_const_key(json, "exit_code", entry->exit_code);
97 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
98 + goto free;
99 + 9180 ret = libjson_set_string_const_key(json, "repo_url", entry->repo_url);
100 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
101 + goto free;
102 + 9180 ret = libjson_set_string_const_key(json, "repo_rev", entry->repo_rev);
103 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
104 + goto free;
105 +
106 + 9180 *_json = json;
107 + 9180 return ret;
108 +
109 + free:
110 + libjson_free(json);
111 +
112 + return ret;
113 + }
114 +
115 + 45900int run_get_id(const struct run *entry)
116 + {
117 + 45900 return entry->id;
118 + }
119 +
120 + 64260const char *run_get_repo_url(const struct run *entry)
121 + {
122 + 64260 return entry->repo_url;
123 + }
124 +
125 + 36720const char *run_get_repo_rev(const struct run *entry)
126 + {
127 + 36720 return entry->repo_rev;
128 + }
129 +
130 + 9180void run_set_id(struct run *entry, int id)
131 + {
132 + 9180 entry->id = id;
133 + 9180}
134 +
135 + 55void run_queue_create(struct run_queue *queue)
136 + {
137 + 55 SIMPLEQ_INIT(queue);
138 + 55}
139 +
140 + 55void run_queue_destroy(struct run_queue *queue)
141 + {
142 + 55 struct run *entry1 = SIMPLEQ_FIRST(queue);
143 +
+ 2/2 +
+
✓ Branch 0 taken 9180 times.
+
✓ Branch 1 taken 55 times.
+
+
+
9235 while (entry1) {
144 + 9180 struct run *entry2 = SIMPLEQ_NEXT(entry1, entries);
145 + 9180 run_destroy(entry1);
146 + 9180 entry1 = entry2;
147 + }
148 + 55 SIMPLEQ_INIT(queue);
149 + 55}
150 +
151 + 26int run_queue_to_json(const struct run_queue *queue, struct json_object **_json)
152 + {
153 + 26 struct json_object *json = NULL;
154 + 26 int ret = 0;
155 +
156 + 26 ret = libjson_new_array(&json);
157 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (ret < 0)
158 + return ret;
159 +
160 + 26 struct run *entry = NULL;
161 +
+ 2/2 +
+
✓ Branch 0 taken 9180 times.
+
✓ Branch 1 taken 26 times.
+
+
+
9206 SIMPLEQ_FOREACH(entry, queue, entries)
162 + {
163 + 9180 struct json_object *entry_json = NULL;
164 + 9180 ret = run_to_json(entry, &entry_json);
165 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
166 + goto free;
167 +
168 + 9180 ret = libjson_append(json, entry_json);
169 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
170 + libjson_free(entry_json);
171 + goto free;
172 + }
173 + }
174 +
175 + 26 *_json = json;
176 + 26 return ret;
177 +
178 + free:
179 + libjson_free(json);
180 +
181 + return ret;
182 + }
183 +
184 + 27472int run_queue_is_empty(const struct run_queue *queue)
185 + {
186 + 27472 return SIMPLEQ_EMPTY(queue);
187 + }
188 +
189 + void run_queue_add_first(struct run_queue *queue, struct run *entry)
190 + {
191 + SIMPLEQ_INSERT_HEAD(queue, entry, entries);
192 + }
193 +
194 + 18360void run_queue_add_last(struct run_queue *queue, struct run *entry)
195 + {
196 + 18360 SIMPLEQ_INSERT_TAIL(queue, entry, entries);
197 + 18360}
198 +
199 + 9180struct run *run_queue_remove_first(struct run_queue *queue)
200 + {
201 + 9180 struct run *entry = SIMPLEQ_FIRST(queue);
202 +
+ 2/2 +
+
✓ Branch 0 taken 78 times.
+
✓ Branch 1 taken 9102 times.
+
+
+
9180 SIMPLEQ_REMOVE_HEAD(queue, entries);
203 + 9180 return entry;
204 + }
205 +
+
+ +
+ + + + diff --git a/coverage/index.server.c.0235f01a49d01b35e981a41f59a9d2d6.html b/coverage/index.server.c.0235f01a49d01b35e981a41f59a9d2d6.html new file mode 100644 index 0000000..3a2d594 --- /dev/null +++ b/coverage/index.server.c.0235f01a49d01b35e981a41f59a9d2d6.html @@ -0,0 +1,4455 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/server.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:19527271.7%
Branches:6114641.8%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "server.h"
9 + #include "command.h"
10 + #include "compiler.h"
11 + #include "const.h"
12 + #include "event_loop.h"
13 + #include "file.h"
14 + #include "json_rpc.h"
15 + #include "log.h"
16 + #include "net.h"
17 + #include "process.h"
18 + #include "protocol.h"
19 + #include "run_queue.h"
20 + #include "signal.h"
21 + #include "storage.h"
22 + #include "storage_sqlite.h"
23 + #include "tcp_server.h"
24 + #include "worker_queue.h"
25 +
26 + #include <poll.h>
27 + #include <pthread.h>
28 + #include <stdlib.h>
29 +
30 + struct server {
31 + pthread_mutex_t server_mtx;
32 + pthread_cond_t server_cv;
33 +
34 + int stopping;
35 +
36 + struct cmd_dispatcher *cmd_dispatcher;
37 +
38 + struct event_loop *event_loop;
39 + int signalfd;
40 +
41 + struct worker_queue worker_queue;
42 + struct run_queue run_queue;
43 +
44 + struct storage storage;
45 +
46 + pthread_t main_thread;
47 +
48 + struct tcp_server *tcp_server;
49 + };
50 +
51 + 18472static int server_lock(struct server *server)
52 + {
53 + 18472 int ret = pthread_mutex_lock(&server->server_mtx);
54 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18472 times.
+
+
+
18472 if (ret) {
55 + pthread_errno(ret, "pthread_mutex_lock");
56 + return ret;
57 + }
58 + 18472 return ret;
59 + }
60 +
61 + 18472static void server_unlock(struct server *server)
62 + {
63 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 18472 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
18472 pthread_errno_if(pthread_mutex_unlock(&server->server_mtx), "pthread_mutex_unlock");
64 + 18472}
65 +
66 + 18292static int server_wait(struct server *server)
67 + {
68 + 18292 int ret = pthread_cond_wait(&server->server_cv, &server->server_mtx);
69 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18292 times.
+
+
+
18292 if (ret) {
70 + pthread_errno(ret, "pthread_cond_wait");
71 + return ret;
72 + }
73 + 18292 return ret;
74 + }
75 +
76 + 18443static void server_notify(struct server *server)
77 + {
78 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 18443 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
18443 pthread_errno_if(pthread_cond_signal(&server->server_cv), "pthread_cond_signal");
79 + 18443}
80 +
81 + 29static int server_set_stopping(UNUSED struct event_loop *loop, UNUSED int fd, UNUSED short revents,
82 + void *_server)
83 + {
84 + 29 struct server *server = (struct server *)_server;
85 + 29 int ret = 0;
86 +
87 + 29 ret = server_lock(server);
88 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
89 + return ret;
90 +
91 + 29 server->stopping = 1;
92 +
93 + 29 server_notify(server);
94 + 29 server_unlock(server);
95 + 29 return ret;
96 + }
97 +
98 + 27255static int server_has_workers(const struct server *server)
99 + {
100 + 27255 return !worker_queue_is_empty(&server->worker_queue);
101 + }
102 +
103 + 9234static int server_enqueue_worker(struct server *server, struct worker *worker)
104 + {
105 + 9234 int ret = 0;
106 +
107 + 9234 ret = server_lock(server);
108 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
109 + return ret;
110 +
111 + 9234 worker_queue_add_last(&server->worker_queue, worker);
112 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9234 times.
+
+
+
9234 log("Added a new worker %d to the queue\n", worker_get_fd(worker));
113 +
114 + 9234 server_notify(server);
115 + 9234 server_unlock(server);
116 + 9234 return ret;
117 + }
118 +
119 + 27472static int server_has_runs(const struct server *server)
120 + {
121 + 27472 return !run_queue_is_empty(&server->run_queue);
122 + }
123 +
124 + 9180static int server_enqueue_run(struct server *server, struct run *run)
125 + {
126 + 9180 int ret = 0;
127 +
128 + 9180 ret = storage_run_create(&server->storage, run_get_repo_url(run), run_get_repo_rev(run));
129 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
130 + return ret;
131 + 9180 run_set_id(run, ret);
132 +
133 + 9180 ret = server_lock(server);
134 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
135 + return ret;
136 +
137 + 9180 run_queue_add_last(&server->run_queue, run);
138 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Added a new run %d for repository %s to the queue\n", run_get_id(run),
139 + run_get_repo_url(run));
140 +
141 + 9180 server_notify(server);
142 + 9180 server_unlock(server);
143 + 9180 return ret;
144 + }
145 +
146 + 27501static int server_ready_for_action(const struct server *server)
147 + {
148 +
+ 6/6 +
+
✓ Branch 0 taken 27472 times.
+
✓ Branch 1 taken 29 times.
+
✓ Branch 3 taken 27255 times.
+
✓ Branch 4 taken 217 times.
+
✓ Branch 6 taken 9180 times.
+
✓ Branch 7 taken 18075 times.
+
+
+
27501 return server->stopping || (server_has_runs(server) && server_has_workers(server));
149 + }
150 +
151 + 9209static int server_wait_for_action(struct server *server)
152 + {
153 + 9209 int ret = 0;
154 +
155 +
+ 2/2 +
+
✓ Branch 1 taken 18292 times.
+
✓ Branch 2 taken 9209 times.
+
+
+
27501 while (!server_ready_for_action(server)) {
156 + 18292 ret = server_wait(server);
157 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18292 times.
+
+
+
18292 if (ret < 0)
158 + return ret;
159 + }
160 +
161 + 9209 return ret;
162 + }
163 +
164 + 9180static void server_assign_run(struct server *server)
165 + {
166 + 9180 struct run *run = run_queue_remove_first(&server->run_queue);
167 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Removed run %d for repository %s from the queue\n", run_get_id(run),
168 + run_get_repo_url(run));
169 +
170 + 9180 struct worker *worker = worker_queue_remove_first(&server->worker_queue);
171 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Removed worker %d from the queue\n", worker_get_fd(worker));
172 +
173 + 9180 struct jsonrpc_request *start_request = NULL;
174 + 9180 int ret = 0;
175 +
176 + 9180 ret = request_create_start_run(&start_request, run);
177 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
178 + goto exit;
179 +
180 + 9180 ret = jsonrpc_request_send(start_request, worker_get_fd(worker));
181 + 9180 jsonrpc_request_destroy(start_request);
182 +
+ 1/2 +
+
✓ Branch 0 taken 9180 times.
+
✗ Branch 1 not taken.
+
+
+
9180 if (ret < 0)
183 + goto exit;
184 +
185 + 9180exit:
186 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
187 + log("Failed to assign run for repository %s to worker %d, requeueing\n",
188 + run_get_repo_url(run), worker_get_fd(worker));
189 + run_queue_add_first(&server->run_queue, run);
190 + } else {
191 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Assigned run %d for repository %s to worker %d\n", run_get_id(run),
192 + run_get_repo_url(run), worker_get_fd(worker));
193 + 9180 run_destroy(run);
194 + }
195 +
196 + 9180 worker_destroy(worker);
197 + 9180}
198 +
199 + 29static void *server_main_thread(void *_server)
200 + {
201 + 29 struct server *server = (struct server *)_server;
202 + 29 int ret = 0;
203 +
204 + 29 ret = server_lock(server);
205 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
206 + goto exit;
207 +
208 + while (1) {
209 + 9209 ret = server_wait_for_action(server);
210 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9209 times.
+
+
+
9209 if (ret < 0)
211 + goto unlock;
212 +
213 +
+ 2/2 +
+
✓ Branch 0 taken 29 times.
+
✓ Branch 1 taken 9180 times.
+
+
+
9209 if (server->stopping)
214 + 29 goto unlock;
215 +
216 + 9180 server_assign_run(server);
217 + }
218 +
219 + 29unlock:
220 + 29 server_unlock(server);
221 +
222 + 29exit:
223 + 29 return NULL;
224 + }
225 +
226 + 9234static int server_handle_cmd_new_worker(UNUSED const struct jsonrpc_request *request,
227 + UNUSED struct jsonrpc_response **response, void *_ctx)
228 + {
229 + 9234 struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx;
230 + 9234 struct server *server = (struct server *)ctx->arg;
231 + 9234 int ret = 0;
232 +
233 + 9234 ret = file_dup(ctx->fd);
234 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
235 + return ret;
236 +
237 + 9234 const int fd = ret;
238 + 9234 struct worker *worker = NULL;
239 +
240 + 9234 ret = worker_create(&worker, fd);
241 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
242 + goto close;
243 +
244 + 9234 ret = server_enqueue_worker(server, worker);
245 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
246 + goto destroy_worker;
247 +
248 + 9234 return ret;
249 +
250 + destroy_worker:
251 + worker_destroy(worker);
252 +
253 + close:
254 + net_close(fd);
255 +
256 + return ret;
257 + }
258 +
259 + 9180static int server_handle_cmd_queue_run(const struct jsonrpc_request *request,
260 + struct jsonrpc_response **response, void *_ctx)
261 + {
262 + 9180 struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx;
263 + 9180 struct server *server = (struct server *)ctx->arg;
264 + 9180 int ret = 0;
265 +
266 + 9180 struct run *run = NULL;
267 +
268 + 9180 ret = request_parse_queue_run(request, &run);
269 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
270 + return ret;
271 +
272 + 9180 ret = jsonrpc_response_create(response, request, NULL);
273 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
274 + goto destroy_run;
275 +
276 + 9180 ret = server_enqueue_run(server, run);
277 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
278 + goto free_response;
279 +
280 + 9180 return ret;
281 +
282 + free_response:
283 + jsonrpc_response_destroy(*response);
284 + *response = NULL;
285 +
286 + destroy_run:
287 + run_destroy(run);
288 +
289 + return ret;
290 + }
291 +
292 + 9180static int server_handle_cmd_finished_run(const struct jsonrpc_request *request,
293 + UNUSED struct jsonrpc_response **response, void *_ctx)
294 + {
295 + 9180 struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx;
296 + 9180 struct server *server = (struct server *)ctx->arg;
297 + 9180 int ret = 0;
298 +
299 + 9180 int run_id = 0;
300 + struct proc_output *output;
301 +
302 + 9180 ret = request_parse_finished_run(request, &run_id, &output);
303 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
304 + return ret;
305 +
306 + 9180 ret = storage_run_finished(&server->storage, run_id, output);
307 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
308 + log_err("Failed to mark run %d as finished\n", run_id);
309 + goto free_output;
310 + }
311 +
312 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Marked run %d as finished\n", run_id);
313 +
314 + 9180free_output:
315 + 9180 proc_output_destroy(output);
316 +
317 + 9180 return ret;
318 + }
319 +
320 + 26static int server_handle_cmd_get_runs(const struct jsonrpc_request *request,
321 + struct jsonrpc_response **response, void *_ctx)
322 + {
323 + 26 struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx;
324 + 26 struct server *server = (struct server *)ctx->arg;
325 + 26 int ret = 0;
326 +
327 + 26 ret = request_parse_get_runs(request);
328 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (ret < 0)
329 + return ret;
330 +
331 + struct run_queue runs;
332 +
333 + 26 ret = storage_get_runs(&server->storage, &runs);
334 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (ret < 0) {
335 + log_err("Failed to fetch runs\n");
336 + return ret;
337 + }
338 +
339 + 26 ret = response_create_get_runs(response, request, &runs);
340 +
+ 1/2 +
+
✓ Branch 0 taken 26 times.
+
✗ Branch 1 not taken.
+
+
+
26 if (ret < 0)
341 + goto destroy_runs;
342 +
343 + 26destroy_runs:
344 + 26 run_queue_destroy(&runs);
345 +
346 + 26 return ret;
347 + }
348 +
349 + static struct cmd_desc commands[] = {
350 + {CMD_NEW_WORKER, server_handle_cmd_new_worker},
351 + {CMD_QUEUE_RUN, server_handle_cmd_queue_run},
352 + {CMD_FINISHED_RUN, server_handle_cmd_finished_run},
353 + {CMD_GET_RUNS, server_handle_cmd_get_runs},
354 + };
355 +
356 + static const size_t numof_commands = sizeof(commands) / sizeof(commands[0]);
357 +
358 + 29int server_create(struct server **_server, const struct settings *settings)
359 + {
360 + struct storage_settings storage_settings;
361 + 29 int ret = 0;
362 +
363 + 29 struct server *server = malloc(sizeof(struct server));
364 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!server) {
365 + log_errno("malloc");
366 + return -1;
367 + }
368 +
369 + 29 ret = pthread_mutex_init(&server->server_mtx, NULL);
370 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret) {
371 + pthread_errno(ret, "pthread_mutex_init");
372 + goto free;
373 + }
374 +
375 + 29 ret = pthread_cond_init(&server->server_cv, NULL);
376 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret) {
377 + pthread_errno(ret, "pthread_cond_init");
378 + goto destroy_mtx;
379 + }
380 +
381 + 29 server->stopping = 0;
382 +
383 + 29 ret = cmd_dispatcher_create(&server->cmd_dispatcher, commands, numof_commands, server);
384 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
385 + goto destroy_cv;
386 +
387 + 29 ret = event_loop_create(&server->event_loop);
388 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
389 + goto destroy_cmd_dispatcher;
390 +
391 + 29 ret = signalfd_create_sigterms();
392 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
393 + goto destroy_event_loop;
394 + 29 server->signalfd = ret;
395 +
396 + 29 ret = event_loop_add(server->event_loop, server->signalfd, POLLIN, server_set_stopping,
397 + server);
398 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
399 + goto close_signalfd;
400 +
401 + 29 worker_queue_create(&server->worker_queue);
402 +
403 + 29 ret = storage_sqlite_settings_create(&storage_settings, settings->sqlite_path);
404 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
405 + goto destroy_worker_queue;
406 +
407 + 29 ret = storage_create(&server->storage, &storage_settings);
408 + 29 storage_settings_destroy(&storage_settings);
409 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
410 + goto destroy_worker_queue;
411 +
412 + 29 ret = storage_get_run_queue(&server->storage, &server->run_queue);
413 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
414 + goto destroy_storage;
415 +
416 + 29 ret = tcp_server_create(&server->tcp_server, server->event_loop, settings->port,
417 + 29 cmd_dispatcher_handle_conn, server->cmd_dispatcher);
418 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
419 + goto destroy_run_queue;
420 +
421 + 29 ret = pthread_create(&server->main_thread, NULL, server_main_thread, server);
422 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret) {
423 + pthread_errno(ret, "pthread_create");
424 + goto destroy_tcp_server;
425 + }
426 +
427 + 29 *_server = server;
428 + 29 return ret;
429 +
430 + destroy_tcp_server:
431 + tcp_server_destroy(server->tcp_server);
432 +
433 + destroy_run_queue:
434 + run_queue_destroy(&server->run_queue);
435 +
436 + destroy_storage:
437 + storage_destroy(&server->storage);
438 +
439 + destroy_worker_queue:
440 + worker_queue_destroy(&server->worker_queue);
441 +
442 + close_signalfd:
443 + signalfd_destroy(server->signalfd);
444 +
445 + destroy_event_loop:
446 + event_loop_destroy(server->event_loop);
447 +
448 + destroy_cmd_dispatcher:
449 + cmd_dispatcher_destroy(server->cmd_dispatcher);
450 +
451 + destroy_cv:
452 + pthread_errno_if(pthread_cond_destroy(&server->server_cv), "pthread_cond_destroy");
453 +
454 + destroy_mtx:
455 + pthread_errno_if(pthread_mutex_destroy(&server->server_mtx), "pthread_mutex_destroy");
456 +
457 + free:
458 + free(server);
459 +
460 + return ret;
461 + }
462 +
463 + 29void server_destroy(struct server *server)
464 + {
465 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 log("Shutting down\n");
466 +
467 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
29 pthread_errno_if(pthread_join(server->main_thread, NULL), "pthread_join");
468 + 29 tcp_server_destroy(server->tcp_server);
469 + 29 storage_destroy(&server->storage);
470 + 29 run_queue_destroy(&server->run_queue);
471 + 29 worker_queue_destroy(&server->worker_queue);
472 + 29 signalfd_destroy(server->signalfd);
473 + 29 event_loop_destroy(server->event_loop);
474 + 29 cmd_dispatcher_destroy(server->cmd_dispatcher);
475 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
29 pthread_errno_if(pthread_cond_destroy(&server->server_cv), "pthread_cond_destroy");
476 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
29 pthread_errno_if(pthread_mutex_destroy(&server->server_mtx), "pthread_mutex_destroy");
477 + 29 free(server);
478 + 29}
479 +
480 + 29static int server_listen_thread(struct server *server)
481 + {
482 + 29 int ret = 0;
483 +
484 +
+ 2/2 +
+
✓ Branch 0 taken 54034 times.
+
✓ Branch 1 taken 29 times.
+
+
+
54063 while (!server->stopping) {
485 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 54034 times.
+
+
+
54034 log("Waiting for new connections\n");
486 +
487 + 54034 ret = event_loop_run(server->event_loop);
488 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54034 times.
+
+
+
54034 if (ret < 0)
489 + return ret;
490 + }
491 +
492 + 29 return 0;
493 + }
494 +
495 + 29int server_main(struct server *server)
496 + {
497 + 29 return server_listen_thread(server);
498 + }
499 +
+
+ +
+ + + + diff --git a/coverage/index.server_main.c.3ca591a47eaf0cc37ef7579efe6031fe.html b/coverage/index.server_main.c.3ca591a47eaf0cc37ef7579efe6031fe.html new file mode 100644 index 0000000..95b0db1 --- /dev/null +++ b/coverage/index.server_main.c.3ca591a47eaf0cc37ef7579efe6031fe.html @@ -0,0 +1,885 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/server_main.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:344379.1%
Branches:101471.4%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "cmd_line.h"
9 + #include "const.h"
10 + #include "log.h"
11 + #include "server.h"
12 +
13 + #include <getopt.h>
14 + #include <unistd.h>
15 +
16 + 35static struct settings default_settings(void)
17 + {
18 + 35 struct settings settings = {
19 + .port = default_port,
20 + .sqlite_path = default_sqlite_path,
21 + };
22 + 35 return settings;
23 + }
24 +
25 + 4const char *get_usage_string(void)
26 + {
27 + 4 return "[-h|--help] [-V|--version] [-v|--verbose] [-p|--port PORT] [-s|--sqlite PATH]";
28 + }
29 +
30 + 35static int parse_settings(struct settings *settings, int argc, char *argv[])
31 + {
32 + int opt, longind;
33 +
34 + 35 *settings = default_settings();
35 +
36 + /* clang-format off */
37 + static struct option long_options[] = {
38 + {"help", no_argument, 0, 'h'},
39 + {"version", no_argument, 0, 'V'},
40 + {"verbose", no_argument, 0, 'v'},
41 + {"port", required_argument, 0, 'p'},
42 + {"sqlite", required_argument, 0, 's'},
43 + {0, 0, 0, 0},
44 + };
45 + /* clang-format on */
46 +
47 +
+ 2/2 +
+
✓ Branch 1 taken 64 times.
+
✓ Branch 2 taken 29 times.
+
+
+
93 while ((opt = getopt_long(argc, argv, "hVvp:s:", long_options, &longind)) != -1) {
48 +
+ 5/6 +
+
✓ Branch 0 taken 2 times.
+
✓ Branch 1 taken 2 times.
+
✗ Branch 2 not taken.
+
✓ Branch 3 taken 29 times.
+
✓ Branch 4 taken 29 times.
+
✓ Branch 5 taken 2 times.
+
+
+
64 switch (opt) {
49 + 2 case 'h':
50 + 2 exit_with_usage(0);
51 + break;
52 + 2 case 'V':
53 + 2 exit_with_version();
54 + break;
55 + case 'v':
56 + g_log_lvl = LOG_LVL_DEBUG;
57 + break;
58 + 29 case 'p':
59 + 29 settings->port = optarg;
60 + 29 break;
61 + 29 case 's':
62 + 29 settings->sqlite_path = optarg;
63 + 29 break;
64 + 2 default:
65 + 2 exit_with_usage(1);
66 + break;
67 + }
68 + }
69 +
70 + 29 return 0;
71 + }
72 +
73 + 35int main(int argc, char *argv[])
74 + {
75 + struct settings settings;
76 + 35 struct server *server = NULL;
77 + 35 int ret = 0;
78 +
79 + 35 ret = parse_settings(&settings, argc, argv);
80 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
81 + return ret;
82 +
83 + 29 ret = server_create(&server, &settings);
84 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
85 + return ret;
86 +
87 + 29 ret = server_main(server);
88 +
+ 1/2 +
+
✓ Branch 0 taken 29 times.
+
✗ Branch 1 not taken.
+
+
+
29 if (ret < 0)
89 + goto destroy_server;
90 +
91 + 29destroy_server:
92 + 29 server_destroy(server);
93 +
94 + 29 return ret;
95 + }
96 +
+
+ +
+ + + + diff --git a/coverage/index.signal.c.71d63611c8a63e0778dd598afad76dfd.html b/coverage/index.signal.c.71d63611c8a63e0778dd598afad76dfd.html new file mode 100644 index 0000000..5ca5cd8 --- /dev/null +++ b/coverage/index.signal.c.71d63611c8a63e0778dd598afad76dfd.html @@ -0,0 +1,826 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/signal.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:313881.6%
Branches:51050.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "signal.h"
9 + #include "file.h"
10 + #include "log.h"
11 +
12 + #include <signal.h>
13 + #include <stddef.h>
14 + #include <sys/signalfd.h>
15 +
16 + static int sigterm_signals[] = {SIGINT, SIGTERM, SIGQUIT};
17 +
18 + 27703static void sigterms_mask(sigset_t *set)
19 + {
20 + 27703 sigemptyset(set);
21 +
+ 2/2 +
+
✓ Branch 0 taken 83109 times.
+
✓ Branch 1 taken 27703 times.
+
+
+
110812 for (size_t i = 0; i < sizeof(sigterm_signals) / sizeof(sigterm_signals[0]); ++i)
22 + 83109 sigaddset(set, sigterm_signals[i]);
23 + 27703}
24 +
25 + 82943static int signal_set_mask_internal(const sigset_t *new, sigset_t *old)
26 + {
27 + 82943 int ret = 0;
28 +
29 + 82943 ret = pthread_sigmask(SIG_SETMASK, new, old);
30 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 82943 times.
+
+
+
82943 if (ret) {
31 + pthread_errno(ret, "pthread_sigmask");
32 + return ret;
33 + }
34 +
35 + 82943 return ret;
36 + }
37 +
38 + 27620int signal_set_mask(const sigset_t *new)
39 + {
40 + 27620 return signal_set_mask_internal(new, NULL);
41 + }
42 +
43 + 27620int signal_block_all(sigset_t *old)
44 + {
45 + sigset_t new;
46 + 27620 sigfillset(&new);
47 + 27620 return signal_set_mask_internal(&new, old);
48 + }
49 +
50 + 27620int signal_block_sigterms(void)
51 + {
52 + sigset_t set;
53 + 27620 sigterms_mask(&set);
54 + 27620 return signal_set_mask_internal(&set, NULL);
55 + }
56 +
57 + 83int signalfd_create(const sigset_t *set)
58 + {
59 + static const int flags = SFD_CLOEXEC;
60 + sigset_t old;
61 + 83 int ret = 0;
62 +
63 + 83 ret = signal_set_mask_internal(set, &old);
64 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 83 times.
+
+
+
83 if (ret < 0)
65 + return ret;
66 +
67 + 83 ret = signalfd(-1, set, flags);
68 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 83 times.
+
+
+
83 if (ret < 0)
69 + goto restore;
70 +
71 + 83 return ret;
72 +
73 + restore:
74 + signal_set_mask_internal(&old, NULL);
75 +
76 + return ret;
77 + }
78 +
79 + 83int signalfd_create_sigterms(void)
80 + {
81 + sigset_t set;
82 + 83 sigterms_mask(&set);
83 + 83 return signalfd_create(&set);
84 + }
85 +
86 + 83void signalfd_destroy(int fd)
87 + {
88 + 83 file_close(fd);
89 + 83}
90 +
+
+ +
+ + + + diff --git a/coverage/index.sqlite.c.13cf77e7262c599539f10e3be0248b3e.html b/coverage/index.sqlite.c.13cf77e7262c599539f10e3be0248b3e.html new file mode 100644 index 0000000..4ef0e01 --- /dev/null +++ b/coverage/index.sqlite.c.13cf77e7262c599539f10e3be0248b3e.html @@ -0,0 +1,2733 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/sqlite.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:10116262.3%
Branches:219522.1%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "sqlite.h"
9 + #include "compiler.h"
10 + #include "log.h"
11 +
12 + #include <sqlite3.h>
13 +
14 + #include <stddef.h>
15 + #include <stdio.h>
16 + #include <stdlib.h>
17 + #include <string.h>
18 +
19 + #define sqlite_errno(var, fn) \
20 + do { \
21 + log_err("%s: %s\n", fn, sqlite3_errstr(var)); \
22 + var = -var; \
23 + } while (0)
24 +
25 + #define sqlite_errno_if(expr, fn) \
26 + do { \
27 + int CONCAT(ret, __LINE__) = expr; \
28 + if (CONCAT(ret, __LINE__)) \
29 + sqlite_errno(CONCAT(ret, __LINE__), fn); \
30 + } while (0)
31 +
32 + 29int sqlite_init(void)
33 + {
34 + 29 int ret = 0;
35 +
36 + 29 ret = sqlite3_initialize();
37 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret) {
38 + sqlite_errno(ret, "sqlite3_initialize");
39 + return ret;
40 + }
41 +
42 + 29 return ret;
43 + }
44 +
45 + 29void sqlite_destroy(void)
46 + {
47 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
29 sqlite_errno_if(sqlite3_shutdown(), "sqlite3_shutdown");
48 + 29}
49 +
50 + 29static int sqlite_open(const char *path, sqlite3 **db, int flags)
51 + {
52 + 29 int ret = 0;
53 +
54 + 29 ret = sqlite3_open_v2(path, db, flags, NULL);
55 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret) {
56 + sqlite_errno(ret, "sqlite3_open_v2");
57 + return ret;
58 + }
59 +
60 + 29 return ret;
61 + }
62 +
63 + 29int sqlite_open_rw(const char *path, sqlite3 **db)
64 + {
65 + static const int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
66 + 29 return sqlite_open(path, db, flags);
67 + }
68 +
69 + int sqlite_open_ro(const char *path, sqlite3 **db)
70 + {
71 + static const int flags = SQLITE_OPEN_READONLY;
72 + return sqlite_open(path, db, flags);
73 + }
74 +
75 + 29void sqlite_close(sqlite3 *db)
76 + {
77 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
29 sqlite_errno_if(sqlite3_close(db), "sqlite3_close");
78 + 29}
79 +
80 + 58int sqlite_exec(sqlite3 *db, const char *stmt, sqlite3_callback callback, void *arg)
81 + {
82 + 58 int ret = 0;
83 +
84 + 58 ret = sqlite3_exec(db, stmt, callback, arg, NULL);
85 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 58 times.
+
+
+
58 if (ret) {
86 + sqlite_errno(ret, "sqlite3_exec");
87 + return ret;
88 + }
89 +
90 + 58 return ret;
91 + }
92 +
93 + int sqlite_exec_log_result(UNUSED void *arg, int numof_columns, char **values, char **column_names)
94 + {
95 + log("Row:\n");
96 + for (int i = 0; i < numof_columns; ++i) {
97 + log("\t%s: %s\n", column_names[i], values[i]);
98 + }
99 + return 0;
100 + }
101 +
102 + 203int sqlite_prepare(sqlite3 *db, const char *stmt, sqlite3_stmt **result)
103 + {
104 + 203 int ret = 0;
105 +
106 + 203 ret = sqlite3_prepare_v2(db, stmt, -1, result, NULL);
107 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 203 times.
+
+
+
203 if (ret) {
108 + sqlite_errno(ret, "sqlite3_prepare_v2");
109 + return ret;
110 + }
111 +
112 + 203 return ret;
113 + }
114 +
115 + 36775void sqlite_reset(sqlite3_stmt *stmt)
116 + {
117 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 36775 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
36775 sqlite_errno_if(sqlite3_reset(stmt), "sqlite3_reset");
118 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 36775 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
36775 sqlite_errno_if(sqlite3_clear_bindings(stmt), "sqlite3_clear_bindings");
119 + 36775}
120 +
121 + 203void sqlite_finalize(sqlite3_stmt *stmt)
122 + {
123 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 203 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
203 sqlite_errno_if(sqlite3_finalize(stmt), "sqlite3_finalize");
124 + 203}
125 +
126 + 45984int sqlite_step(sqlite3_stmt *stmt)
127 + {
128 + 45984 int ret = 0;
129 +
130 + 45984 ret = sqlite3_step(stmt);
131 +
132 +
+ 2/3 +
+
✓ Branch 0 taken 27569 times.
+
✓ Branch 1 taken 18415 times.
+
✗ Branch 2 not taken.
+
+
+
45984 switch (ret) {
133 + 27569 case SQLITE_ROW:
134 + 27569 return 1;
135 + 18415 case SQLITE_DONE:
136 + 18415 return 0;
137 +
138 + default:
139 + sqlite_errno(ret, "sqlite3_step");
140 + return ret;
141 + }
142 + }
143 +
144 + 45929int sqlite_column_int(sqlite3_stmt *stmt, int index)
145 + {
146 + 45929 return sqlite3_column_int(stmt, index);
147 + }
148 +
149 + 18360int sqlite_column_text(sqlite3_stmt *stmt, int index, char **_result)
150 + {
151 + 18360 int ret = 0;
152 +
153 + 18360 const unsigned char *value = sqlite3_column_text(stmt, index);
154 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18360 times.
+
+
+
18360 if (!value) {
155 + ret = sqlite3_errcode(sqlite3_db_handle(stmt));
156 + if (ret) {
157 + sqlite_errno(ret, "sqlite3_column_text");
158 + return ret;
159 + }
160 +
161 + *_result = NULL;
162 + return 0;
163 + }
164 +
165 + 18360 ret = sqlite3_column_bytes(stmt, index);
166 + 18360 size_t nb = (size_t)ret;
167 +
168 + 18360 char *result = calloc(nb + 1, 1);
169 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 18360 times.
+
+
+
18360 if (!result) {
170 + log_errno("calloc");
171 + return -1;
172 + }
173 + 18360 memcpy(result, value, nb);
174 +
175 + 18360 *_result = result;
176 + 18360 return 0;
177 + }
178 +
179 + int sqlite_column_blob(sqlite3_stmt *stmt, int index, unsigned char **_result)
180 + {
181 + int ret = 0;
182 +
183 + const unsigned char *value = sqlite3_column_blob(stmt, index);
184 + if (!value) {
185 + ret = sqlite3_errcode(sqlite3_db_handle(stmt));
186 + if (ret) {
187 + sqlite_errno(ret, "sqlite3_column_text");
188 + return ret;
189 + }
190 +
191 + *_result = NULL;
192 + return 0;
193 + }
194 +
195 + ret = sqlite3_column_bytes(stmt, index);
196 + size_t nb = (size_t)ret;
197 +
198 + unsigned char *result = malloc(nb);
199 + if (!result) {
200 + log_errno("malloc");
201 + return -1;
202 + }
203 + memcpy(result, value, nb);
204 +
205 + *_result = result;
206 + return 0;
207 + }
208 +
209 + 45929int sqlite_bind_int(sqlite3_stmt *stmt, int index, int value)
210 + {
211 + 45929 int ret = 0;
212 +
213 + 45929 ret = sqlite3_bind_int(stmt, index, value);
214 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 45929 times.
+
+
+
45929 if (ret) {
215 + sqlite_errno(ret, "sqlite3_bind_int");
216 + return ret;
217 + }
218 +
219 + 45929 return ret;
220 + }
221 +
222 + 27540int sqlite_bind_text(sqlite3_stmt *stmt, int index, const char *value)
223 + {
224 + 27540 int ret = 0;
225 +
226 + 27540 ret = sqlite3_bind_text(stmt, index, value, -1, SQLITE_STATIC);
227 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27540 times.
+
+
+
27540 if (ret) {
228 + sqlite_errno(ret, "sqlite3_bind_text");
229 + return ret;
230 + }
231 +
232 + 27540 return ret;
233 + }
234 +
235 + 9180int sqlite_bind_blob(sqlite3_stmt *stmt, int index, unsigned char *value, size_t nb)
236 + {
237 + 9180 int ret = 0;
238 +
239 + 9180 ret = sqlite3_bind_blob64(stmt, index, value, nb, SQLITE_STATIC);
240 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret) {
241 + sqlite_errno(ret, "sqlite3_bind_blob64");
242 + return ret;
243 + }
244 +
245 + 9180 return ret;
246 + }
247 +
248 + 29int sqlite_exec_as_transaction(sqlite3 *db, const char *stmt)
249 + {
250 + static const char *const fmt = "BEGIN; %s COMMIT;";
251 + 29 int ret = 0;
252 +
253 + 29 ret = snprintf(NULL, 0, fmt, stmt);
254 + 29 size_t nb = (size_t)ret + 1;
255 + 29 ret = 0;
256 +
257 + 29 char *full_stmt = malloc(nb);
258 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!full_stmt) {
259 + log_errno("malloc");
260 + return -1;
261 + }
262 + 29 snprintf(full_stmt, nb, fmt, stmt);
263 +
264 + 29 ret = sqlite_exec(db, stmt, NULL, NULL);
265 + 29 goto free;
266 +
267 + 29free:
268 + 29 free(full_stmt);
269 +
270 + 29 return ret;
271 + }
272 +
273 + 29int sqlite_get_user_version(sqlite3 *db, unsigned int *output)
274 + {
275 + static const char *const sql = "PRAGMA user_version;";
276 +
277 + 29 sqlite3_stmt *stmt = NULL;
278 + 29 int result = -1, ret = 0;
279 +
280 + 29 ret = sqlite_prepare(db, sql, &stmt);
281 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
282 + return ret;
283 + 29 ret = sqlite_step(stmt);
284 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
285 + goto finalize;
286 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!ret) {
287 + ret = -1;
288 + log_err("Failed to read database version\n");
289 + goto finalize;
290 + }
291 +
292 + 29 result = sqlite_column_int(stmt, 0);
293 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (result < 0) {
294 + log_err("Invalid database version: %d\n", result);
295 + ret = -1;
296 + goto finalize;
297 + }
298 + 29 *output = (unsigned int)result;
299 +
300 + 29 goto finalize;
301 +
302 + 29finalize:
303 + 29 sqlite_finalize(stmt);
304 +
305 + 29 return ret;
306 + }
307 +
308 + 29int sqlite_set_foreign_keys(sqlite3 *db)
309 + {
310 + static const char *const sql = "PRAGMA foreign_keys = ON;";
311 + 29 return sqlite_exec(db, sql, NULL, NULL);
312 + }
313 +
+
+ +
+ + + + diff --git a/coverage/index.storage.c.96d197609feea4b630e7b775fb18af81.html b/coverage/index.storage.c.96d197609feea4b630e7b775fb18af81.html new file mode 100644 index 0000000..97fd758 --- /dev/null +++ b/coverage/index.storage.c.96d197609feea4b630e7b775fb18af81.html @@ -0,0 +1,1189 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/storage.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:374975.5%
Branches:92045.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "storage.h"
9 + #include "log.h"
10 + #include "process.h"
11 + #include "run_queue.h"
12 + #include "storage_sqlite.h"
13 +
14 + #include <stddef.h>
15 +
16 + typedef void (*storage_settings_destroy_t)(const struct storage_settings *);
17 + typedef int (*storage_create_t)(struct storage *, const struct storage_settings *);
18 + typedef void (*storage_destroy_t)(struct storage *);
19 +
20 + typedef int (*storage_run_create_t)(struct storage *, const char *repo_url, const char *rev);
21 + typedef int (*storage_run_finished_t)(struct storage *, int repo_id, const struct proc_output *);
22 +
23 + typedef int (*storage_get_runs_t)(struct storage *, struct run_queue *);
24 + typedef storage_get_runs_t storage_get_run_queue_t;
25 +
26 + struct storage_api {
27 + storage_settings_destroy_t destroy_settings;
28 + storage_create_t create;
29 + storage_destroy_t destroy;
30 +
31 + storage_run_create_t run_create;
32 + storage_run_finished_t run_finished;
33 +
34 + storage_get_runs_t get_runs;
35 + storage_get_run_queue_t get_run_queue;
36 + };
37 +
38 + static const struct storage_api apis[] = {
39 + {
40 + storage_sqlite_settings_destroy,
41 + storage_sqlite_create,
42 + storage_sqlite_destroy,
43 +
44 + storage_sqlite_run_create,
45 + storage_sqlite_run_finished,
46 +
47 + storage_sqlite_get_runs,
48 + storage_sqlite_get_run_queue,
49 + },
50 + };
51 +
52 + 18502static size_t numof_apis(void)
53 + {
54 + 18502 return sizeof(apis) / sizeof(apis[0]);
55 + }
56 +
57 + 18502static const struct storage_api *get_api(enum storage_type type)
58 + {
59 + if (type < 0)
60 + goto invalid_type;
61 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 18502 times.
+
+
+
18502 if ((size_t)type > numof_apis())
62 + goto invalid_type;
63 +
64 + 18502 return &apis[type];
65 +
66 + invalid_type:
67 + log_err("Unsupported storage type: %d\n", type);
68 + return NULL;
69 + }
70 +
71 + 29void storage_settings_destroy(const struct storage_settings *settings)
72 + {
73 + 29 const struct storage_api *api = get_api(settings->type);
74 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!api)
75 + return;
76 + 29 api->destroy_settings(settings);
77 + }
78 +
79 + 29int storage_create(struct storage *storage, const struct storage_settings *settings)
80 + {
81 + 29 int ret = 0;
82 + 29 const struct storage_api *api = get_api(settings->type);
83 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!api)
84 + return -1;
85 + 29 ret = api->create(storage, settings);
86 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
87 + return ret;
88 + 29 storage->type = settings->type;
89 + 29 return ret;
90 + }
91 +
92 + 29void storage_destroy(struct storage *storage)
93 + {
94 + 29 const struct storage_api *api = get_api(storage->type);
95 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!api)
96 + return;
97 + 29 api->destroy(storage);
98 + }
99 +
100 + 9180int storage_run_create(struct storage *storage, const char *repo_url, const char *rev)
101 + {
102 + 9180 const struct storage_api *api = get_api(storage->type);
103 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!api)
104 + return -1;
105 + 9180 return api->run_create(storage, repo_url, rev);
106 + }
107 +
108 + 9180int storage_run_finished(struct storage *storage, int run_id, const struct proc_output *output)
109 + {
110 + 9180 const struct storage_api *api = get_api(storage->type);
111 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!api)
112 + return -1;
113 + 9180 return api->run_finished(storage, run_id, output);
114 + }
115 +
116 + 26int storage_get_runs(struct storage *storage, struct run_queue *queue)
117 + {
118 + 26 const struct storage_api *api = get_api(storage->type);
119 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (!api)
120 + return -1;
121 + 26 return api->get_runs(storage, queue);
122 + }
123 +
124 + 29int storage_get_run_queue(struct storage *storage, struct run_queue *queue)
125 + {
126 + 29 const struct storage_api *api = get_api(storage->type);
127 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!api)
128 + return -1;
129 + 29 return api->get_run_queue(storage, queue);
130 + }
131 +
+
+ +
+ + + + diff --git a/coverage/index.storage_sqlite.c.b44f7f73d467be85cd4227a40c11d12a.html b/coverage/index.storage_sqlite.c.b44f7f73d467be85cd4227a40c11d12a.html new file mode 100644 index 0000000..935b9ed --- /dev/null +++ b/coverage/index.storage_sqlite.c.b44f7f73d467be85cd4227a40c11d12a.html @@ -0,0 +1,4906 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/storage_sqlite.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:24533872.5%
Branches:6615642.3%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "storage_sqlite.h"
9 + #include "log.h"
10 + #include "process.h"
11 + #include "run_queue.h"
12 + #include "sql/sqlite_sql.h"
13 + #include "sqlite.h"
14 + #include "storage.h"
15 +
16 + #include <sqlite3.h>
17 +
18 + #include <pthread.h>
19 + #include <stdio.h>
20 + #include <stdlib.h>
21 + #include <string.h>
22 +
23 + struct storage_sqlite_settings {
24 + char *path;
25 + };
26 +
27 + 29int storage_sqlite_settings_create(struct storage_settings *settings, const char *path)
28 + {
29 + 29 struct storage_sqlite_settings *sqlite = malloc(sizeof(struct storage_sqlite_settings));
30 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!sqlite) {
31 + log_errno("malloc");
32 + return -1;
33 + }
34 +
35 + 29 sqlite->path = strdup(path);
36 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!sqlite->path) {
37 + log_errno("strdup");
38 + goto free;
39 + }
40 +
41 + 29 settings->type = STORAGE_TYPE_SQLITE;
42 + 29 settings->sqlite = sqlite;
43 + 29 return 0;
44 +
45 + free:
46 + free(sqlite);
47 +
48 + return -1;
49 + }
50 +
51 + 29void storage_sqlite_settings_destroy(const struct storage_settings *settings)
52 + {
53 + 29 free(settings->sqlite->path);
54 + 29 free(settings->sqlite);
55 + 29}
56 +
57 + struct prepared_stmt {
58 + pthread_mutex_t mtx;
59 + sqlite3_stmt *impl;
60 + };
61 +
62 + 174static int prepared_stmt_init(struct prepared_stmt *stmt, sqlite3 *db, const char *sql)
63 + {
64 + 174 int ret = 0;
65 +
66 + 174 ret = pthread_mutex_init(&stmt->mtx, NULL);
67 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 174 times.
+
+
+
174 if (ret) {
68 + pthread_errno(ret, "pthread_mutex_init");
69 + return ret;
70 + }
71 +
72 + 174 ret = sqlite_prepare(db, sql, &stmt->impl);
73 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 174 times.
+
+
+
174 if (ret < 0)
74 + goto destroy_mtx;
75 +
76 + 174 return ret;
77 +
78 + destroy_mtx:
79 + pthread_errno_if(pthread_mutex_destroy(&stmt->mtx), "pthread_mutex_destroy");
80 +
81 + return ret;
82 + }
83 +
84 + 174static void prepared_stmt_destroy(struct prepared_stmt *stmt)
85 + {
86 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 174 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
174 pthread_errno_if(pthread_mutex_destroy(&stmt->mtx), "pthread_mutex_destroy");
87 + 174 sqlite_finalize(stmt->impl);
88 + 174}
89 +
90 + 36775static int prepared_stmt_lock(struct prepared_stmt *stmt)
91 + {
92 + 36775 int ret = pthread_mutex_lock(&stmt->mtx);
93 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 36775 times.
+
+
+
36775 if (ret) {
94 + pthread_errno(ret, "pthread_mutex_unlock");
95 + return ret;
96 + }
97 + 36775 return ret;
98 + }
99 +
100 + 36775static void prepared_stmt_unlock(struct prepared_stmt *stmt)
101 + {
102 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 36775 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
36775 pthread_errno_if(pthread_mutex_unlock(&stmt->mtx), "pthread_mutex_unlock");
103 + 36775}
104 +
105 + struct storage_sqlite {
106 + sqlite3 *db;
107 +
108 + struct prepared_stmt stmt_repo_find;
109 + struct prepared_stmt stmt_repo_insert;
110 + struct prepared_stmt stmt_run_insert;
111 + struct prepared_stmt stmt_run_finished;
112 + struct prepared_stmt stmt_get_runs;
113 + struct prepared_stmt stmt_get_run_queue;
114 + };
115 +
116 + 29static int storage_sqlite_upgrade_to(struct storage_sqlite *storage, size_t version)
117 + {
118 + static const char *const fmt = "%s PRAGMA user_version = %zu;";
119 +
120 + 29 const char *script = sqlite_schemas[version];
121 + 29 int ret = 0;
122 +
123 + 29 ret = snprintf(NULL, 0, fmt, script, version + 1);
124 + 29 size_t nb = (size_t)ret + 1;
125 + 29 ret = 0;
126 +
127 + 29 char *full_script = malloc(nb);
128 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!full_script) {
129 + log_errno("malloc");
130 + return -1;
131 + }
132 + 29 snprintf(full_script, nb, fmt, script, version + 1);
133 +
134 + 29 ret = sqlite_exec_as_transaction(storage->db, full_script);
135 + 29 goto free;
136 +
137 + 29free:
138 + 29 free(full_script);
139 +
140 + 29 return ret;
141 + }
142 +
143 + 29static int storage_sqlite_upgrade_from_to(struct storage_sqlite *storage, size_t from, size_t to)
144 + {
145 + 29 int ret = 0;
146 +
147 +
+ 2/2 +
+
✓ Branch 0 taken 29 times.
+
✓ Branch 1 taken 29 times.
+
+
+
58 for (size_t i = from; i < to; ++i) {
148 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 log("Upgrading SQLite database from version %zu to version %zu\n", i, i + 1);
149 + 29 ret = storage_sqlite_upgrade_to(storage, i);
150 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0) {
151 + log_err("Failed to upgrade to version %zu\n", i + 1);
152 + return ret;
153 + }
154 + }
155 +
156 + 29 return ret;
157 + }
158 +
159 + 29static int storage_sqlite_upgrade(struct storage_sqlite *storage)
160 + {
161 + 29 unsigned int current_version = 0;
162 + 29 int ret = 0;
163 +
164 + 29 ret = sqlite_get_user_version(storage->db, &current_version);
165 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
166 + return ret;
167 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 log("SQLite database version: %u\n", current_version);
168 +
169 + 29 size_t newest_version = sizeof(sqlite_schemas) / sizeof(sqlite_schemas[0]);
170 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 log("Newest database version: %zu\n", newest_version);
171 +
172 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (current_version > newest_version) {
173 + log_err("Unknown database version: %u\n", current_version);
174 + return -1;
175 + }
176 +
177 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (current_version == newest_version) {
178 + log("SQLite database already at the newest version\n");
179 + return 0;
180 + }
181 +
182 + 29 return storage_sqlite_upgrade_from_to(storage, current_version, newest_version);
183 + }
184 +
185 + 29static int storage_sqlite_setup(struct storage_sqlite *storage)
186 + {
187 + 29 int ret = 0;
188 +
189 + 29 ret = sqlite_set_foreign_keys(storage->db);
190 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
191 + return ret;
192 +
193 + 29 ret = storage_sqlite_upgrade(storage);
194 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
195 + return ret;
196 +
197 + 29 return ret;
198 + }
199 +
200 + 29static int storage_sqlite_prepare_statements(struct storage_sqlite *storage)
201 + {
202 + static const char *const fmt_repo_find = "SELECT id FROM cimple_repos WHERE url = ?;";
203 + static const char *const fmt_repo_insert =
204 + "INSERT INTO cimple_repos(url) VALUES (?) ON CONFLICT(url) DO NOTHING;";
205 + static const char *const fmt_run_insert =
206 + "INSERT INTO cimple_runs(status, exit_code, output, repo_id, repo_rev) VALUES (?, -1, x'', ?, ?) RETURNING id;";
207 + static const char *const fmt_run_finished =
208 + "UPDATE cimple_runs SET status = ?, exit_code = ?, output = ? WHERE id = ?;";
209 + static const char *const fmt_get_runs =
210 + "SELECT id, status, exit_code, repo_url, repo_rev FROM cimple_runs_view ORDER BY id DESC";
211 + static const char *const fmt_get_run_queue =
212 + "SELECT id, status, exit_code, repo_url, repo_rev FROM cimple_runs_view WHERE status = ? ORDER BY id;";
213 +
214 + 29 int ret = 0;
215 +
216 + 29 ret = prepared_stmt_init(&storage->stmt_repo_find, storage->db, fmt_repo_find);
217 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
218 + return ret;
219 + 29 ret = prepared_stmt_init(&storage->stmt_repo_insert, storage->db, fmt_repo_insert);
220 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
221 + goto finalize_repo_find;
222 + 29 ret = prepared_stmt_init(&storage->stmt_run_insert, storage->db, fmt_run_insert);
223 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
224 + goto finalize_repo_insert;
225 + 29 ret = prepared_stmt_init(&storage->stmt_run_finished, storage->db, fmt_run_finished);
226 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
227 + goto finalize_run_insert;
228 + 29 ret = prepared_stmt_init(&storage->stmt_get_runs, storage->db, fmt_get_runs);
229 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
230 + goto finalize_run_finished;
231 + 29 ret = prepared_stmt_init(&storage->stmt_get_run_queue, storage->db, fmt_get_run_queue);
232 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
233 + goto finalize_get_runs;
234 +
235 + 29 return ret;
236 +
237 + finalize_get_runs:
238 + prepared_stmt_destroy(&storage->stmt_get_runs);
239 + finalize_run_finished:
240 + prepared_stmt_destroy(&storage->stmt_run_finished);
241 + finalize_run_insert:
242 + prepared_stmt_destroy(&storage->stmt_run_insert);
243 + finalize_repo_insert:
244 + prepared_stmt_destroy(&storage->stmt_repo_insert);
245 + finalize_repo_find:
246 + prepared_stmt_destroy(&storage->stmt_repo_find);
247 +
248 + return ret;
249 + }
250 +
251 + 29static void storage_sqlite_finalize_statements(struct storage_sqlite *storage)
252 + {
253 + 29 prepared_stmt_destroy(&storage->stmt_get_run_queue);
254 + 29 prepared_stmt_destroy(&storage->stmt_get_runs);
255 + 29 prepared_stmt_destroy(&storage->stmt_run_finished);
256 + 29 prepared_stmt_destroy(&storage->stmt_run_insert);
257 + 29 prepared_stmt_destroy(&storage->stmt_repo_insert);
258 + 29 prepared_stmt_destroy(&storage->stmt_repo_find);
259 + 29}
260 +
261 + 29int storage_sqlite_create(struct storage *storage, const struct storage_settings *settings)
262 + {
263 + 29 int ret = 0;
264 +
265 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 29 times.
+
+
+
29 log("Using SQLite database at %s\n", settings->sqlite->path);
266 +
267 + 29 struct storage_sqlite *sqlite = malloc(sizeof(struct storage_sqlite));
268 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!sqlite) {
269 + log_errno("malloc");
270 + return -1;
271 + }
272 +
273 + 29 ret = sqlite_init();
274 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
275 + goto free;
276 + 29 ret = sqlite_open_rw(settings->sqlite->path, &sqlite->db);
277 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
278 + goto destroy;
279 + 29 ret = storage_sqlite_setup(sqlite);
280 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
281 + goto close;
282 + 29 ret = storage_sqlite_prepare_statements(sqlite);
283 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
284 + goto close;
285 +
286 + 29 storage->sqlite = sqlite;
287 + 29 return ret;
288 +
289 + close:
290 + sqlite_close(storage->sqlite->db);
291 + destroy:
292 + sqlite_destroy();
293 + free:
294 + free(sqlite);
295 +
296 + return ret;
297 + }
298 +
299 + 29void storage_sqlite_destroy(struct storage *storage)
300 + {
301 + 29 storage_sqlite_finalize_statements(storage->sqlite);
302 + 29 sqlite_close(storage->sqlite->db);
303 + 29 sqlite_destroy();
304 + 29 free(storage->sqlite);
305 + 29}
306 +
307 + 9180static int storage_sqlite_find_repo(struct storage_sqlite *storage, const char *url)
308 + {
309 + 9180 struct prepared_stmt *stmt = &storage->stmt_repo_find;
310 + 9180 int ret = 0;
311 +
312 + 9180 ret = prepared_stmt_lock(stmt);
313 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
314 + return ret;
315 + 9180 ret = sqlite_bind_text(stmt->impl, 1, url);
316 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
317 + goto reset;
318 + 9180 ret = sqlite_step(stmt->impl);
319 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
320 + goto reset;
321 +
322 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!ret)
323 + goto reset;
324 +
325 + 9180 ret = sqlite_column_int(stmt->impl, 0);
326 + 9180 goto reset;
327 +
328 + 9180reset:
329 + 9180 sqlite_reset(stmt->impl);
330 + 9180 prepared_stmt_unlock(stmt);
331 +
332 + 9180 return ret;
333 + }
334 +
335 + 9180static int storage_sqlite_insert_repo(struct storage_sqlite *storage, const char *url)
336 + {
337 + 9180 struct prepared_stmt *stmt = &storage->stmt_repo_insert;
338 + 9180 int ret = 0;
339 +
340 + 9180 ret = prepared_stmt_lock(stmt);
341 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
342 + return ret;
343 + 9180 ret = sqlite_bind_text(stmt->impl, 1, url);
344 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
345 + goto reset;
346 + 9180 ret = sqlite_step(stmt->impl);
347 +
+ 1/2 +
+
✓ Branch 0 taken 9180 times.
+
✗ Branch 1 not taken.
+
+
+
9180 if (ret < 0)
348 + goto reset;
349 +
350 + 9180reset:
351 + 9180 sqlite_reset(stmt->impl);
352 + 9180 prepared_stmt_unlock(stmt);
353 +
354 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
355 + return ret;
356 +
357 + 9180 return storage_sqlite_find_repo(storage, url);
358 + }
359 +
360 + 9180static int storage_sqlite_insert_run(struct storage_sqlite *storage, int repo_id, const char *rev)
361 + {
362 + 9180 struct prepared_stmt *stmt = &storage->stmt_run_insert;
363 + 9180 int ret = 0;
364 +
365 + 9180 ret = prepared_stmt_lock(stmt);
366 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
367 + return ret;
368 + 9180 ret = sqlite_bind_int(stmt->impl, 1, RUN_STATUS_CREATED);
369 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
370 + goto reset;
371 + 9180 ret = sqlite_bind_int(stmt->impl, 2, repo_id);
372 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
373 + goto reset;
374 + 9180 ret = sqlite_bind_text(stmt->impl, 3, rev);
375 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
376 + goto reset;
377 + 9180 ret = sqlite_step(stmt->impl);
378 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
379 + goto reset;
380 +
381 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (!ret) {
382 + ret = -1;
383 + log_err("Failed to insert a run\n");
384 + goto reset;
385 + }
386 +
387 + 9180 ret = sqlite_column_int(stmt->impl, 0);
388 + 9180 goto reset;
389 +
390 + 9180reset:
391 + 9180 sqlite_reset(stmt->impl);
392 + 9180 prepared_stmt_unlock(stmt);
393 +
394 + 9180 return ret;
395 + }
396 +
397 + 9180int storage_sqlite_run_create(struct storage *storage, const char *repo_url, const char *rev)
398 + {
399 + 9180 int ret = 0;
400 +
401 + 9180 ret = storage_sqlite_insert_repo(storage->sqlite, repo_url);
402 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
403 + return ret;
404 +
405 + 9180 ret = storage_sqlite_insert_run(storage->sqlite, ret, rev);
406 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
407 + return ret;
408 +
409 + 9180 return ret;
410 + }
411 +
412 + 9180int storage_sqlite_run_finished(struct storage *storage, int run_id,
413 + const struct proc_output *output)
414 + {
415 + 9180 struct prepared_stmt *stmt = &storage->sqlite->stmt_run_finished;
416 + 9180 int ret = 0;
417 +
418 + 9180 ret = prepared_stmt_lock(stmt);
419 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
420 + return ret;
421 + 9180 ret = sqlite_bind_int(stmt->impl, 1, RUN_STATUS_FINISHED);
422 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
423 + goto reset;
424 + 9180 ret = sqlite_bind_int(stmt->impl, 2, output->ec);
425 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
426 + goto reset;
427 + 9180 ret = sqlite_bind_blob(stmt->impl, 3, output->data, output->data_size);
428 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
429 + goto reset;
430 + 9180 ret = sqlite_bind_int(stmt->impl, 4, run_id);
431 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
432 + goto reset;
433 + 9180 ret = sqlite_step(stmt->impl);
434 +
+ 1/2 +
+
✓ Branch 0 taken 9180 times.
+
✗ Branch 1 not taken.
+
+
+
9180 if (ret < 0)
435 + goto reset;
436 +
437 + 9180reset:
438 + 9180 sqlite_reset(stmt->impl);
439 + 9180 prepared_stmt_unlock(stmt);
440 +
441 + 9180 return ret;
442 + }
443 +
444 + 9180static int storage_sqlite_row_to_run(struct sqlite3_stmt *stmt, struct run **run)
445 + {
446 + 9180 int ret = 0;
447 +
448 + 9180 int id = sqlite_column_int(stmt, 0);
449 + 9180 int status = sqlite_column_int(stmt, 1);
450 + 9180 int exit_code = sqlite_column_int(stmt, 2);
451 +
452 + 9180 char *url = NULL;
453 + 9180 ret = sqlite_column_text(stmt, 3, &url);
454 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
455 + return ret;
456 +
457 + 9180 char *rev = NULL;
458 + 9180 ret = sqlite_column_text(stmt, 4, &rev);
459 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
460 + goto free_url;
461 +
462 + 9180 ret = run_new(run, id, url, rev, status, exit_code);
463 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
464 + goto free_rev;
465 +
466 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9180 times.
+
+
+
9180 log("Adding a run %d for repository %s to the queue\n", id, url);
467 +
468 + 9180free_rev:
469 + 9180 free(rev);
470 +
471 + 9180free_url:
472 + 9180 free(url);
473 +
474 + 9180 return ret;
475 + }
476 +
477 + 55static int storage_sqlite_rows_to_runs(struct sqlite3_stmt *stmt, struct run_queue *queue)
478 + {
479 + 55 int ret = 0;
480 +
481 + 55 run_queue_create(queue);
482 +
483 + 9180 while (1) {
484 + 9235 ret = sqlite_step(stmt);
485 +
+ 2/2 +
+
✓ Branch 0 taken 55 times.
+
✓ Branch 1 taken 9180 times.
+
+
+
9235 if (!ret)
486 + 55 break;
487 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
488 + goto run_queue_destroy;
489 +
490 + 9180 struct run *run = NULL;
491 +
492 + 9180 ret = storage_sqlite_row_to_run(stmt, &run);
493 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
494 + goto run_queue_destroy;
495 +
496 + 9180 run_queue_add_last(queue, run);
497 + }
498 +
499 + 55 return ret;
500 +
501 + run_queue_destroy:
502 + run_queue_destroy(queue);
503 +
504 + return ret;
505 + }
506 +
507 + 26int storage_sqlite_get_runs(struct storage *storage, struct run_queue *queue)
508 + {
509 + 26 struct prepared_stmt *stmt = &storage->sqlite->stmt_get_runs;
510 + 26 int ret = 0;
511 +
512 + 26 ret = prepared_stmt_lock(stmt);
513 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 26 times.
+
+
+
26 if (ret < 0)
514 + return ret;
515 + 26 ret = storage_sqlite_rows_to_runs(stmt->impl, queue);
516 +
+ 1/2 +
+
✓ Branch 0 taken 26 times.
+
✗ Branch 1 not taken.
+
+
+
26 if (ret < 0)
517 + goto reset;
518 +
519 + 26reset:
520 + 26 sqlite_reset(stmt->impl);
521 + 26 prepared_stmt_unlock(stmt);
522 +
523 + 26 return ret;
524 + }
525 +
526 + 29int storage_sqlite_get_run_queue(struct storage *storage, struct run_queue *queue)
527 + {
528 + 29 struct prepared_stmt *stmt = &storage->sqlite->stmt_get_run_queue;
529 + 29 int ret = 0;
530 +
531 + 29 ret = prepared_stmt_lock(stmt);
532 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
533 + return ret;
534 + 29 ret = sqlite_bind_int(stmt->impl, 1, RUN_STATUS_CREATED);
535 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
536 + goto reset;
537 + 29 ret = storage_sqlite_rows_to_runs(stmt->impl, queue);
538 +
+ 1/2 +
+
✓ Branch 0 taken 29 times.
+
✗ Branch 1 not taken.
+
+
+
29 if (ret < 0)
539 + goto reset;
540 +
541 + 29reset:
542 + 29 sqlite_reset(stmt->impl);
543 + 29 prepared_stmt_unlock(stmt);
544 +
545 + 29 return ret;
546 + }
547 +
+
+ +
+ + + + diff --git a/coverage/index.string.c.2a75186e465ffeac1b306a350f4a56f8.html b/coverage/index.string.c.2a75186e465ffeac1b306a350f4a56f8.html new file mode 100644 index 0000000..d4fd91c --- /dev/null +++ b/coverage/index.string.c.2a75186e465ffeac1b306a350f4a56f8.html @@ -0,0 +1,515 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/string.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:62227.3%
Branches:31618.8%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "string.h"
9 + #include "log.h"
10 +
11 + #include <errno.h>
12 + #include <stdlib.h>
13 + #include <string.h>
14 +
15 + /* glibc calls this stpecpy; it's not provided by glibc; however, it does
16 + * provide a possible implementation in string_copying(7), which I copied from. */
17 + 305444char *string_append(char *dst, char *end, const char *src)
18 + {
19 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (!dst)
20 + return NULL;
21 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 305444 times.
+
+
+
305444 if (dst == end)
22 + return end;
23 +
24 + 305444 char *p = memccpy(dst, src, '\0', end - dst);
25 +
+ 1/2 +
+
✓ Branch 0 taken 305444 times.
+
✗ Branch 1 not taken.
+
+
+
305444 if (p)
26 + 305444 return p - 1;
27 +
28 + end[-1] = '\0';
29 + return end;
30 + }
31 +
32 + int string_to_int(const char *src, int *result)
33 + {
34 + char *endptr = NULL;
35 +
36 + errno = 0;
37 + long ret = strtol(src, &endptr, 10);
38 +
39 + if (errno) {
40 + log_errno("strtol");
41 + return -1;
42 + }
43 +
44 + if (endptr == src || *endptr != '\0') {
45 + log_err("Invalid number: %s\n", src);
46 + return -1;
47 + }
48 +
49 + *result = (int)ret;
50 + return 0;
51 + }
52 +
+
+ +
+ + + + diff --git a/coverage/index.tcp_server.c.68fbb5aebb39dbc263f5110d228c9b35.html b/coverage/index.tcp_server.c.68fbb5aebb39dbc263f5110d228c9b35.html new file mode 100644 index 0000000..d3df3c6 --- /dev/null +++ b/coverage/index.tcp_server.c.68fbb5aebb39dbc263f5110d228c9b35.html @@ -0,0 +1,2532 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/tcp_server.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:8712271.3%
Branches:276640.9%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "tcp_server.h"
9 + #include "compiler.h"
10 + #include "event_loop.h"
11 + #include "file.h"
12 + #include "log.h"
13 + #include "net.h"
14 + #include "signal.h"
15 +
16 + #include <poll.h>
17 + #include <pthread.h>
18 + #include <signal.h>
19 + #include <stdlib.h>
20 + #include <sys/eventfd.h>
21 + #include <sys/queue.h>
22 + #include <unistd.h>
23 +
24 + /*
25 + * This is a simple threaded TCP server implementation. Each client is handled
26 + * in a separate thread.
27 + *
28 + * It used to be much simpler; basically, we have two types of client
29 + * connections: those made by cimple-worker and cimple-client respectively.
30 + * cimple-server would keep track of cimple-worker threads/connections, and
31 + * clean them up when assigning tasks/on shutdown.
32 + *
33 + * What about cimple-client connections though? I struggled to come up with a
34 + * scheme that would allow cimple-server to clean them up gracefully. When
35 + * would it do the cleanup even? I didn't want to do it on shutdown, since
36 + * there would be potentially a lot of them.
37 + *
38 + * One solution is to make client threads detached. This is a common advise;
39 + * I really don't understand the merit of this approach though. Client threads
40 + * actively work on shared data, take locks, etc. Data corruption is very
41 + * likely after the main thread exits and all the rest are killed.
42 + *
43 + * Another approach is pre-threading; we make a number of threads beforehand
44 + * and handle all client connections; I view this approach as limiting in
45 + * principle; probably that's foolish of me.
46 + *
47 + * Finally, I cannot bring myself to do non-blocking I/O. I honestly fear the
48 + * amount of work it would require to maintain read buffers, etc.
49 + *
50 + * So I came up with this convoluted scheme. The TCP server adds the listening
51 + * socket to the event loop, as before. Each client thread makes an eventfd
52 + * descriptor that it writes to when it's about to finish. The eventfd
53 + * descriptor is added to the event loop; once it's readable, we clean up the
54 + * client thread quickly from the main event loop thread. The TCP server itself
55 + * keeps track of client threads; on shutdown, it cleans up those still working.
56 + *
57 + * I'm _really_ not sure about this approach, it seems fishy as hell; I guess,
58 + * we'll see.
59 + */
60 +
61 + struct client {
62 + struct tcp_server *server;
63 + int conn_fd;
64 +
65 + int cleanup_fd;
66 +
67 + pid_t tid;
68 + pthread_t thread;
69 +
70 + SIMPLEQ_ENTRY(client) entries;
71 + };
72 +
73 + SIMPLEQ_HEAD(client_queue, client);
74 +
75 + struct tcp_server {
76 + struct event_loop *loop;
77 +
78 + tcp_server_conn_handler conn_handler;
79 + void *conn_handler_arg;
80 +
81 + struct client_queue client_queue;
82 +
83 + int accept_fd;
84 + };
85 +
86 + 27620static void client_destroy(struct client *client)
87 + {
88 +
+ 1/2 +
+
✓ Branch 1 taken 27620 times.
+
✗ Branch 2 not taken.
+
+
+
27620 log_debug("Cleaning up client thread %d\n", client->tid);
89 +
90 +
+ 8/8 +
+
✓ Branch 0 taken 14983 times.
+
✓ Branch 1 taken 12637 times.
+
✓ Branch 2 taken 6743 times.
+
✓ Branch 3 taken 8240 times.
+
✓ Branch 4 taken 8078 times.
+
✓ Branch 5 taken 12637 times.
+
✓ Branch 6 taken 9276 times.
+
✓ Branch 7 taken 3361 times.
+
+
+
35698 SIMPLEQ_REMOVE(&client->server->client_queue, client, client, entries);
91 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 27620 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
27620 pthread_errno_if(pthread_join(client->thread, NULL), "pthread_join");
92 + 27620 file_close(client->cleanup_fd);
93 + 27620 net_close(client->conn_fd);
94 + 27620 free(client);
95 + 27620}
96 +
97 + 27620static int client_destroy_handler(UNUSED struct event_loop *loop, UNUSED int fd,
98 + UNUSED short revents, void *_client)
99 + {
100 + 27620 struct client *client = (struct client *)_client;
101 +
+ 1/2 +
+
✓ Branch 1 taken 27620 times.
+
✗ Branch 2 not taken.
+
+
+
27620 log_debug("Client thread %d indicated that it's done\n", client->tid);
102 +
103 + 27620 client_destroy(client);
104 + 27620 return 0;
105 + }
106 +
107 + 27620static void *client_thread_func(void *_client)
108 + {
109 + 27620 struct client *client = (struct client *)_client;
110 + 27620 int ret = 0;
111 +
112 + 27620 client->tid = gettid();
113 +
+ 1/2 +
+
✓ Branch 1 taken 27620 times.
+
✗ Branch 2 not taken.
+
+
+
27620 log_debug("New client thread thread %d has started\n", client->tid);
114 +
115 + /* Let the client thread handle its signals except those that should be
116 + * handled in the main thread. */
117 + 27620 ret = signal_block_sigterms();
118 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0)
119 + goto cleanup;
120 +
121 + 27620 ret = client->server->conn_handler(client->conn_fd, client->server->conn_handler_arg);
122 +
+ 1/2 +
+
✓ Branch 0 taken 27620 times.
+
✗ Branch 1 not taken.
+
+
+
27620 if (ret < 0)
123 + goto cleanup;
124 +
125 + 27620cleanup:
126 +
+ 1/4 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 27620 times.
+
✗ Branch 4 not taken.
+
✗ Branch 5 not taken.
+
+
+
27620 log_errno_if(eventfd_write(client->cleanup_fd, 1), "eventfd_write");
127 +
128 + 27620 return NULL;
129 + }
130 +
131 + 27620static int client_create_thread(struct client *client)
132 + {
133 + sigset_t old_mask;
134 + 27620 int ret = 0;
135 +
136 + /* Block all signals (we'll unblock them later); the client thread will
137 + * have all signals blocked initially. This allows the main thread to
138 + * handle SIGINT/SIGTERM/etc. */
139 + 27620 ret = signal_block_all(&old_mask);
140 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0)
141 + return ret;
142 +
143 + 27620 ret = pthread_create(&client->thread, NULL, client_thread_func, client);
144 +
+ 1/2 +
+
✓ Branch 0 taken 27620 times.
+
✗ Branch 1 not taken.
+
+
+
27620 if (ret) {
145 + pthread_errno(ret, "pthread_create");
146 + goto restore_mask;
147 + }
148 +
149 + 27620restore_mask:
150 + /* Restore the previously-enabled signals for handling in the main thread. */
151 + 27620 signal_set_mask(&old_mask);
152 +
153 + 27620 return ret;
154 + }
155 +
156 + 27620static int client_create(struct tcp_server *server, int conn_fd)
157 + {
158 + 27620 int ret = 0;
159 +
160 + 27620 struct client *client = calloc(1, sizeof(struct client));
161 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (!client) {
162 + log_errno("calloc");
163 + return -1;
164 + }
165 +
166 + 27620 client->server = server;
167 + 27620 client->conn_fd = conn_fd;
168 +
169 + 27620 ret = eventfd(0, EFD_CLOEXEC);
170 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0) {
171 + log_errno("eventfd");
172 + goto free;
173 + }
174 + 27620 client->cleanup_fd = ret;
175 +
176 + 27620 ret = event_loop_add_once(server->loop, client->cleanup_fd, POLLIN, client_destroy_handler,
177 + client);
178 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0)
179 + goto close_cleanup_fd;
180 +
181 + 27620 SIMPLEQ_INSERT_TAIL(&server->client_queue, client, entries);
182 +
183 + 27620 ret = client_create_thread(client);
184 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0)
185 + goto remove_from_client_queue;
186 +
187 + 27620 return ret;
188 +
189 + remove_from_client_queue:
190 + SIMPLEQ_REMOVE(&server->client_queue, client, client, entries);
191 +
192 + close_cleanup_fd:
193 + file_close(client->cleanup_fd);
194 +
195 + free:
196 + free(client);
197 +
198 + return ret;
199 + }
200 +
201 + 29static void client_queue_create(struct client_queue *client_queue)
202 + {
203 + 29 SIMPLEQ_INIT(client_queue);
204 + 29}
205 +
206 + 29static void client_queue_destroy(struct client_queue *client_queue)
207 + {
208 + 29 struct client *entry1 = SIMPLEQ_FIRST(client_queue);
209 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 while (entry1) {
210 + struct client *entry2 = SIMPLEQ_NEXT(entry1, entries);
211 + client_destroy(entry1);
212 + entry1 = entry2;
213 + }
214 + 29}
215 +
216 + 27620static int tcp_server_accept_handler(UNUSED struct event_loop *loop, UNUSED int fd,
217 + UNUSED short revents, void *_server)
218 + {
219 + 27620 struct tcp_server *server = (struct tcp_server *)_server;
220 + 27620 return tcp_server_accept(server);
221 + }
222 +
223 + 29int tcp_server_create(struct tcp_server **_server, struct event_loop *loop, const char *port,
224 + tcp_server_conn_handler conn_handler, void *conn_handler_arg)
225 + {
226 + 29 int ret = 0;
227 +
228 + 29 struct tcp_server *server = calloc(1, sizeof(struct tcp_server));
229 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (!server) {
230 + log_errno("calloc");
231 + return -1;
232 + }
233 +
234 + 29 server->loop = loop;
235 +
236 + 29 server->conn_handler = conn_handler;
237 + 29 server->conn_handler_arg = conn_handler_arg;
238 +
239 + 29 client_queue_create(&server->client_queue);
240 +
241 + 29 ret = net_bind(port);
242 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
243 + goto free;
244 + 29 server->accept_fd = ret;
245 +
246 + 29 ret = event_loop_add(loop, server->accept_fd, POLLIN, tcp_server_accept_handler, server);
247 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 29 times.
+
+
+
29 if (ret < 0)
248 + goto close;
249 +
250 + 29 *_server = server;
251 + 29 return ret;
252 +
253 + close:
254 + net_close(server->accept_fd);
255 + free:
256 + free(server);
257 +
258 + return ret;
259 + }
260 +
261 + 29void tcp_server_destroy(struct tcp_server *server)
262 + {
263 + 29 net_close(server->accept_fd);
264 + 29 client_queue_destroy(&server->client_queue);
265 + 29 free(server);
266 + 29}
267 +
268 + 27620int tcp_server_accept(struct tcp_server *server)
269 + {
270 + 27620 int conn_fd = -1, ret = 0;
271 +
272 + 27620 ret = net_accept(server->accept_fd);
273 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0)
274 + return ret;
275 + 27620 conn_fd = ret;
276 +
277 + 27620 ret = client_create(server, conn_fd);
278 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 27620 times.
+
+
+
27620 if (ret < 0)
279 + goto close_conn;
280 +
281 + 27620 return ret;
282 +
283 + close_conn:
284 + net_close(conn_fd);
285 +
286 + return ret;
287 + }
288 +
+
+ +
+ + + + diff --git a/coverage/index.worker.c.4cbdfac39be7d0330fdfd94f65ce9ea9.html b/coverage/index.worker.c.4cbdfac39be7d0330fdfd94f65ce9ea9.html new file mode 100644 index 0000000..86f8955 --- /dev/null +++ b/coverage/index.worker.c.4cbdfac39be7d0330fdfd94f65ce9ea9.html @@ -0,0 +1,2492 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/worker.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:10615170.2%
Branches:276243.5%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "worker.h"
9 + #include "ci.h"
10 + #include "command.h"
11 + #include "compiler.h"
12 + #include "const.h"
13 + #include "event_loop.h"
14 + #include "git.h"
15 + #include "log.h"
16 + #include "net.h"
17 + #include "process.h"
18 + #include "protocol.h"
19 + #include "run_queue.h"
20 + #include "signal.h"
21 +
22 + #include <poll.h>
23 + #include <stdlib.h>
24 + #include <string.h>
25 +
26 + struct worker {
27 + struct settings *settings;
28 +
29 + int stopping;
30 +
31 + struct cmd_dispatcher *cmd_dispatcher;
32 +
33 + struct event_loop *event_loop;
34 + int signalfd;
35 +
36 + struct run *run;
37 + };
38 +
39 + 54static struct settings *worker_settings_copy(const struct settings *src)
40 + {
41 + 54 struct settings *result = malloc(sizeof(*src));
42 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (!result) {
43 + log_errno("malloc");
44 + return NULL;
45 + }
46 +
47 + 54 result->host = strdup(src->host);
48 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (!result->host) {
49 + log_errno("strdup");
50 + goto free_result;
51 + }
52 +
53 + 54 result->port = strdup(src->port);
54 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (!result->port) {
55 + log_errno("strdup");
56 + goto free_host;
57 + }
58 +
59 + 54 return result;
60 +
61 + free_host:
62 + free((void *)result->host);
63 +
64 + free_result:
65 + free(result);
66 +
67 + return NULL;
68 + }
69 +
70 + 54static void worker_settings_destroy(struct settings *settings)
71 + {
72 + 54 free((void *)settings->port);
73 + 54 free((void *)settings->host);
74 + 54 free(settings);
75 + 54}
76 +
77 + 54static int worker_set_stopping(UNUSED struct event_loop *loop, UNUSED int fd, UNUSED short revents,
78 + void *_worker)
79 + {
80 + 54 struct worker *worker = (struct worker *)_worker;
81 + 54 worker->stopping = 1;
82 + 54 return 0;
83 + }
84 +
85 + 9180static int worker_handle_cmd_start_run(const struct jsonrpc_request *request,
86 + UNUSED struct jsonrpc_response **response, void *_ctx)
87 + {
88 + 9180 struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx;
89 + 9180 struct worker *worker = (struct worker *)ctx->arg;
90 + 9180 int ret = 0;
91 +
92 + 9180 ret = request_parse_start_run(request, &worker->run);
93 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
94 + return ret;
95 +
96 + 9180 return ret;
97 + }
98 +
99 + static struct cmd_desc commands[] = {
100 + {CMD_START_RUN, worker_handle_cmd_start_run},
101 + };
102 +
103 + static const size_t numof_commands = sizeof(commands) / sizeof(commands[0]);
104 +
105 + 54int worker_create(struct worker **_worker, const struct settings *settings)
106 + {
107 + 54 int ret = 0;
108 +
109 + 54 struct worker *worker = malloc(sizeof(struct worker));
110 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (!worker) {
111 + log_errno("malloc");
112 + return -1;
113 + }
114 +
115 + 54 worker->settings = worker_settings_copy(settings);
116 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (!worker->settings) {
117 + ret = -1;
118 + goto free;
119 + }
120 +
121 + 54 worker->stopping = 0;
122 +
123 + 54 ret = cmd_dispatcher_create(&worker->cmd_dispatcher, commands, numof_commands, worker);
124 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
125 + goto free_settings;
126 +
127 + 54 ret = event_loop_create(&worker->event_loop);
128 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
129 + goto destroy_cmd_dispatcher;
130 +
131 + 54 ret = signalfd_create_sigterms();
132 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
133 + goto destroy_event_loop;
134 + 54 worker->signalfd = ret;
135 +
136 + 54 ret = event_loop_add(worker->event_loop, worker->signalfd, POLLIN, worker_set_stopping,
137 + worker);
138 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
139 + goto close_signalfd;
140 +
141 + 54 ret = libgit_init();
142 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
143 + goto close_signalfd;
144 +
145 + 54 *_worker = worker;
146 + 54 return ret;
147 +
148 + close_signalfd:
149 + signalfd_destroy(worker->signalfd);
150 +
151 + destroy_event_loop:
152 + event_loop_destroy(worker->event_loop);
153 +
154 + destroy_cmd_dispatcher:
155 + cmd_dispatcher_destroy(worker->cmd_dispatcher);
156 +
157 + free_settings:
158 + worker_settings_destroy(worker->settings);
159 +
160 + free:
161 + free(worker);
162 +
163 + return ret;
164 + }
165 +
166 + 54void worker_destroy(struct worker *worker)
167 + {
168 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 54 times.
+
+
+
54 log("Shutting down\n");
169 +
170 + 54 libgit_shutdown();
171 + 54 signalfd_destroy(worker->signalfd);
172 + 54 event_loop_destroy(worker->event_loop);
173 + 54 cmd_dispatcher_destroy(worker->cmd_dispatcher);
174 + 54 worker_settings_destroy(worker->settings);
175 + 54 free(worker);
176 + 54}
177 +
178 + 9180static int worker_do_run(struct worker *worker)
179 + {
180 + 9180 int ret = 0;
181 +
182 + 9180 struct proc_output *result = NULL;
183 + 9180 ret = proc_output_create(&result);
184 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
185 + return ret;
186 +
187 + 9180 ret = ci_run_git_repo(run_get_repo_url(worker->run), run_get_repo_rev(worker->run), result);
188 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0) {
189 + log_err("Run failed with an error\n");
190 + goto free_output;
191 + }
192 +
193 + 9180 proc_output_dump(result);
194 +
195 + 9180 struct jsonrpc_request *finished_request = NULL;
196 +
197 + 9180 ret = request_create_finished_run(&finished_request, run_get_id(worker->run), result);
198 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
199 + goto free_output;
200 +
201 + 9180 ret = net_connect(worker->settings->host, worker->settings->port);
202 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
203 + goto free_request;
204 + 9180 int fd = ret;
205 +
206 + 9180 ret = jsonrpc_request_send(finished_request, fd);
207 +
+ 1/2 +
+
✓ Branch 0 taken 9180 times.
+
✗ Branch 1 not taken.
+
+
+
9180 if (ret < 0)
208 + goto close_conn;
209 +
210 + 9180close_conn:
211 + 9180 net_close(fd);
212 +
213 + 9180free_request:
214 + 9180 jsonrpc_request_destroy(finished_request);
215 +
216 + 9180free_output:
217 + 9180 proc_output_destroy(result);
218 +
219 + 9180 run_destroy(worker->run);
220 +
221 + 9180 return ret;
222 + }
223 +
224 + 9234static int worker_get_run(struct worker *worker)
225 + {
226 + 9234 int ret = 0, fd = -1;
227 +
228 + 9234 ret = net_connect(worker->settings->host, worker->settings->port);
229 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
230 + return ret;
231 + 9234 fd = ret;
232 +
233 + 9234 struct jsonrpc_request *new_worker_request = NULL;
234 + 9234 ret = request_create_new_worker(&new_worker_request);
235 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
236 + goto close;
237 +
238 + 9234 ret = jsonrpc_request_send(new_worker_request, fd);
239 + 9234 jsonrpc_request_destroy(new_worker_request);
240 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
241 + goto close;
242 +
243 + 9234 ret = event_loop_add_once(worker->event_loop, fd, POLLIN, cmd_dispatcher_handle_event,
244 + 9234 worker->cmd_dispatcher);
245 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
246 + goto close;
247 +
248 +
+ 1/2 +
+
✗ Branch 1 not taken.
+
✓ Branch 2 taken 9234 times.
+
+
+
9234 log("Waiting for a new command\n");
249 +
250 + 9234 ret = event_loop_run(worker->event_loop);
251 +
+ 1/2 +
+
✓ Branch 0 taken 9234 times.
+
✗ Branch 1 not taken.
+
+
+
9234 if (ret < 0)
252 + goto close;
253 +
254 + 9234close:
255 + 9234 net_close(fd);
256 +
257 + 9234 return ret;
258 + }
259 +
260 + 54int worker_main(struct worker *worker)
261 + {
262 + 54 int ret = 0;
263 +
264 + while (1) {
265 + 9234 ret = worker_get_run(worker);
266 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (ret < 0)
267 + return ret;
268 +
269 +
+ 2/2 +
+
✓ Branch 0 taken 54 times.
+
✓ Branch 1 taken 9180 times.
+
+
+
9234 if (worker->stopping)
270 + 54 break;
271 +
272 + 9180 ret = worker_do_run(worker);
273 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9180 times.
+
+
+
9180 if (ret < 0)
274 + return ret;
275 + }
276 +
277 + 54 return ret;
278 + }
279 +
+
+ +
+ + + + diff --git a/coverage/index.worker_main.c.3e96ea0429977547c8b5eee564591fe0.html b/coverage/index.worker_main.c.3e96ea0429977547c8b5eee564591fe0.html new file mode 100644 index 0000000..a7f416f --- /dev/null +++ b/coverage/index.worker_main.c.3e96ea0429977547c8b5eee564591fe0.html @@ -0,0 +1,885 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/worker_main.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:344379.1%
Branches:101471.4%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "cmd_line.h"
9 + #include "const.h"
10 + #include "log.h"
11 + #include "worker.h"
12 +
13 + #include <getopt.h>
14 + #include <unistd.h>
15 +
16 + 60static struct settings default_settings(void)
17 + {
18 + 60 struct settings settings = {
19 + .host = default_host,
20 + .port = default_port,
21 + };
22 + 60 return settings;
23 + }
24 +
25 + 4const char *get_usage_string(void)
26 + {
27 + 4 return "[-h|--help] [-V|--version] [-v|--verbose] [-H|--host HOST] [-p|--port PORT]";
28 + }
29 +
30 + 60static int parse_settings(struct settings *settings, int argc, char *argv[])
31 + {
32 + int opt, longind;
33 +
34 + 60 *settings = default_settings();
35 +
36 + /* clang-format off */
37 + static struct option long_options[] = {
38 + {"help", no_argument, 0, 'h'},
39 + {"version", no_argument, 0, 'V'},
40 + {"verbose", no_argument, 0, 'v'},
41 + {"host", required_argument, 0, 'H'},
42 + {"port", required_argument, 0, 'p'},
43 + {0, 0, 0, 0},
44 + };
45 + /* clang-format on */
46 +
47 +
+ 2/2 +
+
✓ Branch 1 taken 114 times.
+
✓ Branch 2 taken 54 times.
+
+
+
168 while ((opt = getopt_long(argc, argv, "hVvH:p:", long_options, &longind)) != -1) {
48 +
+ 5/6 +
+
✓ Branch 0 taken 2 times.
+
✓ Branch 1 taken 2 times.
+
✗ Branch 2 not taken.
+
✓ Branch 3 taken 54 times.
+
✓ Branch 4 taken 54 times.
+
✓ Branch 5 taken 2 times.
+
+
+
114 switch (opt) {
49 + 2 case 'h':
50 + 2 exit_with_usage(0);
51 + break;
52 + 2 case 'V':
53 + 2 exit_with_version();
54 + break;
55 + case 'v':
56 + g_log_lvl = LOG_LVL_DEBUG;
57 + break;
58 + 54 case 'H':
59 + 54 settings->host = optarg;
60 + 54 break;
61 + 54 case 'p':
62 + 54 settings->port = optarg;
63 + 54 break;
64 + 2 default:
65 + 2 exit_with_usage(1);
66 + break;
67 + }
68 + }
69 +
70 + 54 return 0;
71 + }
72 +
73 + 60int main(int argc, char *argv[])
74 + {
75 + struct settings settings;
76 + 60 struct worker *worker = NULL;
77 + 60 int ret = 0;
78 +
79 + 60 ret = parse_settings(&settings, argc, argv);
80 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
81 + return ret;
82 +
83 + 54 ret = worker_create(&worker, &settings);
84 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 54 times.
+
+
+
54 if (ret < 0)
85 + return ret;
86 +
87 + 54 ret = worker_main(worker);
88 +
+ 1/2 +
+
✓ Branch 0 taken 54 times.
+
✗ Branch 1 not taken.
+
+
+
54 if (ret < 0)
89 + goto destroy_worker;
90 +
91 + 54destroy_worker:
92 + 54 worker_destroy(worker);
93 +
94 + 54 return ret;
95 + }
96 +
+
+ +
+ + + + diff --git a/coverage/index.worker_queue.c.aeb7258cd8f695c41a9aa8634701b38c.html b/coverage/index.worker_queue.c.aeb7258cd8f695c41a9aa8634701b38c.html new file mode 100644 index 0000000..9402dd1 --- /dev/null +++ b/coverage/index.worker_queue.c.aeb7258cd8f695c41a9aa8634701b38c.html @@ -0,0 +1,755 @@ + + + + + + GCC Code Coverage Report + + + + + +

GCC Code Coverage Report

+ +
+ +
+
+ + + + + + + + + + + + + +
Directory:src/
File:src/worker_queue.c
Date:2024-04-25 03:45:42
+
+
+ + + + + + + + + + + + + + + + + + + +
ExecTotalCoverage
Lines:323688.9%
Branches:51050.0%
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineBranchExecSource
1 + /*
2 + * Copyright (c) 2023 Egor Tensin <egor@tensin.name>
3 + * This file is part of the "cimple" project.
4 + * For details, see https://github.com/egor-tensin/cimple.
5 + * Distributed under the MIT License.
6 + */
7 +
8 + #include "worker_queue.h"
9 + #include "log.h"
10 + #include "net.h"
11 +
12 + #include <stdlib.h>
13 + #include <sys/queue.h>
14 +
15 + struct worker {
16 + int fd;
17 + SIMPLEQ_ENTRY(worker) entries;
18 + };
19 +
20 + 9234int worker_create(struct worker **_entry, int fd)
21 + {
22 + 9234 struct worker *entry = malloc(sizeof(struct worker));
23 +
+ 1/2 +
+
✗ Branch 0 not taken.
+
✓ Branch 1 taken 9234 times.
+
+
+
9234 if (!entry) {
24 + log_errno("malloc");
25 + return -1;
26 + }
27 +
28 + 9234 entry->fd = fd;
29 +
30 + 9234 *_entry = entry;
31 + 9234 return 0;
32 + }
33 +
34 + 9234void worker_destroy(struct worker *entry)
35 + {
36 + 9234 net_close(entry->fd);
37 + 9234 free(entry);
38 + 9234}
39 +
40 + 36774int worker_get_fd(const struct worker *entry)
41 + {
42 + 36774 return entry->fd;
43 + }
44 +
45 + 29void worker_queue_create(struct worker_queue *queue)
46 + {
47 + 29 SIMPLEQ_INIT(queue);
48 + 29}
49 +
50 + 29void worker_queue_destroy(struct worker_queue *queue)
51 + {
52 + 29 struct worker *entry1 = SIMPLEQ_FIRST(queue);
53 +
+ 2/2 +
+
✓ Branch 0 taken 54 times.
+
✓ Branch 1 taken 29 times.
+
+
+
83 while (entry1) {
54 + 54 struct worker *entry2 = SIMPLEQ_NEXT(entry1, entries);
55 + 54 worker_destroy(entry1);
56 + 54 entry1 = entry2;
57 + }
58 + 29 SIMPLEQ_INIT(queue);
59 + 29}
60 +
61 + 27255int worker_queue_is_empty(const struct worker_queue *queue)
62 + {
63 + 27255 return SIMPLEQ_EMPTY(queue);
64 + }
65 +
66 + void worker_queue_add_first(struct worker_queue *queue, struct worker *entry)
67 + {
68 + SIMPLEQ_INSERT_HEAD(queue, entry, entries);
69 + }
70 +
71 + 9234void worker_queue_add_last(struct worker_queue *queue, struct worker *entry)
72 + {
73 + 9234 SIMPLEQ_INSERT_TAIL(queue, entry, entries);
74 + 9234}
75 +
76 + 9180struct worker *worker_queue_remove_first(struct worker_queue *queue)
77 + {
78 + 9180 struct worker *entry = SIMPLEQ_FIRST(queue);
79 +
+ 2/2 +
+
✓ Branch 0 taken 9098 times.
+
✓ Branch 1 taken 82 times.
+
+
+
9180 SIMPLEQ_REMOVE_HEAD(queue, entries);
80 + 9180 return entry;
81 + }
82 +
+
+ +
+ + + + -- cgit v1.2.3