Skip to content

Commit cef1658

Browse files
authored
test(pageserver): add gc-compaction tests with delta will_init (#9724)
I had an impression that gc-compaction didn't test the case where the first record of the key history is will_init because of there are some code path that will panic in this case. Luckily it got fixed in #9026 so we can now implement such tests. Part of #9114 ## Summary of changes * Randomly changed some images into will_init neon wal record * Split `test_simple_bottom_most_compaction_deltas` into two test cases, one of them has the bottom layer as delta layer with will_init flags, while the other is the original one with image layers. --------- Signed-off-by: Alex Chi Z <[email protected]>
1 parent 6b19867 commit cef1658

File tree

4 files changed

+104
-28
lines changed

4 files changed

+104
-28
lines changed

libs/pageserver_api/src/record.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,18 @@ impl NeonWalRecord {
8080
}
8181

8282
#[cfg(feature = "testing")]
83-
pub fn wal_clear() -> Self {
83+
pub fn wal_clear(s: impl AsRef<str>) -> Self {
8484
Self::Test {
85-
append: "".to_string(),
85+
append: s.as_ref().to_string(),
8686
clear: true,
8787
will_init: false,
8888
}
8989
}
9090

9191
#[cfg(feature = "testing")]
92-
pub fn wal_init() -> Self {
92+
pub fn wal_init(s: impl AsRef<str>) -> Self {
9393
Self::Test {
94-
append: "".to_string(),
94+
append: s.as_ref().to_string(),
9595
clear: true,
9696
will_init: true,
9797
}

pageserver/src/tenant.rs

Lines changed: 94 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7757,13 +7757,13 @@ mod tests {
77577757
(
77587758
get_key(3),
77597759
Lsn(0x20),
7760-
Value::WalRecord(NeonWalRecord::wal_clear()),
7760+
Value::WalRecord(NeonWalRecord::wal_clear("c")),
77617761
),
77627762
(get_key(4), Lsn(0x10), Value::Image("0x10".into())),
77637763
(
77647764
get_key(4),
77657765
Lsn(0x20),
7766-
Value::WalRecord(NeonWalRecord::wal_init()),
7766+
Value::WalRecord(NeonWalRecord::wal_init("i")),
77677767
),
77687768
];
77697769
let image1 = vec![(get_key(1), "0x10".into())];
@@ -7912,8 +7912,30 @@ mod tests {
79127912

79137913
#[cfg(feature = "testing")]
79147914
#[tokio::test]
7915-
async fn test_simple_bottom_most_compaction_deltas() -> anyhow::Result<()> {
7916-
let harness = TenantHarness::create("test_simple_bottom_most_compaction_deltas").await?;
7915+
async fn test_simple_bottom_most_compaction_deltas_1() -> anyhow::Result<()> {
7916+
test_simple_bottom_most_compaction_deltas_helper(
7917+
"test_simple_bottom_most_compaction_deltas_1",
7918+
false,
7919+
)
7920+
.await
7921+
}
7922+
7923+
#[cfg(feature = "testing")]
7924+
#[tokio::test]
7925+
async fn test_simple_bottom_most_compaction_deltas_2() -> anyhow::Result<()> {
7926+
test_simple_bottom_most_compaction_deltas_helper(
7927+
"test_simple_bottom_most_compaction_deltas_2",
7928+
true,
7929+
)
7930+
.await
7931+
}
7932+
7933+
#[cfg(feature = "testing")]
7934+
async fn test_simple_bottom_most_compaction_deltas_helper(
7935+
test_name: &'static str,
7936+
use_delta_bottom_layer: bool,
7937+
) -> anyhow::Result<()> {
7938+
let harness = TenantHarness::create(test_name).await?;
79177939
let (tenant, ctx) = harness.load().await;
79187940

79197941
fn get_key(id: u32) -> Key {
@@ -7944,6 +7966,16 @@ mod tests {
79447966
let img_layer = (0..10)
79457967
.map(|id| (get_key(id), Bytes::from(format!("value {id}@0x10"))))
79467968
.collect_vec();
7969+
// or, delta layer at 0x10 if `use_delta_bottom_layer` is true
7970+
let delta4 = (0..10)
7971+
.map(|id| {
7972+
(
7973+
get_key(id),
7974+
Lsn(0x08),
7975+
Value::WalRecord(NeonWalRecord::wal_init(format!("value {id}@0x10"))),
7976+
)
7977+
})
7978+
.collect_vec();
79477979

79487980
let delta1 = vec![
79497981
(
@@ -7997,21 +8029,61 @@ mod tests {
79978029
),
79988030
];
79998031

8000-
let tline = tenant
8001-
.create_test_timeline_with_layers(
8002-
TIMELINE_ID,
8003-
Lsn(0x10),
8004-
DEFAULT_PG_VERSION,
8005-
&ctx,
8006-
vec![
8007-
DeltaLayerTestDesc::new_with_inferred_key_range(Lsn(0x10)..Lsn(0x48), delta1),
8008-
DeltaLayerTestDesc::new_with_inferred_key_range(Lsn(0x10)..Lsn(0x48), delta2),
8009-
DeltaLayerTestDesc::new_with_inferred_key_range(Lsn(0x48)..Lsn(0x50), delta3),
8010-
], // delta layers
8011-
vec![(Lsn(0x10), img_layer)], // image layers
8012-
Lsn(0x50),
8013-
)
8014-
.await?;
8032+
let tline = if use_delta_bottom_layer {
8033+
tenant
8034+
.create_test_timeline_with_layers(
8035+
TIMELINE_ID,
8036+
Lsn(0x08),
8037+
DEFAULT_PG_VERSION,
8038+
&ctx,
8039+
vec![
8040+
DeltaLayerTestDesc::new_with_inferred_key_range(
8041+
Lsn(0x08)..Lsn(0x10),
8042+
delta4,
8043+
),
8044+
DeltaLayerTestDesc::new_with_inferred_key_range(
8045+
Lsn(0x20)..Lsn(0x48),
8046+
delta1,
8047+
),
8048+
DeltaLayerTestDesc::new_with_inferred_key_range(
8049+
Lsn(0x20)..Lsn(0x48),
8050+
delta2,
8051+
),
8052+
DeltaLayerTestDesc::new_with_inferred_key_range(
8053+
Lsn(0x48)..Lsn(0x50),
8054+
delta3,
8055+
),
8056+
], // delta layers
8057+
vec![], // image layers
8058+
Lsn(0x50),
8059+
)
8060+
.await?
8061+
} else {
8062+
tenant
8063+
.create_test_timeline_with_layers(
8064+
TIMELINE_ID,
8065+
Lsn(0x10),
8066+
DEFAULT_PG_VERSION,
8067+
&ctx,
8068+
vec![
8069+
DeltaLayerTestDesc::new_with_inferred_key_range(
8070+
Lsn(0x10)..Lsn(0x48),
8071+
delta1,
8072+
),
8073+
DeltaLayerTestDesc::new_with_inferred_key_range(
8074+
Lsn(0x10)..Lsn(0x48),
8075+
delta2,
8076+
),
8077+
DeltaLayerTestDesc::new_with_inferred_key_range(
8078+
Lsn(0x48)..Lsn(0x50),
8079+
delta3,
8080+
),
8081+
], // delta layers
8082+
vec![(Lsn(0x10), img_layer)], // image layers
8083+
Lsn(0x50),
8084+
)
8085+
.await?
8086+
};
80158087
{
80168088
// Update GC info
80178089
let mut guard = tline.gc_info.write().unwrap();
@@ -8121,7 +8193,7 @@ mod tests {
81218193
(
81228194
key,
81238195
Lsn(0x10),
8124-
Value::Image(Bytes::copy_from_slice(b"0x10")),
8196+
Value::WalRecord(NeonWalRecord::wal_init("0x10")),
81258197
),
81268198
(
81278199
key,
@@ -8183,7 +8255,7 @@ mod tests {
81838255
Lsn(0x20),
81848256
KeyLogAtLsn(vec![(
81858257
Lsn(0x20),
8186-
Value::Image(Bytes::copy_from_slice(b"0x10;0x20")),
8258+
Value::Image(Bytes::from_static(b"0x10;0x20")),
81878259
)]),
81888260
),
81898261
(
@@ -9165,7 +9237,7 @@ mod tests {
91659237

91669238
let will_init = will_init_keys.contains(&i);
91679239
if will_init {
9168-
delta_layer_spec.push((key, lsn, Value::WalRecord(NeonWalRecord::wal_init())));
9240+
delta_layer_spec.push((key, lsn, Value::WalRecord(NeonWalRecord::wal_init(""))));
91699241

91709242
expected_key_values.insert(key, "".to_string());
91719243
} else {

pageserver/src/tenant/storage_layer/merge_iterator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ mod tests {
562562
(
563563
get_key(0),
564564
Lsn(0x10),
565-
Value::WalRecord(NeonWalRecord::wal_init()),
565+
Value::WalRecord(NeonWalRecord::wal_init("")),
566566
),
567567
(
568568
get_key(0),
@@ -572,7 +572,7 @@ mod tests {
572572
(
573573
get_key(5),
574574
Lsn(0x10),
575-
Value::WalRecord(NeonWalRecord::wal_init()),
575+
Value::WalRecord(NeonWalRecord::wal_init("")),
576576
),
577577
(
578578
get_key(5),

pageserver/src/walredo/apply_neon.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ pub(crate) fn apply_in_neon(
253253
use bytes::BufMut;
254254
if *will_init {
255255
assert!(*clear, "init record must be clear to ensure correctness");
256+
assert!(
257+
page.is_empty(),
258+
"init record must be the first entry to ensure correctness"
259+
);
256260
}
257261
if *clear {
258262
page.clear();

0 commit comments

Comments
 (0)