From 0733dce60870261e1c41e578ab4e6f949ff87499 Mon Sep 17 00:00:00 2001 From: Scott Sandre Date: Wed, 29 Jan 2025 16:14:58 -0800 Subject: [PATCH 1/4] Update LogSegment.java --- .../kernel/internal/snapshot/LogSegment.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java b/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java index 7abde22225e..0985bf76d45 100644 --- a/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java +++ b/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java @@ -16,8 +16,12 @@ package io.delta.kernel.internal.snapshot; +import static io.delta.kernel.internal.util.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + import io.delta.kernel.internal.fs.Path; import io.delta.kernel.internal.lang.Lazy; +import io.delta.kernel.internal.util.FileNames; import io.delta.kernel.utils.FileStatus; import java.util.Collections; import java.util.Comparator; @@ -50,7 +54,7 @@ public static LogSegment empty(Path logPath) { * @param version The Snapshot version to generate * @param deltas The delta commit files (.json) to read * @param checkpoints The checkpoint file(s) to read - * @param checkpointVersionOpt The checkpoint version used to start replay + * @param checkpointVersionOpt The version of the checkpoint file(s) * @param lastCommitTimestamp The "unadjusted" timestamp of the last commit within this segment. * By unadjusted, we mean that the commit timestamps may not necessarily be monotonically * increasing for the commits within this segment. @@ -62,6 +66,29 @@ public LogSegment( List checkpoints, Optional checkpointVersionOpt, long lastCommitTimestamp) { + requireNonNull(logPath, "logPath is null"); + requireNonNull(deltas, "deltas is null"); + requireNonNull(checkpoints, "checkpoints is null"); + requireNonNull(checkpointVersionOpt, "checkpointVersionOpt is null"); + checkArgument( + checkpoints.isEmpty() == !checkpointVersionOpt.isPresent(), + "checkpoints and checkpointVersionOpt must either be both empty or both non-empty"); + checkArgument( + deltas.stream().allMatch(fs -> FileNames.isCommitFile(fs.getPath())), + "deltas must all be actual delta (commit) files"); + checkArgument( + checkpoints.stream().allMatch(fs -> FileNames.isCheckpointFile(fs.getPath())), + "checkpoints must all be actual checkpoint files"); + checkpointVersionOpt.ifPresent( + checkpointVersion -> { + checkArgument( + checkpoints.stream() + .allMatch( + fs -> + FileNames.checkpointVersion(new Path(fs.getPath())) == checkpointVersion), + "All checkpoint files must have the same version as the checkpointVersionOpt"); + }); + this.logPath = logPath; this.version = version; this.deltas = deltas; From 4a4aa54e926b487fc98eb2d0daade39ac9c41fab Mon Sep 17 00:00:00 2001 From: Scott Sandre Date: Wed, 29 Jan 2025 16:15:01 -0800 Subject: [PATCH 2/4] Create LogSegmentSuite.scala --- .../internal/snapshot/LogSegmentSuite.scala | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala diff --git a/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala b/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala new file mode 100644 index 00000000000..7b76a4761df --- /dev/null +++ b/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala @@ -0,0 +1,111 @@ +/* + * Copyright (2025) The Delta Lake Project Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.delta.kernel.internal.snapshot + +import java.util.{Collections, Optional} + +import io.delta.kernel.internal.fs.Path +import io.delta.kernel.internal.util.FileNames +import io.delta.kernel.utils.FileStatus +import org.scalatest.funsuite.AnyFunSuite + +class LogSegmentSuite extends AnyFunSuite { + private val logPath = new Path("/a/_delta_log") + private val checkpointFs10 = Collections.singletonList( + FileStatus.of(FileNames.checkpointFileSingular(logPath, 10).toString, 0, 0)) + private val deltaFs11 = Collections.singletonList( + FileStatus.of(FileNames.deltaFile(logPath, 11), 0, 0)) + private val badJson = Collections.singletonList( + FileStatus.of(s"${logPath.toString}/gibberish.json", 0, 0)) + private val badCheckpoint = Collections.singletonList( + FileStatus.of(s"${logPath.toString}/gibberish.checkpoint.parquet", 0, 0)) + + test("LogSegment::constructor -- valid case (empty)") { + LogSegment.empty(new Path("/a/_delta_log")) + } + + test("LogSegment::constructor -- valid case (non-empty)") { + val logPath = new Path("/a/_delta_log") + new LogSegment(logPath, 11, deltaFs11, checkpointFs10, Optional.of(10), 1) + } + + test("LogSegment::constructor -- null arguments") { + // case: logPath is null + intercept[NullPointerException] { + new LogSegment( + null, 1, Collections.emptyList(), Collections.emptyList(), Optional.empty(), -1) + } + // case: deltas is null + intercept[NullPointerException] { + new LogSegment( + new Path("/a/_delta_log"), 1, null, Collections.emptyList(), Optional.empty(), -1) + } + // case: checkpoints is null + intercept[NullPointerException] { + new LogSegment( + new Path("/a/_delta_log"), 1, Collections.emptyList(), null, Optional.empty(), -1) + } + // case: checkpointVersionOpt is null + intercept[NullPointerException] { + new LogSegment( + new Path("/a/_delta_log"), 1, Collections.emptyList(), Collections.emptyList(), null, -1) + } + } + + test("LogSegment::constructor -- only one of checkpoints and checkpointVersionOpt is empty") { + // case: checkpoints is empty but checkpointVersionOpt is not + val exMsg1 = intercept[IllegalArgumentException] { + new LogSegment( + logPath, 11, Collections.emptyList(), Collections.emptyList(), Optional.of(10), 1) + }.getMessage + assert( + exMsg1 === "checkpoints and checkpointVersionOpt must either be both empty or both non-empty") + + // case: checkpoints is not empty but checkpointVersionOpt is + val exMsg2 = intercept[IllegalArgumentException] { + new LogSegment( + logPath, 11, Collections.emptyList(), checkpointFs10, Optional.empty(), 1) + }.getMessage + assert( + exMsg2 === "checkpoints and checkpointVersionOpt must either be both empty or both non-empty") + } + + test("LogSegment::constructor -- pass in non-delta file") { + val exMsg = intercept[IllegalArgumentException] { + new LogSegment( + logPath, 11, badJson, checkpointFs10, Optional.of(10), 1) + }.getMessage + assert(exMsg === "deltas must all be actual delta (commit) files") + } + + test("LogSegment::constructor -- pass in non-checkpoint file") { + val exMsg = intercept[IllegalArgumentException] { + new LogSegment( + logPath, 11, deltaFs11, badCheckpoint, Optional.of(10), 1) + }.getMessage + assert(exMsg === "checkpoints must all be actual checkpoint files") + } + + test("LogSegment::constructor -- checkpoint file version != checkpointVersionOpt") { + // checkpointFs10 has version 10 but checkpointVersionOpt is 5 + val exMsg = intercept[IllegalArgumentException] { + new LogSegment( + logPath, 11, deltaFs11, checkpointFs10, Optional.of(5), 1) + }.getMessage + assert(exMsg === "All checkpoint files must have the same version as the checkpointVersionOpt") + } +} From ce487d779fa9a43db219cc39a3b98150dfe61acc Mon Sep 17 00:00:00 2001 From: Scott Sandre Date: Thu, 30 Jan 2025 09:35:43 -0800 Subject: [PATCH 3/4] Remove latestCompleteCheckpointOpt as constructor param; more validations/tests --- .../kernel/internal/snapshot/LogSegment.java | 65 ++++++++++++----- .../internal/snapshot/SnapshotManager.java | 1 - .../internal/snapshot/LogSegmentSuite.scala | 73 ++++++++++--------- 3 files changed, 85 insertions(+), 54 deletions(-) diff --git a/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java b/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java index 0985bf76d45..1e710ec2281 100644 --- a/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java +++ b/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/LogSegment.java @@ -21,6 +21,7 @@ import io.delta.kernel.internal.fs.Path; import io.delta.kernel.internal.lang.Lazy; +import io.delta.kernel.internal.lang.ListUtils; import io.delta.kernel.internal.util.FileNames; import io.delta.kernel.utils.FileStatus; import java.util.Collections; @@ -42,8 +43,7 @@ public class LogSegment { private final Lazy> allFilesReversed; public static LogSegment empty(Path logPath) { - return new LogSegment( - logPath, -1, Collections.emptyList(), Collections.emptyList(), Optional.empty(), -1); + return new LogSegment(logPath, -1, Collections.emptyList(), Collections.emptyList(), -1); } /** @@ -54,7 +54,6 @@ public static LogSegment empty(Path logPath) { * @param version The Snapshot version to generate * @param deltas The delta commit files (.json) to read * @param checkpoints The checkpoint file(s) to read - * @param checkpointVersionOpt The version of the checkpoint file(s) * @param lastCommitTimestamp The "unadjusted" timestamp of the last commit within this segment. * By unadjusted, we mean that the commit timestamps may not necessarily be monotonically * increasing for the commits within this segment. @@ -64,36 +63,66 @@ public LogSegment( long version, List deltas, List checkpoints, - Optional checkpointVersionOpt, long lastCommitTimestamp) { + + /////////////////////// + // Input validations // + /////////////////////// + requireNonNull(logPath, "logPath is null"); requireNonNull(deltas, "deltas is null"); requireNonNull(checkpoints, "checkpoints is null"); - requireNonNull(checkpointVersionOpt, "checkpointVersionOpt is null"); - checkArgument( - checkpoints.isEmpty() == !checkpointVersionOpt.isPresent(), - "checkpoints and checkpointVersionOpt must either be both empty or both non-empty"); checkArgument( deltas.stream().allMatch(fs -> FileNames.isCommitFile(fs.getPath())), "deltas must all be actual delta (commit) files"); checkArgument( checkpoints.stream().allMatch(fs -> FileNames.isCheckpointFile(fs.getPath())), "checkpoints must all be actual checkpoint files"); - checkpointVersionOpt.ifPresent( - checkpointVersion -> { - checkArgument( - checkpoints.stream() - .allMatch( - fs -> - FileNames.checkpointVersion(new Path(fs.getPath())) == checkpointVersion), - "All checkpoint files must have the same version as the checkpointVersionOpt"); - }); + + this.checkpointVersionOpt = + checkpoints.isEmpty() + ? Optional.empty() + : Optional.of(FileNames.checkpointVersion(new Path(checkpoints.get(0).getPath()))); + + checkArgument( + checkpoints.stream() + .map(fs -> FileNames.checkpointVersion(new Path(fs.getPath()))) + .allMatch(v -> checkpointVersionOpt.get().equals(v)), + "All checkpoint files must have the same version"); + + if (version != -1) { + checkArgument(!deltas.isEmpty() || !checkpoints.isEmpty(), "No files to read"); + + if (!deltas.isEmpty()) { + this.checkpointVersionOpt.ifPresent( + checkpointVersion -> { + checkArgument( + FileNames.deltaVersion(deltas.get(0).getPath()) == checkpointVersion + 1, + "First delta file version must equal checkpointVersion + 1"); + }); + + checkArgument( + FileNames.deltaVersion(ListUtils.getLast(deltas).getPath()) == version, + "Last delta file version must equal the version of this LogSegment"); + } else { + this.checkpointVersionOpt.ifPresent( + checkpointVersion -> { + checkArgument( + checkpointVersion == version, + "If there are no deltas, then checkpointVersion must equal the version " + + "of this LogSegment"); + }); + } + } + + //////////////////////////////// + // Member variable assignment // + //////////////////////////////// this.logPath = logPath; this.version = version; this.deltas = deltas; this.checkpoints = checkpoints; - this.checkpointVersionOpt = checkpointVersionOpt; this.lastCommitTimestamp = lastCommitTimestamp; this.allFiles = diff --git a/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/SnapshotManager.java b/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/SnapshotManager.java index 4f305ad9e0f..a561c849385 100644 --- a/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/SnapshotManager.java +++ b/kernel/kernel-api/src/main/java/io/delta/kernel/internal/snapshot/SnapshotManager.java @@ -564,7 +564,6 @@ public LogSegment getLogSegmentForVersion(Engine engine, Optional versionT newVersion, deltasAfterCheckpoint, latestCompleteCheckpointFileStatuses, - latestCompleteCheckpointOpt.map(x -> x.version), lastCommitTimestamp); } diff --git a/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala b/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala index 7b76a4761df..db5a5029eb1 100644 --- a/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala +++ b/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala @@ -34,78 +34,81 @@ class LogSegmentSuite extends AnyFunSuite { private val badCheckpoint = Collections.singletonList( FileStatus.of(s"${logPath.toString}/gibberish.checkpoint.parquet", 0, 0)) - test("LogSegment::constructor -- valid case (empty)") { + test("constructor -- valid case (empty)") { LogSegment.empty(new Path("/a/_delta_log")) } - test("LogSegment::constructor -- valid case (non-empty)") { + test("constructor -- valid case (non-empty)") { val logPath = new Path("/a/_delta_log") - new LogSegment(logPath, 11, deltaFs11, checkpointFs10, Optional.of(10), 1) + new LogSegment(logPath, 11, deltaFs11, checkpointFs10, 1) } - test("LogSegment::constructor -- null arguments") { - // case: logPath is null + test("constructor -- null arguments => throw") { + // logPath is null intercept[NullPointerException] { new LogSegment( - null, 1, Collections.emptyList(), Collections.emptyList(), Optional.empty(), -1) + null, 1, Collections.emptyList(), Collections.emptyList(), -1) } - // case: deltas is null + // deltas is null intercept[NullPointerException] { new LogSegment( - new Path("/a/_delta_log"), 1, null, Collections.emptyList(), Optional.empty(), -1) + new Path("/a/_delta_log"), 1, null, Collections.emptyList(), -1) } - // case: checkpoints is null + // checkpoints is null intercept[NullPointerException] { new LogSegment( - new Path("/a/_delta_log"), 1, Collections.emptyList(), null, Optional.empty(), -1) + new Path("/a/_delta_log"), 1, Collections.emptyList(), null, -1) } - // case: checkpointVersionOpt is null - intercept[NullPointerException] { + } + + test("constructor -- all deltas must be actual delta files") { + val exMsg = intercept[IllegalArgumentException] { new LogSegment( - new Path("/a/_delta_log"), 1, Collections.emptyList(), Collections.emptyList(), null, -1) - } + logPath, 11, badJson, checkpointFs10, 1) + }.getMessage + assert(exMsg === "deltas must all be actual delta (commit) files") } - test("LogSegment::constructor -- only one of checkpoints and checkpointVersionOpt is empty") { - // case: checkpoints is empty but checkpointVersionOpt is not - val exMsg1 = intercept[IllegalArgumentException] { + test("constructor -- all checkpoints must be actual checkpoint files") { + val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, Collections.emptyList(), Collections.emptyList(), Optional.of(10), 1) + logPath, 11, deltaFs11, badCheckpoint, 1) }.getMessage - assert( - exMsg1 === "checkpoints and checkpointVersionOpt must either be both empty or both non-empty") + assert(exMsg === "checkpoints must all be actual checkpoint files") + } - // case: checkpoints is not empty but checkpointVersionOpt is - val exMsg2 = intercept[IllegalArgumentException] { + test("constructor -- if version >= 0 then both deltas and checkpoints cannot be empty") { + val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, Collections.emptyList(), checkpointFs10, Optional.empty(), 1) + logPath, 11, Collections.emptyList(), Collections.emptyList(), 1) }.getMessage - assert( - exMsg2 === "checkpoints and checkpointVersionOpt must either be both empty or both non-empty") + assert(exMsg === "No files to read") } - test("LogSegment::constructor -- pass in non-delta file") { + test("constructor -- if deltas non-empty then first delta must equal checkpointVersion + 1") { + val deltaFs12 = Collections.singletonList( + FileStatus.of(FileNames.deltaFile(logPath, 12), 0, 0)) val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, badJson, checkpointFs10, Optional.of(10), 1) + logPath, 12, deltaFs12, checkpointFs10, 1) }.getMessage - assert(exMsg === "deltas must all be actual delta (commit) files") + assert(exMsg === "First delta file version must equal checkpointVersion + 1") } - test("LogSegment::constructor -- pass in non-checkpoint file") { + test("constructor -- if deltas non-empty then last delta must equal version") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, deltaFs11, badCheckpoint, Optional.of(10), 1) + logPath, 12, deltaFs11, checkpointFs10, 1) }.getMessage - assert(exMsg === "checkpoints must all be actual checkpoint files") + assert(exMsg === "Last delta file version must equal the version of this LogSegment") } - test("LogSegment::constructor -- checkpoint file version != checkpointVersionOpt") { - // checkpointFs10 has version 10 but checkpointVersionOpt is 5 + test("constructor -- if no deltas then checkpointVersion must equal version") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, deltaFs11, checkpointFs10, Optional.of(5), 1) + logPath, 11, Collections.emptyList(), checkpointFs10, 1) }.getMessage - assert(exMsg === "All checkpoint files must have the same version as the checkpointVersionOpt") + assert(exMsg === + "If there are no deltas, then checkpointVersion must equal the version of this LogSegment") } } From f7304cc91f7cdab2489f30668b1fc8540e07c72c Mon Sep 17 00:00:00 2001 From: Scott Sandre Date: Thu, 30 Jan 2025 12:29:57 -0800 Subject: [PATCH 4/4] Update LogSegmentSuite.scala --- .../internal/snapshot/LogSegmentSuite.scala | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala b/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala index db5a5029eb1..a3134d60360 100644 --- a/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala +++ b/kernel/kernel-api/src/test/scala/io/delta/kernel/internal/snapshot/LogSegmentSuite.scala @@ -16,6 +16,7 @@ package io.delta.kernel.internal.snapshot +import java.util.Arrays import java.util.{Collections, Optional} import io.delta.kernel.internal.fs.Path @@ -25,14 +26,18 @@ import org.scalatest.funsuite.AnyFunSuite class LogSegmentSuite extends AnyFunSuite { private val logPath = new Path("/a/_delta_log") - private val checkpointFs10 = Collections.singletonList( - FileStatus.of(FileNames.checkpointFileSingular(logPath, 10).toString, 0, 0)) - private val deltaFs11 = Collections.singletonList( - FileStatus.of(FileNames.deltaFile(logPath, 11), 0, 0)) - private val badJson = Collections.singletonList( - FileStatus.of(s"${logPath.toString}/gibberish.json", 0, 0)) - private val badCheckpoint = Collections.singletonList( - FileStatus.of(s"${logPath.toString}/gibberish.checkpoint.parquet", 0, 0)) + private val checkpointFs10 = + FileStatus.of(FileNames.checkpointFileSingular(logPath, 10).toString, 1, 1) + private val checkpointFs10List = Collections.singletonList(checkpointFs10) + private val deltaFs11 = FileStatus.of(FileNames.deltaFile(logPath, 11), 1, 1) + private val deltaFs11List = Collections.singletonList(deltaFs11) + private val deltaFs12 = FileStatus.of(FileNames.deltaFile(logPath, 12), 1, 1) + private val deltaFs12List = Collections.singletonList(deltaFs12) + private val deltasFs11To12List = Arrays.asList(deltaFs11, deltaFs12) + private val badJsonsList = Collections.singletonList( + FileStatus.of(s"${logPath.toString}/gibberish.json", 1, 1)) + private val badCheckpointsList = Collections.singletonList( + FileStatus.of(s"${logPath.toString}/gibberish.checkpoint.parquet", 1, 1)) test("constructor -- valid case (empty)") { LogSegment.empty(new Path("/a/_delta_log")) @@ -40,7 +45,7 @@ class LogSegmentSuite extends AnyFunSuite { test("constructor -- valid case (non-empty)") { val logPath = new Path("/a/_delta_log") - new LogSegment(logPath, 11, deltaFs11, checkpointFs10, 1) + new LogSegment(logPath, 12, deltasFs11To12List, checkpointFs10List, 1) } test("constructor -- null arguments => throw") { @@ -64,7 +69,7 @@ class LogSegmentSuite extends AnyFunSuite { test("constructor -- all deltas must be actual delta files") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, badJson, checkpointFs10, 1) + logPath, 12, badJsonsList, checkpointFs10List, 1) }.getMessage assert(exMsg === "deltas must all be actual delta (commit) files") } @@ -72,7 +77,7 @@ class LogSegmentSuite extends AnyFunSuite { test("constructor -- all checkpoints must be actual checkpoint files") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, deltaFs11, badCheckpoint, 1) + logPath, 12, deltasFs11To12List, badCheckpointsList, 1) }.getMessage assert(exMsg === "checkpoints must all be actual checkpoint files") } @@ -80,17 +85,15 @@ class LogSegmentSuite extends AnyFunSuite { test("constructor -- if version >= 0 then both deltas and checkpoints cannot be empty") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, Collections.emptyList(), Collections.emptyList(), 1) + logPath, 12, Collections.emptyList(), Collections.emptyList(), 1) }.getMessage assert(exMsg === "No files to read") } test("constructor -- if deltas non-empty then first delta must equal checkpointVersion + 1") { - val deltaFs12 = Collections.singletonList( - FileStatus.of(FileNames.deltaFile(logPath, 12), 0, 0)) val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 12, deltaFs12, checkpointFs10, 1) + logPath, 12, deltaFs12List, checkpointFs10List, 1) }.getMessage assert(exMsg === "First delta file version must equal checkpointVersion + 1") } @@ -98,7 +101,7 @@ class LogSegmentSuite extends AnyFunSuite { test("constructor -- if deltas non-empty then last delta must equal version") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 12, deltaFs11, checkpointFs10, 1) + logPath, 12, deltaFs11List, checkpointFs10List, 1) }.getMessage assert(exMsg === "Last delta file version must equal the version of this LogSegment") } @@ -106,7 +109,7 @@ class LogSegmentSuite extends AnyFunSuite { test("constructor -- if no deltas then checkpointVersion must equal version") { val exMsg = intercept[IllegalArgumentException] { new LogSegment( - logPath, 11, Collections.emptyList(), checkpointFs10, 1) + logPath, 11, Collections.emptyList(), checkpointFs10List, 1) }.getMessage assert(exMsg === "If there are no deltas, then checkpointVersion must equal the version of this LogSegment")