]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / RuntimeDxeUnitTest / VariableLockRequestToLockUnitTest.c
1 /** @file
2 This is a host-based unit test for the VariableLockRequestToLock shim.
3
4 Copyright (c) Microsoft Corporation.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <stddef.h>
13 #include <setjmp.h>
14 #include <cmocka.h>
15
16 #include <Uefi.h>
17 #include <Library/DebugLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/UnitTestLib.h>
21 #include <Library/VariablePolicyLib.h>
22 #include <Library/VariablePolicyHelperLib.h>
23
24 #include <Protocol/VariableLock.h>
25
26 #define UNIT_TEST_NAME "VarPol/VarLock Shim Unit Test"
27 #define UNIT_TEST_VERSION "1.0"
28
29 /// === CODE UNDER TEST ===========================================================================
30
31 EFI_STATUS
32 EFIAPI
33 VariableLockRequestToLock (
34 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
35 IN CHAR16 *VariableName,
36 IN EFI_GUID *VendorGuid
37 );
38
39 /// === TEST DATA ==================================================================================
40
41 //
42 // Test GUID 1 {F955BA2D-4A2C-480C-BFD1-3CC522610592}
43 //
44 EFI_GUID mTestGuid1 = {
45 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0xc5, 0x22, 0x61, 0x5, 0x92 }
46 };
47
48 //
49 // Test GUID 2 {2DEA799E-5E73-43B9-870E-C945CE82AF3A}
50 //
51 EFI_GUID mTestGuid2 = {
52 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x45, 0xce, 0x82, 0xaf, 0x3a }
53 };
54
55 //
56 // Test GUID 3 {698A2BFD-A616-482D-B88C-7100BD6682A9}
57 //
58 EFI_GUID mTestGuid3 = {
59 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0x0, 0xbd, 0x66, 0x82, 0xa9 }
60 };
61
62 #define TEST_VAR_1_NAME L"TestVar1"
63 #define TEST_VAR_2_NAME L"TestVar2"
64 #define TEST_VAR_3_NAME L"TestVar3"
65
66 #define TEST_POLICY_ATTRIBUTES_NULL 0
67 #define TEST_POLICY_MIN_SIZE_NULL 0
68 #define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32
69
70 #define TEST_POLICY_MIN_SIZE_10 10
71 #define TEST_POLICY_MAX_SIZE_200 200
72
73 /// === HELPER FUNCTIONS ===========================================================================
74
75 /**
76 Mocked version of GetVariable, for testing.
77
78 @param VariableName
79 @param VendorGuid
80 @param Attributes
81 @param DataSize
82 @param Data
83 **/
84 EFI_STATUS
85 EFIAPI
86 StubGetVariableNull (
87 IN CHAR16 *VariableName,
88 IN EFI_GUID *VendorGuid,
89 OUT UINT32 *Attributes OPTIONAL,
90 IN OUT UINTN *DataSize,
91 OUT VOID *Data OPTIONAL
92 )
93 {
94 UINT32 MockedAttr;
95 UINTN MockedDataSize;
96 VOID *MockedData;
97 EFI_STATUS MockedReturn;
98
99 check_expected_ptr (VariableName);
100 check_expected_ptr (VendorGuid);
101 check_expected_ptr (DataSize);
102
103 MockedAttr = (UINT32)mock ();
104 MockedDataSize = (UINTN)mock ();
105 MockedData = (VOID *)(UINTN)mock ();
106 MockedReturn = (EFI_STATUS)mock ();
107
108 if (Attributes != NULL) {
109 *Attributes = MockedAttr;
110 }
111
112 if ((Data != NULL) && !EFI_ERROR (MockedReturn)) {
113 CopyMem (Data, MockedData, MockedDataSize);
114 }
115
116 *DataSize = MockedDataSize;
117
118 return MockedReturn;
119 }
120
121 //
122 // Anything you think might be helpful that isn't a test itself.
123 //
124
125 /**
126 This is a common setup function that will ensure the library is always
127 initialized with the stubbed GetVariable.
128
129 Not used by all test cases, but by most.
130
131 @param[in] Context Unit test case context
132 **/
133 STATIC
134 UNIT_TEST_STATUS
135 EFIAPI
136 LibInitMocked (
137 IN UNIT_TEST_CONTEXT Context
138 )
139 {
140 return EFI_ERROR (InitVariablePolicyLib (StubGetVariableNull)) ? UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
141 }
142
143 /**
144 Common cleanup function to make sure that the library is always de-initialized
145 prior to the next test case.
146
147 @param[in] Context Unit test case context
148 **/
149 STATIC
150 VOID
151 EFIAPI
152 LibCleanup (
153 IN UNIT_TEST_CONTEXT Context
154 )
155 {
156 DeinitVariablePolicyLib ();
157 }
158
159 /// === TEST CASES =================================================================================
160
161 /// ===== SHIM SUITE ===========================================================
162
163 /**
164 Test Case that locks a single variable using the Variable Lock Protocol.
165 The call is expected to succeed.
166
167 @param[in] Context Unit test case context
168 **/
169 UNIT_TEST_STATUS
170 EFIAPI
171 LockingWithoutAnyPoliciesShouldSucceed (
172 IN UNIT_TEST_CONTEXT Context
173 )
174 {
175 EFI_STATUS Status;
176
177 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
178 UT_ASSERT_NOT_EFI_ERROR (Status);
179
180 return UNIT_TEST_PASSED;
181 }
182
183 /**
184 Test Case that locks the same variable twice using the Variable Lock Protocol.
185 Both calls are expected to succeed.
186
187 @param[in] Context Unit test case context
188 **/
189 UNIT_TEST_STATUS
190 EFIAPI
191 LockingTwiceShouldSucceed (
192 IN UNIT_TEST_CONTEXT Context
193 )
194 {
195 EFI_STATUS Status;
196
197 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
198 UT_ASSERT_NOT_EFI_ERROR (Status);
199
200 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
201 UT_ASSERT_NOT_EFI_ERROR (Status);
202
203 return UNIT_TEST_PASSED;
204 }
205
206 /**
207 Test Case that locks a variable using the Variable Policy Protocol then locks
208 the same variable using the Variable Lock Protocol.
209 Both calls are expected to succeed.
210
211 @param[in] Context Unit test case context
212 **/
213 UNIT_TEST_STATUS
214 EFIAPI
215 LockingALockedVariableShouldSucceed (
216 IN UNIT_TEST_CONTEXT Context
217 )
218 {
219 EFI_STATUS Status;
220 VARIABLE_POLICY_ENTRY *NewEntry;
221
222 //
223 // Create a variable policy that locks the variable.
224 //
225 Status = CreateBasicVariablePolicy (
226 &mTestGuid1,
227 TEST_VAR_1_NAME,
228 TEST_POLICY_MIN_SIZE_NULL,
229 TEST_POLICY_MAX_SIZE_200,
230 TEST_POLICY_ATTRIBUTES_NULL,
231 TEST_POLICY_ATTRIBUTES_NULL,
232 VARIABLE_POLICY_TYPE_LOCK_NOW,
233 &NewEntry
234 );
235 UT_ASSERT_NOT_EFI_ERROR (Status);
236
237 //
238 // Register the new policy.
239 //
240 Status = RegisterVariablePolicy (NewEntry);
241
242 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
243 UT_ASSERT_NOT_EFI_ERROR (Status);
244
245 FreePool (NewEntry);
246
247 return UNIT_TEST_PASSED;
248 }
249
250 /**
251 Test Case that locks a variable using the Variable Policy Protocol with a
252 policy other than LOCK_NOW then attempts to lock the same variable using the
253 Variable Lock Protocol. The call to Variable Policy is expected to succeed
254 and the call to Variable Lock is expected to fail.
255
256 @param[in] Context Unit test case context
257 **/
258 UNIT_TEST_STATUS
259 EFIAPI
260 LockingAnUnlockedVariableShouldFail (
261 IN UNIT_TEST_CONTEXT Context
262 )
263 {
264 EFI_STATUS Status;
265 VARIABLE_POLICY_ENTRY *NewEntry;
266
267 // Create a variable policy that locks the variable.
268 Status = CreateVarStateVariablePolicy (
269 &mTestGuid1,
270 TEST_VAR_1_NAME,
271 TEST_POLICY_MIN_SIZE_NULL,
272 TEST_POLICY_MAX_SIZE_200,
273 TEST_POLICY_ATTRIBUTES_NULL,
274 TEST_POLICY_ATTRIBUTES_NULL,
275 &mTestGuid2,
276 1,
277 TEST_VAR_2_NAME,
278 &NewEntry
279 );
280 UT_ASSERT_NOT_EFI_ERROR (Status);
281
282 // Register the new policy.
283 Status = RegisterVariablePolicy (NewEntry);
284
285 // Configure the stub to not care about parameters. We're testing errors.
286 expect_any_always (StubGetVariableNull, VariableName);
287 expect_any_always (StubGetVariableNull, VendorGuid);
288 expect_any_always (StubGetVariableNull, DataSize);
289
290 // With a policy, make sure that writes still work, since the variable doesn't exist.
291 will_return (StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL); // Attributes
292 will_return (StubGetVariableNull, 0); // Size
293 will_return (StubGetVariableNull, (UINTN)NULL); // DataPtr
294 will_return (StubGetVariableNull, EFI_NOT_FOUND); // Status
295
296 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
297 UT_ASSERT_TRUE (EFI_ERROR (Status));
298
299 FreePool (NewEntry);
300
301 return UNIT_TEST_PASSED;
302 }
303
304 /**
305 Test Case that locks a variable using the Variable Policy Protocol with a
306 policy other than LOCK_NOW, but is currently locked. Then attempts to lock
307 the same variable using the Variable Lock Protocol. The call to Variable
308 Policy is expected to succeed and the call to Variable Lock also expected to
309 succeed.
310
311 @param[in] Context Unit test case context
312 **/
313 UNIT_TEST_STATUS
314 EFIAPI
315 LockingALockedVariableWithMatchingDataShouldSucceed (
316 IN UNIT_TEST_CONTEXT Context
317 )
318 {
319 EFI_STATUS Status;
320 VARIABLE_POLICY_ENTRY *NewEntry;
321 UINT8 Data;
322
323 // Create a variable policy that locks the variable.
324 Status = CreateVarStateVariablePolicy (
325 &mTestGuid1,
326 TEST_VAR_1_NAME,
327 TEST_POLICY_MIN_SIZE_NULL,
328 TEST_POLICY_MAX_SIZE_200,
329 TEST_POLICY_ATTRIBUTES_NULL,
330 TEST_POLICY_ATTRIBUTES_NULL,
331 &mTestGuid2,
332 1,
333 TEST_VAR_2_NAME,
334 &NewEntry
335 );
336 UT_ASSERT_NOT_EFI_ERROR (Status);
337
338 // Register the new policy.
339 Status = RegisterVariablePolicy (NewEntry);
340
341 // Configure the stub to not care about parameters. We're testing errors.
342 expect_any_always (StubGetVariableNull, VariableName);
343 expect_any_always (StubGetVariableNull, VendorGuid);
344 expect_any_always (StubGetVariableNull, DataSize);
345
346 // With a policy, make sure that writes still work, since the variable doesn't exist.
347 Data = 1;
348 will_return (StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL); // Attributes
349 will_return (StubGetVariableNull, sizeof (Data)); // Size
350 will_return (StubGetVariableNull, (UINTN)&Data); // DataPtr
351 will_return (StubGetVariableNull, EFI_SUCCESS); // Status
352
353 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
354 UT_ASSERT_TRUE (!EFI_ERROR (Status));
355
356 FreePool (NewEntry);
357
358 return UNIT_TEST_PASSED;
359 }
360
361 /**
362 Test Case that locks a variable using the Variable Policy Protocol with a
363 policy other than LOCK_NOW, but variable data does not match. Then attempts
364 to lock the same variable using the Variable Lock Protocol. The call to
365 Variable Policy is expected to succeed and the call to Variable Lock is
366 expected to fail.
367
368 @param[in] Context Unit test case context
369 **/
370 UNIT_TEST_STATUS
371 EFIAPI
372 LockingALockedVariableWithNonMatchingDataShouldFail (
373 IN UNIT_TEST_CONTEXT Context
374 )
375 {
376 EFI_STATUS Status;
377 VARIABLE_POLICY_ENTRY *NewEntry;
378 UINT8 Data;
379
380 // Create a variable policy that locks the variable.
381 Status = CreateVarStateVariablePolicy (
382 &mTestGuid1,
383 TEST_VAR_1_NAME,
384 TEST_POLICY_MIN_SIZE_NULL,
385 TEST_POLICY_MAX_SIZE_200,
386 TEST_POLICY_ATTRIBUTES_NULL,
387 TEST_POLICY_ATTRIBUTES_NULL,
388 &mTestGuid2,
389 1,
390 TEST_VAR_2_NAME,
391 &NewEntry
392 );
393 UT_ASSERT_NOT_EFI_ERROR (Status);
394
395 // Register the new policy.
396 Status = RegisterVariablePolicy (NewEntry);
397
398 // Configure the stub to not care about parameters. We're testing errors.
399 expect_any_always (StubGetVariableNull, VariableName);
400 expect_any_always (StubGetVariableNull, VendorGuid);
401 expect_any_always (StubGetVariableNull, DataSize);
402
403 // With a policy, make sure that writes still work, since the variable doesn't exist.
404 Data = 2;
405 will_return (StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL); // Attributes
406 will_return (StubGetVariableNull, sizeof (Data)); // Size
407 will_return (StubGetVariableNull, (UINTN)&Data); // DataPtr
408 will_return (StubGetVariableNull, EFI_SUCCESS); // Status
409
410 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
411 UT_ASSERT_TRUE (EFI_ERROR (Status));
412
413 FreePool (NewEntry);
414
415 return UNIT_TEST_PASSED;
416 }
417
418 /**
419 Test Case that locks a variable using Variable Lock Protocol Policy Protocol
420 then and then attempts to lock the same variable using the Variable Policy
421 Protocol. The call to Variable Lock is expected to succeed and the call to
422 Variable Policy is expected to fail.
423
424 @param[in] Context Unit test case context
425 **/
426 UNIT_TEST_STATUS
427 EFIAPI
428 SettingPolicyForALockedVariableShouldFail (
429 IN UNIT_TEST_CONTEXT Context
430 )
431 {
432 EFI_STATUS Status;
433 VARIABLE_POLICY_ENTRY *NewEntry;
434
435 // Lock the variable.
436 Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
437 UT_ASSERT_NOT_EFI_ERROR (Status);
438
439 // Create a variable policy that locks the variable.
440 Status = CreateVarStateVariablePolicy (
441 &mTestGuid1,
442 TEST_VAR_1_NAME,
443 TEST_POLICY_MIN_SIZE_NULL,
444 TEST_POLICY_MAX_SIZE_200,
445 TEST_POLICY_ATTRIBUTES_NULL,
446 TEST_POLICY_ATTRIBUTES_NULL,
447 &mTestGuid2,
448 1,
449 TEST_VAR_2_NAME,
450 &NewEntry
451 );
452 UT_ASSERT_NOT_EFI_ERROR (Status);
453
454 // Register the new policy.
455 Status = RegisterVariablePolicy (NewEntry);
456 UT_ASSERT_TRUE (EFI_ERROR (Status));
457
458 FreePool (NewEntry);
459
460 return UNIT_TEST_PASSED;
461 }
462
463 /**
464 Main entry point to this unit test application.
465
466 Sets up and runs the test suites.
467 **/
468 VOID
469 EFIAPI
470 UnitTestMain (
471 VOID
472 )
473 {
474 EFI_STATUS Status;
475 UNIT_TEST_FRAMEWORK_HANDLE Framework;
476 UNIT_TEST_SUITE_HANDLE ShimTests;
477
478 Framework = NULL;
479
480 DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
481
482 //
483 // Start setting up the test framework for running the tests.
484 //
485 Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
486 if (EFI_ERROR (Status)) {
487 DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
488 goto EXIT;
489 }
490
491 //
492 // Add all test suites and tests.
493 //
494 Status = CreateUnitTestSuite (
495 &ShimTests,
496 Framework,
497 "Variable Lock Shim Tests",
498 "VarPolicy.VarLockShim",
499 NULL,
500 NULL
501 );
502 if (EFI_ERROR (Status)) {
503 DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for ShimTests\n"));
504 Status = EFI_OUT_OF_RESOURCES;
505 goto EXIT;
506 }
507
508 AddTestCase (
509 ShimTests,
510 "Locking a variable with no matching policies should always work",
511 "EmptyPolicies",
512 LockingWithoutAnyPoliciesShouldSucceed,
513 LibInitMocked,
514 LibCleanup,
515 NULL
516 );
517 AddTestCase (
518 ShimTests,
519 "Locking a variable twice should always work",
520 "DoubleLock",
521 LockingTwiceShouldSucceed,
522 LibInitMocked,
523 LibCleanup,
524 NULL
525 );
526 AddTestCase (
527 ShimTests,
528 "Locking a variable that's already locked by another policy should work",
529 "LockAfterPolicy",
530 LockingALockedVariableShouldSucceed,
531 LibInitMocked,
532 LibCleanup,
533 NULL
534 );
535 AddTestCase (
536 ShimTests,
537 "Locking a variable that already has an unlocked policy should fail",
538 "LockAfterUnlockedPolicy",
539 LockingAnUnlockedVariableShouldFail,
540 LibInitMocked,
541 LibCleanup,
542 NULL
543 );
544 AddTestCase (
545 ShimTests,
546 "Locking a variable that already has an locked policy should succeed",
547 "LockAfterLockedPolicyMatchingData",
548 LockingALockedVariableWithMatchingDataShouldSucceed,
549 LibInitMocked,
550 LibCleanup,
551 NULL
552 );
553 AddTestCase (
554 ShimTests,
555 "Locking a variable that already has an locked policy with matching data should succeed",
556 "LockAfterLockedPolicyNonMatchingData",
557 LockingALockedVariableWithNonMatchingDataShouldFail,
558 LibInitMocked,
559 LibCleanup,
560 NULL
561 );
562 AddTestCase (
563 ShimTests,
564 "Adding a policy for a variable that has previously been locked should always fail",
565 "SetPolicyAfterLock",
566 SettingPolicyForALockedVariableShouldFail,
567 LibInitMocked,
568 LibCleanup,
569 NULL
570 );
571
572 //
573 // Execute the tests.
574 //
575 Status = RunAllTestSuites (Framework);
576
577 EXIT:
578 if (Framework != NULL) {
579 FreeUnitTestFramework (Framework);
580 }
581
582 return;
583 }
584
585 ///
586 /// Avoid ECC error for function name that starts with lower case letter
587 ///
588 #define Main main
589
590 /**
591 Standard POSIX C entry point for host based unit test execution.
592
593 @param[in] Argc Number of arguments
594 @param[in] Argv Array of pointers to arguments
595
596 @retval 0 Success
597 @retval other Error
598 **/
599 INT32
600 Main (
601 IN INT32 Argc,
602 IN CHAR8 *Argv[]
603 )
604 {
605 UnitTestMain ();
606 return 0;
607 }