diff --git a/vault/activity_log_test.go b/vault/activity_log_test.go index 6248e9667e7a..1e3ee97d5aad 100644 --- a/vault/activity_log_test.go +++ b/vault/activity_log_test.go @@ -32,6 +32,7 @@ import ( "github.com/mitchellh/mapstructure" ) +// TestActivityLog_Creation calls AddEntityToFragment and verifies that it appears correctly in a.fragment. func TestActivityLog_Creation(t *testing.T) { core, _, _ := TestCoreUnsealed(t) @@ -102,6 +103,8 @@ func TestActivityLog_Creation(t *testing.T) { } } +// TestActivityLog_Creation_WrappingTokens calls HandleTokenUsage for two wrapping tokens, and verifies that this +// doesn't create a fragment. func TestActivityLog_Creation_WrappingTokens(t *testing.T) { core, _, _ := TestCoreUnsealed(t) @@ -170,6 +173,8 @@ func checkExpectedEntitiesInMap(t *testing.T, a *ActivityLog, entityIDs []string } } +// TestActivityLog_UniqueEntities calls AddEntityToFragment 4 times with 2 different clients, then verifies that there +// are only 2 clients in the fragment and that they have the earlier timestamps. func TestActivityLog_UniqueEntities(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -274,6 +279,9 @@ func expectedEntityIDs(t *testing.T, out *activity.EntityActivityLog, ids []stri } } +// TestActivityLog_SaveTokensToStorage calls AddTokenToFragment with duplicate namespaces and then saves the segment to +// storage. The test then reads and unmarshals the segment, and verifies that the results have the correct counts by +// namespace. func TestActivityLog_SaveTokensToStorage(t *testing.T) { core, _, _ := TestCoreUnsealed(t) ctx := context.Background() @@ -426,6 +434,8 @@ func TestActivityLog_SaveTokensToStorageDoesNotUpdateTokenCount(t *testing.T) { } } +// TestActivityLog_SaveEntitiesToStorage calls AddEntityToFragment with clients with different namespaces and then +// writes the segment to storage. Read back from storage, and verify that client IDs exist in storage. func TestActivityLog_SaveEntitiesToStorage(t *testing.T) { core, _, _ := TestCoreUnsealed(t) ctx := context.Background() @@ -477,7 +487,8 @@ func TestActivityLog_SaveEntitiesToStorage(t *testing.T) { expectedEntityIDs(t, out, ids) } -// Test to check store hyperloglog and fetch hyperloglog from storage +// TestActivityLog_StoreAndReadHyperloglog inserts into a hyperloglog, stores it and then reads it back. The test +// verifies the estimate count is correct. func TestActivityLog_StoreAndReadHyperloglog(t *testing.T) { core, _, _ := TestCoreUnsealed(t) ctx := context.Background() @@ -505,6 +516,8 @@ func TestActivityLog_StoreAndReadHyperloglog(t *testing.T) { } } +// TestModifyResponseMonthsNilAppend calls modifyResponseMonths for a range of 5 months ago to now. It verifies that the +// 5 months in the range are correct. func TestModifyResponseMonthsNilAppend(t *testing.T) { end := time.Now().UTC() start := timeutil.StartOfMonth(end).AddDate(0, -5, 0) @@ -535,6 +548,9 @@ func TestModifyResponseMonthsNilAppend(t *testing.T) { } } +// TestActivityLog_ReceivedFragment calls receivedFragment with a fragment and verifies it gets added to +// standbyFragmentsReceived. Send the same fragment again and then verify that it doesn't change the entity map but does +// get added to standbyFragmentsReceived. func TestActivityLog_ReceivedFragment(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -586,6 +602,8 @@ func TestActivityLog_ReceivedFragment(t *testing.T) { } } +// TestActivityLog_availableLogsEmptyDirectory verifies that availableLogs returns an empty slice when the log directory +// is empty. func TestActivityLog_availableLogsEmptyDirectory(t *testing.T) { // verify that directory is empty, and nothing goes wrong core, _, _ := TestCoreUnsealed(t) @@ -599,6 +617,8 @@ func TestActivityLog_availableLogsEmptyDirectory(t *testing.T) { } } +// TestActivityLog_availableLogs writes to the direct token paths and entity paths and verifies that the correct start +// times are returned. func TestActivityLog_availableLogs(t *testing.T) { // set up a few files in storage core, _, _ := TestCoreUnsealed(t) @@ -626,6 +646,9 @@ func TestActivityLog_availableLogs(t *testing.T) { } } +// TestActivityLog_MultipleFragmentsAndSegments adds 4000 clients to a fragment and saves it and reads it. The test then +// adds 4000 more clients and calls receivedFragment with 200 more entities. The current segment is saved to storage and +// read back. The test verifies that there are 5000 clients in the first segment index, then the rest in the second index. func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -794,6 +817,7 @@ func TestActivityLog_MultipleFragmentsAndSegments(t *testing.T) { } } +// TestActivityLog_API_ConfigCRUD performs various CRUD operations on internal/counters/config. func TestActivityLog_API_ConfigCRUD(t *testing.T) { core, b, _ := testCoreSystemBackend(t) view := core.systemBarrierView @@ -936,6 +960,7 @@ func TestActivityLog_API_ConfigCRUD(t *testing.T) { } } +// TestActivityLog_parseSegmentNumberFromPath verifies that the segment number is extracted correctly from a path. func TestActivityLog_parseSegmentNumberFromPath(t *testing.T) { testCases := []struct { input string @@ -985,6 +1010,7 @@ func TestActivityLog_parseSegmentNumberFromPath(t *testing.T) { } } +// TestActivityLog_getLastEntitySegmentNumber verifies that the last segment number is correctly returned. func TestActivityLog_getLastEntitySegmentNumber(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -1040,6 +1066,8 @@ func TestActivityLog_getLastEntitySegmentNumber(t *testing.T) { } } +// TestActivityLog_tokenCountExists writes to the direct tokens segment path and verifies that segment count exists +// returns true for the segments at these paths. func TestActivityLog_tokenCountExists(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -1164,6 +1192,8 @@ func (a *ActivityLog) resetEntitiesInMemory(t *testing.T) { a.partialMonthClientTracker = make(map[string]*activity.EntityRecord) } +// TestActivityLog_loadCurrentClientSegment writes entity segments and calls loadCurrentClientSegment, then verifies +// that the correct values are returned when querying the current segment. func TestActivityLog_loadCurrentClientSegment(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -1280,6 +1310,8 @@ func TestActivityLog_loadCurrentClientSegment(t *testing.T) { } } +// TestActivityLog_loadPriorEntitySegment writes entities to two months and calls loadPriorEntitySegment for each month, +// verifying that the active clients are correct. func TestActivityLog_loadPriorEntitySegment(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -1424,6 +1456,9 @@ func TestActivityLog_loadTokenCount(t *testing.T) { } } +// TestActivityLog_StopAndRestart disables the activity log, waits for deletes to complete, and then enables the +// activity log. The activity log is then stopped and started again, to simulate a seal and unseal. The test then +// verifies that there's no error adding an entity, direct token, and when writing a segment to storage. func TestActivityLog_StopAndRestart(t *testing.T) { core, b, _ := testCoreSystemBackend(t) sysView := core.systemBarrierView @@ -1555,6 +1590,8 @@ func setupActivityRecordsInStorage(t *testing.T, base time.Time, includeEntities return a, entityRecords, tokenRecords } +// TestActivityLog_refreshFromStoredLog writes records for 3 months ago and this month, then calls refreshFromStoredLog. +// The test verifies that current entities and current tokens are correct. func TestActivityLog_refreshFromStoredLog(t *testing.T) { a, expectedClientRecords, expectedTokenCounts := setupActivityRecordsInStorage(t, time.Now().UTC(), true, true) a.SetEnable(true) @@ -1592,6 +1629,9 @@ func TestActivityLog_refreshFromStoredLog(t *testing.T) { } } +// TestActivityLog_refreshFromStoredLogWithBackgroundLoadingCancelled writes data from 3 months ago to this month. The +// test closes a.doneCh and calls refreshFromStoredLog, which will not do any processing because the doneCh is closed. +// The test verifies that the current data is not loaded. func TestActivityLog_refreshFromStoredLogWithBackgroundLoadingCancelled(t *testing.T) { a, expectedClientRecords, expectedTokenCounts := setupActivityRecordsInStorage(t, time.Now().UTC(), true, true) a.SetEnable(true) @@ -1633,6 +1673,8 @@ func TestActivityLog_refreshFromStoredLogWithBackgroundLoadingCancelled(t *testi } } +// TestActivityLog_refreshFromStoredLogContextCancelled writes data from 3 months ago to this month and calls +// refreshFromStoredLog with a canceled context, verifying that the function errors because of the canceled context. func TestActivityLog_refreshFromStoredLogContextCancelled(t *testing.T) { a, _, _ := setupActivityRecordsInStorage(t, time.Now().UTC(), true, true) @@ -1646,6 +1688,8 @@ func TestActivityLog_refreshFromStoredLogContextCancelled(t *testing.T) { } } +// TestActivityLog_refreshFromStoredLogNoTokens writes only entities from 3 months ago to today, then calls +// refreshFromStoredLog. It verifies that there are no tokens loaded. func TestActivityLog_refreshFromStoredLogNoTokens(t *testing.T) { a, expectedClientRecords, _ := setupActivityRecordsInStorage(t, time.Now().UTC(), true, false) a.SetEnable(true) @@ -1681,6 +1725,8 @@ func TestActivityLog_refreshFromStoredLogNoTokens(t *testing.T) { } } +// TestActivityLog_refreshFromStoredLogNoEntities writes only direct tokens from 3 months ago to today, and runs +// refreshFromStoredLog. It verifies that there are no entities or clients loaded. func TestActivityLog_refreshFromStoredLogNoEntities(t *testing.T) { a, _, expectedTokenCounts := setupActivityRecordsInStorage(t, time.Now().UTC(), false, true) a.SetEnable(true) @@ -1708,6 +1754,8 @@ func TestActivityLog_refreshFromStoredLogNoEntities(t *testing.T) { } } +// TestActivityLog_refreshFromStoredLogNoData writes nothing and calls refreshFromStoredLog, and verifies that the +// current segment counts are zero. func TestActivityLog_refreshFromStoredLogNoData(t *testing.T) { now := time.Now().UTC() a, _, _ := setupActivityRecordsInStorage(t, now, false, false) @@ -1723,6 +1771,8 @@ func TestActivityLog_refreshFromStoredLogNoData(t *testing.T) { a.ExpectCurrentSegmentRefreshed(t, now.Unix(), false) } +// TestActivityLog_refreshFromStoredLogTwoMonthsPrevious creates segment data from 5 months ago to 2 months ago and +// calls refreshFromStoredLog, then verifies that the current segment counts are zero. func TestActivityLog_refreshFromStoredLogTwoMonthsPrevious(t *testing.T) { // test what happens when the most recent data is from month M-2 (or earlier - same effect) now := time.Now().UTC() @@ -1740,6 +1790,8 @@ func TestActivityLog_refreshFromStoredLogTwoMonthsPrevious(t *testing.T) { a.ExpectCurrentSegmentRefreshed(t, now.Unix(), false) } +// TestActivityLog_refreshFromStoredLogPreviousMonth creates segment data from 4 months ago to 1 month ago, then calls +// refreshFromStoredLog, then verifies that these clients are included in the current segment. func TestActivityLog_refreshFromStoredLogPreviousMonth(t *testing.T) { // test what happens when most recent data is from month M-1 // we expect to load the data from the previous month so that the activeFragmentWorker @@ -1782,6 +1834,8 @@ func TestActivityLog_refreshFromStoredLogPreviousMonth(t *testing.T) { } } +// TestActivityLog_Export writes overlapping client for 5 months with various mounts and namespaces. It performs an +// export for various month ranges in the range, and verifies that the outputs are correct. func TestActivityLog_Export(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -1973,6 +2027,8 @@ func (f *fakeResponseWriter) WriteHeader(statusCode int) { panic("unimplmeneted") } +// TestActivityLog_IncludeNamespace verifies that includeInResponse returns true for namespaces that are children of +// their parents. func TestActivityLog_IncludeNamespace(t *testing.T) { root := namespace.RootNamespace a := &ActivityLog{} @@ -2020,6 +2076,8 @@ func TestActivityLog_IncludeNamespace(t *testing.T) { } } +// TestActivityLog_DeleteWorker writes segments for entities and direct tokens for 2 different timestamps, then runs the +// deleteLogWorker for one of the timestamps. The test verifies that the correct segment is deleted, and the other remains. func TestActivityLog_DeleteWorker(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -2075,6 +2133,9 @@ func checkAPIWarnings(t *testing.T, originalEnabled, newEnabled bool, resp *logi } } +// TestActivityLog_EnableDisable writes a segment, adds an entity to the in-memory fragment, then disables the activity +// log. The test verifies that the segment doesn't exist. The activity log is enabled, then verified that an empty +// segment is written and new clients can be added and written to segments. func TestActivityLog_EnableDisable(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -2712,6 +2773,9 @@ func TestActivityLog_SaveAfterDisable(t *testing.T) { expectMissingSegment(t, core, path) } +// TestActivityLog_Precompute creates segments over a range of 11 months, with overlapping clients and namespaces. +// Create intent logs and run precomputedQueryWorker for various month ranges. Verify that the precomputed queries have +// the correct counts, including per namespace. func TestActivityLog_Precompute(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -3599,6 +3663,8 @@ func (b *BlockingInmemStorage) Delete(ctx context.Context, key string) error { return errors.New("fake implementation") } +// TestActivityLog_PrecomputeCancel stops the activity log before running the precomputedQueryWorker, and verifies that +// the context used to query storage has been canceled. func TestActivityLog_PrecomputeCancel(t *testing.T) { core, _, _ := TestCoreUnsealed(t) a := core.activityLog @@ -3627,6 +3693,8 @@ func TestActivityLog_PrecomputeCancel(t *testing.T) { } } +// TestActivityLog_NextMonthStart sets the activity log start timestamp, then verifies that StartOfNextMonth returns the +// correct value. func TestActivityLog_NextMonthStart(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -3679,6 +3747,8 @@ func waitForRetentionWorkerToFinish(t *testing.T, a *ActivityLog) { } } +// TestActivityLog_Deletion writes entity, direct tokens, and queries for dates ranging over 20 months. Then the test +// calls the retentionWorker with decreasing retention values, and verifies that the correct paths are being deleted. func TestActivityLog_Deletion(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -3794,6 +3864,8 @@ func TestActivityLog_Deletion(t *testing.T) { checkPresent(21) } +// TestActivityLog_partialMonthClientCount writes segment data for the curren month and runs refreshFromStoredLog and +// then partialMonthClientCount. The test verifies that the values returned by partialMonthClientCount are correct. func TestActivityLog_partialMonthClientCount(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -3863,6 +3935,8 @@ func TestActivityLog_partialMonthClientCount(t *testing.T) { } } +// TestActivityLog_partialMonthClientCountUsingHandleQuery writes segments for the current month and calls +// refreshFromStoredLog, then handleQuery. The test verifies that the results from handleQuery are correct. func TestActivityLog_partialMonthClientCountUsingHandleQuery(t *testing.T) { timeutil.SkipAtEndOfMonth(t) @@ -3990,7 +4064,7 @@ func TestActivityLog_partialMonthClientCountUsingHandleQuery(t *testing.T) { } // TestActivityLog_handleQuery_normalizedMountPaths ensures that the mount paths returned by the activity log always have a trailing slash and client accounting is done correctly when there's no trailing slash. -// Two clients that have the same mount path, but one has a trailing slash, should be considered part of the same mount path +// Two clients that have the same mount path, but one has a trailing slash, should be considered part of the same mount path. func TestActivityLog_handleQuery_normalizedMountPaths(t *testing.T) { timeutil.SkipAtEndOfMonth(t) diff --git a/vault/activity_log_util_common_test.go b/vault/activity_log_util_common_test.go index 5eef6686ca34..f0a6ce6777f0 100644 --- a/vault/activity_log_util_common_test.go +++ b/vault/activity_log_util_common_test.go @@ -10,6 +10,11 @@ import ( "github.com/hashicorp/vault/helper/timeutil" ) +// Test_ActivityLog_ComputeCurrentMonthForBillingPeriodInternal creates 3 months of hyperloglogs and fills them with +// overlapping clients. The test calls computeCurrentMonthForBillingPeriodInternal with the current month map having +// some overlap with the previous months. The test then verifies that the results have the correct number of entity and +// non-entity clients. The test also calls computeCurrentMonthForBillingPeriodInternal with an empty current month map, +// and verifies that the results are all 0. func Test_ActivityLog_ComputeCurrentMonthForBillingPeriodInternal(t *testing.T) { // populate the first month with clients 1-10 monthOneHLL := hyperloglog.New()