Skip to content

Commit

Permalink
Add unit test coverage for racing updaters (#2292)
Browse files Browse the repository at this point in the history
It would be good to also add some coverage in
update_client::UrlFetcherDownloader; we can plan to do that in a
separate change.

b/309841211

Change-Id: I6505843004aafc920a1a7e84a6c61551dbbbb7a3
  • Loading branch information
hlwarriner authored Jan 31, 2024
1 parent 57d564c commit 106bcd6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 3 deletions.
1 change: 1 addition & 0 deletions components/update_client/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ target(gtest_target_type, "cobalt_slot_management_test") {
"//net:test_support",
"//starboard/loader_app:app_key_files",
"//starboard/loader_app:drain_file",
"//starboard/loader_app:drain_file_helper",
"//starboard/loader_app:installation_manager",
"//testing/gmock",
"//testing/gtest",
Expand Down
29 changes: 28 additions & 1 deletion components/update_client/cobalt_slot_management_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

#include "base/strings/string_util.h"
#include "starboard/common/file.h"
#include "starboard/common/time.h"
#include "starboard/extension/free_space.h"
#include "starboard/loader_app/app_key_files.h"
#include "starboard/loader_app/drain_file.h"
#include "starboard/loader_app/drain_file_helper.h"
#include "starboard/loader_app/installation_manager.h"
#include "starboard/loader_app/system_get_extension_shim.h"
#include "testing/gtest/include/gtest/gtest.h"
Expand Down Expand Up @@ -117,7 +119,7 @@ TEST_F(CobaltSlotManagementTest, SelectEmptySlot) {
base::CompareCase::SENSITIVE));
}

TEST_F(CobaltSlotManagementTest, SelectSlotBailOnDraining) {
TEST_F(CobaltSlotManagementTest, SelectSlotBailsIfOtherAppIsDraining) {
if (!storage_path_implemented_) {
return;
}
Expand Down Expand Up @@ -185,6 +187,31 @@ TEST_F(CobaltSlotManagementTest, ConfirmSlot) {
ASSERT_EQ(IM_MAX_NUM_TRIES, ImGetInstallationNumTriesLeft(1));
}

// Tests the "racing updaters" scenario.
TEST_F(CobaltSlotManagementTest, ConfirmSlotBailsIfOtherAppStartedDrainFirst) {
if (!storage_path_implemented_) {
return;
}

CobaltSlotManagement cobalt_slot_management;
std::string slot_path = storage_path_;
slot_path += kSbFileSepString;
slot_path += "installation_1";
ASSERT_TRUE(cobalt_slot_management.Init(api_));
base::FilePath dir;
ASSERT_TRUE(cobalt_slot_management.SelectSlot(&dir));

// In order to be higher ranked, the other app's drain file needs to be older
// but not expired.
int64_t current_time_us =
starboard::PosixTimeToWindowsTime(starboard::CurrentPosixTime());
starboard::loader_app::ScopedDrainFile racing_drain_file(
slot_path, kTestAppKey2,
current_time_us - (kDrainFileMaximumAgeUsec / 2));

ASSERT_FALSE(cobalt_slot_management.ConfirmSlot(dir));
}

TEST_F(CobaltSlotManagementTest, CleanupAllDrainFiles) {
if (!storage_path_implemented_) {
return;
Expand Down
16 changes: 14 additions & 2 deletions starboard/loader_app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,28 @@ static_library("drain_file") {
deps = [ "//starboard/common" ]
}

target(gtest_target_type, "drain_file_test") {
static_library("drain_file_helper") {
testonly = true
sources = [
"//starboard/common/test_main.cc",
"drain_file_helper.cc",
"drain_file_helper.h",
]
deps = [
":drain_file",
"//starboard/common",
"//testing/gtest",
]
}

target(gtest_target_type, "drain_file_test") {
testonly = true
sources = [
"//starboard/common/test_main.cc",
"drain_file_test.cc",
]
deps = [
":drain_file",
":drain_file_helper",
"//testing/gmock",
"//testing/gtest",
]
Expand Down
10 changes: 10 additions & 0 deletions starboard/loader_app/drain_file_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ TEST_F(DrainFileTest, SunnyDayRankCorrectlyIgnoresExpired) {
EXPECT_TRUE(SbFileDelete(early_and_expired.path().c_str()));
}

// Tests the "racing updaters" scenario.
TEST_F(DrainFileTest, RankAndCheckWithFirstRankedFileFromOtherAppReturnsFalse) {
const int64_t timestamp = PosixTimeToWindowsTime(CurrentPosixTime());

ScopedDrainFile earlier(GetTempDir(), "a", timestamp);
ScopedDrainFile later(GetTempDir(), "b", timestamp + kDrainFileAgeUnitUsec);

EXPECT_FALSE(DrainFileRankAndCheck(GetTempDir(), "b"));
}

// All files in the directory should be cleared except for drain files with an
// app key matching the provided app key.
TEST_F(DrainFileTest, SunnyDayPrepareDirectory) {
Expand Down

0 comments on commit 106bcd6

Please sign in to comment.