2 This is a host-based unit test for the VariableLockRequestToLock shim.
4 Copyright (c) Microsoft Corporation.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
24 #include <Protocol/VariableLock.h>
26 #define UNIT_TEST_NAME "VarPol/VarLock Shim Unit Test"
27 #define UNIT_TEST_VERSION "1.0"
29 /// === CODE UNDER TEST ===========================================================================
33 VariableLockRequestToLock (
34 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL
*This
,
35 IN CHAR16
*VariableName
,
36 IN EFI_GUID
*VendorGuid
39 /// === TEST DATA ==================================================================================
42 // Test GUID 1 {F955BA2D-4A2C-480C-BFD1-3CC522610592}
44 EFI_GUID mTestGuid1
= {
45 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0xc5, 0x22, 0x61, 0x5, 0x92 }
49 // Test GUID 2 {2DEA799E-5E73-43B9-870E-C945CE82AF3A}
51 EFI_GUID mTestGuid2
= {
52 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x45, 0xce, 0x82, 0xaf, 0x3a }
56 // Test GUID 3 {698A2BFD-A616-482D-B88C-7100BD6682A9}
58 EFI_GUID mTestGuid3
= {
59 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0x0, 0xbd, 0x66, 0x82, 0xa9 }
62 #define TEST_VAR_1_NAME L"TestVar1"
63 #define TEST_VAR_2_NAME L"TestVar2"
64 #define TEST_VAR_3_NAME L"TestVar3"
66 #define TEST_POLICY_ATTRIBUTES_NULL 0
67 #define TEST_POLICY_MIN_SIZE_NULL 0
68 #define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32
70 #define TEST_POLICY_MIN_SIZE_10 10
71 #define TEST_POLICY_MAX_SIZE_200 200
73 /// === HELPER FUNCTIONS ===========================================================================
76 Mocked version of GetVariable, for testing.
87 IN CHAR16
*VariableName
,
88 IN EFI_GUID
*VendorGuid
,
89 OUT UINT32
*Attributes OPTIONAL
,
90 IN OUT UINTN
*DataSize
,
91 OUT VOID
*Data OPTIONAL
97 EFI_STATUS MockedReturn
;
99 check_expected_ptr (VariableName
);
100 check_expected_ptr (VendorGuid
);
101 check_expected_ptr (DataSize
);
103 MockedAttr
= (UINT32
)mock ();
104 MockedDataSize
= (UINTN
)mock ();
105 MockedData
= (VOID
*)(UINTN
)mock ();
106 MockedReturn
= (EFI_STATUS
)mock ();
108 if (Attributes
!= NULL
) {
109 *Attributes
= MockedAttr
;
112 if ((Data
!= NULL
) && !EFI_ERROR (MockedReturn
)) {
113 CopyMem (Data
, MockedData
, MockedDataSize
);
116 *DataSize
= MockedDataSize
;
122 // Anything you think might be helpful that isn't a test itself.
126 This is a common setup function that will ensure the library is always
127 initialized with the stubbed GetVariable.
129 Not used by all test cases, but by most.
131 @param[in] Context Unit test case context
137 IN UNIT_TEST_CONTEXT Context
140 return EFI_ERROR (InitVariablePolicyLib (StubGetVariableNull
)) ? UNIT_TEST_ERROR_PREREQUISITE_NOT_MET
: UNIT_TEST_PASSED
;
144 Common cleanup function to make sure that the library is always de-initialized
145 prior to the next test case.
147 @param[in] Context Unit test case context
153 IN UNIT_TEST_CONTEXT Context
156 DeinitVariablePolicyLib ();
159 /// === TEST CASES =================================================================================
161 /// ===== SHIM SUITE ===========================================================
164 Test Case that locks a single variable using the Variable Lock Protocol.
165 The call is expected to succeed.
167 @param[in] Context Unit test case context
171 LockingWithoutAnyPoliciesShouldSucceed (
172 IN UNIT_TEST_CONTEXT Context
177 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
178 UT_ASSERT_NOT_EFI_ERROR (Status
);
180 return UNIT_TEST_PASSED
;
184 Test Case that locks the same variable twice using the Variable Lock Protocol.
185 Both calls are expected to succeed.
187 @param[in] Context Unit test case context
191 LockingTwiceShouldSucceed (
192 IN UNIT_TEST_CONTEXT Context
197 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
198 UT_ASSERT_NOT_EFI_ERROR (Status
);
200 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
201 UT_ASSERT_NOT_EFI_ERROR (Status
);
203 return UNIT_TEST_PASSED
;
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.
211 @param[in] Context Unit test case context
215 LockingALockedVariableShouldSucceed (
216 IN UNIT_TEST_CONTEXT Context
220 VARIABLE_POLICY_ENTRY
*NewEntry
;
223 // Create a variable policy that locks the variable.
225 Status
= CreateBasicVariablePolicy (
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
,
235 UT_ASSERT_NOT_EFI_ERROR (Status
);
238 // Register the new policy.
240 Status
= RegisterVariablePolicy (NewEntry
);
242 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
243 UT_ASSERT_NOT_EFI_ERROR (Status
);
247 return UNIT_TEST_PASSED
;
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.
256 @param[in] Context Unit test case context
260 LockingAnUnlockedVariableShouldFail (
261 IN UNIT_TEST_CONTEXT Context
265 VARIABLE_POLICY_ENTRY
*NewEntry
;
267 // Create a variable policy that locks the variable.
268 Status
= CreateVarStateVariablePolicy (
271 TEST_POLICY_MIN_SIZE_NULL
,
272 TEST_POLICY_MAX_SIZE_200
,
273 TEST_POLICY_ATTRIBUTES_NULL
,
274 TEST_POLICY_ATTRIBUTES_NULL
,
280 UT_ASSERT_NOT_EFI_ERROR (Status
);
282 // Register the new policy.
283 Status
= RegisterVariablePolicy (NewEntry
);
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
);
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
296 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
297 UT_ASSERT_TRUE (EFI_ERROR (Status
));
301 return UNIT_TEST_PASSED
;
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
311 @param[in] Context Unit test case context
315 LockingALockedVariableWithMatchingDataShouldSucceed (
316 IN UNIT_TEST_CONTEXT Context
320 VARIABLE_POLICY_ENTRY
*NewEntry
;
323 // Create a variable policy that locks the variable.
324 Status
= CreateVarStateVariablePolicy (
327 TEST_POLICY_MIN_SIZE_NULL
,
328 TEST_POLICY_MAX_SIZE_200
,
329 TEST_POLICY_ATTRIBUTES_NULL
,
330 TEST_POLICY_ATTRIBUTES_NULL
,
336 UT_ASSERT_NOT_EFI_ERROR (Status
);
338 // Register the new policy.
339 Status
= RegisterVariablePolicy (NewEntry
);
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
);
346 // With a policy, make sure that writes still work, since the variable doesn't exist.
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
353 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
354 UT_ASSERT_TRUE (!EFI_ERROR (Status
));
358 return UNIT_TEST_PASSED
;
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
368 @param[in] Context Unit test case context
372 LockingALockedVariableWithNonMatchingDataShouldFail (
373 IN UNIT_TEST_CONTEXT Context
377 VARIABLE_POLICY_ENTRY
*NewEntry
;
380 // Create a variable policy that locks the variable.
381 Status
= CreateVarStateVariablePolicy (
384 TEST_POLICY_MIN_SIZE_NULL
,
385 TEST_POLICY_MAX_SIZE_200
,
386 TEST_POLICY_ATTRIBUTES_NULL
,
387 TEST_POLICY_ATTRIBUTES_NULL
,
393 UT_ASSERT_NOT_EFI_ERROR (Status
);
395 // Register the new policy.
396 Status
= RegisterVariablePolicy (NewEntry
);
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
);
403 // With a policy, make sure that writes still work, since the variable doesn't exist.
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
410 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
411 UT_ASSERT_TRUE (EFI_ERROR (Status
));
415 return UNIT_TEST_PASSED
;
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.
424 @param[in] Context Unit test case context
428 SettingPolicyForALockedVariableShouldFail (
429 IN UNIT_TEST_CONTEXT Context
433 VARIABLE_POLICY_ENTRY
*NewEntry
;
435 // Lock the variable.
436 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
437 UT_ASSERT_NOT_EFI_ERROR (Status
);
439 // Create a variable policy that locks the variable.
440 Status
= CreateVarStateVariablePolicy (
443 TEST_POLICY_MIN_SIZE_NULL
,
444 TEST_POLICY_MAX_SIZE_200
,
445 TEST_POLICY_ATTRIBUTES_NULL
,
446 TEST_POLICY_ATTRIBUTES_NULL
,
452 UT_ASSERT_NOT_EFI_ERROR (Status
);
454 // Register the new policy.
455 Status
= RegisterVariablePolicy (NewEntry
);
456 UT_ASSERT_TRUE (EFI_ERROR (Status
));
460 return UNIT_TEST_PASSED
;
464 Main entry point to this unit test application.
466 Sets up and runs the test suites.
475 UNIT_TEST_FRAMEWORK_HANDLE Framework
;
476 UNIT_TEST_SUITE_HANDLE ShimTests
;
480 DEBUG ((DEBUG_INFO
, "%a v%a\n", UNIT_TEST_NAME
, UNIT_TEST_VERSION
));
483 // Start setting up the test framework for running the tests.
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
));
492 // Add all test suites and tests.
494 Status
= CreateUnitTestSuite (
497 "Variable Lock Shim Tests",
498 "VarPolicy.VarLockShim",
502 if (EFI_ERROR (Status
)) {
503 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for ShimTests\n"));
504 Status
= EFI_OUT_OF_RESOURCES
;
510 "Locking a variable with no matching policies should always work",
512 LockingWithoutAnyPoliciesShouldSucceed
,
519 "Locking a variable twice should always work",
521 LockingTwiceShouldSucceed
,
528 "Locking a variable that's already locked by another policy should work",
530 LockingALockedVariableShouldSucceed
,
537 "Locking a variable that already has an unlocked policy should fail",
538 "LockAfterUnlockedPolicy",
539 LockingAnUnlockedVariableShouldFail
,
546 "Locking a variable that already has an locked policy should succeed",
547 "LockAfterLockedPolicyMatchingData",
548 LockingALockedVariableWithMatchingDataShouldSucceed
,
555 "Locking a variable that already has an locked policy with matching data should succeed",
556 "LockAfterLockedPolicyNonMatchingData",
557 LockingALockedVariableWithNonMatchingDataShouldFail
,
564 "Adding a policy for a variable that has previously been locked should always fail",
565 "SetPolicyAfterLock",
566 SettingPolicyForALockedVariableShouldFail
,
573 // Execute the tests.
575 Status
= RunAllTestSuites (Framework
);
578 if (Framework
!= NULL
) {
579 FreeUnitTestFramework (Framework
);
586 /// Avoid ECC error for function name that starts with lower case letter
591 Standard POSIX C entry point for host based unit test execution.
593 @param[in] Argc Number of arguments
594 @param[in] Argv Array of pointers to arguments