Imported Upstream version 1.5.7
[platform/upstream/libpipeline.git] / tests / read.c
1 /*
2  * Copyright (C) 2013 Peter Schiffer.
3  *
4  * This file is part of libpipeline.
5  *
6  * libpipeline is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or (at
9  * your option) any later version.
10  *
11  * libpipeline is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with libpipeline; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19  * USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/select.h>
30 #include <unistd.h>
31
32 #include "xalloc.h"
33 #include "xvasprintf.h"
34
35 #include "common.h"
36
37 const char *program_name = "read";
38
39 /* Must be 8194 or bigger */
40 #define RANDOM_STR_LEN 9000
41
42 /* Unit test for bug: https://bugzilla.redhat.com/show_bug.cgi?id=876108 */
43 START_TEST (test_read_long_line)
44 {
45         /* Generate long random string */
46         static const char *alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
47                                       "abcdefghijklmnopqrstuvwxyz";
48         char random_string[RANDOM_STR_LEN] = "";
49         unsigned i;
50
51         for (i = 0; i < RANDOM_STR_LEN - 2; i++) {
52                 random_string[i] = alphanum[rand () % (strlen (alphanum) - 1)];
53         }
54         random_string[RANDOM_STR_LEN - 1] = '\0';
55
56         /* Write the random string to file */
57         char *testfile = xasprintf ("%s/test", temp_dir);
58         FILE *tfd = fopen (testfile, "w");
59         if (!tfd) {
60                 ck_abort_msg ("fopen failed: %s", strerror (errno));
61                 return;
62         }
63         fprintf (tfd, "%s\n", random_string);
64         fclose (tfd);
65
66         char *expected_output = xasprintf ("%s\n", random_string);
67
68         pipeline *p;
69         const char *line;
70         char *read_result = NULL, *temp = NULL;
71
72         /* File must be read twice to reproduce the bug */
73         p = pipeline_new ();
74         pipeline_want_infile (p, testfile);
75         pipeline_want_out (p, -1);
76         pipeline_start (p);
77         while ((line = pipeline_readline (p)) != NULL) {
78                 if (read_result) {
79                         temp = read_result;
80                         read_result = xasprintf ("%s%s", read_result, line);
81                         free (temp);
82                 } else {
83                         read_result = xasprintf ("%s", line);
84                 }
85         }
86         pipeline_free (p);
87         ck_assert_str_eq (read_result, expected_output);
88
89         free (read_result);
90         read_result = NULL;
91
92         p = pipeline_new ();
93         pipeline_want_infile (p, testfile);
94         pipeline_want_out (p, -1);
95         pipeline_start (p);
96         while ((line = pipeline_readline (p)) != NULL) {
97                 if (read_result) {
98                         temp = read_result;
99                         read_result = xasprintf ("%s%s", read_result, line);
100                         free (temp);
101                 } else {
102                         read_result = xasprintf ("%s", line);
103                 }
104         }
105         pipeline_free (p);
106         ck_assert_str_eq (read_result, expected_output);
107
108         free (testfile);
109         free (expected_output);
110         free (read_result);
111 }
112 END_TEST
113
114 /* Write the first character of a string quickly, followed by the rest of it
115  * a little later.
116  */
117 static void slow_line_helper (void *data)
118 {
119         const char *s = data;
120         struct timeval timeout;
121
122         setbuf (stdout, NULL);
123         putchar (s[0]);
124         timeout.tv_sec = 0;
125         timeout.tv_usec = 100000;
126         select (0, NULL, NULL, NULL, &timeout);
127         fputs (s + 1, stdout);
128 }
129
130 START_TEST (test_read_readline_slow)
131 {
132         pipeline *p;
133         pipecmd *cmd;
134
135         p = pipeline_new ();
136         cmd = pipecmd_new_function ("slow_line_helper", slow_line_helper, free,
137                                     xstrdup ("a line\nsome more"));
138         pipeline_command (p, cmd);
139         pipeline_want_out (p, -1);
140         pipeline_start (p);
141         ck_assert_str_eq (pipeline_readline (p), "a line\n");
142         pipeline_free (p);
143 }
144 END_TEST
145
146 static Suite *read_suite (void)
147 {
148         Suite *s = suite_create ("Read");
149
150         TEST_CASE_WITH_FIXTURE (s, read, long_line, temp_dir_setup,
151                                 temp_dir_teardown);
152         TEST_CASE (s, read, readline_slow);
153
154         return s;
155 }
156
157 MAIN (read)