@@ -18,27 +18,157 @@ package io.delta.kernel.internal.catalogManaged
18
18
19
19
import java .util .Collections
20
20
21
+ import scala .collection .JavaConverters ._
22
+
21
23
import io .delta .kernel .TableManager
24
+ import io .delta .kernel .exceptions .KernelException
22
25
import io .delta .kernel .internal .actions .Protocol
26
+ import io .delta .kernel .internal .files .ParsedLogData
27
+ import io .delta .kernel .internal .files .ParsedLogData .ParsedLogType
23
28
import io .delta .kernel .internal .table .ResolvedTableInternal
24
- import io .delta .kernel .test .{ActionUtils , MockFileSystemClientUtils }
29
+ import io .delta .kernel .test .{ActionUtils , MockFileSystemClientUtils , VectorTestUtils }
25
30
import io .delta .kernel .types .{IntegerType , StructType }
26
31
27
32
import org .scalatest .funsuite .AnyFunSuite
28
33
29
34
class ResolvedTableBuilderSuite extends AnyFunSuite
30
- with MockFileSystemClientUtils with ActionUtils {
35
+ with MockFileSystemClientUtils
36
+ with ActionUtils
37
+ with VectorTestUtils {
31
38
32
- test(" if P & M are provided then LogSegment is not loaded" ) {
33
- val testSchema = new StructType ().add(" c1" , IntegerType .INTEGER )
34
- val engine = createMockFSListFromEngine(Nil )
39
+ private val emptyMockEngine = createMockFSListFromEngine(Nil )
40
+ private val protocol = new Protocol (1 , 2 )
41
+ private val metadata = testMetadata(new StructType ().add(" c1" , IntegerType .INTEGER ))
42
+
43
+ // /////////////////////////////////////
44
+ // Builder Validation Tests -- START //
45
+ // /////////////////////////////////////
46
+
47
+ test(" loadTable: null path throws NullPointerException" ) {
48
+ assertThrows[NullPointerException ] {
49
+ TableManager .loadTable(null )
50
+ }
51
+ }
52
+
53
+ // ===== Version Tests ===== //
54
+
55
+ test(" atVersion: negative version throws IllegalArgumentException" ) {
56
+ val builder = TableManager .loadTable(dataPath.toString).atVersion(- 1 )
57
+
58
+ val exMsg = intercept[IllegalArgumentException ] {
59
+ builder.build(emptyMockEngine)
60
+ }.getMessage
61
+
62
+ assert(exMsg === " version must be >= 0" )
63
+ }
64
+
65
+ // ===== Protocol and Metadata Tests ===== //
66
+
67
+ test(" withProtocolAndMetadata: null protocol throws NullPointerException" ) {
68
+ assertThrows[NullPointerException ] {
69
+ TableManager .loadTable(dataPath.toString)
70
+ .withProtocolAndMetadata(null , metadata)
71
+ }
72
+
73
+ assertThrows[NullPointerException ] {
74
+ TableManager .loadTable(dataPath.toString)
75
+ .withProtocolAndMetadata(protocol, null )
76
+ }
77
+ }
78
+
79
+ test(" withProtocolAndMetadata: only if version is provided" ) {
80
+ val exMsg = intercept[IllegalArgumentException ] {
81
+ TableManager .loadTable(dataPath.toString)
82
+ .withProtocolAndMetadata(protocol, metadata)
83
+ .build(emptyMockEngine)
84
+ }.getMessage
85
+
86
+ assert(exMsg === " protocol and metadata can only be provided if a version is provided" )
87
+ }
88
+
89
+ test(" withProtocolAndMetadata: invalid readerVersion throws KernelException" ) {
90
+ val exMsg = intercept[KernelException ] {
91
+ TableManager .loadTable(dataPath.toString)
92
+ .atVersion(10 )
93
+ .withProtocolAndMetadata(new Protocol (999 , 2 ), metadata)
94
+ .build(emptyMockEngine)
95
+ }.getMessage
96
+
97
+ assert(exMsg.contains(" Unsupported Delta protocol reader version" ))
98
+ }
99
+
100
+ test(" withProtocolAndMetadata: unknown reader feature throws KernelException" ) {
101
+ val exMsg = intercept[KernelException ] {
102
+ TableManager .loadTable(dataPath.toString)
103
+ .atVersion(10 )
104
+ .withProtocolAndMetadata(
105
+ new Protocol (3 , 7 , Set (" unknownReaderFeature" ).asJava, Collections .emptySet()),
106
+ metadata)
107
+ .build(emptyMockEngine)
108
+ }.getMessage
109
+
110
+ assert(exMsg.contains(" Unsupported Delta table feature" ))
111
+ }
112
+
113
+ // ===== LogData Tests ===== //
35
114
115
+ test(" withLogData: null input throws NullPointerException" ) {
116
+ assertThrows[NullPointerException ] {
117
+ TableManager .loadTable(dataPath.toString).withLogData(null )
118
+ }
119
+ }
120
+
121
+ Seq (
122
+ ParsedLogData .forInlineData(1 , ParsedLogType .RATIFIED_INLINE_COMMIT , emptyColumnarBatch),
123
+ ParsedLogData .forFileStatus(logCompactionStatus(0 , 1 ))).foreach { parsedLogData =>
124
+ val suffix = s " - type= ${parsedLogData.`type`}"
125
+ test(s " withLogData: non-RATIFIED_STAGED_COMMIT throws IllegalArgumentException $suffix" ) {
126
+ val builder = TableManager
127
+ .loadTable(dataPath.toString)
128
+ .atVersion(1 )
129
+ .withLogData(Collections .singletonList(parsedLogData))
130
+
131
+ val exMsg = intercept[IllegalArgumentException ] {
132
+ builder.build(emptyMockEngine)
133
+ }.getMessage
134
+
135
+ assert(exMsg.contains(" Only RATIFIED_STAGED_COMMIT log data is supported" ))
136
+ }
137
+ }
138
+
139
+ test(" withLogData: non-contiguous input throws IllegalArgumentException" ) {
140
+ val exMsg = intercept[IllegalArgumentException ] {
141
+ TableManager .loadTable(dataPath.toString)
142
+ .atVersion(2 )
143
+ .withLogData(parsedRatifiedStagedCommits(Seq (0 , 2 )).toList.asJava)
144
+ .build(emptyMockEngine)
145
+ }.getMessage
146
+
147
+ assert(exMsg.contains(" Log data must be sorted and contiguous" ))
148
+ }
149
+
150
+ test(" withLogData: non-sorted input throws IllegalArgumentException" ) {
151
+ val exMsg = intercept[IllegalArgumentException ] {
152
+ TableManager .loadTable(dataPath.toString)
153
+ .atVersion(2 )
154
+ .withLogData(parsedRatifiedStagedCommits(Seq (2 , 1 , 0 )).toList.asJava)
155
+ .build(emptyMockEngine)
156
+ }.getMessage
157
+
158
+ assert(exMsg.contains(" Log data must be sorted and contiguous" ))
159
+ }
160
+
161
+ // ///////////////////////////////////
162
+ // Builder Validation Tests -- END //
163
+ // ///////////////////////////////////
164
+
165
+ test(" if P & M are provided then LogSegment is not loaded" ) {
36
166
val resolvedTable = TableManager
37
167
.loadTable(dataPath.toString)
38
168
.atVersion(13 )
39
- .withProtocolAndMetadata(new Protocol ( 1 , 2 ), testMetadata(testSchema) )
169
+ .withProtocolAndMetadata(protocol, metadata )
40
170
.withLogData(Collections .emptyList())
41
- .build(engine )
171
+ .build(emptyMockEngine )
42
172
.asInstanceOf [ResolvedTableInternal ]
43
173
44
174
assert(! resolvedTable.getLazyLogSegment.isPresent)
0 commit comments