findstr: Add basic functionality.
[wine.git] / programs / findstr / tests / findstr.c
blob1f565210e798feffaacfcd3be3d7a2798839b1f1
1 /*
2 * Copyright 2023 Zhiyi Zhang for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <windows.h>
20 #include "wine/test.h"
22 #define MAX_BUFFER 65536
24 static char stdout_buffer[MAX_BUFFER], stderr_buffer[MAX_BUFFER];
25 static DWORD stdout_size, stderr_size;
27 static void read_all_from_handle(HANDLE handle, char *buffer, DWORD *size)
29 char bytes[4096];
30 DWORD bytes_read;
32 memset(buffer, 0, MAX_BUFFER);
33 *size = 0;
34 for (;;)
36 BOOL success = ReadFile(handle, bytes, sizeof(bytes), &bytes_read, NULL);
37 if (!success || !bytes_read)
38 break;
39 if (*size + bytes_read > MAX_BUFFER)
41 ok(FALSE, "Insufficient buffer.\n");
42 break;
44 memcpy(buffer + *size, bytes, bytes_read);
45 *size += bytes_read;
49 static void write_to_handle(HANDLE handle, const char *str, int len)
51 DWORD dummy;
53 WriteFile(handle, str, len, &dummy, NULL);
56 #define run_find_stdin(a, b, c) _run_find_stdin(__FILE__, __LINE__, a, b, c)
57 static void _run_find_stdin(const char *file, int line, const char *commandline, const char *input,
58 int exitcode_expected)
60 HANDLE parent_stdin_write, parent_stdout_read, parent_stderr_read;
61 HANDLE child_stdin_read, child_stdout_write, child_stderr_write;
62 SECURITY_ATTRIBUTES security_attributes = {0};
63 PROCESS_INFORMATION process_info = {0};
64 STARTUPINFOA startup_info = {0};
65 char cmd[4096];
66 DWORD exitcode;
68 security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
69 security_attributes.bInheritHandle = TRUE;
71 CreatePipe(&child_stdin_read, &parent_stdin_write, &security_attributes, 0);
72 CreatePipe(&parent_stdout_read, &child_stdout_write, &security_attributes, 0);
73 CreatePipe(&parent_stderr_read, &child_stderr_write, &security_attributes, 0);
75 SetHandleInformation(parent_stdin_write, HANDLE_FLAG_INHERIT, 0);
76 SetHandleInformation(parent_stdout_read, HANDLE_FLAG_INHERIT, 0);
77 SetHandleInformation(parent_stderr_read, HANDLE_FLAG_INHERIT, 0);
79 startup_info.cb = sizeof(STARTUPINFOA);
80 startup_info.hStdInput = child_stdin_read;
81 startup_info.hStdOutput = child_stdout_write;
82 startup_info.hStdError = child_stderr_write;
83 startup_info.dwFlags |= STARTF_USESTDHANDLES;
85 sprintf(cmd, "findstr.exe %s", commandline);
87 CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info);
88 CloseHandle(child_stdin_read);
89 CloseHandle(child_stdout_write);
90 CloseHandle(child_stderr_write);
92 write_to_handle(parent_stdin_write, input, lstrlenA(input));
93 CloseHandle(parent_stdin_write);
95 read_all_from_handle(parent_stdout_read, stdout_buffer, &stdout_size);
96 read_all_from_handle(parent_stderr_read, stderr_buffer, &stderr_size);
97 CloseHandle(parent_stdout_read);
98 CloseHandle(parent_stderr_read);
100 WaitForSingleObject(process_info.hProcess, INFINITE);
101 GetExitCodeProcess(process_info.hProcess, &exitcode);
102 CloseHandle(process_info.hProcess);
103 CloseHandle(process_info.hThread);
104 ok_(file, line)(exitcode == exitcode_expected, "Expected exitcode %d, got %ld\n",
105 exitcode_expected, exitcode);
108 #define run_find_file(a, b, c) _run_find_file(__FILE__, __LINE__, a, b, c)
109 static void _run_find_file(const char *file, int line, const char *commandline, const char *input,
110 int exitcode_expected)
112 char path_temp_file[MAX_PATH], path_temp_dir[MAX_PATH], commandline_new[MAX_PATH];
113 HANDLE handle_file;
115 GetTempPathA(ARRAY_SIZE(path_temp_dir), path_temp_dir);
116 GetTempFileNameA(path_temp_dir, "", 0, path_temp_file);
117 handle_file = CreateFileA(path_temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
118 write_to_handle(handle_file, input, lstrlenA(input));
119 CloseHandle(handle_file);
121 sprintf(commandline_new, "%s %s", commandline, path_temp_file);
122 _run_find_stdin(file, line, commandline_new, "", exitcode_expected);
124 DeleteFileA(path_temp_file);
127 static void test_basic(void)
129 int ret;
131 /* No options */
132 run_find_stdin("", "", 2);
133 ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
134 ok(stderr_size > 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
135 ret = strcmp(stderr_buffer, "FINDSTR: Bad command line\r\n");
136 ok(!ret, "Got the wrong result.\n");
138 /* /? */
139 run_find_stdin("/?", "", 0);
140 ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
141 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
143 /* find string in stdin */
144 run_find_stdin("abc", "abc", 0);
145 ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
146 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
147 ret = strcmp(stdout_buffer, "abc\r\n");
148 ok(!ret, "Got the wrong result.\n");
150 /* find string in stdin fails */
151 run_find_stdin("abc", "cba", 1);
152 ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
153 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
155 /* find string in file */
156 run_find_file("abc", "abc", 0);
157 ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
158 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
159 ret = strcmp(stdout_buffer, "abc");
160 ok(!ret, "Got the wrong result.\n");
162 /* find string in file fails */
163 run_find_file("abc", "cba", 1);
164 ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
165 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
167 /* find string in stdin with space separator */
168 run_find_stdin("\"abc cba\"", "abc", 0);
169 ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
170 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
171 ret = strcmp(stdout_buffer, "abc\r\n");
172 ok(!ret, "Got the wrong result.\n");
174 /* find string in stdin with /C: */
175 run_find_stdin("/C:abc", "abc", 0);
176 ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
177 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
178 ret = strcmp(stdout_buffer, "abc\r\n");
179 ok(!ret, "Got the wrong result.\n");
181 /* find string in stdin with /C:"abc" */
182 run_find_stdin("/C:\"abc\"", "abc", 0);
183 ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
184 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
185 ret = strcmp(stdout_buffer, "abc\r\n");
186 ok(!ret, "Got the wrong result.\n");
188 /* find string in stdin with /C:"abc cba" fails */
189 run_find_stdin("/C:\"abc cba\"", "abc", 1);
190 ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
191 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
193 /* find string in stdin with /C: fails */
194 run_find_stdin("/C:abc", "cba", 1);
195 ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size);
196 ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size);
199 START_TEST(findstr)
201 if (PRIMARYLANGID(GetUserDefaultUILanguage()) != LANG_ENGLISH)
203 skip("Tests only work with English locale.\n");
204 return;
207 test_basic();