Skip to content

Commit 5e45e52

Browse files
committed
feat(test): add Spark integration tests for Hadoop table CRUD
Add cross-compatibility integration tests verifying CreateTable, LoadTable, and CheckTableExists work between Go and Spark Hadoop catalogs. Pre-create the hadoop-warehouse directory before Docker compose to ensure runner ownership in CI.
1 parent e07732c commit 5e45e52

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

catalog/hadoop/hadoop_integration_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"strings"
2727
"testing"
2828

29+
"github.com/apache/iceberg-go"
2930
"github.com/apache/iceberg-go/catalog"
3031
"github.com/apache/iceberg-go/catalog/hadoop"
3132
"github.com/apache/iceberg-go/internal/recipe"
@@ -228,6 +229,82 @@ func (s *HadoopIntegrationSuite) TestDropTableThenListReflects() {
228229
s.Equal("keep", tables[0][len(tables[0])-1])
229230
}
230231

232+
// TestGoCreateSparkDescribe creates a table from Go, then asks Spark to
233+
// DESCRIBE it and verifies that Spark sees the expected columns.
234+
func (s *HadoopIntegrationSuite) TestGoCreateSparkDescribe() {
235+
// Create namespace from Go so the directory is owned by the runner
236+
// process and Go can create table subdirectories inside it.
237+
err := s.cat.CreateNamespace(s.ctx, []string{"describe_ns"}, nil)
238+
s.Require().NoError(err)
239+
240+
schema := iceberg.NewSchema(1,
241+
iceberg.NestedField{ID: 1, Name: "id", Type: iceberg.PrimitiveTypes.Int64, Required: true},
242+
iceberg.NestedField{ID: 2, Name: "name", Type: iceberg.PrimitiveTypes.String, Required: false},
243+
)
244+
245+
tbl, err := s.cat.CreateTable(s.ctx, []string{"describe_ns", "go_created_table"}, schema)
246+
s.Require().NoError(err)
247+
s.NotNil(tbl)
248+
249+
output := s.sparkSQL("DESCRIBE TABLE hadoop_test.describe_ns.go_created_table")
250+
s.Contains(output, "id")
251+
s.Contains(output, "name")
252+
}
253+
254+
// TestSparkCreateGoLoad creates a table from Spark, then loads it from
255+
// Go and verifies schema and metadata are consistent.
256+
func (s *HadoopIntegrationSuite) TestSparkCreateGoLoad() {
257+
// Spark creates both namespace and table — Go only reads here.
258+
s.sparkSQL("CREATE NAMESPACE IF NOT EXISTS hadoop_test.load_ns")
259+
s.sparkSQL("CREATE TABLE hadoop_test.load_ns.spark_created_table (age INT, city STRING) USING iceberg")
260+
261+
tbl, err := s.cat.LoadTable(s.ctx, []string{"load_ns", "spark_created_table"})
262+
s.Require().NoError(err)
263+
s.NotNil(tbl)
264+
265+
fields := tbl.Schema().Fields()
266+
fieldNames := make([]string, len(fields))
267+
for i, f := range fields {
268+
fieldNames[i] = f.Name
269+
}
270+
271+
s.Contains(fieldNames, "age")
272+
s.Contains(fieldNames, "city")
273+
}
274+
275+
// TestGoCreateSparkSelect creates a table from Go, then runs a SELECT
276+
// from Spark to confirm the table is queryable (should return empty).
277+
func (s *HadoopIntegrationSuite) TestGoCreateSparkSelect() {
278+
err := s.cat.CreateNamespace(s.ctx, []string{"select_ns"}, nil)
279+
s.Require().NoError(err)
280+
281+
schema := iceberg.NewSchema(1,
282+
iceberg.NestedField{ID: 1, Name: "value", Type: iceberg.PrimitiveTypes.Int32, Required: true},
283+
)
284+
285+
_, err = s.cat.CreateTable(s.ctx, []string{"select_ns", "go_select_table"}, schema)
286+
s.Require().NoError(err)
287+
288+
output := s.sparkSQL("SELECT * FROM hadoop_test.select_ns.go_select_table")
289+
s.Contains(output, "value")
290+
}
291+
292+
// TestGoCheckTableExistsForSparkTable verifies that CheckTableExists
293+
// returns true for a table created by Spark.
294+
func (s *HadoopIntegrationSuite) TestGoCheckTableExistsForSparkTable() {
295+
// Spark creates both namespace and table — Go only checks existence.
296+
s.sparkSQL("CREATE NAMESPACE IF NOT EXISTS hadoop_test.exists_ns")
297+
s.sparkSQL("CREATE TABLE hadoop_test.exists_ns.spark_exists_table (x INT) USING iceberg")
298+
299+
exists, err := s.cat.CheckTableExists(s.ctx, []string{"exists_ns", "spark_exists_table"})
300+
s.Require().NoError(err)
301+
s.True(exists)
302+
303+
exists, err = s.cat.CheckTableExists(s.ctx, []string{"exists_ns", "no_such_table"})
304+
s.Require().NoError(err)
305+
s.False(exists)
306+
}
307+
231308
func TestHadoopIntegration(t *testing.T) {
232309
suite.Run(t, new(HadoopIntegrationSuite))
233310
}

0 commit comments

Comments
 (0)