using System.Collections.Generic; using AGVNavigationCore.Models; namespace AGVPathTester { /// /// AGV 경로 탐색 테스트 케이스 정의 /// public static class TestCases { /// /// 기본 경로 탐색 테스트 케이스 /// public class BasicPathTestCase { public string StartNodeId { get; set; } public string TargetNodeId { get; set; } public AgvDirection CurrentDirection { get; set; } public string Description { get; set; } public bool ExpectedSuccess { get; set; } public BasicPathTestCase(string startNodeId, string targetNodeId, AgvDirection currentDirection, string description, bool expectedSuccess = true) { StartNodeId = startNodeId; TargetNodeId = targetNodeId; CurrentDirection = currentDirection; Description = description; ExpectedSuccess = expectedSuccess; } } /// /// 방향 전환 테스트 케이스 /// public class DirectionChangeTestCase { public string StartNodeId { get; set; } public string TargetNodeId { get; set; } public AgvDirection CurrentDirection { get; set; } public AgvDirection RequiredDirection { get; set; } public string Description { get; set; } public bool ExpectedSuccess { get; set; } public List ExpectedPath { get; set; } public DirectionChangeTestCase(string startNodeId, string targetNodeId, AgvDirection currentDirection, AgvDirection requiredDirection, string description, bool expectedSuccess = true, List expectedPath = null) { StartNodeId = startNodeId; TargetNodeId = targetNodeId; CurrentDirection = currentDirection; RequiredDirection = requiredDirection; Description = description; ExpectedSuccess = expectedSuccess; ExpectedPath = expectedPath ?? new List(); } } /// /// 이동 기반 테스트 케이스 (이전 위치 → 현재 위치 → 목표 위치) /// public class MovementBasedTestCase { public string PreviousRfid { get; set; } public string CurrentRfid { get; set; } public string TargetRfid { get; set; } public AgvDirection ExpectedDirection { get; set; } public string Description { get; set; } public bool ExpectedSuccess { get; set; } public List ExpectedRfidPath { get; set; } public MovementBasedTestCase(string previousRfid, string currentRfid, string targetRfid, AgvDirection expectedDirection, string description, bool expectedSuccess = true, List expectedRfidPath = null) { PreviousRfid = previousRfid; CurrentRfid = currentRfid; TargetRfid = targetRfid; ExpectedDirection = expectedDirection; Description = description; ExpectedSuccess = expectedSuccess; ExpectedRfidPath = expectedRfidPath ?? new List(); } } /// /// 기본 경로 탐색 테스트 케이스 목록 (RFID 기반으로 수정) /// RFID 매핑: 001→N001, 005→N011, 037→N015, 041→존재하지않음 /// public static List GetBasicPathTestCases() { return new List { // 단순 직선 경로 new BasicPathTestCase("N001", "N002", AgvDirection.Forward, "단순 인접 노드 이동"), new BasicPathTestCase("N001", "N003", AgvDirection.Forward, "단거리 직선 경로"), // 중거리 경로 new BasicPathTestCase("N001", "N010", AgvDirection.Forward, "중거리 경로 탐색"), new BasicPathTestCase("N011", "N019", AgvDirection.Backward, "RFID 005→015: 후진 상태에서 중거리 이동"), // 갈림길을 포함한 경로 new BasicPathTestCase("N001", "N020", AgvDirection.Forward, "갈림길 포함 경로"), new BasicPathTestCase("N010", "N030", AgvDirection.Forward, "복잡한 갈림길 경로"), // RFID 기반 실제 경로 (PATHSCENARIO.md 기반) - 올바른 NodeID 매핑 사용 new BasicPathTestCase("N013", "N019", AgvDirection.Forward, "RFID 007→015: 직진 경로"), new BasicPathTestCase("N013", "N026", AgvDirection.Forward, "RFID 007→019: 충전기 경로"), new BasicPathTestCase("N013", "N001", AgvDirection.Forward, "RFID 007→001: 장비 경로"), // 갈림길 테스트 (RFID 005는 N011 갈림길) new BasicPathTestCase("N004", "N019", AgvDirection.Forward, "RFID 004→015: N011 갈림길 통과"), new BasicPathTestCase("N012", "N023", AgvDirection.Backward, "RFID 012→016: 갈림길 역방향"), }; } /// /// 방향 전환 테스트 케이스 목록 (PATHSCENARIO.md RFID 기반) /// RFID → NodeID 매핑: 005→N011, 037→N028, 007→N013, 015→N019, 001→N001, 004→N004 /// public static List GetDirectionChangeTestCases() { return new List { // PATHSCENARIO.md Case 1: AGV가 전진방향으로 008→007 이동 후 // Q1: 007→015 (충전기, 전진 도킹) - 방향전환 불필요 new DirectionChangeTestCase("N013", "N019", AgvDirection.Forward, AgvDirection.Forward, "Q1: RFID 007→015 (충전기, 전진 도킹) - 방향전환 불필요", true, new List { "N013", "N012", "N011", "N004", "N022", "N023", "N024", "N019" }), // Q2: 007→019 (충전기, 전진 도킹) - 방향전환 불필요 new DirectionChangeTestCase("N013", "N026", AgvDirection.Forward, AgvDirection.Forward, "Q2: RFID 007→019 (충전기, 전진 도킹) - 방향전환 불필요", true, new List { "N013", "N012", "N011", "N004", "N022", "N023", "N024", "N025", "N026" }), // Q3: 007→001 (장비, 후진 도킹) - 005 갈림길에서 037 우회 new DirectionChangeTestCase("N013", "N001", AgvDirection.Forward, AgvDirection.Backward, "Q3: RFID 007→001 (장비, 후진 도킹) - 005 갈림길에서 037 우회", true, new List { "N013", "N012", "N011", "N028", "N011", "N004", "N003", "N002", "N001" }), // Q4: 007→011 (장비, 후진 도킹) - 005 갈림길에서 037 우회 // RFID 011 → N010 new DirectionChangeTestCase("N013", "N010", AgvDirection.Forward, AgvDirection.Backward, "Q4: RFID 007→011 (장비, 후진 도킹) - 005 갈림길에서 037 우회", true, new List { "N013", "N012", "N011", "N028", "N011", "N004", "N031", "N008", "N009", "N010" }), // Case 2: AGV가 후진방향으로 008→007 이동 후 // Q7: 007→015 (충전기, 전진 도킹) - 005에서 037 우회 후 전환 new DirectionChangeTestCase("N013", "N019", AgvDirection.Backward, AgvDirection.Forward, "Q7: RFID 007→015 (충전기, 전진 도킹) - 005에서 037 우회 후 전환", true, new List { "N013", "N012", "N011", "N028", "N011", "N004", "N022", "N023", "N024", "N019" }), // 실제 맵 기반 간단한 테스트들 // N004 갈림길 활용 (N003, N022, N031 연결) new DirectionChangeTestCase("N003", "N022", AgvDirection.Forward, AgvDirection.Backward, "N004 갈림길: N003→N022 (전진→후진 전환)", true, new List { "N003", "N004", "N022" }), new DirectionChangeTestCase("N003", "N031", AgvDirection.Forward, AgvDirection.Backward, "N004 갈림길: N003→N031 (전진→후진 전환)", true, new List { "N003", "N004", "N031" }), // N011 갈림길 활용 (N012, N004, N015 연결) - RFID 005는 N011 new DirectionChangeTestCase("N012", "N019", AgvDirection.Forward, AgvDirection.Backward, "N011 갈림길 (RFID 005): N012→N019 (전진→후진 전환)", true, new List { "N012", "N011", "N004", "N022", "N023", "N024", "N019" }), // 방향 전환이 필요 없는 경우 (같은 방향) new DirectionChangeTestCase("N013", "N019", AgvDirection.Forward, AgvDirection.Forward, "방향 전환 불필요: RFID 007→015 (전진→전진)", true, new List { "N013", "N012", "N011", "N004", "N022", "N023", "N024", "N019" }), new DirectionChangeTestCase("N012", "N019", AgvDirection.Backward, AgvDirection.Backward, "방향 전환 불필요: N012→N019 (후진→후진)", true, new List { "N012", "N011", "N004", "N022", "N023", "N024", "N019" }) }; } /// /// 특정 문제 시나리오 테스트 케이스 (디버깅용) /// public static List GetProblematicTestCases() { return new List { // 사용자가 직접 보고한 문제들 (RFID 매핑 적용) new DirectionChangeTestCase("N004", "N015", AgvDirection.Forward, AgvDirection.Backward, "🚨 사용자 보고: RFID 004→037(N015) 되돌아가기 발생"), new DirectionChangeTestCase("N012", "N015", AgvDirection.Backward, AgvDirection.Backward, "🚨 사용자 보고: RFID 012→037(N015) 비효율적 경로"), new DirectionChangeTestCase("N012", "N023", AgvDirection.Backward, AgvDirection.Forward, "🚨 사용자 보고: RFID 012→016(N023) 되돌아가기 발생"), }; } /// /// 스트레스 테스트용 대량 케이스 생성 /// public static List GenerateStressTestCases(List allNodeIds, int count = 50) { var testCases = new List(); var random = new System.Random(42); // 고정 시드로 재현 가능한 테스트 for (int i = 0; i < count; i++) { var startNodeId = allNodeIds[random.Next(allNodeIds.Count)]; var targetNodeId = allNodeIds[random.Next(allNodeIds.Count)]; var direction = random.Next(2) == 0 ? AgvDirection.Forward : AgvDirection.Backward; if (startNodeId != targetNodeId) { testCases.Add(new BasicPathTestCase( startNodeId, targetNodeId, direction, $"스트레스 테스트 #{i + 1}" )); } } return testCases; } /// /// 이동 기반 테스트 케이스 목록 (실제 AGV 이동 시나리오) /// public static List GetMovementBasedTestCases() { return new List { // 핵심 시나리오: 033→032 후진 이동 중인 AGV가 001로 가는 경우 new MovementBasedTestCase("033", "032", "001", AgvDirection.Backward, "🎯 핵심 시나리오: RFID 033→032 후진 이동 AGV가 001(장비) 목적지", true, new List { "032", "031", "030", "...", "001" }), // 다양한 이동 패턴 테스트 new MovementBasedTestCase("001", "002", "015", AgvDirection.Forward, "RFID 001→002 전진 이동 AGV가 015(충전기) 목적지", true, new List { "002", "003", "004", "012", "013", "014", "015" }), new MovementBasedTestCase("015", "014", "001", AgvDirection.Backward, "RFID 015→014 후진 이동 AGV가 001(장비) 목적지", true, new List { "014", "013", "012", "004", "003", "002", "001" }), new MovementBasedTestCase("004", "005", "019", AgvDirection.Forward, "RFID 004→005 전진 이동(갈림길 진입) AGV가 019(충전기) 목적지", true, new List { "005", "037", "036", "035", "034", "018", "019" }), new MovementBasedTestCase("005", "004", "037", AgvDirection.Backward, "RFID 005→004 후진 이동(갈림길 이탈) AGV가 037 목적지", true, new List { "004", "005", "037" }), // 🚨 AGV 물리적 제약사항 테스트: 갈림길 즉시 방향전환 금지 new MovementBasedTestCase("018", "019", "015", AgvDirection.Forward, "🚨 물리적 제약: RFID 018→019 전진 이동 AGV가 015(충전기) 목적지 - 012 갈림길 즉시 방향전환 금지", true, new List { "019", "018", "017", "016", "012", "004", "012", "013", "014", "015" }), new MovementBasedTestCase("016", "012", "013", AgvDirection.Backward, "🚨 물리적 제약: RFID 016→012 후진 이동 AGV가 013 목적지 - 012에서 즉시 013 전진 금지", true, new List { "012", "004", "012", "013" }), // 🔥 핵심 시나리오: AGV 물리적 방향과 갈림길 방향전환 new MovementBasedTestCase("032", "031", "008", AgvDirection.Backward, "🔥 핵심 시나리오: RFID 032→031 후진 이동 AGV가 008 목적지 - 031→005(전진)→004(좌회전)→008(후진)", true, new List { "031", "032", "033", "034", "035", "036", "037", "005", "004", "012", "006", "007", "008" }), // 방향 전환이 필요한 시나리오 new MovementBasedTestCase("032", "033", "001", AgvDirection.Forward, "RFID 032→033 전진 이동 AGV가 001(후진 도킹) 목적지 - 방향 전환 필요", true, new List { "033", "034", "018", "017", "016", "037", "005", "004", "003", "002", "001" }), new MovementBasedTestCase("007", "006", "015", AgvDirection.Backward, "RFID 007→006 후진 이동 AGV가 015(전진 도킹) 목적지 - 방향 전환 필요", true, new List { "006", "005", "037", "005", "004", "012", "013", "014", "015" }), }; } } }