From a73188028c03dc4d77733dff3af36e37a6735a32 Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Sun, 7 Jul 2024 18:01:22 +0300 Subject: [PATCH] routing: test persist/reset of MC data on disk Signed-off-by: Mohamed Awnallah --- routing/missioncontrol_store_test.go | 172 +++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/routing/missioncontrol_store_test.go b/routing/missioncontrol_store_test.go index 34b925a3e17..65254c42a3b 100644 --- a/routing/missioncontrol_store_test.go +++ b/routing/missioncontrol_store_test.go @@ -1,6 +1,7 @@ package routing import ( + "encoding/json" "fmt" "os" "testing" @@ -293,3 +294,174 @@ func BenchmarkMissionControlStoreFlushing(b *testing.B) { }) } } + +// timeToUnix converts a time.Time value to its Unix time representation. +func timeToUnix(t time.Time) int64 { + return t.Unix() +} + +// timedPairResultsAreEqual compares two TimedPairResult structs for equality. +// It returns true if the FailTime, FailAmt, SuccessTime, and SuccessAmt fields +// of both TimedPairResult structs are equal. The comparison of FailTime and +// SuccessTime is done by converting them to Unix time to avoid issues with +// internal representation differences. +// +// Parameters: +// - tpr1: The first TimedPairResult to compare. +// - tpr2: The second TimedPairResult to compare. +// +// Returns: +// - bool: true if both TimedPairResult structs are equal, false otherwise. +func timedPairResultsAreEqual(tpr1, tpr2 TimedPairResult) bool { + return timeToUnix(tpr1.FailTime) == timeToUnix(tpr2.FailTime) && + tpr1.FailAmt == tpr2.FailAmt && + timeToUnix(tpr1.SuccessTime) == timeToUnix(tpr2.SuccessTime) && + tpr1.SuccessAmt == tpr2.SuccessAmt +} + +// TestPersistMCData verifies that the persistMCData function correctly +// stores a given MissionControlSnapshot into the database and retrieves it +// accurately using fetchMCData. +// +// It performs the following steps: +// 1. Creates a test harness for the mission control store. +// 2. Prepares a sample MissionControlSnapshot with timed pair results. +// 3. Persists the snapshot using persistMCData. +// 4. Fetches the stored data using fetchMCData. +// 5. Verifies that the fetched data matches the original snapshot. +func TestPersistMCData(t *testing.T) { + h := newMCStoreTestHarness(t, testMaxRecords, time.Second) + store := h.store + + // Prepare a sample mission control snapshot. + snapshot := &MissionControlSnapshot{ + Pairs: []MissionControlPairSnapshot{ + { + Pair: DirectedNodePair{ + From: route.Vertex{1}, + To: route.Vertex{2}, + }, + TimedPairResult: TimedPairResult{ + SuccessTime: time.Now().Add(-time.Hour), + SuccessAmt: lnwire.MilliSatoshi(1500), + }, + }, + { + Pair: DirectedNodePair{ + From: route.Vertex{3}, + To: route.Vertex{4}, + }, + TimedPairResult: TimedPairResult{ + FailTime: time.Now().Add(-time.Hour), + FailAmt: lnwire.MilliSatoshi(3000), + }, + }, + }, + } + + // Persist the mission control snapshot. + err := store.persistMCData(snapshot) + require.NoError(t, err) + + // Fetch the data to verify. + mcSnapshots, err := store.fetchMCData() + require.NoError(t, err) + require.Len(t, mcSnapshots, 1) + require.Len(t, mcSnapshots[0].Pairs, 2) + require.Equal(t, snapshot.Pairs[0].Pair, mcSnapshots[0].Pairs[0].Pair) + require.Equal(t, snapshot.Pairs[1].Pair, mcSnapshots[0].Pairs[1].Pair) + require.True( + t, timedPairResultsAreEqual( + snapshot.Pairs[0].TimedPairResult, + mcSnapshots[0].Pairs[0].TimedPairResult, + ), + ) + require.True( + t, timedPairResultsAreEqual( + snapshot.Pairs[1].TimedPairResult, + mcSnapshots[0].Pairs[1].TimedPairResult, + ), + ) +} + +// TestResetMCData verifies that the resetMCData function correctly +// clears all mission control data from the database. +// +// It performs the following steps: +// 1. Creates a test harness for the mission control store. +// 2. Prepares and persists a sample MissionControlSnapshot. +// 3. Calls resetMCData to clear the mission control data. +// 4. Fetches the data using fetchMCData to verify that it has been reset. +func TestResetMCData(t *testing.T) { + h := newMCStoreTestHarness(t, testMaxRecords, time.Second) + store := h.store + + // Prepare a sample mission control snapshot. + snapshot := &MissionControlSnapshot{ + Pairs: []MissionControlPairSnapshot{ + { + Pair: DirectedNodePair{ + From: route.Vertex{1}, + To: route.Vertex{2}, + }, + TimedPairResult: TimedPairResult{ + SuccessTime: time.Now().Add(-time.Hour), + SuccessAmt: lnwire.MilliSatoshi(2000), + }, + }, + }, + } + + // Persist the mission control snapshot. + err := store.persistMCData(snapshot) + require.NoError(t, err) + + // Reset the mission control data. + err = store.resetMCData() + require.NoError(t, err) + + // Fetch the data to verify it has been reset. + mcSnapshots, err := store.fetchMCData() + require.NoError(t, err) + require.Len(t, mcSnapshots, 0) +} + +// TestDeserializeMCData verifies that the deserializeMCData function correctly +// deserializes key and value bytes into a MissionControlPairSnapshot. +// +// It performs the following steps: +// 1. Prepares sample data for serialization, including 'From' and 'To' public +// keys and a TimedPairResult. +// 2. Serializes the TimedPairResult into JSON format. +// 3. Concatenates the 'From' and 'To' public keys to form the key. +// 4. Deserializes the mission control data using deserializeMCData. +// 5. Verifies that the deserialized data matches the original data. +func TestDeserializeMCData(t *testing.T) { + // Prepare sample data for serialization. + from := route.Vertex{1} + to := route.Vertex{2} + timedPairResult := TimedPairResult{ + FailTime: time.Now(), + FailAmt: lnwire.MilliSatoshi(1000), + SuccessTime: time.Now().Add(-time.Hour), + SuccessAmt: lnwire.MilliSatoshi(2000), + } + data, err := json.Marshal(timedPairResult) + require.NoError(t, err) + + // Concatenate the 'From' and 'To' public keys to form the key. + // Create the key by concatenating From and To bytes. + key := append([]byte{}, from[:]...) + key = append(key, to[:]...) + + // Deserialize the mission control data. + mcSnapshot, err := deserializeMCData(key, data) + require.NoError(t, err) + require.Equal(t, from, mcSnapshot.Pair.From) + require.Equal(t, to, mcSnapshot.Pair.To) + require.True( + t, timedPairResultsAreEqual( + timedPairResult, mcSnapshot.TimedPairResult, + ), + ) +}