From 2b1e39469da4bf25a3af993d8d8ab5785556147e Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Thu, 13 Mar 2025 22:32:11 -0700 Subject: [PATCH] [SPARK-51510] Add SQL-file based `SQLTests` suite --- .github/.licenserc.yaml | 1 + Package.swift | 5 +- .../Resources/queries/pipesyntax.sql | 2 + .../Resources/queries/pipesyntax.sql.json | 1 + .../Resources/queries/select.sql | 1 + .../Resources/queries/select.sql.json | 1 + Tests/SparkConnectTests/SQLTests.swift | 48 +++++++++++++++++++ 7 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Tests/SparkConnectTests/Resources/queries/pipesyntax.sql create mode 100644 Tests/SparkConnectTests/Resources/queries/pipesyntax.sql.json create mode 100644 Tests/SparkConnectTests/Resources/queries/select.sql create mode 100644 Tests/SparkConnectTests/Resources/queries/select.sql.json create mode 100644 Tests/SparkConnectTests/SQLTests.swift diff --git a/.github/.licenserc.yaml b/.github/.licenserc.yaml index 27bf15a..5f08a50 100644 --- a/.github/.licenserc.yaml +++ b/.github/.licenserc.yaml @@ -16,5 +16,6 @@ header: - '.nojekyll' - 'Package.swift' - '**/*pb.swift' + - 'Tests/SparkConnectTests/Resources/queries/**' comment: on-failure diff --git a/Package.swift b/Package.swift index 58aa421..7f3074a 100644 --- a/Package.swift +++ b/Package.swift @@ -53,7 +53,10 @@ let package = Package( ), .testTarget( name: "SparkConnectTests", - dependencies: ["SparkConnect"] + dependencies: ["SparkConnect"], + resources: [ + .copy("Resources/queries") + ] ), ] ) diff --git a/Tests/SparkConnectTests/Resources/queries/pipesyntax.sql b/Tests/SparkConnectTests/Resources/queries/pipesyntax.sql new file mode 100644 index 0000000..cc057cb --- /dev/null +++ b/Tests/SparkConnectTests/Resources/queries/pipesyntax.sql @@ -0,0 +1,2 @@ +VALUES (0), (1) tab(col) +|> EXTEND col * 2 AS result diff --git a/Tests/SparkConnectTests/Resources/queries/pipesyntax.sql.json b/Tests/SparkConnectTests/Resources/queries/pipesyntax.sql.json new file mode 100644 index 0000000..bfa3b54 --- /dev/null +++ b/Tests/SparkConnectTests/Resources/queries/pipesyntax.sql.json @@ -0,0 +1 @@ +[["0","0"],["1","2"]] diff --git a/Tests/SparkConnectTests/Resources/queries/select.sql b/Tests/SparkConnectTests/Resources/queries/select.sql new file mode 100644 index 0000000..2e3761f --- /dev/null +++ b/Tests/SparkConnectTests/Resources/queries/select.sql @@ -0,0 +1 @@ +SELECT 1 diff --git a/Tests/SparkConnectTests/Resources/queries/select.sql.json b/Tests/SparkConnectTests/Resources/queries/select.sql.json new file mode 100644 index 0000000..0a0ab46 --- /dev/null +++ b/Tests/SparkConnectTests/Resources/queries/select.sql.json @@ -0,0 +1 @@ +[["1"]] diff --git a/Tests/SparkConnectTests/SQLTests.swift b/Tests/SparkConnectTests/SQLTests.swift new file mode 100644 index 0000000..3ed3568 --- /dev/null +++ b/Tests/SparkConnectTests/SQLTests.swift @@ -0,0 +1,48 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +// + +import Foundation +import Testing + +@testable import SparkConnect + +/// A test suite for various SQL statements. +struct SQLTests { + let fm = FileManager.default + let path = Bundle.module.path(forResource: "queries", ofType: "")! + let encoder = JSONEncoder() + +#if !os(Linux) + @Test + func runAll() async throws { + let spark = try await SparkSession.builder.getOrCreate() + for name in try! fm.contentsOfDirectory(atPath: path).sorted() { + guard name.hasSuffix(".sql") else { continue } + print(name) + + let sql = try String(contentsOf: URL(fileURLWithPath: "\(path)/\(name)"), encoding: .utf8) + let jsonData = try encoder.encode(try await spark.sql(sql).collect()) + let answer = String(data: jsonData, encoding: .utf8)! + let expected = try String(contentsOf: URL(fileURLWithPath: "\(path)/\(name).json"), encoding: .utf8) + #expect(answer == expected.trimmingCharacters(in: .whitespacesAndNewlines)) + } + await spark.stop() + } +#endif +}