Skip to content

Commit 2557a5d

Browse files
anrossiguhetier
andauthored
Add Writability to Storage Abstraction (#5133)
* Add Writability to Storage Abstraction * Add tests from #5132 --------- Co-authored-by: Guillaume Hetier <guhetier@microsoft.com>
1 parent e08fd6e commit 2557a5d

File tree

12 files changed

+1101
-623
lines changed

12 files changed

+1101
-623
lines changed

src/core/configuration.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ MsQuicConfigurationOpen(
128128
NULL,
129129
(CXPLAT_STORAGE_CHANGE_CALLBACK_HANDLER)QuicConfigurationSettingsChanged,
130130
Configuration,
131+
CXPLAT_STORAGE_OPEN_FLAG_READ,
131132
&Configuration->Storage);
132133
if (QUIC_FAILED(Status)) {
133134
QuicTraceLogWarning(
@@ -156,6 +157,7 @@ MsQuicConfigurationOpen(
156157
SpecificAppKey,
157158
(CXPLAT_STORAGE_CHANGE_CALLBACK_HANDLER)QuicConfigurationSettingsChanged,
158159
Configuration,
160+
CXPLAT_STORAGE_OPEN_FLAG_READ,
159161
&Configuration->AppSpecificStorage);
160162
if (QUIC_FAILED(Status)) {
161163
QuicTraceLogWarning(

src/core/library.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ MsQuicLibraryInitialize(
419419
NULL,
420420
MsQuicLibraryReadSettings,
421421
(void*)TRUE, // Non-null indicates registrations should be updated
422+
CXPLAT_STORAGE_OPEN_FLAG_READ,
422423
&MsQuicLib.Storage);
423424
if (QUIC_FAILED(Status)) {
424425
QuicTraceLogWarning(

src/core/unittest/SettingsTest.cpp

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
1010
--*/
1111

12+
#define QUIC_UNIT_TESTS
13+
1214
#include "main.h"
1315
#ifdef QUIC_CLOG
1416
#include "SettingsTest.cpp.clog.h"
@@ -335,6 +337,247 @@ TEST(SettingsTest, StreamRecvWindowDefaultGetsOverridenByIndividualLimits)
335337
#define SETTINGS_SIZE_THRU_FIELD(SettingsType, Field) \
336338
(FIELD_OFFSET(SettingsType, Field) + sizeof(((SettingsType*)0)->Field))
337339

340+
TEST(SettingsTest, QuicSettingsSetDefault_DoesNotOverwriteSetFields)
341+
{
342+
QUIC_SETTINGS_INTERNAL Settings;
343+
CxPlatZeroMemory(&Settings, sizeof(Settings));
344+
345+
// Set a few fields and mark them as set
346+
Settings.IsSet.SendBufferingEnabled = 1;
347+
Settings.SendBufferingEnabled = 0;
348+
Settings.IsSet.PacingEnabled = 1;
349+
Settings.PacingEnabled = 0;
350+
QuicSettingsSetDefault(&Settings);
351+
352+
// These should not be overwritten
353+
ASSERT_EQ(Settings.SendBufferingEnabled, 0);
354+
ASSERT_EQ(Settings.PacingEnabled, 0);
355+
356+
// But an unset field should be set to default
357+
ASSERT_EQ(Settings.MigrationEnabled, QUIC_DEFAULT_MIGRATION_ENABLED);
358+
}
359+
360+
class QuicStorageSettingScopeGuard {
361+
public:
362+
static
363+
QuicStorageSettingScopeGuard Create(
364+
_In_opt_ const char* StorageName = nullptr)
365+
{
366+
return QuicStorageSettingScopeGuard(StorageName);
367+
}
368+
369+
QuicStorageSettingScopeGuard(const QuicStorageSettingScopeGuard&) = delete;
370+
QuicStorageSettingScopeGuard& operator=(const QuicStorageSettingScopeGuard&) = delete;
371+
372+
QuicStorageSettingScopeGuard(
373+
_In_ QuicStorageSettingScopeGuard&& Other) noexcept : m_Storage(Other.m_Storage)
374+
{
375+
Other.m_Storage = nullptr;
376+
}
377+
378+
QuicStorageSettingScopeGuard& operator=(
379+
_In_ QuicStorageSettingScopeGuard&& Other)
380+
{
381+
if (this == &Other)
382+
{
383+
return Other;
384+
}
385+
ClearAndClose(m_Storage);
386+
m_Storage = Other.m_Storage;
387+
Other.m_Storage = nullptr;
388+
return *this;
389+
}
390+
391+
~QuicStorageSettingScopeGuard()
392+
{
393+
ClearAndClose(m_Storage);
394+
}
395+
396+
operator CXPLAT_STORAGE*() const {
397+
return m_Storage;
398+
}
399+
400+
private:
401+
QuicStorageSettingScopeGuard(
402+
_In_opt_ const char* StorageName)
403+
{
404+
EXPECT_EQ(
405+
QUIC_STATUS_SUCCESS,
406+
CxPlatStorageOpen(
407+
StorageName,
408+
nullptr,
409+
nullptr,
410+
CXPLAT_STORAGE_OPEN_FLAG_DELETE | CXPLAT_STORAGE_OPEN_FLAG_WRITE | CXPLAT_STORAGE_OPEN_FLAG_CREATE,
411+
&m_Storage));
412+
EXPECT_NE(m_Storage, nullptr);
413+
}
414+
415+
void ClearAndClose(
416+
_In_opt_ CXPLAT_STORAGE* Storage)
417+
{
418+
if (Storage != nullptr) {
419+
EXPECT_EQ(QUIC_STATUS_SUCCESS, CxPlatStorageClear(Storage));
420+
CxPlatStorageClose(Storage);
421+
}
422+
}
423+
424+
CXPLAT_STORAGE* m_Storage = nullptr;
425+
};
426+
427+
// --- Test: QuicSettingsLoad sets fields from storage ---
428+
TEST(SettingsTest, QuicSettingsLoad_SetsFieldsFromStorage)
429+
{
430+
CXPLAT_STORAGE* TestStorage = NULL;
431+
432+
QUIC_STATUS Status =
433+
CxPlatStorageOpen(
434+
"Apps\\MsQuicUnitTestStorage",
435+
nullptr,
436+
nullptr,
437+
CXPLAT_STORAGE_OPEN_FLAG_CREATE,
438+
&TestStorage);
439+
440+
if (Status == QUIC_STATUS_NOT_SUPPORTED) {
441+
GTEST_SKIP() << "Skipping test because storage is not available. Status:" << Status;
442+
}
443+
CxPlatStorageClose(TestStorage);
444+
445+
ASSERT_EQ(Status, QUIC_STATUS_SUCCESS);
446+
447+
QuicStorageSettingScopeGuard StorageGuard =
448+
QuicStorageSettingScopeGuard::Create("Apps\\MsQuicUnitTestStorage");
449+
450+
uint32_t Value = 0;
451+
ASSERT_EQ(
452+
QUIC_STATUS_SUCCESS,
453+
CxPlatStorageWriteValue(
454+
StorageGuard,
455+
QUIC_SETTING_SEND_BUFFERING_DEFAULT,
456+
CXPLAT_STORAGE_TYPE_UINT32,
457+
sizeof(Value),
458+
(uint8_t*)&Value));
459+
460+
ASSERT_EQ(
461+
QUIC_STATUS_SUCCESS,
462+
CxPlatStorageWriteValue(
463+
StorageGuard,
464+
QUIC_SETTING_SEND_PACING_DEFAULT,
465+
CXPLAT_STORAGE_TYPE_UINT32,
466+
sizeof(Value),
467+
(uint8_t*)&Value));
468+
469+
ASSERT_EQ(
470+
QUIC_STATUS_SUCCESS,
471+
CxPlatStorageWriteValue(
472+
StorageGuard,
473+
QUIC_SETTING_MIGRATION_ENABLED,
474+
CXPLAT_STORAGE_TYPE_UINT32,
475+
sizeof(Value),
476+
(uint8_t*)&Value));
477+
478+
Value = 7;
479+
ASSERT_EQ(
480+
QUIC_STATUS_SUCCESS,
481+
CxPlatStorageWriteValue(
482+
StorageGuard,
483+
QUIC_SETTING_MAX_OPERATIONS_PER_DRAIN,
484+
CXPLAT_STORAGE_TYPE_UINT32,
485+
sizeof(Value),
486+
(uint8_t*)&Value));
487+
488+
QUIC_SETTINGS_INTERNAL Settings;
489+
CxPlatZeroMemory(&Settings, sizeof(Settings));
490+
QuicSettingsLoad(&Settings, StorageGuard);
491+
492+
// Check that the values were loaded
493+
ASSERT_EQ(Settings.SendBufferingEnabled, 0u);
494+
ASSERT_EQ(Settings.PacingEnabled, 0u);
495+
ASSERT_EQ(Settings.MigrationEnabled, 0u);
496+
ASSERT_EQ(Settings.MaxOperationsPerDrain, 7u);
497+
498+
QuicSettingsDumpNew(&Settings);
499+
}
500+
501+
// --- Test: QuicSettingsLoad does not overwrite set fields ---
502+
TEST(SettingsTest, QuicSettingsLoad_DoesNotOverwriteSetFields)
503+
{
504+
CXPLAT_STORAGE* TestStorage = NULL;
505+
506+
QUIC_STATUS Status =
507+
CxPlatStorageOpen(
508+
"Apps\\MsQuicUnitTestStorage",
509+
nullptr,
510+
nullptr,
511+
CXPLAT_STORAGE_OPEN_FLAG_CREATE,
512+
&TestStorage);
513+
514+
if (Status == QUIC_STATUS_NOT_SUPPORTED) {
515+
GTEST_SKIP() << "Skipping test because storage is not available. Status:" << Status;
516+
}
517+
CxPlatStorageClose(TestStorage);
518+
519+
ASSERT_EQ(Status, QUIC_STATUS_SUCCESS);
520+
521+
QuicStorageSettingScopeGuard StorageGuard =
522+
QuicStorageSettingScopeGuard::Create("Apps\\MsQuicUnitTestStorage");
523+
524+
uint32_t Value = 0;
525+
ASSERT_EQ(
526+
QUIC_STATUS_SUCCESS,
527+
CxPlatStorageWriteValue(
528+
StorageGuard,
529+
QUIC_SETTING_SEND_BUFFERING_DEFAULT,
530+
CXPLAT_STORAGE_TYPE_UINT32,
531+
sizeof(Value),
532+
(uint8_t*)&Value));
533+
534+
QUIC_SETTINGS_INTERNAL Settings;
535+
CxPlatZeroMemory(&Settings, sizeof(Settings));
536+
537+
// Mark SendBufferingEnabled as set
538+
Settings.IsSet.SendBufferingEnabled = 1;
539+
Settings.SendBufferingEnabled = 1;
540+
541+
QuicSettingsLoad(&Settings, StorageGuard);
542+
543+
// Should not be overwritten
544+
ASSERT_EQ(Settings.SendBufferingEnabled, 1u);
545+
}
546+
547+
// --- Test: QuicSettingsLoad uses default if storage missing ---
548+
TEST(SettingsTest, QuicSettingsLoad_UsesDefaultIfStorageMissing)
549+
{
550+
CXPLAT_STORAGE* TestStorage = NULL;
551+
552+
QUIC_STATUS Status =
553+
CxPlatStorageOpen(
554+
"Apps\\MsQuicUnitTestStorage",
555+
nullptr,
556+
nullptr,
557+
CXPLAT_STORAGE_OPEN_FLAG_CREATE,
558+
&TestStorage);
559+
560+
if (Status == QUIC_STATUS_NOT_SUPPORTED) {
561+
GTEST_SKIP() << "Skipping test because storage is not available. Status:" << Status;
562+
}
563+
CxPlatStorageClose(TestStorage);
564+
565+
ASSERT_EQ(Status, QUIC_STATUS_SUCCESS);
566+
567+
QuicStorageSettingScopeGuard StorageGuard =
568+
QuicStorageSettingScopeGuard::Create("Apps\\MsQuicUnitTestStorage");
569+
570+
QUIC_SETTINGS_INTERNAL Settings;
571+
CxPlatZeroMemory(&Settings, sizeof(Settings));
572+
QuicSettingsLoad(&Settings, StorageGuard);
573+
574+
// Should use default
575+
ASSERT_EQ(Settings.SendBufferingEnabled, QUIC_DEFAULT_SEND_BUFFERING_ENABLE);
576+
ASSERT_EQ(Settings.PacingEnabled, QUIC_DEFAULT_SEND_PACING);
577+
ASSERT_EQ(Settings.MigrationEnabled, QUIC_DEFAULT_MIGRATION_ENABLED);
578+
579+
}
580+
338581
TEST(SettingsTest, SettingsSizesGet)
339582
{
340583
uint8_t Buffer[sizeof(QUIC_SETTINGS) * 2];

src/generated/linux/storage_winuser.c.clog.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ tracepoint(CLOG_STORAGE_WINUSER_C, StorageOpenKey , arg2);\
4747
// Decoder Ring for LibraryErrorStatus
4848
// [ lib] ERROR, %u, %s.
4949
// QuicTraceEvent(
50-
LibraryErrorStatus,
51-
"[ lib] ERROR, %u, %s.",
52-
Status,
53-
"RegOpenKeyExA failed");
50+
LibraryErrorStatus,
51+
"[ lib] ERROR, %u, %s.",
52+
Status,
53+
"RegCreateKeyExA failed");
5454
// arg2 = arg2 = Status = arg2
55-
// arg3 = arg3 = "RegOpenKeyExA failed" = arg3
55+
// arg3 = arg3 = "RegCreateKeyExA failed" = arg3
5656
----------------------------------------------------------*/
5757
#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus
5858
#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\

src/generated/linux/storage_winuser.c.clog.h.lttng.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ TRACEPOINT_EVENT(CLOG_STORAGE_WINUSER_C, StorageOpenKey,
2424
// Decoder Ring for LibraryErrorStatus
2525
// [ lib] ERROR, %u, %s.
2626
// QuicTraceEvent(
27-
LibraryErrorStatus,
28-
"[ lib] ERROR, %u, %s.",
29-
Status,
30-
"RegOpenKeyExA failed");
27+
LibraryErrorStatus,
28+
"[ lib] ERROR, %u, %s.",
29+
Status,
30+
"RegCreateKeyExA failed");
3131
// arg2 = arg2 = Status = arg2
32-
// arg3 = arg3 = "RegOpenKeyExA failed" = arg3
32+
// arg3 = arg3 = "RegCreateKeyExA failed" = arg3
3333
----------------------------------------------------------*/
3434
TRACEPOINT_EVENT(CLOG_STORAGE_WINUSER_C, LibraryErrorStatus,
3535
TP_ARGS(

0 commit comments

Comments
 (0)