diff options
author | t3sserakt <t3ss@posteo.de> | 2023-07-14 16:59:30 +0200 |
---|---|---|
committer | t3sserakt <t3ss@posteo.de> | 2023-07-14 16:59:30 +0200 |
commit | 40a5a650d3b61aca9474692416adeba7272e61b3 (patch) | |
tree | 0b02421352144cb978a9016ccb1c61f7f1d9519b /src | |
parent | b138491b9e4878607ea954254f84f1106202017b (diff) | |
download | gnunet-40a5a650d3b61aca9474692416adeba7272e61b3.tar.gz gnunet-40a5a650d3b61aca9474692416adeba7272e61b3.zip |
NEWS: Added command to execute a script.
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_testing_ng_lib.h | 206 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_exec_bash_script.c | 217 |
2 files changed, 422 insertions, 1 deletions
diff --git a/src/include/gnunet_testing_ng_lib.h b/src/include/gnunet_testing_ng_lib.h index 77e9bd74a..98ba65b59 100644 --- a/src/include/gnunet_testing_ng_lib.h +++ b/src/include/gnunet_testing_ng_lib.h | |||
@@ -519,6 +519,20 @@ struct GNUNET_TESTING_Timer | |||
519 | unsigned int num_retries; | 519 | unsigned int num_retries; |
520 | }; | 520 | }; |
521 | 521 | ||
522 | /** | ||
523 | * Command to execute a script synchronously. | ||
524 | * | ||
525 | * @param label Label of the command. | ||
526 | * @param script The name of the script. | ||
527 | * @param script_argv The arguments of the script. | ||
528 | */ | ||
529 | const struct GNUNET_TESTING_Command | ||
530 | GNUNET_TESTING_cmd_exec_bash_script (const char *label, | ||
531 | const char *script, | ||
532 | char *const script_argv[], | ||
533 | int argc, | ||
534 | GNUNET_ChildCompletedCallback cb); | ||
535 | |||
522 | 536 | ||
523 | /** | 537 | /** |
524 | * Retrieve peer identity from the test system with the unique node id. | 538 | * Retrieve peer identity from the test system with the unique node id. |
@@ -603,6 +617,188 @@ GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits, | |||
603 | /* ****** Specific traits supported by this component ******* */ | 617 | /* ****** Specific traits supported by this component ******* */ |
604 | 618 | ||
605 | 619 | ||
620 | typedef void * | ||
621 | (*GNUNET_TESTING_notify_connect_cb) (struct GNUNET_TESTING_Interpreter *is, | ||
622 | const struct GNUNET_PeerIdentity *peer); | ||
623 | |||
624 | |||
625 | /** | ||
626 | * Struct to store information needed in callbacks. | ||
627 | * | ||
628 | */ | ||
629 | struct ConnectPeersState | ||
630 | { | ||
631 | /** | ||
632 | * Context for our asynchronous completion. | ||
633 | */ | ||
634 | struct GNUNET_TESTING_AsyncContext ac; | ||
635 | |||
636 | GNUNET_TESTING_notify_connect_cb notify_connect; | ||
637 | |||
638 | /** | ||
639 | * The testing system of this node. | ||
640 | */ | ||
641 | const struct GNUNET_TESTING_System *tl_system; | ||
642 | |||
643 | // Label of the cmd which started the test system. | ||
644 | const char *create_label; | ||
645 | |||
646 | /** | ||
647 | * Number globally identifying the node. | ||
648 | * | ||
649 | */ | ||
650 | uint32_t num; | ||
651 | |||
652 | /** | ||
653 | * Label of the cmd to start a peer. | ||
654 | * | ||
655 | */ | ||
656 | const char *start_peer_label; | ||
657 | |||
658 | /** | ||
659 | * The topology of the test setup. | ||
660 | */ | ||
661 | struct GNUNET_TESTING_NetjailTopology *topology; | ||
662 | |||
663 | /** | ||
664 | * Connections to other peers. | ||
665 | */ | ||
666 | struct GNUNET_TESTING_NodeConnection *node_connections_head; | ||
667 | |||
668 | struct GNUNET_TESTING_Interpreter *is; | ||
669 | |||
670 | /** | ||
671 | * Number of connections. | ||
672 | */ | ||
673 | unsigned int con_num; | ||
674 | |||
675 | /** | ||
676 | * Number of additional connects this cmd will wait for not triggered by this cmd. | ||
677 | */ | ||
678 | unsigned int additional_connects; | ||
679 | |||
680 | /** | ||
681 | * Number of connections we already have a notification for. | ||
682 | */ | ||
683 | unsigned int con_num_notified; | ||
684 | |||
685 | /** | ||
686 | * Number of additional connects this cmd will wait for not triggered by this cmd we already have a notification for. | ||
687 | */ | ||
688 | unsigned int additional_connects_notified; | ||
689 | |||
690 | /** | ||
691 | * Flag indicating, whether the command is waiting for peers to connect that are configured to connect. | ||
692 | */ | ||
693 | unsigned int wait_for_connect; | ||
694 | }; | ||
695 | |||
696 | |||
697 | struct GNUNET_TESTING_StartPeerState | ||
698 | { | ||
699 | /** | ||
700 | * Context for our asynchronous completion. | ||
701 | */ | ||
702 | struct GNUNET_TESTING_AsyncContext ac; | ||
703 | |||
704 | /** | ||
705 | * The ip of a node. | ||
706 | */ | ||
707 | char *node_ip; | ||
708 | |||
709 | /** | ||
710 | * Receive callback | ||
711 | */ | ||
712 | struct GNUNET_MQ_MessageHandler *handlers; | ||
713 | |||
714 | /** | ||
715 | * GNUnet configuration file used to start a peer. | ||
716 | */ | ||
717 | char *cfgname; | ||
718 | |||
719 | /** | ||
720 | * Peer's configuration | ||
721 | */ | ||
722 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
723 | |||
724 | /** | ||
725 | * struct GNUNET_TESTING_Peer returned by GNUNET_TESTING_peer_configure. | ||
726 | */ | ||
727 | struct GNUNET_TESTING_Peer *peer; | ||
728 | |||
729 | /** | ||
730 | * Peer identity | ||
731 | */ | ||
732 | struct GNUNET_PeerIdentity id; | ||
733 | |||
734 | /** | ||
735 | * Peer's transport service handle | ||
736 | */ | ||
737 | struct GNUNET_TRANSPORT_CoreHandle *th; | ||
738 | |||
739 | /** | ||
740 | * Application handle | ||
741 | */ | ||
742 | struct GNUNET_TRANSPORT_ApplicationHandle *ah; | ||
743 | |||
744 | /** | ||
745 | * Peer's PEERSTORE Handle | ||
746 | */ | ||
747 | struct GNUNET_PEERSTORE_Handle *ph; | ||
748 | |||
749 | /** | ||
750 | * Hello get task | ||
751 | */ | ||
752 | struct GNUNET_SCHEDULER_Task *rh_task; | ||
753 | |||
754 | /** | ||
755 | * Peer's transport get hello handle to retrieve peer's HELLO message | ||
756 | */ | ||
757 | struct GNUNET_PEERSTORE_IterateContext *pic; | ||
758 | |||
759 | /** | ||
760 | * Hello | ||
761 | */ | ||
762 | char *hello; | ||
763 | |||
764 | /** | ||
765 | * Hello size | ||
766 | */ | ||
767 | size_t hello_size; | ||
768 | |||
769 | /** | ||
770 | * The label of the command which was started by calling GNUNET_TESTING_cmd_system_create. | ||
771 | */ | ||
772 | char *system_label; | ||
773 | |||
774 | /** | ||
775 | * An unique number to identify the peer | ||
776 | */ | ||
777 | unsigned int no; | ||
778 | |||
779 | /** | ||
780 | * A map with struct GNUNET_MQ_Handle values for each peer this peer | ||
781 | * is connected to. | ||
782 | */ | ||
783 | struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map; | ||
784 | |||
785 | /** | ||
786 | * Test setup for this peer. | ||
787 | */ | ||
788 | const struct GNUNET_TESTING_System *tl_system; | ||
789 | |||
790 | /** | ||
791 | * Callback which is called on neighbour connect events. | ||
792 | */ | ||
793 | GNUNET_TESTING_notify_connect_cb notify_connect; | ||
794 | |||
795 | /** | ||
796 | * Flag indicating, if udp broadcast should be switched on. | ||
797 | */ | ||
798 | enum GNUNET_GenericReturnValue broadcast; | ||
799 | }; | ||
800 | |||
801 | |||
606 | /** | 802 | /** |
607 | * Create headers for a trait with name @a name for | 803 | * Create headers for a trait with name @a name for |
608 | * statically allocated data of type @a type. | 804 | * statically allocated data of type @a type. |
@@ -697,7 +893,15 @@ GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits, | |||
697 | */ | 893 | */ |
698 | #define GNUNET_TESTING_SIMPLE_TRAITS(op) \ | 894 | #define GNUNET_TESTING_SIMPLE_TRAITS(op) \ |
699 | op (batch_cmds, struct GNUNET_TESTING_Command *) \ | 895 | op (batch_cmds, struct GNUNET_TESTING_Command *) \ |
700 | op (process, struct GNUNET_OS_Process *) | 896 | op (process, struct GNUNET_OS_Process *) \ |
897 | op (peer_id, const struct GNUNET_PeerIdentity) \ | ||
898 | op (connected_peers_map, const struct GNUNET_CONTAINER_MultiShortmap) \ | ||
899 | op (hello_size, const size_t) \ | ||
900 | op (hello, const char) \ | ||
901 | op (application_handle, const struct GNUNET_TRANSPORT_ApplicationHandle) \ | ||
902 | op (connect_peer_state, const struct ConnectPeersState) \ | ||
903 | op (state, const struct GNUNET_TESTING_StartPeerState) \ | ||
904 | op (broadcast, const enum GNUNET_GenericReturnValue) | ||
701 | 905 | ||
702 | 906 | ||
703 | /** | 907 | /** |
diff --git a/src/testing/testing_api_cmd_exec_bash_script.c b/src/testing/testing_api_cmd_exec_bash_script.c new file mode 100644 index 000000000..5b9f5cbbb --- /dev/null +++ b/src/testing/testing_api_cmd_exec_bash_script.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2023 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file testing_api_cmd_local_test_prepared.c | ||
23 | * @brief cmd to block the interpreter loop until all peers started. | ||
24 | * @author t3sserakt | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_testing_ng_lib.h" | ||
29 | |||
30 | #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) | ||
31 | |||
32 | struct BashScriptState | ||
33 | { | ||
34 | /** | ||
35 | * Context for our asynchronous completion. | ||
36 | */ | ||
37 | struct GNUNET_TESTING_AsyncContext ac; | ||
38 | |||
39 | /** | ||
40 | * Callback handed over to the command, which should | ||
41 | * be called upon death or completion of the script. | ||
42 | */ | ||
43 | GNUNET_ChildCompletedCallback cb; | ||
44 | |||
45 | // Child Wait handle | ||
46 | struct GNUNET_ChildWaitHandle *cwh; | ||
47 | |||
48 | /** | ||
49 | * The process id of the script. | ||
50 | */ | ||
51 | struct GNUNET_OS_Process *start_proc; | ||
52 | |||
53 | /** | ||
54 | * Script this cmd will execute. | ||
55 | */ | ||
56 | const char *script; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Arguments for the script | ||
61 | */ | ||
62 | char **script_argv; | ||
63 | |||
64 | /** | ||
65 | * Size of script_argv. | ||
66 | */ | ||
67 | int argc; | ||
68 | }; | ||
69 | |||
70 | /** | ||
71 | * The cleanup function of this cmd frees resources the cmd allocated. | ||
72 | * | ||
73 | */ | ||
74 | static void | ||
75 | exec_bash_script_cleanup (void *cls) | ||
76 | { | ||
77 | struct BashScriptState *bss = cls; | ||
78 | |||
79 | if (NULL != bss->cwh) | ||
80 | { | ||
81 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
82 | "Cancel child\n"); | ||
83 | GNUNET_wait_child_cancel (bss->cwh); | ||
84 | bss->cwh = NULL; | ||
85 | } | ||
86 | if (NULL != bss->start_proc) | ||
87 | { | ||
88 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
89 | "Kill process\n"); | ||
90 | GNUNET_assert (0 == | ||
91 | GNUNET_OS_process_kill (bss->start_proc, | ||
92 | SIGKILL)); | ||
93 | GNUNET_assert (GNUNET_OK == | ||
94 | GNUNET_OS_process_wait (bss->start_proc)); | ||
95 | GNUNET_OS_process_destroy (bss->start_proc); | ||
96 | bss->start_proc = NULL; | ||
97 | } | ||
98 | GNUNET_free (bss); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Callback which will be called if the setup script finished. | ||
103 | * | ||
104 | */ | ||
105 | static void | ||
106 | child_completed_callback (void *cls, | ||
107 | enum GNUNET_OS_ProcessStatusType type, | ||
108 | long unsigned int exit_code) | ||
109 | { | ||
110 | struct BashScriptState *bss = cls; | ||
111 | |||
112 | GNUNET_OS_process_destroy (bss->start_proc); | ||
113 | bss->start_proc = NULL; | ||
114 | bss->cwh = NULL; | ||
115 | if (0 == exit_code) | ||
116 | { | ||
117 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
118 | "Child succeeded!\n", | ||
119 | exit_code); | ||
120 | GNUNET_TESTING_async_finish (&bss->ac); | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
125 | "Child failed with error %lu!\n", | ||
126 | exit_code); | ||
127 | GNUNET_TESTING_async_fail (&bss->ac); | ||
128 | } | ||
129 | bss->cb (cls, type, exit_code); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Run method of the command created by the interpreter to wait for another | ||
134 | * command to finish. | ||
135 | * | ||
136 | */ | ||
137 | static void | ||
138 | exec_bash_script_run (void *cls, | ||
139 | struct GNUNET_TESTING_Interpreter *is) | ||
140 | { | ||
141 | struct BashScriptState *bss = cls; | ||
142 | enum GNUNET_GenericReturnValue helper_check; | ||
143 | char *argv[bss->argc + 2]; | ||
144 | |||
145 | char *data_dir; | ||
146 | char *script_name; | ||
147 | |||
148 | data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
149 | GNUNET_asprintf (&script_name, "%s%s", data_dir, bss->script); | ||
150 | |||
151 | helper_check = GNUNET_OS_check_helper_binary ( | ||
152 | script_name, | ||
153 | GNUNET_YES, | ||
154 | NULL); | ||
155 | |||
156 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
157 | "script_name %s\n", | ||
158 | script_name); | ||
159 | |||
160 | if (GNUNET_NO == helper_check) | ||
161 | { | ||
162 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
163 | "No SUID for %s!\n", | ||
164 | script_name); | ||
165 | GNUNET_TESTING_interpreter_fail (is); | ||
166 | return; | ||
167 | } | ||
168 | if (GNUNET_SYSERR == helper_check) | ||
169 | { | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
171 | "%s not found!\n", | ||
172 | script_name); | ||
173 | GNUNET_TESTING_interpreter_fail (is); | ||
174 | return; | ||
175 | } | ||
176 | argv[0] = script_name; | ||
177 | if (NULL != bss->script_argv) | ||
178 | { | ||
179 | for (int i = 0; i < bss->argc;i++) | ||
180 | argv[i + 1] = bss->script_argv[i]; | ||
181 | } | ||
182 | argv[bss->argc] = NULL; | ||
183 | |||
184 | bss->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR, | ||
185 | NULL, | ||
186 | NULL, | ||
187 | NULL, | ||
188 | script_name, | ||
189 | argv); | ||
190 | bss->cwh = GNUNET_wait_child (bss->start_proc, | ||
191 | &child_completed_callback, | ||
192 | bss); | ||
193 | GNUNET_break (NULL != bss->cwh); | ||
194 | } | ||
195 | |||
196 | const struct GNUNET_TESTING_Command | ||
197 | GNUNET_TESTING_cmd_exec_bash_script (const char *label, | ||
198 | const char *script, | ||
199 | char *const script_argv[], | ||
200 | int argc, | ||
201 | GNUNET_ChildCompletedCallback cb) | ||
202 | { | ||
203 | struct BashScriptState *bss; | ||
204 | |||
205 | bss = GNUNET_new (struct BashScriptState); | ||
206 | bss->script = script; | ||
207 | bss->script_argv = script_argv; | ||
208 | bss->argc = argc; | ||
209 | bss->cb = cb; | ||
210 | |||
211 | return GNUNET_TESTING_command_new (bss, | ||
212 | label, | ||
213 | &exec_bash_script_run, | ||
214 | &exec_bash_script_cleanup, | ||
215 | NULL, | ||
216 | &bss->ac); | ||
217 | } | ||