blob: 8b00440d62c11735e688352ef99019f8e4d4a4bc [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined(HAS_GTEST)
#include <gtest/gtest.h>
#else
#include "gtest_stubs.h"
#endif
#include <string.h>
#include <nvram/core/nvram_manager.h>
#include <nvram/core/persistence.h>
#include "fake_storage.h"
namespace nvram {
namespace {
class NvramManagerTest : public testing::Test {
protected:
NvramManagerTest() {
storage::Clear();
}
static void SetupHeader(uint32_t header_version, uint32_t index) {
NvramHeader header;
header.version = header_version;
ASSERT_TRUE(header.allocated_indices.Resize(1));
header.allocated_indices[0] = index;
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
}
static void ReadAndCompareSpaceData(NvramManager* nvram,
uint32_t index,
const void* expected_contents,
size_t expected_size) {
ReadSpaceRequest read_space_request;
read_space_request.index = index;
ReadSpaceResponse read_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram->ReadSpace(read_space_request, &read_space_response));
ASSERT_EQ(expected_size, read_space_response.buffer.size());
EXPECT_EQ(0, memcmp(read_space_response.buffer.data(), expected_contents,
expected_size));
}
static uint32_t GetControlsMask(const Vector<nvram_control_t>& controls) {
uint32_t mask = 0;
for (nvram_control_t control : controls) {
mask |= (1 << control);
}
return mask;
}
};
TEST_F(NvramManagerTest, Init_FromScratch) {
NvramManager nvram;
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 1;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(
NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
}
TEST_F(NvramManagerTest, Init_TrailingStorageBytes) {
// Set up a pre-existing space and add some trailing bytes.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
Blob space_blob;
ASSERT_EQ(storage::Status::kSuccess, storage::LoadSpace(1, &space_blob));
ASSERT_TRUE(space_blob.Resize(space_blob.size() + 10));
ASSERT_EQ(storage::Status::kSuccess, storage::StoreSpace(1, space_blob));
// Produce a matching header and append some trailing bytes.
NvramHeader header;
header.version = NvramHeader::kVersion;
ASSERT_TRUE(header.allocated_indices.Resize(1));
header.allocated_indices[0] = 1;
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
Blob header_blob;
ASSERT_EQ(storage::Status::kSuccess, storage::LoadHeader(&header_blob));
ASSERT_TRUE(header_blob.Resize(header_blob.size() + 10));
ASSERT_EQ(storage::Status::kSuccess, storage::StoreHeader(header_blob));
// Initialize the |NvramManager| and check that the header and space blobs get
// loaded successfully.
NvramManager nvram;
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.GetInfo(get_info_request, &get_info_response));
ASSERT_EQ(1U, get_info_response.space_list.size());
EXPECT_EQ(1U, get_info_response.space_list[0]);
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 1;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10U, get_space_info_response.size);
}
TEST_F(NvramManagerTest, Init_SpacesPresent) {
// Set up two pre-existing spaces.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
ASSERT_TRUE(space.contents.Resize(20));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(2, space));
// Indicate 3 present spaces in the header, including one that doesn't have
// space data in storage.
NvramHeader header;
header.version = NvramHeader::kVersion;
ASSERT_TRUE(header.allocated_indices.Resize(3));
header.allocated_indices[0] = 1;
header.allocated_indices[1] = 2;
header.allocated_indices[2] = 3;
header.provisional_index.Activate() = 4;
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
NvramManager nvram;
// Check that the spaces are correctly recovered.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 1;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10u, get_space_info_response.size);
get_space_info_request.index = 2;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(20u, get_space_info_response.size);
get_space_info_request.index = 3;
EXPECT_EQ(
NV_RESULT_INTERNAL_ERROR,
nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
get_space_info_request.index = 4;
EXPECT_EQ(
NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
}
TEST_F(NvramManagerTest, Init_BadSpacePresent) {
// Set up a good and a bad NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
const uint8_t kBadSpaceData[] = {0xba, 0xad};
Blob bad_space_blob;
ASSERT_TRUE(bad_space_blob.Assign(kBadSpaceData, sizeof(kBadSpaceData)));
ASSERT_EQ(storage::Status::kSuccess,
storage::StoreSpace(2, bad_space_blob));
NvramHeader header;
header.version = NvramHeader::kVersion;
ASSERT_TRUE(header.allocated_indices.Resize(2));
header.allocated_indices[0] = 1;
header.allocated_indices[1] = 2;
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
NvramManager nvram;
// The bad index will fail requests.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 2;
GetSpaceInfoResponse get_space_info_response;
nvram_result_t result =
nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response);
EXPECT_NE(NV_RESULT_SUCCESS, result);
EXPECT_NE(NV_RESULT_SPACE_DOES_NOT_EXIST, result);
// A request to get info for the good index should succeed.
get_space_info_request.index = 1;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10u, get_space_info_response.size);
}
TEST_F(NvramManagerTest, Init_NewerStorageVersion) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
SetupHeader(NvramHeader::kVersion + 1, 1);
NvramManager nvram;
// Requests should fail due to version mismatch.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 1;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(
NV_RESULT_INTERNAL_ERROR,
nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
}
TEST_F(NvramManagerTest, Init_StorageObjectTypeMismatch) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
// Copy the space blob to the header storage.
Blob space_blob;
ASSERT_EQ(storage::Status::kSuccess, storage::LoadSpace(1, &space_blob));
ASSERT_EQ(storage::Status::kSuccess, storage::StoreHeader(space_blob));
NvramManager nvram;
// Initialization should detect that the header storage object doesn't look
// like a header, so initialization should fail.
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.GetInfo(get_info_request, &get_info_response));
}
TEST_F(NvramManagerTest, CreateSpace_Success) {
NvramManager nvram;
// Make a call to CreateSpace, which should succeed.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 32;
ASSERT_TRUE(create_space_request.controls.Resize(5));
create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
create_space_request.controls[1] = NV_CONTROL_BOOT_READ_LOCK;
create_space_request.controls[2] = NV_CONTROL_WRITE_AUTHORIZATION;
create_space_request.controls[3] = NV_CONTROL_READ_AUTHORIZATION;
create_space_request.controls[4] = NV_CONTROL_WRITE_EXTEND;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.CreateSpace(create_space_request, &create_space_response));
// GetSpaceInfo should reflect the space parameters set during creation.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 1;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(32u, get_space_info_response.size);
EXPECT_EQ(GetControlsMask(create_space_request.controls),
GetControlsMask(get_space_info_response.controls));
EXPECT_EQ(false, get_space_info_response.read_locked);
EXPECT_EQ(false, get_space_info_response.write_locked);
}
TEST_F(NvramManagerTest, CreateSpace_Existing) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
SetupHeader(NvramHeader::kVersion, 1);
NvramManager nvram;
// A request to create another space with the same index should fail.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_SPACE_ALREADY_EXISTS,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, CreateSpace_TooLarge) {
NvramManager nvram;
// A request to create a space with a too large content size should fail.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16384;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, CreateSpace_AuthTooLarge) {
NvramManager nvram;
// A request to create a space with a too large authorization value size
// should fail.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
ASSERT_TRUE(create_space_request.authorization_value.Resize(256));
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, CreateSpace_BadControl) {
NvramManager nvram;
// A request to create a space with an unknown control value should fail.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16;
ASSERT_TRUE(create_space_request.controls.Resize(2));
create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
create_space_request.controls[1] = 17;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, CreateSpace_ControlWriteLockExclusive) {
NvramManager nvram;
// Spaces may not be created with conflicting write lock modes.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16;
ASSERT_TRUE(create_space_request.controls.Resize(2));
create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
create_space_request.controls[1] = NV_CONTROL_PERSISTENT_WRITE_LOCK;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, CreateSpace_WriteExtendSpaceSize) {
NvramManager nvram;
// Write-extend spaces must match SHA256 hash size, i.e. 32 bytes.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16;
ASSERT_TRUE(create_space_request.controls.Resize(1));
create_space_request.controls[0] = NV_CONTROL_WRITE_EXTEND;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, CreateSpace_HeaderWriteError) {
// If the header fails to get written to storage, the creation request should
// fail.
storage::SetHeaderWriteError(true);
NvramManager nvram;
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.CreateSpace(create_space_request, &create_space_response));
// The space shouldn't be present.
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.GetInfo(get_info_request, &get_info_response));
EXPECT_EQ(0U, get_info_response.space_list.size());
// Creation of the space after clearing the error should work.
storage::SetHeaderWriteError(false);
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.CreateSpace(create_space_request, &create_space_response));
// The space should be reported as allocated now.
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.GetInfo(get_info_request, &get_info_response));
ASSERT_EQ(1U, get_info_response.space_list.size());
EXPECT_EQ(1U, get_info_response.space_list[0]);
}
TEST_F(NvramManagerTest, CreateSpace_SpaceWriteError) {
storage::SetSpaceWriteError(1, true);
NvramManager nvram;
// A request to create another space with the same index should fail.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 16;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.CreateSpace(create_space_request, &create_space_response));
// Reloading the state after a crash should not show any traces of the space.
storage::SetSpaceWriteError(1, false);
NvramManager nvram2;
// The space shouldn't exist in the space list.
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram2.GetInfo(get_info_request, &get_info_response));
EXPECT_EQ(0U, get_info_response.space_list.size());
// The space info request should indicate the space doesn't exist.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 1;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(
NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram2.GetSpaceInfo(get_space_info_request, &get_space_info_response));
}
TEST_F(NvramManagerTest, DeleteSpace_SpaceAbsent) {
NvramManager nvram;
// Attempt to delete a non-existing space.
DeleteSpaceRequest delete_space_request;
delete_space_request.index = 42;
DeleteSpaceResponse delete_space_response;
EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.DeleteSpace(delete_space_request, &delete_space_response));
}
TEST_F(NvramManagerTest, DeleteSpace_Success) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
SetupHeader(NvramHeader::kVersion, 42);
NvramManager nvram;
// Successful deletion.
DeleteSpaceRequest delete_space_request;
delete_space_request.index = 42;
DeleteSpaceResponse delete_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.DeleteSpace(delete_space_request, &delete_space_response));
}
TEST_F(NvramManagerTest, DeleteSpace_AuthorizationFailure) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_WRITE_AUTHORIZATION);
const char kAuthorizationValue[] = "secret";
ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
sizeof(kAuthorizationValue)));
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
SetupHeader(NvramHeader::kVersion, 42);
NvramManager nvram;
// Deletion should fail if correct secret is not provided.
DeleteSpaceRequest delete_space_request;
delete_space_request.index = 42;
DeleteSpaceResponse delete_space_response;
EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
nvram.DeleteSpace(delete_space_request, &delete_space_response));
}
TEST_F(NvramManagerTest, DeleteSpace_HalfDeleted) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
SetupHeader(NvramHeader::kVersion, 42);
// Hold on to the space data.
Blob space_data;
ASSERT_EQ(storage::Status::kSuccess, storage::LoadSpace(42, &space_data));
NvramManager nvram;
// Delete the space.
DeleteSpaceRequest delete_space_request;
delete_space_request.index = 42;
DeleteSpaceResponse delete_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.DeleteSpace(delete_space_request, &delete_space_response));
// Put the space data back into place to simulate a half-completed deletion.
ASSERT_EQ(storage::Status::kSuccess, storage::StoreSpace(42, space_data));
// The space should remain deleted after re-initialization.
NvramManager nvram2;
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 42;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(
NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram2.GetSpaceInfo(get_space_info_request, &get_space_info_response));
// Re-creation of a space with the same index should work.
CreateSpaceRequest create_space_request;
create_space_request.index = 42;
create_space_request.size = 32;
ASSERT_TRUE(create_space_request.controls.Resize(1));
create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram2.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, DeleteSpace_SpaceDeleteError) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
SetupHeader(NvramHeader::kVersion, 42);
// Make space deletion fail.
storage::SetSpaceWriteError(42, true);
NvramManager nvram;
// Attempt to delete the space.
DeleteSpaceRequest delete_space_request;
delete_space_request.index = 42;
DeleteSpaceResponse delete_space_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.DeleteSpace(delete_space_request, &delete_space_response));
// The space should remain present.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 42;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10U, get_space_info_response.size);
// Starting up from scratch shouldn't destroy the space either.
storage::SetSpaceWriteError(42, false);
NvramManager nvram2;
GetSpaceInfoResponse get_space_info_response_2;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response_2));
EXPECT_EQ(10U, get_space_info_response_2.size);
}
TEST_F(NvramManagerTest, DeleteSpace_HeaderWriteError) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
SetupHeader(NvramHeader::kVersion, 42);
// Header write on deletion will fail.
storage::SetHeaderWriteError(true);
NvramManager nvram;
// Attempt to delete the space.
DeleteSpaceRequest delete_space_request;
delete_space_request.index = 42;
DeleteSpaceResponse delete_space_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.DeleteSpace(delete_space_request, &delete_space_response));
// The space should remain present.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 42;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10U, get_space_info_response.size);
// Starting up from scratch shouldn't destroy the space either.
storage::SetSpaceWriteError(42, false);
NvramManager nvram2;
GetSpaceInfoResponse get_space_info_response_2;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response_2));
EXPECT_EQ(10U, get_space_info_response_2.size);
}
TEST_F(NvramManagerTest, DisableCreate_Success) {
NvramManager nvram;
// Issue a successful disable create request.
DisableCreateRequest disable_create_request;
DisableCreateResponse disable_create_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.DisableCreate(disable_create_request,
&disable_create_response));
// Make sure space creation request fail afterwards.
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 32;
ASSERT_TRUE(create_space_request.controls.Resize(1));
create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram.CreateSpace(create_space_request, &create_space_response));
// Redundant requests to disable creation are OK.
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.DisableCreate(disable_create_request,
&disable_create_response));
// Space creation should remain disabled even after a reboot.
NvramManager nvram2;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram2.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, DisableCreate_WriteError) {
// Make header writes fail.
storage::SetHeaderWriteError(true);
NvramManager nvram;
// The disable request should fail.
DisableCreateRequest disable_create_request;
DisableCreateResponse disable_create_response;
EXPECT_EQ(
NV_RESULT_INTERNAL_ERROR,
nvram.DisableCreate(disable_create_request, &disable_create_response));
// We should still be able to create spaces after clearing the error.
storage::SetHeaderWriteError(false);
CreateSpaceRequest create_space_request;
create_space_request.index = 1;
create_space_request.size = 32;
ASSERT_TRUE(create_space_request.controls.Resize(1));
create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
CreateSpaceResponse create_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.CreateSpace(create_space_request, &create_space_response));
}
TEST_F(NvramManagerTest, WriteSpace_SpaceAbsent) {
NvramManager nvram;
// Attempt to write a non-existing space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("0123456789", 10));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.WriteSpace(write_space_request, &write_space_response));
}
TEST_F(NvramManagerTest, WriteSpace_Success) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Write the space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("0123456789", 10));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.WriteSpace(write_space_request,
&write_space_response));
// Read back the space and compare contents.
ReadAndCompareSpaceData(&nvram, 17, "0123456789", 10);
// The data should persist even after a reboot.
NvramManager nvram2;
ReadAndCompareSpaceData(&nvram2, 17, "0123456789", 10);
}
TEST_F(NvramManagerTest, WriteSpace_ExcessData) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Write the space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("0123456789abcdef", 16));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.WriteSpace(write_space_request, &write_space_response));
}
TEST_F(NvramManagerTest, WriteSpace_ShortData) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
memset(space.contents.data(), 'X', space.contents.size());
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Write the space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("01234", 5));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.WriteSpace(write_space_request, &write_space_response));
// Read back the space data and verify that the missing content bytes have
// been set to 0.
const uint8_t kExpectedContents[] = {'0', '1', '2', '3', '4', 0, 0, 0, 0, 0};
ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 10);
}
TEST_F(NvramManagerTest, WriteSpace_WriteExtend) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_WRITE_EXTEND);
ASSERT_TRUE(space.contents.Resize(32));
memset(space.contents.data(), 0, space.contents.size());
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Write the space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.WriteSpace(write_space_request, &write_space_response));
// Read back the space data and verify the hash.
const uint8_t kExpectedContents[] = {
0xee, 0x84, 0x52, 0x88, 0xbb, 0x60, 0x7e, 0x02, 0xfd, 0xfb, 0x31,
0x95, 0x3a, 0x77, 0x23, 0xcf, 0x67, 0xea, 0x6e, 0x2d, 0xd7, 0xdb,
0x8c, 0xb4, 0xe4, 0xd2, 0xfd, 0xb4, 0x76, 0x7a, 0x67, 0x89,
};
ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 32);
}
TEST_F(NvramManagerTest, WriteSpace_WriteExtendShortSpace) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_WRITE_EXTEND);
ASSERT_TRUE(space.contents.Resize(16));
memset(space.contents.data(), 0, space.contents.size());
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Write the space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.WriteSpace(write_space_request, &write_space_response));
// Read back the space data and verify the truncated hash.
const uint8_t kExpectedContents[] = {
0x24, 0x2a, 0xbb, 0x36, 0x10, 0x37, 0x92, 0x3f,
0x7d, 0x7d, 0x92, 0x3a, 0x16, 0x65, 0xd2, 0xa2,
};
ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 16);
}
TEST_F(NvramManagerTest, WriteSpace_WriteExtendLongSpace) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_WRITE_EXTEND);
ASSERT_TRUE(space.contents.Resize(33));
memset(space.contents.data(), 'X', space.contents.size());
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Write the space.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.WriteSpace(write_space_request, &write_space_response));
// Read back the space data and verify the hash and trailing 0 bytes.
const uint8_t kExpectedContents[] = {
0x99, 0xb8, 0x5f, 0xd0, 0xf7, 0x9b, 0x17, 0x2e, 0x0e, 0x58, 0x3d,
0x3c, 0x9a, 0x29, 0xa3, 0xaf, 0x0a, 0x4c, 0x68, 0x97, 0x72, 0x8c,
0x0c, 0xa4, 0x37, 0xad, 0x39, 0xf3, 0x8c, 0x6e, 0x64, 0xd7, 0x00,
};
ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 33);
}
TEST_F(NvramManagerTest, WriteSpace_AuthorizationFailure) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_WRITE_AUTHORIZATION);
ASSERT_TRUE(space.contents.Resize(10));
const char kAuthorizationValue[] = "secret";
ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
sizeof(kAuthorizationValue)));
ASSERT_TRUE(space.contents.Assign("0123456789", 10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Attempt a write with the wrong authorization value.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
nvram.WriteSpace(write_space_request, &write_space_response));
// The previous data should remain effective.
ReadAndCompareSpaceData(&nvram, 17, "0123456789", 10);
}
TEST_F(NvramManagerTest, WriteSpace_WriteError) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Assign("0123456789", 10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
storage::SetSpaceWriteError(17, true);
// Attempt a write, which should fail.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.WriteSpace(write_space_request, &write_space_response));
// The previous data should remain effective.
ReadAndCompareSpaceData(&nvram, 17, "0123456789", 10);
}
TEST_F(NvramManagerTest, ReadSpace_SpaceAbsent) {
NvramManager nvram;
// Attempt a read from a space that doesn't exist.
ReadSpaceRequest read_space_request;
read_space_request.index = 17;
ReadSpaceResponse read_space_response;
EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.ReadSpace(read_space_request, &read_space_response));
}
TEST_F(NvramManagerTest, ReadSpace_AuthorizationFailure) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_READ_AUTHORIZATION);
ASSERT_TRUE(space.contents.Resize(10));
const char kAuthorizationValue[] = "secret";
ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
sizeof(kAuthorizationValue)));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Attempt a read from the space.
ReadSpaceRequest read_space_request;
read_space_request.index = 17;
ReadSpaceResponse read_space_response;
EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
nvram.ReadSpace(read_space_request, &read_space_response));
EXPECT_EQ(0U, read_space_response.buffer.size());
}
TEST_F(NvramManagerTest, LockSpaceWrite_SpaceAbsent) {
NvramManager nvram;
// Attempt to lock a space that doesn't exist.
LockSpaceWriteRequest lock_space_write_request;
lock_space_write_request.index = 17;
LockSpaceWriteResponse lock_space_write_response;
EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.LockSpaceWrite(lock_space_write_request,
&lock_space_write_response));
}
TEST_F(NvramManagerTest, LockSpaceWrite_AuthorizationFailure) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_PERSISTENT_WRITE_LOCK) |
(1 << NV_CONTROL_WRITE_AUTHORIZATION);
ASSERT_TRUE(space.contents.Resize(10));
const char kAuthorizationValue[] = "secret";
ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
sizeof(kAuthorizationValue)));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Attempt to lock a space without valid authentication.
LockSpaceWriteRequest lock_space_write_request;
lock_space_write_request.index = 17;
LockSpaceWriteResponse lock_space_write_response;
EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
nvram.LockSpaceWrite(lock_space_write_request,
&lock_space_write_response));
}
TEST_F(NvramManagerTest, LockSpaceWrite_SuccessPersistent) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_PERSISTENT_WRITE_LOCK);
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Lock the space.
LockSpaceWriteRequest lock_space_write_request;
lock_space_write_request.index = 17;
LockSpaceWriteResponse lock_space_write_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.LockSpaceWrite(lock_space_write_request,
&lock_space_write_response));
// Writing should fail now.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram.WriteSpace(write_space_request, &write_space_response));
// The lock should be persistent, so writing should fail after reboot.
NvramManager nvram2;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram2.WriteSpace(write_space_request, &write_space_response));
}
TEST_F(NvramManagerTest, LockSpaceWrite_SuccessBoot) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_BOOT_WRITE_LOCK);
ASSERT_TRUE(space.contents.Assign("01234567890", 10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Lock the space.
LockSpaceWriteRequest lock_space_write_request;
lock_space_write_request.index = 17;
LockSpaceWriteResponse lock_space_write_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.LockSpaceWrite(lock_space_write_request,
&lock_space_write_response));
// Writing should fail now.
WriteSpaceRequest write_space_request;
write_space_request.index = 17;
ASSERT_TRUE(write_space_request.buffer.Assign("newcontent", 10));
WriteSpaceResponse write_space_response;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram.WriteSpace(write_space_request, &write_space_response));
// We configured a per-boot lock, so writing should succeed after reboot.
NvramManager nvram2;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram2.WriteSpace(write_space_request, &write_space_response));
ReadAndCompareSpaceData(&nvram2, 17, "newcontent", 10);
}
TEST_F(NvramManagerTest, LockSpaceWrite_NotLockable) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Attempt to lock a space without valid authentication.
LockSpaceWriteRequest lock_space_write_request;
lock_space_write_request.index = 17;
LockSpaceWriteResponse lock_space_write_response;
EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
nvram.LockSpaceWrite(lock_space_write_request,
&lock_space_write_response));
}
TEST_F(NvramManagerTest, LockSpaceRead_SpaceAbsent) {
NvramManager nvram;
// Attempt to lock a non-existing space.
LockSpaceReadRequest lock_space_read_request;
lock_space_read_request.index = 17;
LockSpaceReadResponse lock_space_read_response;
EXPECT_EQ(
NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.LockSpaceRead(lock_space_read_request, &lock_space_read_response));
}
TEST_F(NvramManagerTest, LockSpaceRead_AuthorizationFailure) {
// Set up an NVRAM space.
NvramSpace space;
space.controls =
(1 << NV_CONTROL_BOOT_READ_LOCK) | (1 << NV_CONTROL_READ_AUTHORIZATION);
ASSERT_TRUE(space.contents.Resize(10));
const char kAuthorizationValue[] = "secret";
ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
sizeof(kAuthorizationValue)));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Attempt to lock a space without valid authorization.
LockSpaceReadRequest lock_space_read_request;
lock_space_read_request.index = 17;
LockSpaceReadResponse lock_space_read_response;
EXPECT_EQ(
NV_RESULT_ACCESS_DENIED,
nvram.LockSpaceRead(lock_space_read_request, &lock_space_read_response));
}
TEST_F(NvramManagerTest, LockSpaceRead_Success) {
// Set up an NVRAM space.
NvramSpace space;
space.controls = (1 << NV_CONTROL_BOOT_READ_LOCK);
ASSERT_TRUE(space.contents.Assign("0123456789", 10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Lock the space.
LockSpaceReadRequest lock_space_read_request;
lock_space_read_request.index = 17;
LockSpaceReadResponse lock_space_read_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.LockSpaceRead(lock_space_read_request,
&lock_space_read_response));
// Read requests should fail now.
ReadSpaceRequest read_space_request;
read_space_request.index = 17;
ReadSpaceResponse read_space_response;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram.ReadSpace(read_space_request, &read_space_response));
EXPECT_EQ(0U, read_space_response.buffer.size());
// This is a non-persistent lock, so reads should work again after a reboot.
NvramManager nvram2;
ReadAndCompareSpaceData(&nvram2, 17, "0123456789", 10);
}
TEST_F(NvramManagerTest, LockSpaceRead_NotLockable) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Attempt to lock a space without valid authorization.
LockSpaceReadRequest lock_space_read_request;
lock_space_read_request.index = 17;
LockSpaceReadResponse lock_space_read_response;
EXPECT_EQ(
NV_RESULT_INVALID_PARAMETER,
nvram.LockSpaceRead(lock_space_read_request, &lock_space_read_response));
}
TEST_F(NvramManagerTest, WipeStorage_Success) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
// Check that the space is visible.
NvramManager nvram;
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 17;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10U, get_space_info_response.size);
// Request a wipe.
WipeStorageRequest wipe_storage_request;
WipeStorageResponse wipe_storage_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.WipeStorage(wipe_storage_request, &wipe_storage_response));
// The space should no longer be declared.
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.GetInfo(get_info_request, &get_info_response));
EXPECT_EQ(0U, get_info_response.space_list.size());
// Accessing the space should fail.
EXPECT_EQ(
NV_RESULT_SPACE_DOES_NOT_EXIST,
nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
}
TEST_F(NvramManagerTest, WipeStorage_Abort) {
// Set up two pre-existing spaces and a matching header.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
ASSERT_TRUE(space.contents.Resize(20));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(2, space));
NvramHeader header;
header.version = NvramHeader::kVersion;
ASSERT_TRUE(header.allocated_indices.Resize(2));
header.allocated_indices[0] = 1;
header.allocated_indices[1] = 2;
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
// Check that the spaces are visible.
NvramManager nvram;
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.GetInfo(get_info_request, &get_info_response));
EXPECT_EQ(2U, get_info_response.space_list.size());
int space_mask = 0;
for (size_t i = 0; i < get_info_response.space_list.size(); ++i) {
space_mask |= (1 << get_info_response.space_list[i]);
}
EXPECT_EQ(0x6, space_mask);
// Set things up so the deletion request for the second space fails.
storage::SetSpaceWriteError(2, true);
// The wipe request should fail now.
WipeStorageRequest wipe_storage_request;
WipeStorageResponse wipe_storage_response;
EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
nvram.WipeStorage(wipe_storage_request, &wipe_storage_response));
// New wipe attempt with a fresh instance after clearing the error.
storage::SetSpaceWriteError(2, false);
NvramManager nvram2;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram2.WipeStorage(wipe_storage_request, &wipe_storage_response));
// No spaces should remain.
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram2.GetInfo(get_info_request, &get_info_response));
EXPECT_EQ(0U, get_info_response.space_list.size());
}
TEST_F(NvramManagerTest, WipeStorage_Disable) {
// Set up an NVRAM space.
NvramSpace space;
ASSERT_TRUE(space.contents.Resize(10));
ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
SetupHeader(NvramHeader::kVersion, 17);
NvramManager nvram;
// Disable wiping.
DisableWipeRequest disable_wipe_request;
DisableWipeResponse disable_wipe_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.DisableWipe(disable_wipe_request, &disable_wipe_response));
// A wipe request should fail.
WipeStorageRequest wipe_storage_request;
WipeStorageResponse wipe_storage_response;
EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
nvram.WipeStorage(wipe_storage_request, &wipe_storage_response));
// The space should remain declared.
GetInfoRequest get_info_request;
GetInfoResponse get_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS,
nvram.GetInfo(get_info_request, &get_info_response));
ASSERT_EQ(1U, get_info_response.space_list.size());
EXPECT_EQ(17U, get_info_response.space_list[0]);
// The space data should remain present.
GetSpaceInfoRequest get_space_info_request;
get_space_info_request.index = 17;
GetSpaceInfoResponse get_space_info_response;
EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
&get_space_info_response));
EXPECT_EQ(10U, get_space_info_response.size);
}
} // namespace
} // namespace nvram