| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- // Tests/SwiftProtobufPluginLibraryTests/Test_ProtoFileToModuleMappings.swift - Test ProtoFile to Modules helper
- //
- // Copyright (c) 2014 - 2017 Apple Inc. and the project authors
- // Licensed under Apache License v2.0 with Runtime Library Exception
- //
- // See LICENSE.txt for license information:
- // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
- //
- // -----------------------------------------------------------------------------
- import SwiftProtobuf
- import SwiftProtobufPluginLibrary
- import SwiftProtobufTestHelpers
- import XCTest
- // Helpers to make test cases.
- private typealias FileDescriptorProto = Google_Protobuf_FileDescriptorProto
- final class Test_ProtoFileToModuleMappings: XCTestCase {
- func test_Initialization() {
- // ProtoFileToModuleMappings always includes mappings for the protos that
- // ship with the library, so they will show in the counts below.
- let baselineEntries = SwiftProtobufInfo.bundledProtoFiles.count
- let baselineModules = 1 // Since those files are in SwiftProtobuf.
- // (config, num_expected_mappings, num_expected_modules)
- let tests: [(String, Int, Int)] = [
- ("", 0, 0),
- ("mapping { module_name: \"good\", proto_file_path: \"file.proto\" }", 1, 1),
- ("mapping { module_name: \"good\", proto_file_path: [\"a\",\"b\"] }", 2, 1),
- // Two mapping {}, same module.
- (
- "mapping { module_name: \"good\", proto_file_path: \"a\" }\n"
- + "mapping { module_name: \"good\", proto_file_path: \"b\" }", 2, 1
- ),
- // Two mapping {}, different modules.
- (
- "mapping { module_name: \"one\", proto_file_path: \"a\" }\n"
- + "mapping { module_name: \"two\", proto_file_path: \"b\" }", 2, 2
- ),
- // Same file listed twice; odd, but ok since no conflict.
- ("mapping { module_name: \"foo\", proto_file_path: [\"abc\", \"abc\"] }", 1, 1),
- // Same module/file listing; odd, but ok since no conflict.
- (
- "mapping { module_name: \"foo\", proto_file_path: [\"mno\", \"abc\"] }\n"
- + "mapping { module_name: \"foo\", proto_file_path: [\"abc\", \"xyz\"] }", 3, 1
- ),
- ]
- for (idx, (configText, expectMappings, expectedModules)) in tests.enumerated() {
- let config: SwiftProtobuf_GenSwift_ModuleMappings
- do {
- config = try SwiftProtobuf_GenSwift_ModuleMappings(textFormatString: configText)
- } catch {
- XCTFail("Index: \(idx) - Test case wasn't valid TextFormat")
- continue
- }
- do {
- let mapper = try ProtoFileToModuleMappings(moduleMappingsProto: config)
- XCTAssertEqual(mapper.mappings.count, expectMappings + baselineEntries, "Index: \(idx)")
- XCTAssertEqual(Set(mapper.mappings.values).count, expectedModules + baselineModules, "Index: \(idx)")
- XCTAssert(mapper.hasMappings == (expectMappings != 0), "Index: \(idx)")
- } catch let error {
- XCTFail("Index \(idx) - Unexpected error: \(error)")
- }
- }
- }
- func test_Initialization_InvalidConfigs() {
- // This are valid text format, but not valid config protos.
- // (input, expected_error_type)
- let partialConfigs: [(String, ProtoFileToModuleMappings.LoadError)] = [
- // No module or proto files
- ("mapping { }", .entryMissingModuleName(mappingIndex: 0)),
- // No proto files
- ("mapping { module_name: \"foo\" }", .entryHasNoProtoPaths(mappingIndex: 0)),
- // No module
- ("mapping { proto_file_path: [\"foo\"] }", .entryMissingModuleName(mappingIndex: 0)),
- ("mapping { proto_file_path: [\"foo\", \"bar\"] }", .entryMissingModuleName(mappingIndex: 0)),
- // Empty module name.
- ("mapping { module_name: \"\" }", .entryMissingModuleName(mappingIndex: 0)),
- ("mapping { module_name: \"\", proto_file_path: [\"foo\"] }", .entryMissingModuleName(mappingIndex: 0)),
- (
- "mapping { module_name: \"\", proto_file_path: [\"foo\", \"bar\"] }",
- .entryMissingModuleName(mappingIndex: 0)
- ),
- // Throw some on a second entry just to check that also.
- (
- "mapping { module_name: \"good\", proto_file_path: \"file.proto\" }\n" + "mapping { }",
- .entryMissingModuleName(mappingIndex: 1)
- ),
- (
- "mapping { module_name: \"good\", proto_file_path: \"file.proto\" }\n"
- + "mapping { module_name: \"foo\" }",
- .entryHasNoProtoPaths(mappingIndex: 1)
- ),
- // Duplicates
- (
- "mapping { module_name: \"foo\", proto_file_path: \"abc\" }\n"
- + "mapping { module_name: \"bar\", proto_file_path: \"abc\" }",
- .duplicateProtoPathMapping(path: "abc", firstModule: "foo", secondModule: "bar")
- ),
- (
- "mapping { module_name: \"foo\", proto_file_path: \"abc\" }\n"
- + "mapping { module_name: \"bar\", proto_file_path: \"xyz\" }\n"
- + "mapping { module_name: \"baz\", proto_file_path: \"abc\" }",
- .duplicateProtoPathMapping(path: "abc", firstModule: "foo", secondModule: "baz")
- ),
- ]
- for (idx, (configText, expected)) in partialConfigs.enumerated() {
- let config: SwiftProtobuf_GenSwift_ModuleMappings
- do {
- config = try SwiftProtobuf_GenSwift_ModuleMappings(textFormatString: configText)
- } catch {
- XCTFail("Index: \(idx) - Test case wasn't valid TextFormat")
- continue
- }
- do {
- let _ = try ProtoFileToModuleMappings(moduleMappingsProto: config)
- XCTFail("Shouldn't have gotten here, index \(idx)")
- } catch let error as ProtoFileToModuleMappings.LoadError {
- XCTAssertEqual(error, expected, "Index \(idx)")
- } catch let error {
- XCTFail("Index \(idx) - Unexpected error: \(error)")
- }
- }
- }
- func test_moduleName_forFile() {
- let configText = [
- "mapping { module_name: \"foo\", proto_file_path: \"file\" }",
- "mapping { module_name: \"bar\", proto_file_path: \"dir1/file\" }",
- "mapping { module_name: \"baz\", proto_file_path: [\"dir2/file\",\"file4\"] }",
- "mapping { module_name: \"foo\", proto_file_path: \"file5\" }",
- ].joined(separator: "\n")
- let config = try! SwiftProtobuf_GenSwift_ModuleMappings(textFormatString: configText)
- let mapper = try! ProtoFileToModuleMappings(moduleMappingsProto: config)
- let tests: [(String, String?)] = [
- ("file", "foo"),
- ("dir1/file", "bar"),
- ("dir2/file", "baz"),
- ("file4", "baz"),
- ("file5", "foo"),
- ("", nil),
- ("not found", nil),
- ]
- for (name, expected) in tests {
- let descSet = DescriptorSet(protos: [FileDescriptorProto(name: name)])
- XCTAssertEqual(mapper.moduleName(forFile: descSet.files.first!), expected, "Looking for \(name)")
- }
- }
- func test_neededModules_forFile() {
- let configText = [
- "mapping { module_name: \"foo\", proto_file_path: \"file\" }",
- "mapping { module_name: \"bar\", proto_file_path: \"dir1/file\" }",
- "mapping { module_name: \"baz\", proto_file_path: [\"dir2/file\",\"file4\"] }",
- "mapping { module_name: \"foo\", proto_file_path: \"file5\" }",
- ].joined(separator: "\n")
- let config = try! SwiftProtobuf_GenSwift_ModuleMappings(textFormatString: configText)
- let mapper = try! ProtoFileToModuleMappings(moduleMappingsProto: config)
- let fileProtos = [
- FileDescriptorProto(name: "file"),
- FileDescriptorProto(name: "google/protobuf/any.proto"),
- FileDescriptorProto(name: "dir1/file", dependencies: ["file"]),
- FileDescriptorProto(name: "dir2/file", dependencies: ["google/protobuf/any.proto"]),
- FileDescriptorProto(name: "file4", dependencies: ["dir2/file", "dir1/file", "file"]),
- FileDescriptorProto(name: "file5", dependencies: ["file"]),
- ]
- let descSet = DescriptorSet(protos: fileProtos)
- // ( filename, [deps] )
- let tests: [(String, [String]?)] = [
- ("file", nil),
- ("dir1/file", ["foo"]),
- ("dir2/file", nil),
- ("file4", ["bar", "foo"]),
- ("file5", nil),
- ]
- for (name, expected) in tests {
- let fileDesc = descSet.files.filter { $0.name == name }.first!
- let result = mapper.neededModules(forFile: fileDesc)
- if let expected = expected {
- XCTAssertEqual(result!, expected, "Looking for \(name)")
- } else {
- XCTAssertNil(result, "Looking for \(name)")
- }
- }
- }
- func test_neededModules_forFile_PublicImports() {
- // See the note in neededModules(forFile:) about how public import complicate things.
- // Given:
- //
- // + File: a.proto
- // message A {}
- //
- // + File: imports_a_publicly.proto
- // import public "a.proto";
- //
- // message ImportsAPublicly {
- // A a = 1;
- // }
- //
- // + File: imports_imports_a_publicly.proto
- // import public "imports_a_publicly.proto";
- //
- // message ImportsImportsAPublicly {
- // A a = 1;
- // }
- //
- // + File: uses_a_transitively.proto
- // import "imports_a_publicly.proto";
- //
- // message UsesATransitively {
- // A a = 1;
- // }
- //
- // + File: uses_a_transitively2.proto
- // import "imports_imports_a_publicly.proto";
- //
- // message UsesATransitively2 {
- // A a = 1;
- // }
- //
- // With a mapping file of:
- //
- // mapping {
- // module_name: "A"
- // proto_file_path: "a.proto"
- // }
- // mapping {
- // module_name: "ImportsAPublicly"
- // proto_file_path: "imports_a_publicly.proto"
- // }
- // mapping {
- // module_name: "ImportsImportsAPublicly"
- // proto_file_path: "imports_imports_a_publicly.proto"
- // }
- let configText = [
- "mapping { module_name: \"A\", proto_file_path: \"a.proto\" }",
- "mapping { module_name: \"ImportsAPublicly\", proto_file_path: \"imports_a_publicly.proto\" }",
- "mapping { module_name: \"ImportsImportsAPublicly\", proto_file_path: \"imports_imports_a_publicly.proto\" }",
- ].joined(separator: "\n")
- let config = try! SwiftProtobuf_GenSwift_ModuleMappings(textFormatString: configText)
- let mapper = try! ProtoFileToModuleMappings(moduleMappingsProto: config)
- let fileProtos = [
- FileDescriptorProto(name: "a.proto"),
- FileDescriptorProto(
- name: "imports_a_publicly.proto",
- dependencies: ["a.proto"],
- publicDependencies: [0]
- ),
- FileDescriptorProto(
- name: "imports_imports_a_publicly.proto",
- dependencies: ["imports_a_publicly.proto"],
- publicDependencies: [0]
- ),
- FileDescriptorProto(
- name: "uses_a_transitively.proto",
- dependencies: ["imports_a_publicly.proto"]
- ),
- FileDescriptorProto(
- name: "uses_a_transitively2.proto",
- dependencies: ["imports_imports_a_publicly.proto"]
- ),
- ]
- let descSet = DescriptorSet(protos: fileProtos)
- // ( filename, [deps] )
- let tests: [(String, [String]?)] = [
- ("a.proto", nil),
- ("imports_a_publicly.proto", ["A"]),
- ("imports_imports_a_publicly.proto", ["A", "ImportsAPublicly"]),
- ("uses_a_transitively.proto", ["A", "ImportsAPublicly"]),
- ("uses_a_transitively2.proto", ["A", "ImportsAPublicly", "ImportsImportsAPublicly"]),
- ]
- for (name, expected) in tests {
- let fileDesc = descSet.files.filter { $0.name == name }.first!
- let result = mapper.neededModules(forFile: fileDesc)
- if let expected = expected {
- XCTAssertEqual(result!, expected, "Looking for \(name)")
- } else {
- XCTAssertNil(result, "Looking for \(name)")
- }
- }
- }
- }
|