1 /*
2  * Test suite for Task interface
3  *
4  * Copyright (C) 2008 Google (Roy Shea)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define COBJMACROS
22 
23 #include <corerror.h>
24 
25 #include "mstask.h"
26 #include "wine/test.h"
27 
28 static ITaskScheduler *test_task_scheduler;
29 static ITask *test_task;
30 static ITaskTrigger *test_trigger;
31 static WORD trigger_index;
32 
33 static BOOL setup_trigger(void)
34 {
35     HRESULT hres;
36     const WCHAR task_name[] = {'T','e','s','t','i','n','g', 0};
37 
38     hres = CoCreateInstance(&CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER,
39             &IID_ITaskScheduler, (void **) &test_task_scheduler);
40     if(hres != S_OK)
41         return FALSE;
42     hres = ITaskScheduler_NewWorkItem(test_task_scheduler, task_name,
43             &CLSID_CTask, &IID_ITask, (IUnknown**)&test_task);
44     if(hres != S_OK)
45     {
46         ITaskScheduler_Release(test_task_scheduler);
47         return FALSE;
48     }
49     hres = ITask_CreateTrigger(test_task, &trigger_index, &test_trigger);
50     if(hres != S_OK)
51     {
52         ITask_Release(test_task);
53         ITaskScheduler_Release(test_task_scheduler);
54         return FALSE;
55     }
56     return TRUE;
57 }
58 
59 static void cleanup_trigger(void)
60 {
61     ITaskTrigger_Release(test_trigger);
62     ITask_Release(test_task);
63     ITaskScheduler_Release(test_task_scheduler);
64 }
65 
66 static BOOL compare_trigger_state(TASK_TRIGGER found_state,
67         TASK_TRIGGER expected_state)
68 {
69     ok(found_state.cbTriggerSize == expected_state.cbTriggerSize,
70             "cbTriggerSize: Found %d but expected %d\n",
71             found_state.cbTriggerSize, expected_state.cbTriggerSize);
72 
73     ok(found_state.Reserved1 == expected_state.Reserved1,
74             "Reserved1: Found %d but expected %d\n",
75             found_state.Reserved1, expected_state.Reserved1);
76 
77     ok(found_state.wBeginYear == expected_state.wBeginYear,
78             "wBeginYear: Found %d but expected %d\n",
79             found_state.wBeginYear, expected_state.wBeginYear);
80 
81     ok(found_state.wBeginMonth == expected_state.wBeginMonth,
82             "wBeginMonth: Found %d but expected %d\n",
83             found_state.wBeginMonth, expected_state.wBeginMonth);
84 
85     ok(found_state.wBeginDay == expected_state.wBeginDay,
86             "wBeginDay: Found %d but expected %d\n",
87             found_state.wBeginDay, expected_state.wBeginDay);
88 
89     ok(found_state.wEndYear == expected_state.wEndYear,
90             "wEndYear: Found %d but expected %d\n",
91             found_state.wEndYear, expected_state.wEndYear);
92 
93     ok(found_state.wEndMonth == expected_state.wEndMonth,
94             "wEndMonth: Found %d but expected %d\n",
95             found_state.wEndMonth, expected_state.wEndMonth);
96 
97     ok(found_state.wEndDay == expected_state.wEndDay,
98             "wEndDay: Found %d but expected %d\n",
99             found_state.wEndDay, expected_state.wEndDay);
100 
101     ok(found_state.wStartHour == expected_state.wStartHour,
102             "wStartHour: Found %d but expected %d\n",
103             found_state.wStartHour, expected_state.wStartHour);
104 
105     ok(found_state.wStartMinute == expected_state.wStartMinute,
106             "wStartMinute: Found %d but expected %d\n",
107             found_state.wStartMinute, expected_state.wStartMinute);
108 
109     ok(found_state.MinutesDuration == expected_state.MinutesDuration,
110             "MinutesDuration: Found %d but expected %d\n",
111             found_state.MinutesDuration, expected_state.MinutesDuration);
112 
113     ok(found_state.MinutesInterval == expected_state.MinutesInterval,
114             "MinutesInterval: Found %d but expected %d\n",
115             found_state.MinutesInterval, expected_state.MinutesInterval);
116 
117     ok(found_state.rgFlags == expected_state.rgFlags,
118             "rgFlags: Found %d but expected %d\n",
119             found_state.rgFlags, expected_state.rgFlags);
120 
121     ok(found_state.TriggerType == expected_state.TriggerType,
122             "TriggerType: Found %d but expected %d\n",
123             found_state.TriggerType, expected_state.TriggerType);
124 
125     ok(found_state.Type.Daily.DaysInterval == expected_state.Type.Daily.DaysInterval,
126             "Type.Daily.DaysInterval: Found %d but expected %d\n",
127             found_state.Type.Daily.DaysInterval, expected_state.Type.Daily.DaysInterval);
128 
129     ok(found_state.Reserved2 == expected_state.Reserved2,
130             "Reserved2: Found %d but expected %d\n",
131             found_state.Reserved2, expected_state.Reserved2);
132 
133     ok(found_state.wRandomMinutesInterval == expected_state.wRandomMinutesInterval,
134             "wRandomMinutesInterval: Found %d but expected %d\n",
135             found_state.wRandomMinutesInterval, expected_state.wRandomMinutesInterval);
136 
137     return TRUE;
138 }
139 
140 static void test_SetTrigger_GetTrigger(void)
141 {
142     BOOL setup;
143     HRESULT hres;
144     TASK_TRIGGER trigger_state;
145     TASK_TRIGGER empty_trigger_state = {
146         sizeof(trigger_state), 0,
147         0, 0, 0,
148         0, 0, 0,
149         0, 0, 0, 0,
150         TASK_TRIGGER_FLAG_DISABLED, TASK_TIME_TRIGGER_DAILY, {{1}},
151         0, 0
152     };
153     TASK_TRIGGER normal_trigger_state = {
154         sizeof(trigger_state), 0,
155         1980, 1, 1,
156         2980, 2, 2,
157         3, 3,
158         0, 0,
159         TASK_TRIGGER_FLAG_DISABLED, TASK_TIME_TRIGGER_DAILY, {{1}},
160         0, 0
161     };
162     SYSTEMTIME time;
163 
164     setup = setup_trigger();
165     ok(setup, "Failed to setup test_task\n");
166     if (!setup)
167     {
168         skip("Failed to create task.  Skipping tests.\n");
169         return;
170     }
171 
172     /* Setup a trigger with base values for this test run */
173     GetLocalTime(&time);
174     empty_trigger_state.wStartHour = time.wHour;
175     empty_trigger_state.wStartMinute = time.wMinute;
176     empty_trigger_state.wBeginYear = time.wYear;
177     empty_trigger_state.wBeginMonth = time.wMonth;
178     empty_trigger_state.wBeginDay = time.wDay;
179 
180     /* Test trigger state after trigger creation but before setting * state */
181     memset(&trigger_state, 0xcf, sizeof(trigger_state));
182     trigger_state.cbTriggerSize = sizeof(trigger_state);
183     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
184     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
185     compare_trigger_state(trigger_state, empty_trigger_state);
186 
187     /* Test setting basic empty trigger */
188     hres = ITaskTrigger_SetTrigger(test_trigger, &empty_trigger_state);
189     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
190     memset(&trigger_state, 0xcf, sizeof(trigger_state));
191     trigger_state.cbTriggerSize = sizeof(trigger_state);
192     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
193     ok(hres == S_OK, "Failed to GetTrigger\n");
194     compare_trigger_state(trigger_state, empty_trigger_state);
195 
196     /* Test setting basic non-empty trigger */
197     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
198     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
199     memset(&trigger_state, 0xcf, sizeof(trigger_state));
200     trigger_state.cbTriggerSize = sizeof(trigger_state);
201     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
202     ok(hres == S_OK, "Failed to GetTrigger\n");
203     compare_trigger_state(trigger_state, normal_trigger_state);
204 
205     /* The following tests modify the normal_trigger_state structure
206      * before each test, and return the normal_trigger_state structure
207      * back to its original valid state after each test.  This keeps
208      * each test run independent. */
209 
210     /* Test setting trigger with invalid cbTriggerSize */
211     normal_trigger_state.cbTriggerSize = sizeof(trigger_state) - 1;
212     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
213     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
214     normal_trigger_state.cbTriggerSize = sizeof(trigger_state) + 1;
215     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
216     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
217     normal_trigger_state.cbTriggerSize = sizeof(trigger_state);
218 
219     /* Test setting trigger with invalid Reserved fields */
220     normal_trigger_state.Reserved1 = 80;
221     normal_trigger_state.Reserved2 = 80;
222     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
223     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
224     memset(&trigger_state, 0xcf, sizeof(trigger_state));
225     trigger_state.cbTriggerSize = sizeof(trigger_state);
226     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
227     ok(hres == S_OK, "Expected S_OK: 0x%08x\n", hres);
228     ok(trigger_state.Reserved1 == 0 && trigger_state.Reserved2 == 0,
229             "Reserved fields should be set to zero\n");
230     normal_trigger_state.Reserved1 = 0;
231     normal_trigger_state.Reserved2 = 0;
232 
233     /* Test setting trigger with invalid month */
234     normal_trigger_state.wBeginMonth = 0;
235     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
236     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
237     normal_trigger_state.wBeginMonth = 13;
238     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
239     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
240     normal_trigger_state.wBeginMonth = 1;
241 
242     /* Test setting trigger with invalid begin date */
243     normal_trigger_state.wBeginDay = 0;
244     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
245     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
246     normal_trigger_state.wBeginDay = 32;
247     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
248     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
249     normal_trigger_state.wBeginMonth = 2;
250     normal_trigger_state.wBeginDay = 30;
251     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
252     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
253     normal_trigger_state.wBeginMonth = 1;
254     normal_trigger_state.wBeginDay = 1;
255 
256     /* Test setting trigger invalid end date */
257     normal_trigger_state.wEndYear = 0;
258     normal_trigger_state.wEndMonth = 200;
259     normal_trigger_state.wEndDay = 200;
260     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
261     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
262     memset(&trigger_state, 0xcf, sizeof(trigger_state));
263     trigger_state.cbTriggerSize = sizeof(trigger_state);
264     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
265     ok(hres == S_OK, "Expected S_OK: 0x%08x\n", hres);
266     ok(trigger_state.wEndYear == 0, "End year should be 0: %d\n",
267             trigger_state.wEndYear);
268     ok(trigger_state.wEndMonth == 200, "End month should be 200: %d\n",
269             trigger_state.wEndMonth);
270     ok(trigger_state.wEndDay == 200, "End day should be 200: %d\n",
271             trigger_state.wEndDay);
272     normal_trigger_state.rgFlags =
273             TASK_TRIGGER_FLAG_DISABLED | TASK_TRIGGER_FLAG_HAS_END_DATE;
274     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
275     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
276     normal_trigger_state.rgFlags = TASK_TRIGGER_FLAG_DISABLED;
277     normal_trigger_state.wEndYear = 2980;
278     normal_trigger_state.wEndMonth = 1;
279     normal_trigger_state.wEndDay = 1;
280 
281     /* Test setting trigger with invalid hour or minute*/
282     normal_trigger_state.wStartHour = 24;
283     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
284     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
285     normal_trigger_state.wStartHour = 60;
286     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
287     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
288     normal_trigger_state.wStartHour = 3;
289 
290     /* Test setting trigger with invalid duration / interval pairs */
291     normal_trigger_state.MinutesDuration = 5;
292     normal_trigger_state.MinutesInterval = 5;
293     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
294     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
295     normal_trigger_state.MinutesDuration = 5;
296     normal_trigger_state.MinutesInterval = 6;
297     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
298     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
299     normal_trigger_state.MinutesDuration = 0;
300     normal_trigger_state.MinutesInterval = 6;
301     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
302     ok(hres == E_INVALIDARG, "Expected E_INVALIDARG: 0x%08x\n", hres);
303     normal_trigger_state.MinutesDuration = 5;
304     normal_trigger_state.MinutesInterval = 0;
305     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
306     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
307     normal_trigger_state.MinutesDuration = 0;
308     normal_trigger_state.MinutesInterval = 0;
309 
310     /* Test setting trigger with end date before start date */
311     normal_trigger_state.wEndYear = 1979;
312     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
313     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
314     normal_trigger_state.rgFlags =
315             TASK_TRIGGER_FLAG_DISABLED | TASK_TRIGGER_FLAG_HAS_END_DATE;
316     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
317     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
318     normal_trigger_state.rgFlags = TASK_TRIGGER_FLAG_DISABLED;
319     normal_trigger_state.wEndYear = 2980;
320     normal_trigger_state.wEndMonth = 1;
321     normal_trigger_state.wEndDay = 1;
322 
323 
324     /* Test setting trigger with invalid TriggerType and Type */
325     normal_trigger_state.TriggerType = TASK_TIME_TRIGGER_ONCE;
326     normal_trigger_state.Type.Weekly.WeeksInterval = 2;
327     normal_trigger_state.Type.Weekly.rgfDaysOfTheWeek = (TASK_MONDAY | TASK_TUESDAY);
328     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
329     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
330     memset(&trigger_state, 0xcf, sizeof(trigger_state));
331     trigger_state.cbTriggerSize = sizeof(trigger_state);
332     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
333     ok(hres == S_OK, "Expected S_OK: 0x%08x\n", hres);
334     ok(trigger_state.Type.Weekly.WeeksInterval == 0xcfcf,
335             "Expected WeeksInterval set remain untouched: %d\n",
336             trigger_state.Type.Weekly.WeeksInterval);
337     ok(trigger_state.Type.Weekly.rgfDaysOfTheWeek == 0xcfcf,
338             "Expected WeeksInterval set remain untouched: %d\n",
339             trigger_state.Type.Weekly.rgfDaysOfTheWeek);
340     normal_trigger_state.TriggerType = TASK_TIME_TRIGGER_DAILY;
341     normal_trigger_state.Type.Daily.DaysInterval = 1;
342     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
343     ok(hres == S_OK, "Expected S_OK: 0x%08x\n", hres);
344 
345     /* Test setting trigger with set wRandomMinutesInterval */
346     normal_trigger_state.wRandomMinutesInterval = 5;
347     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
348     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
349     memset(&trigger_state, 0xcf, sizeof(trigger_state));
350     trigger_state.cbTriggerSize = sizeof(trigger_state);
351     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
352     ok(hres == S_OK, "Expected S_OK: 0x%08x\n", hres);
353     ok(trigger_state.wRandomMinutesInterval == 0,
354             "wRandomMinutesInterval should be set to zero\n");
355     normal_trigger_state.wRandomMinutesInterval = 0;
356 
357     /* Test GetTrigger using invalid cbTriggerSiz in pTrigger.  In
358      * contrast to available documentation, this succeeds in practice. */
359     hres = ITaskTrigger_SetTrigger(test_trigger, &normal_trigger_state);
360     ok(hres == S_OK, "Failed to set trigger: 0x%08x\n", hres);
361     memset(&trigger_state, 0xcf, sizeof(trigger_state));
362     trigger_state.cbTriggerSize = sizeof(trigger_state) - 1;
363     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
364     ok(hres == S_OK, "Failed to GetTrigger\n");
365     ok(compare_trigger_state(trigger_state, normal_trigger_state),
366             "Invalid state\n");
367     memset(&trigger_state, 0xcf, sizeof(trigger_state));
368     trigger_state.cbTriggerSize = 0;
369     hres = ITaskTrigger_GetTrigger(test_trigger, &trigger_state);
370     ok(hres == S_OK, "Failed to GetTrigger\n");
371     ok(compare_trigger_state(trigger_state, normal_trigger_state),
372             "Invalid state\n");
373 
374 
375     cleanup_trigger();
376     return;
377 }
378 
379 
380 START_TEST(task_trigger)
381 {
382     CoInitialize(NULL);
383     test_SetTrigger_GetTrigger();
384     CoUninitialize();
385 }
386