// p4rse, Copyright 2026, Will Hawkins // // This file is part of p4rse. // // This file is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . import Foundation import Macros import P4Compiler import P4Lang import P4Runtime import SwiftTreeSitter import System import Testing import TreeSitter import TreeSitterP4 @testable import Common @Test func test_preprocessor() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/simple.p4") let expected_file = FilePath.init(FileManager().currentDirectoryPath + "/" + file.string).lexicallyNormalized() let source = try! (#UseOkResult(prep.preprocess(file))) let program = try! #UseOkResult(Program.Compile(source.getSource())) #expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser"))))) #expect(source.getLocations().getPath() == expected_file) } @Test func test_preprocessor_search_for_file() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "simple.p4") let expected_file = FilePath.init(FileManager().currentDirectoryPath + "/TestData/Sources/simple.p4") let source = try! (#UseOkResult(prep.preprocess(file))) let program = try! #UseOkResult(Program.Compile(source.getSource())) #expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser"))))) #expect(source.getLocations().getPath() == expected_file) } @Test func test_preprocessor_nested_includes() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/simple-split.p4") let expected_file = FilePath.init(FileManager().currentDirectoryPath + "/" + file.string).lexicallyNormalized() #expect(#RequireOkResult(prep.preprocess(file))) let source = try! (#UseOkResult(prep.preprocess(file))) let program = try! #UseOkResult(Program.Compile(source.getSource())) #expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser"))))) #expect(source.getLocations().getPath() == expected_file) } @Test func test_preprocessor_oneline_includes() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/simple-split-oneline.p4") let expected_file = FilePath.init(FileManager().currentDirectoryPath + "/" + file.string).lexicallyNormalized() #expect(#RequireOkResult(prep.preprocess(file))) let source = try! (#UseOkResult(prep.preprocess(file))) let program = try! #UseOkResult(Program.Compile(source.getSource())) #expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser"))))) #expect(source.getLocations().getPath() == expected_file) } @Test func test_preprocessor_missing_file() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/unfound.p4") #expect( #RequireErrorResult( Error(withMessage: "Could not open ./TestData/Sources/unfound.p4 for preprocessing"), (prep.preprocess(file)))) } @Test func test_preprocessor_missing_included_file() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/simple-unfound.p4") #expect( #RequireErrorResult( Error(withMessage: "Could not open unfound.p4 for inclusion"), (prep.preprocess(file)))) } @Test func test_preprocessor_no_change_locations() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "testing.p4") let source = try! (#UseOkResult(prep.preprocess(file))) #expect(source.getLocations().getLocation() == SourceLocation(0..<173)) } @Test func test_preprocessor_change_locations() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "testing-split-a.p4") let source = try! (#UseOkResult(prep.preprocess(file))) #expect(source.getLocations().getLocation() == SourceLocation(0..<173)) #expect(source.getLocations().getNestedLocations()[0].getLocation() == SourceLocation(48..<173)) } @Test func test_preprocessor_oneline_includes_locations() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/simple-split-oneline.p4") #expect(#RequireOkResult(prep.preprocess(file))) let source = try! (#UseOkResult(prep.preprocess(file))) #expect(source.getLocations().getLocation() == SourceLocation(0..<173)) #expect(source.getLocations().getNestedLocations()[0].getLocation() == SourceLocation(0..<70)) #expect(source.getLocations().getNestedLocations()[1].getLocation() == SourceLocation(70..<173)) } @Test func test_preprocessor_nested_includes_locations() async throws { let sm = SourceManager(["./TestData/Sources/"]) let prep = SourceCodePreprocessor(sm) let file = FilePath.init(stringLiteral: "./TestData/Sources/nested-split.p4") #expect(#RequireOkResult(prep.preprocess(file))) let source = try! (#UseOkResult(prep.preprocess(file))) #expect(source.getLocations().getLocation() == SourceLocation(0..<173)) #expect( source.getLocations().getNestedLocations()[0].getNestedLocations()[0].getLocation() == SourceLocation(27..<47)) #expect( source.getLocations().getNestedLocations()[0].getNestedLocations()[1].getLocation() == SourceLocation(48..<166)) } @Test func test_source_location_contains() async throws { let outer = SourceLocation(0..<500) let inner = SourceLocation(0..<499) #expect(outer.contains(inner)) } @Test func test_source_location_contains_a() async throws { let outer = SourceLocation(0, 500) let inner = SourceLocation(0, 499) #expect(outer.contains(inner)) } @Test func test_source_location_contains2() async throws { let outer = SourceLocation(0..<500) let not_inner = SourceLocation(0..<501) #expect(!outer.contains(not_inner)) } @Test func test_source_location_contains2_a() async throws { let outer = SourceLocation(0,500) let not_inner = SourceLocation(0,501) #expect(!outer.contains(not_inner)) } @Test func test_source_location_contains3() async throws { let outer = SourceLocation(200..<500) let inner = SourceLocation(200..<499) #expect(outer.contains(inner)) } @Test func test_source_location_contains3_a() async throws { let outer = SourceLocation(200,300) let inner = SourceLocation(200,299) #expect(outer.contains(inner)) } @Test func test_source_location_contains4() async throws { let outer = SourceLocation(200..<500) let inner = SourceLocation(200, 299) #expect(outer.contains(inner)) } @Test func test_source_location_contains5() async throws { let outer = SourceLocation(200..<300) let not_inner = SourceLocation(200,101) #expect(!outer.contains(not_inner)) }