// 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 Common import Foundation import Macros import Runtime import SwiftTreeSitter import Testing import TreeSitter import TreeSitterP4 import P4Lang @testable import P4Compiler @Test func test_simple_control_declaration() async throws { let simple_parser_declaration = """ control simple() { action a() { } table t { key = { true: exact; } } apply { } }; """ let x = { (tipe: P4QualifiedType) -> Bool in switch tipe.baseType() { case let c as Control: c.name == "simple" default: false } } let program = try! #UseOkResult(Program.Compile(simple_parser_declaration)) #expect(program.InstancesWithTypes(x).count == 1) } @Test func test_simple_control_declaration2() async throws { let simple_parser_declaration = """ struct Testing { }; control simple() { action a() { } table t { key = { true: exact; } } apply { } }; control complex() { action b() { } table t { key = { true: exact; } } apply { } }; """ let filter = { (tipe: P4QualifiedType) -> Bool in switch tipe.baseType() { case let c as Control: c.name == "simple" || c.name == "complex" default: false } } let program = try! #UseOkResult(Program.Compile(simple_parser_declaration)) #expect(program.InstancesWithTypes(filter).count == 2) } @Test func test_simple_control_declaration_with_actions() async throws { let simple_parser_declaration = """ control simple() { action a() { } table t { key = { true: exact; } actions = { a; } } apply { } }; """ let x = { (tipe: P4QualifiedType) -> Bool in switch tipe.baseType() { case let c as Control: c.name == "simple" default: false } } let program = try! #UseOkResult(Program.Compile(simple_parser_declaration)) #expect(program.InstancesWithTypes(x).count == 1) } @Test func test_simple_control_declaration_with_misnamed_actions() async throws { let simple_parser_declaration = """ control simple() { action a() { } table t { key = { true: exact; } actions = { b; } } apply { } }; """ #expect( #RequireErrorResult( Error( withMessage: "{54, 63}: Error(s) parsing property list: {91, 26}: Error(s) parsing table actions: Cannot find b in lexical scope." ), Program.Compile(simple_parser_declaration)) ) } @Test func test_simple_control_declaration_with_misnamed_actions2() async throws { let simple_parser_declaration = """ control simple() { action a() { } table t { key = { true: exact; } actions = { a; b; } } apply { } }; """ #expect( #RequireErrorResult( Error( withMessage: "{54, 72}: Error(s) parsing property list: {91, 35}: Error(s) parsing table actions: Cannot find b in lexical scope." ), Program.Compile(simple_parser_declaration)) ) } @Test func test_simple_control_declaration_with_mistyped_actions() async throws { let simple_parser_declaration = """ bool a() { return true; }; control simple() { table t { key = { true: exact; } actions = { a; } } apply { } }; """ #expect( #RequireErrorResult( Error( withMessage: "{64, 63}: Error(s) parsing property list: {101, 26}: Error(s) parsing table actions: {101, 26}: a does not name an action" ), Program.Compile(simple_parser_declaration)) ) } @Test func test_simple_control_declaration_with_parameters() async throws { let simple_parser_declaration = """ control simple(bool x, bool y) { action a() { } table t { key = { x: exact; y: exact; } } apply { } }; """ #expect(#RequireOkResult(Program.Compile(simple_parser_declaration))) } @Test func test_simple_control_declaration_with_multiple_tables() async throws { let simple_parser_declaration = """ control simple(bool x, bool y, bool a, bool b) { action a() { } table t { key = { x: exact; y: exact; } } table u { key = { a: exact; b: exact; } } apply { } }; """ #expect( #RequireErrorResult( Error( withMessage: "{0, 215}: More than one table in control declaration" ), Program.Compile(simple_parser_declaration)) ) } @Test func test_simple_control_declaration_with_action_using_parameter() async throws { let simple_parser_declaration = """ control simple(bool x, bool y) { action a(int z) { z = 5; } table t { key = { x: exact; y: exact; } } apply { } }; """ #expect(#RequireOkResult(Program.Compile(simple_parser_declaration))) } @Test func test_simple_control_declaration_with_action_using_parameter_wrong_type() async throws { let simple_parser_declaration = """ control simple(bool x, bool y) { action a(int z) { z = false; } table t { key = { x: exact; y: exact; } } apply { } }; """ #expect( #RequireErrorResult( Error( withMessage: "{57, 10}: Failed to parse a statement element: {57, 1}: Cannot assign value with type Boolean to identifier z with type Int" ), Program.Compile(simple_parser_declaration)) ) } @Test func test_simple_control_declaration_with_element_after_apply() async throws { let simple_parser_declaration = """ control simple(bool x, bool y) { action a(int z) { z = false; } table t { key = { x: exact; y: exact; } } apply { } table x { key = { x: exact; y: exact; } } }; """ #expect( #RequireErrorResult( Error( withMessage: "Could not compile the P4 program" ), Program.Compile(simple_parser_declaration)) ) }