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
;
111 if (Data
!= NULL
&& !EFI_ERROR (MockedReturn
)) {
112 CopyMem (Data
, MockedData
, MockedDataSize
);
115 *DataSize
= MockedDataSize
;
121 // Anything you think might be helpful that isn't a test itself.
125 This is a common setup function that will ensure the library is always
126 initialized with the stubbed GetVariable.
128 Not used by all test cases, but by most.
130 @param[in] Context Unit test case context
136 IN UNIT_TEST_CONTEXT Context
139 return EFI_ERROR (InitVariablePolicyLib (StubGetVariableNull
)) ? UNIT_TEST_ERROR_PREREQUISITE_NOT_MET
: UNIT_TEST_PASSED
;
143 Common cleanup function to make sure that the library is always de-initialized
144 prior to the next test case.
146 @param[in] Context Unit test case context
152 IN UNIT_TEST_CONTEXT Context
155 DeinitVariablePolicyLib();
158 ///=== TEST CASES =================================================================================
160 ///===== SHIM SUITE ===========================================================
163 Test Case that locks a single variable using the Variable Lock Protocol.
164 The call is expected to succeed.
166 @param[in] Context Unit test case context
170 LockingWithoutAnyPoliciesShouldSucceed (
171 IN UNIT_TEST_CONTEXT Context
176 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
177 UT_ASSERT_NOT_EFI_ERROR (Status
);
179 return UNIT_TEST_PASSED
;
183 Test Case that locks the same variable twice using the Variable Lock Protocol.
184 Both calls are expected to succeed.
186 @param[in] Context Unit test case context
190 LockingTwiceShouldSucceed (
191 IN UNIT_TEST_CONTEXT Context
196 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
197 UT_ASSERT_NOT_EFI_ERROR (Status
);
199 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
200 UT_ASSERT_NOT_EFI_ERROR (Status
);
202 return UNIT_TEST_PASSED
;
206 Test Case that locks a variable using the Variable Policy Protocol then locks
207 the same variable using the Variable Lock Protocol.
208 Both calls are expected to succeed.
210 @param[in] Context Unit test case context
214 LockingALockedVariableShouldSucceed (
215 IN UNIT_TEST_CONTEXT Context
219 VARIABLE_POLICY_ENTRY
*NewEntry
;
222 // Create a variable policy that locks the variable.
224 Status
= CreateBasicVariablePolicy (
227 TEST_POLICY_MIN_SIZE_NULL
,
228 TEST_POLICY_MAX_SIZE_200
,
229 TEST_POLICY_ATTRIBUTES_NULL
,
230 TEST_POLICY_ATTRIBUTES_NULL
,
231 VARIABLE_POLICY_TYPE_LOCK_NOW
,
234 UT_ASSERT_NOT_EFI_ERROR (Status
);
237 // Register the new policy.
239 Status
= RegisterVariablePolicy (NewEntry
);
241 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
242 UT_ASSERT_NOT_EFI_ERROR (Status
);
246 return UNIT_TEST_PASSED
;
250 Test Case that locks a variable using the Variable Policy Protocol with a
251 policy other than LOCK_NOW then attempts to lock the same variable using the
252 Variable Lock Protocol. The call to Variable Policy is expected to succeed
253 and the call to Variable Lock is expected to fail.
255 @param[in] Context Unit test case context
259 LockingAnUnlockedVariableShouldFail (
260 IN UNIT_TEST_CONTEXT Context
264 VARIABLE_POLICY_ENTRY
*NewEntry
;
266 // Create a variable policy that locks the variable.
267 Status
= CreateVarStateVariablePolicy (&mTestGuid1
,
269 TEST_POLICY_MIN_SIZE_NULL
,
270 TEST_POLICY_MAX_SIZE_200
,
271 TEST_POLICY_ATTRIBUTES_NULL
,
272 TEST_POLICY_ATTRIBUTES_NULL
,
277 UT_ASSERT_NOT_EFI_ERROR (Status
);
279 // Register the new policy.
280 Status
= RegisterVariablePolicy (NewEntry
);
282 // Configure the stub to not care about parameters. We're testing errors.
283 expect_any_always( StubGetVariableNull
, VariableName
);
284 expect_any_always( StubGetVariableNull
, VendorGuid
);
285 expect_any_always( StubGetVariableNull
, DataSize
);
287 // With a policy, make sure that writes still work, since the variable doesn't exist.
288 will_return( StubGetVariableNull
, TEST_POLICY_ATTRIBUTES_NULL
); // Attributes
289 will_return( StubGetVariableNull
, 0 ); // Size
290 will_return( StubGetVariableNull
, (UINTN
)NULL
); // DataPtr
291 will_return( StubGetVariableNull
, EFI_NOT_FOUND
); // Status
293 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
294 UT_ASSERT_TRUE (EFI_ERROR (Status
));
298 return UNIT_TEST_PASSED
;
302 Test Case that locks a variable using the Variable Policy Protocol with a
303 policy other than LOCK_NOW, but is currently locked. Then attempts to lock
304 the same variable using the Variable Lock Protocol. The call to Variable
305 Policy is expected to succeed and the call to Variable Lock also expected to
308 @param[in] Context Unit test case context
312 LockingALockedVariableWithMatchingDataShouldSucceed (
313 IN UNIT_TEST_CONTEXT Context
317 VARIABLE_POLICY_ENTRY
*NewEntry
;
320 // Create a variable policy that locks the variable.
321 Status
= CreateVarStateVariablePolicy (&mTestGuid1
,
323 TEST_POLICY_MIN_SIZE_NULL
,
324 TEST_POLICY_MAX_SIZE_200
,
325 TEST_POLICY_ATTRIBUTES_NULL
,
326 TEST_POLICY_ATTRIBUTES_NULL
,
331 UT_ASSERT_NOT_EFI_ERROR (Status
);
333 // Register the new policy.
334 Status
= RegisterVariablePolicy (NewEntry
);
336 // Configure the stub to not care about parameters. We're testing errors.
337 expect_any_always( StubGetVariableNull
, VariableName
);
338 expect_any_always( StubGetVariableNull
, VendorGuid
);
339 expect_any_always( StubGetVariableNull
, DataSize
);
341 // With a policy, make sure that writes still work, since the variable doesn't exist.
343 will_return( StubGetVariableNull
, TEST_POLICY_ATTRIBUTES_NULL
); // Attributes
344 will_return( StubGetVariableNull
, sizeof (Data
) ); // Size
345 will_return( StubGetVariableNull
, (UINTN
)&Data
); // DataPtr
346 will_return( StubGetVariableNull
, EFI_SUCCESS
); // Status
348 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
349 UT_ASSERT_TRUE (!EFI_ERROR (Status
));
353 return UNIT_TEST_PASSED
;
357 Test Case that locks a variable using the Variable Policy Protocol with a
358 policy other than LOCK_NOW, but variable data does not match. Then attempts
359 to lock the same variable using the Variable Lock Protocol. The call to
360 Variable Policy is expected to succeed and the call to Variable Lock is
363 @param[in] Context Unit test case context
367 LockingALockedVariableWithNonMatchingDataShouldFail (
368 IN UNIT_TEST_CONTEXT Context
372 VARIABLE_POLICY_ENTRY
*NewEntry
;
375 // Create a variable policy that locks the variable.
376 Status
= CreateVarStateVariablePolicy (&mTestGuid1
,
378 TEST_POLICY_MIN_SIZE_NULL
,
379 TEST_POLICY_MAX_SIZE_200
,
380 TEST_POLICY_ATTRIBUTES_NULL
,
381 TEST_POLICY_ATTRIBUTES_NULL
,
386 UT_ASSERT_NOT_EFI_ERROR (Status
);
388 // Register the new policy.
389 Status
= RegisterVariablePolicy (NewEntry
);
391 // Configure the stub to not care about parameters. We're testing errors.
392 expect_any_always( StubGetVariableNull
, VariableName
);
393 expect_any_always( StubGetVariableNull
, VendorGuid
);
394 expect_any_always( StubGetVariableNull
, DataSize
);
396 // With a policy, make sure that writes still work, since the variable doesn't exist.
398 will_return( StubGetVariableNull
, TEST_POLICY_ATTRIBUTES_NULL
); // Attributes
399 will_return( StubGetVariableNull
, sizeof (Data
) ); // Size
400 will_return( StubGetVariableNull
, (UINTN
)&Data
); // DataPtr
401 will_return( StubGetVariableNull
, EFI_SUCCESS
); // Status
403 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
404 UT_ASSERT_TRUE (EFI_ERROR (Status
));
408 return UNIT_TEST_PASSED
;
412 Test Case that locks a variable using Variable Lock Protocol Policy Protocol
413 then and then attempts to lock the same variable using the Variable Policy
414 Protocol. The call to Variable Lock is expected to succeed and the call to
415 Variable Policy is expected to fail.
417 @param[in] Context Unit test case context
421 SettingPolicyForALockedVariableShouldFail (
422 IN UNIT_TEST_CONTEXT Context
426 VARIABLE_POLICY_ENTRY
*NewEntry
;
428 // Lock the variable.
429 Status
= VariableLockRequestToLock (NULL
, TEST_VAR_1_NAME
, &mTestGuid1
);
430 UT_ASSERT_NOT_EFI_ERROR (Status
);
432 // Create a variable policy that locks the variable.
433 Status
= CreateVarStateVariablePolicy (&mTestGuid1
,
435 TEST_POLICY_MIN_SIZE_NULL
,
436 TEST_POLICY_MAX_SIZE_200
,
437 TEST_POLICY_ATTRIBUTES_NULL
,
438 TEST_POLICY_ATTRIBUTES_NULL
,
443 UT_ASSERT_NOT_EFI_ERROR (Status
);
445 // Register the new policy.
446 Status
= RegisterVariablePolicy (NewEntry
);
447 UT_ASSERT_TRUE (EFI_ERROR (Status
));
451 return UNIT_TEST_PASSED
;
455 Main entry point to this unit test application.
457 Sets up and runs the test suites.
466 UNIT_TEST_FRAMEWORK_HANDLE Framework
;
467 UNIT_TEST_SUITE_HANDLE ShimTests
;
471 DEBUG ((DEBUG_INFO
, "%a v%a\n", UNIT_TEST_NAME
, UNIT_TEST_VERSION
));
474 // Start setting up the test framework for running the tests.
476 Status
= InitUnitTestFramework (&Framework
, UNIT_TEST_NAME
, gEfiCallerBaseName
, UNIT_TEST_VERSION
);
477 if (EFI_ERROR (Status
)) {
478 DEBUG ((DEBUG_ERROR
, "Failed in InitUnitTestFramework. Status = %r\n", Status
));
483 // Add all test suites and tests.
485 Status
= CreateUnitTestSuite (
486 &ShimTests
, Framework
,
487 "Variable Lock Shim Tests", "VarPolicy.VarLockShim", NULL
, NULL
489 if (EFI_ERROR (Status
)) {
490 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for ShimTests\n"));
491 Status
= EFI_OUT_OF_RESOURCES
;
496 "Locking a variable with no matching policies should always work", "EmptyPolicies",
497 LockingWithoutAnyPoliciesShouldSucceed
, LibInitMocked
, LibCleanup
, NULL
501 "Locking a variable twice should always work", "DoubleLock",
502 LockingTwiceShouldSucceed
, LibInitMocked
, LibCleanup
, NULL
506 "Locking a variable that's already locked by another policy should work", "LockAfterPolicy",
507 LockingALockedVariableShouldSucceed
, LibInitMocked
, LibCleanup
, NULL
511 "Locking a variable that already has an unlocked policy should fail", "LockAfterUnlockedPolicy",
512 LockingAnUnlockedVariableShouldFail
, LibInitMocked
, LibCleanup
, NULL
516 "Locking a variable that already has an locked policy should succeed", "LockAfterLockedPolicyMatchingData",
517 LockingALockedVariableWithMatchingDataShouldSucceed
, LibInitMocked
, LibCleanup
, NULL
521 "Locking a variable that already has an locked policy with matching data should succeed", "LockAfterLockedPolicyNonMatchingData",
522 LockingALockedVariableWithNonMatchingDataShouldFail
, LibInitMocked
, LibCleanup
, NULL
526 "Adding a policy for a variable that has previously been locked should always fail", "SetPolicyAfterLock",
527 SettingPolicyForALockedVariableShouldFail
, LibInitMocked
, LibCleanup
, NULL
531 // Execute the tests.
533 Status
= RunAllTestSuites (Framework
);
536 if (Framework
!= NULL
) {
537 FreeUnitTestFramework (Framework
);
544 /// Avoid ECC error for function name that starts with lower case letter
549 Standard POSIX C entry point for host based unit test execution.
551 @param[in] Argc Number of arguments
552 @param[in] Argv Array of pointers to arguments