<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19119">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">test: Add test coverage for capture child process output<br><br>ASTERISK-30037 #close<br><br>Change-Id: I0273e85eeeb6b8e46703f24cd74d84f3daf0a69a<br>---<br>M configure<br>M configure.ac<br>M makeopts.in<br>M tests/Makefile<br>A tests/test_capture.c<br>5 files changed, 417 insertions(+), 0 deletions(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configure b/configure</span><br><span>index 573f4ef..168d791 100755</span><br><span>--- a/configure</span><br><span>+++ b/configure</span><br><span>@@ -711,6 +711,7 @@</span><br><span> AST_NATIVE_ARCH</span><br><span> AST_SHADOW_WARNINGS</span><br><span> AST_NO_STRINGOP_TRUNCATION</span><br><span style="color: hsl(120, 100%, 40%);">+AST_NO_FORMAT_Y2K</span><br><span> AST_NO_FORMAT_TRUNCATION</span><br><span> AST_NO_STRICT_OVERFLOW</span><br><span> AST_FORTIFY_SOURCE</span><br><span>@@ -20949,6 +20950,19 @@</span><br><span> fi</span><br><span> </span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -Wno-format-y2k" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+printf %s "checking for -Wno-format-y2k... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+if $(${CC} -Wno-format-y2k -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then</span><br><span style="color: hsl(120, 100%, 40%);">+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+printf "%s\n" "yes" >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_NO_FORMAT_Y2K=-Wno-format-y2k</span><br><span style="color: hsl(120, 100%, 40%);">+else</span><br><span style="color: hsl(120, 100%, 40%);">+       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+printf "%s\n" "no" >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_NO_FORMAT_Y2K=</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -Wno-stringop-truncation" >&5</span><br><span> printf %s "checking for -Wno-stringop-truncation... " >&6; }</span><br><span> if $(${CC} -Wno-stringop-truncation -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then</span><br><span>diff --git a/configure.ac b/configure.ac</span><br><span>index 5ee72b4..b7a206d 100644</span><br><span>--- a/configure.ac</span><br><span>+++ b/configure.ac</span><br><span>@@ -1398,6 +1398,16 @@</span><br><span> fi</span><br><span> AC_SUBST(AST_NO_FORMAT_TRUNCATION)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+AC_MSG_CHECKING(for -Wno-format-y2k)</span><br><span style="color: hsl(120, 100%, 40%);">+if $(${CC} -Wno-format-y2k -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then</span><br><span style="color: hsl(120, 100%, 40%);">+     AC_MSG_RESULT(yes)</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_NO_FORMAT_Y2K=-Wno-format-y2k</span><br><span style="color: hsl(120, 100%, 40%);">+else</span><br><span style="color: hsl(120, 100%, 40%);">+       AC_MSG_RESULT(no)</span><br><span style="color: hsl(120, 100%, 40%);">+     AST_NO_FORMAT_Y2K=</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+AC_SUBST(AST_NO_FORMAT_Y2K)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AC_MSG_CHECKING(for -Wno-stringop-truncation)</span><br><span> if $(${CC} -Wno-stringop-truncation -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then</span><br><span>        AC_MSG_RESULT(yes)</span><br><span>diff --git a/makeopts.in b/makeopts.in</span><br><span>index e99cd50..4f3778f 100644</span><br><span>--- a/makeopts.in</span><br><span>+++ b/makeopts.in</span><br><span>@@ -120,6 +120,7 @@</span><br><span> AST_TRAMPOLINES=@AST_TRAMPOLINES@</span><br><span> AST_NO_STRICT_OVERFLOW=@AST_NO_STRICT_OVERFLOW@</span><br><span> AST_NO_FORMAT_TRUNCATION=@AST_NO_FORMAT_TRUNCATION@</span><br><span style="color: hsl(120, 100%, 40%);">+AST_NO_FORMAT_Y2K=@AST_NO_FORMAT_Y2K@</span><br><span> AST_NO_STRINGOP_TRUNCATION=@AST_NO_STRINGOP_TRUNCATION@</span><br><span> AST_SHADOW_WARNINGS=@AST_SHADOW_WARNINGS@</span><br><span> AST_NESTED_FUNCTIONS=@AST_NESTED_FUNCTIONS@</span><br><span>diff --git a/tests/Makefile b/tests/Makefile</span><br><span>index 715c3f8..a3fc9dc 100644</span><br><span>--- a/tests/Makefile</span><br><span>+++ b/tests/Makefile</span><br><span>@@ -20,5 +20,7 @@</span><br><span> include $(ASTTOPDIR)/Makefile.moddir_rules</span><br><span> </span><br><span> test_astobj2.o: _ASTCFLAGS+=$(call get_menuselect_cflags,AO2_DEBUG)</span><br><span style="color: hsl(120, 100%, 40%);">+# can't use '%y' in strftime() without warnings since it's not y2k compliant</span><br><span style="color: hsl(120, 100%, 40%);">+test_capture.o: _ASTCFLAGS+=$(AST_NO_FORMAT_Y2K)</span><br><span> test_strings.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION) $(AST_NO_STRINGOP_TRUNCATION)</span><br><span> test_voicemail_api.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)</span><br><span>diff --git a/tests/test_capture.c b/tests/test_capture.c</span><br><span>new file mode 100644</span><br><span>index 0000000..33809df</span><br><span>--- /dev/null</span><br><span>+++ b/tests/test_capture.c</span><br><span>@@ -0,0 +1,379 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2022, Philip Prindeville</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Philip Prindeville <philipp@redfish-solutions.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Make basic use of capture capability in test framework.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author\verbatim Philip Prindeville <philipp@redfish-solutions.com> \endverbatim</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Exercise the capture capabilities built into the test framework so</span><br><span style="color: hsl(120, 100%, 40%);">+ * that external commands might be used to generate validating results</span><br><span style="color: hsl(120, 100%, 40%);">+ * used on corroborating tests.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \ingroup tests</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+      <depend>TEST_FRAMEWORK</depend></span><br><span style="color: hsl(120, 100%, 40%);">+   <support_level>core</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/test.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_capture_true)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int status = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *command = "true";</span><br><span style="color: hsl(120, 100%, 40%);">+       char *const args[] = { "true", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "test_capture_true";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->category = "/main/test_capture/";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->summary = "capture true exit unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+           info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Capture exit code from true command.";</span><br><span style="color: hsl(120, 100%, 40%);">+             return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_status_update(test, "Executing true exit test...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+            return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_capture_command(&cap, command, args, NULL, 0) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.outlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "unexpected value for stdout\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "unexpected value for stderr\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   status = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_capture_false)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int status = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *command = "false";</span><br><span style="color: hsl(120, 100%, 40%);">+      char *const args[] = { "false", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "test_capture_false";</span><br><span style="color: hsl(120, 100%, 40%);">+               info->category = "/main/test_capture/";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->summary = "capture false exit unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Capture exit code from false command.";</span><br><span style="color: hsl(120, 100%, 40%);">+            return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_status_update(test, "Executing false exit test...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+            return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_capture_command(&cap, command, args, NULL, 0) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.outlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "unexpected value for stdout\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "unexpected value for stderr\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.exitcode != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   status = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_capture_with_stdin)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int status = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *command = "base64";</span><br><span style="color: hsl(120, 100%, 40%);">+     char *const args[] = { "base64", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+    const char data[] = "Mary had a little lamb.";</span><br><span style="color: hsl(120, 100%, 40%);">+      const unsigned datalen = sizeof(data) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char output[] = "TWFyeSBoYWQgYSBsaXR0bGUgbGFtYi4=\n";</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned outputlen = sizeof(output) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "test_capture_with_stdin";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->category = "/main/test_capture/";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->summary = "capture with stdin unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Capture output from stdin transformation command.";</span><br><span style="color: hsl(120, 100%, 40%);">+                return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_status_update(test, "Executing stdin test...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+            return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_capture_command(&cap, command, args, data, datalen) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.outlen != outputlen || memcmp(cap.outbuf, output, cap.outlen)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "unexpected value for stdout\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "unexpected value for stderr\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   status = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_capture_with_dynamic)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int status = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *command = "date";</span><br><span style="color: hsl(120, 100%, 40%);">+       char *args[] = { "date", "DATE", "FORMAT", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+      char date[40];</span><br><span style="color: hsl(120, 100%, 40%);">+        const char format[] = "+%a, %d %b %y %T %z";</span><br><span style="color: hsl(120, 100%, 40%);">+        const char format2[] = "%a, %d %b %y %T %z\n";</span><br><span style="color: hsl(120, 100%, 40%);">+      char myresult[64];</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned myresultlen;</span><br><span style="color: hsl(120, 100%, 40%);">+ time_t now;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct tm *tm;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "test_capture_with_dynamic";</span><br><span style="color: hsl(120, 100%, 40%);">+                info->category = "/main/test_capture/";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->summary = "capture with dynamic argument unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+               info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Capture output from dynamic transformation command.";</span><br><span style="color: hsl(120, 100%, 40%);">+              return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_status_update(test, "Executing dynamic argument test...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+            return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   time(&now);</span><br><span style="color: hsl(120, 100%, 40%);">+       snprintf(date, sizeof(date), "--date=@%lu", now);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ tm = localtime(&now);</span><br><span style="color: hsl(120, 100%, 40%);">+     strftime(myresult, sizeof(myresult), format2, tm);</span><br><span style="color: hsl(120, 100%, 40%);">+    myresultlen = strlen(myresult);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     args[1] = date;</span><br><span style="color: hsl(120, 100%, 40%);">+       args[2] = (char *)format;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_capture_command(&cap, command, args, NULL, 0) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.outlen != myresultlen || memcmp(cap.outbuf, myresult, cap.outlen)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "unexpected value for stdout\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "unexpected value for stderr\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   status = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_capture_stdout_stderr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int status = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *command = "sh";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *const args[] = { "sh", "-c", "echo -n 'foo' >&2 ; echo -n 'zzz' >&1 ; echo -n 'bar' >&2", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "test_capture_stdout_stderr";</span><br><span style="color: hsl(120, 100%, 40%);">+               info->category = "/main/test_capture/";</span><br><span style="color: hsl(120, 100%, 40%);">+          info->summary = "capture stdout & stderr unit test";</span><br><span style="color: hsl(120, 100%, 40%);">+         info->description =</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Capture both stdout and stderr from shell.";</span><br><span style="color: hsl(120, 100%, 40%);">+               return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_status_update(test, "Executing stdout/stderr test...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+            return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_capture_command(&cap, command, args, NULL, 0) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return status;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.outlen != 3 || memcmp(cap.outbuf, "zzz", 3)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "unexpected value for stdout\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.errlen != 6 || memcmp(cap.errbuf, "foobar", 6)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_test_status_update(test, "unexpected value for stderr\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_status_update(test, "invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_test_status_update(test, "child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+            goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   status = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_TEST_UNREGISTER(test_capture_with_stdin);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(test_capture_with_dynamic);</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_TEST_UNREGISTER(test_capture_stdout_stderr);</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_TEST_UNREGISTER(test_capture_true);</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_TEST_UNREGISTER(test_capture_false);</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_TEST_REGISTER(test_capture_with_stdin);</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_TEST_REGISTER(test_capture_with_dynamic);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(test_capture_stdout_stderr);</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_TEST_REGISTER(test_capture_true);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(test_capture_false);</span><br><span style="color: hsl(120, 100%, 40%);">+        return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Capture support test");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19119">change 19119</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/19119"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: I0273e85eeeb6b8e46703f24cd74d84f3daf0a69a </div>
<div style="display:none"> Gerrit-Change-Number: 19119 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Philip Prindeville <philipp@redfish-solutions.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>