@@ -10,6 +10,7 @@ import (
10
10
"net/http"
11
11
"os"
12
12
"path/filepath"
13
+ "strings"
13
14
"sync"
14
15
"time"
15
16
)
@@ -548,8 +549,120 @@ func (manager *TestManager) EndTest(suiteID TestSuiteID, testID TestID, result *
548
549
result .LogOffsets = offsets
549
550
}
550
551
552
+ // Auto-register shared clients with this test if they weren't already registered
553
+ // but only if the test name contains the client name (for backwards compatibility)
554
+ if testSuite .SharedClients != nil && (testCase .ClientInfo == nil || len (testCase .ClientInfo ) == 0 ) {
555
+ // Initialize client info map if needed
556
+ if testCase .ClientInfo == nil {
557
+ testCase .ClientInfo = make (map [string ]* ClientInfo )
558
+ }
559
+
560
+ // First, group shared clients by name to identify if there are multiple of the same type
561
+ clientsByName := make (map [string ][]struct {
562
+ ID string
563
+ Info * ClientInfo
564
+ })
565
+ for clientID , clientInfo := range testSuite .SharedClients {
566
+ clientsByName [clientInfo .Name ] = append (clientsByName [clientInfo .Name ],
567
+ struct {
568
+ ID string
569
+ Info * ClientInfo
570
+ }{ID : clientID , Info : clientInfo })
571
+ }
572
+
573
+ // Now check if the test name contains a client name and there's exactly one of that type
574
+ for clientName , clientList := range clientsByName {
575
+ if strings .Contains (testCase .Name , clientName ) && len (clientList ) == 1 {
576
+ // Safe to auto-register as there's only one client of this type
577
+ clientID := clientList [0 ].ID
578
+ clientInfo := clientList [0 ].Info
579
+
580
+ slog .Debug ("Auto-registering shared client with test" ,
581
+ "testID" , testID ,
582
+ "clientID" , clientID ,
583
+ "clientName" , clientInfo .Name ,
584
+ "testName" , testCase .Name )
585
+
586
+ testCase .ClientInfo [clientID ] = & ClientInfo {
587
+ ID : clientInfo .ID ,
588
+ IP : clientInfo .IP ,
589
+ Name : clientInfo .Name ,
590
+ InstantiatedAt : clientInfo .InstantiatedAt ,
591
+ LogFile : clientInfo .LogFile ,
592
+ IsShared : true ,
593
+ SharedClientID : clientID ,
594
+ LogPosition : clientInfo .LogPosition ,
595
+ SuiteID : suiteID ,
596
+ }
597
+ } else if strings .Contains (testCase .Name , clientName ) && len (clientList ) > 1 {
598
+ // When there are multiple clients of the same type, we can try to find the right one by creation time
599
+ // Newer tests generally use newer clients, so find the most recently created client
600
+ var mostRecentClient struct {
601
+ ID string
602
+ Info * ClientInfo
603
+ }
604
+ var mostRecentTime time.Time
605
+
606
+ for _ , client := range clientList {
607
+ if mostRecentTime .IsZero () || client .Info .InstantiatedAt .After (mostRecentTime ) {
608
+ mostRecentTime = client .Info .InstantiatedAt
609
+ mostRecentClient = client
610
+ }
611
+ }
612
+
613
+ if ! mostRecentTime .IsZero () {
614
+ clientID := mostRecentClient .ID
615
+ clientInfo := mostRecentClient .Info
616
+
617
+ slog .Debug ("Auto-registering most recent shared client with test" ,
618
+ "testID" , testID ,
619
+ "clientID" , clientID ,
620
+ "clientName" , clientInfo .Name ,
621
+ "instantiatedAt" , clientInfo .InstantiatedAt ,
622
+ "testName" , testCase .Name )
623
+
624
+ testCase .ClientInfo [clientID ] = & ClientInfo {
625
+ ID : clientInfo .ID ,
626
+ IP : clientInfo .IP ,
627
+ Name : clientInfo .Name ,
628
+ InstantiatedAt : clientInfo .InstantiatedAt ,
629
+ LogFile : clientInfo .LogFile ,
630
+ IsShared : true ,
631
+ SharedClientID : clientID ,
632
+ LogPosition : clientInfo .LogPosition ,
633
+ SuiteID : suiteID ,
634
+ }
635
+ } else {
636
+ // Log a warning if we couldn't determine which client to use
637
+ slog .Debug ("Skipping auto-registration - multiple clients of same type" ,
638
+ "testID" , testID ,
639
+ "clientName" , clientName ,
640
+ "count" , len (clientList ),
641
+ "testName" , testCase .Name )
642
+ }
643
+ }
644
+ }
645
+ }
646
+
551
647
// Process client logs for shared clients
552
648
result .ClientLogs = make (map [string ]* ClientLogSegment )
649
+
650
+ // Log the number of clients in the test case for debugging
651
+ if len (testCase .ClientInfo ) > 0 {
652
+ slog .Debug ("Processing client logs" ,
653
+ "testID" , testID ,
654
+ "clientCount" , len (testCase .ClientInfo ),
655
+ "clientTypes" , fmt .Sprintf ("%v" , func () []string {
656
+ types := make ([]string , 0 , len (testCase .ClientInfo ))
657
+ for _ , ci := range testCase .ClientInfo {
658
+ types = append (types , ci .Name )
659
+ }
660
+ return types
661
+ }()))
662
+ } else {
663
+ slog .Debug ("No clients registered with test" , "testID" , testID )
664
+ }
665
+
553
666
for nodeID , clientInfo := range testCase .ClientInfo {
554
667
if clientInfo .IsShared {
555
668
// Get current log position
@@ -624,7 +737,15 @@ func (manager *TestManager) getClientCurrentLogPosition(clientInfo *ClientInfo)
624
737
return 0 , fmt .Errorf ("no log file for client %s" , clientInfo .ID )
625
738
}
626
739
627
- fileInfo , err := os .Stat (clientInfo .LogFile )
740
+ // Fix the log file path by converting it to an absolute path if it's not already
741
+ logFilePath := clientInfo .LogFile
742
+ if ! filepath .IsAbs (logFilePath ) {
743
+ logFilePath = filepath .Join (manager .config .LogDir , logFilePath )
744
+ }
745
+
746
+ slog .Debug ("Getting client log position" , "client" , clientInfo .ID , "logFile" , clientInfo .LogFile , "fullPath" , logFilePath )
747
+
748
+ fileInfo , err := os .Stat (logFilePath )
628
749
if err != nil {
629
750
return 0 , err
630
751
}
@@ -675,6 +796,16 @@ func (manager *TestManager) RegisterNode(testID TestID, nodeID string, nodeInfo
675
796
nodeInfo .LogPosition = 0
676
797
}
677
798
799
+ // If this is a shared client, log detailed information for debugging
800
+ if nodeInfo .IsShared {
801
+ slog .Debug ("Registering shared client with test" ,
802
+ "testID" , testID ,
803
+ "nodeID" , nodeID ,
804
+ "clientName" , nodeInfo .Name ,
805
+ "logPosition" , nodeInfo .LogPosition ,
806
+ "logFile" , nodeInfo .LogFile )
807
+ }
808
+
678
809
testCase .ClientInfo [nodeID ] = nodeInfo
679
810
return nil
680
811
}
0 commit comments