@@ -34,7 +34,6 @@ import (
34
34
"github.com/stretchr/testify/require"
35
35
"go.uber.org/goleak"
36
36
"golang.org/x/crypto/ssh"
37
- "golang.org/x/exp/maps"
38
37
"golang.org/x/xerrors"
39
38
"tailscale.com/net/speedtest"
40
39
"tailscale.com/tailcfg"
@@ -882,16 +881,15 @@ func TestAgent_StartupScript(t *testing.T) {
882
881
t .Run ("Success" , func (t * testing.T ) {
883
882
t .Parallel ()
884
883
logger := slogtest .Make (t , nil ).Leveled (slog .LevelDebug )
885
- client := & client {
886
- t : t ,
887
- agentID : uuid .New (),
888
- manifest : agentsdk.Manifest {
884
+ client := agenttest .NewClient (t ,
885
+ uuid .New (),
886
+ agentsdk.Manifest {
889
887
StartupScript : command ,
890
888
DERPMap : & tailcfg.DERPMap {},
891
889
},
892
- statsChan : make (chan * agentsdk.Stats ),
893
- coordinator : tailnet .NewCoordinator (logger ),
894
- }
890
+ make (chan * agentsdk.Stats ),
891
+ tailnet .NewCoordinator (logger ),
892
+ )
895
893
closer := agent .New (agent.Options {
896
894
Client : client ,
897
895
Filesystem : afero .NewMemMapFs (),
@@ -902,36 +900,35 @@ func TestAgent_StartupScript(t *testing.T) {
902
900
_ = closer .Close ()
903
901
})
904
902
assert .Eventually (t , func () bool {
905
- got := client .getLifecycleStates ()
903
+ got := client .GetLifecycleStates ()
906
904
return len (got ) > 0 && got [len (got )- 1 ] == codersdk .WorkspaceAgentLifecycleReady
907
905
}, testutil .WaitShort , testutil .IntervalMedium )
908
906
909
- require .Len (t , client .getStartupLogs (), 1 )
910
- require .Equal (t , output , client .getStartupLogs ()[0 ].Output )
907
+ require .Len (t , client .GetStartupLogs (), 1 )
908
+ require .Equal (t , output , client .GetStartupLogs ()[0 ].Output )
911
909
})
912
910
// This ensures that even when coderd sends back that the startup
913
911
// script has written too many lines it will still succeed!
914
912
t .Run ("OverflowsAndSkips" , func (t * testing.T ) {
915
913
t .Parallel ()
916
914
logger := slogtest .Make (t , nil ).Leveled (slog .LevelDebug )
917
- client := & client {
918
- t : t ,
919
- agentID : uuid .New (),
920
- manifest : agentsdk.Manifest {
915
+ client := agenttest .NewClient (t ,
916
+ uuid .New (),
917
+ agentsdk.Manifest {
921
918
StartupScript : command ,
922
919
DERPMap : & tailcfg.DERPMap {},
923
920
},
924
- patchWorkspaceLogs : func () error {
925
- resp := httptest . NewRecorder ()
926
- httpapi . Write ( context . Background (), resp , http . StatusRequestEntityTooLarge , codersdk. Response {
927
- Message : "Too many lines!" ,
928
- } )
929
- res := resp . Result ()
930
- defer res . Body . Close ()
931
- return codersdk . ReadBodyAsError ( res )
932
- },
933
- statsChan : make ( chan * agentsdk. Stats ),
934
- coordinator : tailnet . NewCoordinator ( logger ),
921
+ make ( chan * agentsdk. Stats , 100 ),
922
+ tailnet . NewCoordinator ( logger ),
923
+ )
924
+ client . PatchWorkspaceLogs = func () error {
925
+ resp := httptest . NewRecorder ( )
926
+ httpapi . Write ( context . Background (), resp , http . StatusRequestEntityTooLarge , codersdk. Response {
927
+ Message : "Too many lines!" ,
928
+ } )
929
+ res := resp . Result ()
930
+ defer res . Body . Close ()
931
+ return codersdk . ReadBodyAsError ( res )
935
932
}
936
933
closer := agent .New (agent.Options {
937
934
Client : client ,
@@ -943,10 +940,10 @@ func TestAgent_StartupScript(t *testing.T) {
943
940
_ = closer .Close ()
944
941
})
945
942
assert .Eventually (t , func () bool {
946
- got := client .getLifecycleStates ()
943
+ got := client .GetLifecycleStates ()
947
944
return len (got ) > 0 && got [len (got )- 1 ] == codersdk .WorkspaceAgentLifecycleReady
948
945
}, testutil .WaitShort , testutil .IntervalMedium )
949
- require .Len (t , client .getStartupLogs (), 0 )
946
+ require .Len (t , client .GetStartupLogs (), 0 )
950
947
})
951
948
}
952
949
@@ -1283,17 +1280,17 @@ func TestAgent_Lifecycle(t *testing.T) {
1283
1280
logger := slogtest .Make (t , nil ).Leveled (slog .LevelDebug )
1284
1281
expected := "this-is-shutdown"
1285
1282
derpMap , _ := tailnettest .RunDERPAndSTUN (t )
1286
- client := & client {
1287
- t : t ,
1288
- agentID : uuid .New (),
1289
- manifest : agentsdk.Manifest {
1283
+
1284
+ client := agenttest . NewClient ( t ,
1285
+ uuid .New (),
1286
+ agentsdk.Manifest {
1290
1287
DERPMap : derpMap ,
1291
1288
StartupScript : "echo 1" ,
1292
1289
ShutdownScript : "echo " + expected ,
1293
1290
},
1294
- statsChan : make (chan * agentsdk.Stats ),
1295
- coordinator : tailnet .NewCoordinator (logger ),
1296
- }
1291
+ make (chan * agentsdk.Stats , 100 ),
1292
+ tailnet .NewCoordinator (logger ),
1293
+ )
1297
1294
1298
1295
fs := afero .NewMemMapFs ()
1299
1296
agent := agent .New (agent.Options {
@@ -1554,17 +1551,16 @@ func TestAgent_Reconnect(t *testing.T) {
1554
1551
defer coordinator .Close ()
1555
1552
1556
1553
agentID := uuid .New ()
1557
- statsCh := make (chan * agentsdk.Stats )
1554
+ statsCh := make (chan * agentsdk.Stats , 50 )
1558
1555
derpMap , _ := tailnettest .RunDERPAndSTUN (t )
1559
- client := & client {
1560
- t : t ,
1561
- agentID : agentID ,
1562
- manifest : agentsdk.Manifest {
1556
+ client := agenttest .NewClient (t ,
1557
+ agentID ,
1558
+ agentsdk.Manifest {
1563
1559
DERPMap : derpMap ,
1564
1560
},
1565
- statsChan : statsCh ,
1566
- coordinator : coordinator ,
1567
- }
1561
+ statsCh ,
1562
+ coordinator ,
1563
+ )
1568
1564
initialized := atomic.Int32 {}
1569
1565
closer := agent .New (agent.Options {
1570
1566
ExchangeToken : func (ctx context.Context ) (string , error ) {
@@ -1579,7 +1575,7 @@ func TestAgent_Reconnect(t *testing.T) {
1579
1575
require .Eventually (t , func () bool {
1580
1576
return coordinator .Node (agentID ) != nil
1581
1577
}, testutil .WaitShort , testutil .IntervalFast )
1582
- client .lastWorkspaceAgent ()
1578
+ client .LastWorkspaceAgent ()
1583
1579
require .Eventually (t , func () bool {
1584
1580
return initialized .Load () == 2
1585
1581
}, testutil .WaitShort , testutil .IntervalFast )
@@ -1591,16 +1587,15 @@ func TestAgent_WriteVSCodeConfigs(t *testing.T) {
1591
1587
coordinator := tailnet .NewCoordinator (logger )
1592
1588
defer coordinator .Close ()
1593
1589
1594
- client := & client {
1595
- t : t ,
1596
- agentID : uuid .New (),
1597
- manifest : agentsdk.Manifest {
1590
+ client := agenttest .NewClient (t ,
1591
+ uuid .New (),
1592
+ agentsdk.Manifest {
1598
1593
GitAuthConfigs : 1 ,
1599
1594
DERPMap : & tailcfg.DERPMap {},
1600
1595
},
1601
- statsChan : make (chan * agentsdk.Stats ),
1602
- coordinator : coordinator ,
1603
- }
1596
+ make (chan * agentsdk.Stats , 50 ),
1597
+ coordinator ,
1598
+ )
1604
1599
filesystem := afero .NewMemMapFs ()
1605
1600
closer := agent .New (agent.Options {
1606
1601
ExchangeToken : func (ctx context.Context ) (string , error ) {
@@ -1685,12 +1680,6 @@ func setupSSHSession(t *testing.T, options agentsdk.Manifest) *ssh.Session {
1685
1680
return session
1686
1681
}
1687
1682
1688
- type closeFunc func () error
1689
-
1690
- func (c closeFunc ) Close () error {
1691
- return c ()
1692
- }
1693
-
1694
1683
func setupAgent (t * testing.T , metadata agentsdk.Manifest , ptyTimeout time.Duration , opts ... func (agent.Options ) agent.Options ) (
1695
1684
* codersdk.WorkspaceAgentConn ,
1696
1685
* agenttest.Client ,
@@ -1803,136 +1792,6 @@ func assertWritePayload(t *testing.T, w io.Writer, payload []byte) {
1803
1792
assert .Equal (t , len (payload ), n , "payload length does not match" )
1804
1793
}
1805
1794
1806
- type client struct {
1807
- t * testing.T
1808
- agentID uuid.UUID
1809
- manifest agentsdk.Manifest
1810
- metadata map [string ]agentsdk.PostMetadataRequest
1811
- statsChan chan * agentsdk.Stats
1812
- coordinator tailnet.Coordinator
1813
- lastWorkspaceAgent func ()
1814
- patchWorkspaceLogs func () error
1815
-
1816
- mu sync.Mutex // Protects following.
1817
- lifecycleStates []codersdk.WorkspaceAgentLifecycle
1818
- startup agentsdk.PostStartupRequest
1819
- logs []agentsdk.StartupLog
1820
- }
1821
-
1822
- func (c * client ) Manifest (_ context.Context ) (agentsdk.Manifest , error ) {
1823
- return c .manifest , nil
1824
- }
1825
-
1826
- func (c * client ) Listen (_ context.Context ) (net.Conn , error ) {
1827
- clientConn , serverConn := net .Pipe ()
1828
- closed := make (chan struct {})
1829
- c .lastWorkspaceAgent = func () {
1830
- _ = serverConn .Close ()
1831
- _ = clientConn .Close ()
1832
- <- closed
1833
- }
1834
- c .t .Cleanup (c .lastWorkspaceAgent )
1835
- go func () {
1836
- _ = c .coordinator .ServeAgent (serverConn , c .agentID , "" )
1837
- close (closed )
1838
- }()
1839
- return clientConn , nil
1840
- }
1841
-
1842
- func (c * client ) ReportStats (ctx context.Context , _ slog.Logger , statsChan <- chan * agentsdk.Stats , setInterval func (time.Duration )) (io.Closer , error ) {
1843
- doneCh := make (chan struct {})
1844
- ctx , cancel := context .WithCancel (ctx )
1845
-
1846
- go func () {
1847
- defer close (doneCh )
1848
-
1849
- setInterval (500 * time .Millisecond )
1850
- for {
1851
- select {
1852
- case <- ctx .Done ():
1853
- return
1854
- case stat := <- statsChan :
1855
- select {
1856
- case c .statsChan <- stat :
1857
- case <- ctx .Done ():
1858
- return
1859
- default :
1860
- // We don't want to send old stats.
1861
- continue
1862
- }
1863
- }
1864
- }
1865
- }()
1866
- return closeFunc (func () error {
1867
- cancel ()
1868
- <- doneCh
1869
- close (c .statsChan )
1870
- return nil
1871
- }), nil
1872
- }
1873
-
1874
- func (c * client ) getLifecycleStates () []codersdk.WorkspaceAgentLifecycle {
1875
- c .mu .Lock ()
1876
- defer c .mu .Unlock ()
1877
- return c .lifecycleStates
1878
- }
1879
-
1880
- func (c * client ) PostLifecycle (_ context.Context , req agentsdk.PostLifecycleRequest ) error {
1881
- c .mu .Lock ()
1882
- defer c .mu .Unlock ()
1883
- c .lifecycleStates = append (c .lifecycleStates , req .State )
1884
- return nil
1885
- }
1886
-
1887
- func (* client ) PostAppHealth (_ context.Context , _ agentsdk.PostAppHealthsRequest ) error {
1888
- return nil
1889
- }
1890
-
1891
- func (c * client ) getStartup () agentsdk.PostStartupRequest {
1892
- c .mu .Lock ()
1893
- defer c .mu .Unlock ()
1894
- return c .startup
1895
- }
1896
-
1897
- func (c * client ) getMetadata () map [string ]agentsdk.PostMetadataRequest {
1898
- c .mu .Lock ()
1899
- defer c .mu .Unlock ()
1900
- return maps .Clone (c .metadata )
1901
- }
1902
-
1903
- func (c * client ) PostMetadata (_ context.Context , key string , req agentsdk.PostMetadataRequest ) error {
1904
- c .mu .Lock ()
1905
- defer c .mu .Unlock ()
1906
- if c .metadata == nil {
1907
- c .metadata = make (map [string ]agentsdk.PostMetadataRequest )
1908
- }
1909
- c .metadata [key ] = req
1910
- return nil
1911
- }
1912
-
1913
- func (c * client ) PostStartup (_ context.Context , startup agentsdk.PostStartupRequest ) error {
1914
- c .mu .Lock ()
1915
- defer c .mu .Unlock ()
1916
- c .startup = startup
1917
- return nil
1918
- }
1919
-
1920
- func (c * client ) getStartupLogs () []agentsdk.StartupLog {
1921
- c .mu .Lock ()
1922
- defer c .mu .Unlock ()
1923
- return c .logs
1924
- }
1925
-
1926
- func (c * client ) PatchStartupLogs (_ context.Context , logs agentsdk.PatchStartupLogs ) error {
1927
- c .mu .Lock ()
1928
- defer c .mu .Unlock ()
1929
- if c .patchWorkspaceLogs != nil {
1930
- return c .patchWorkspaceLogs ()
1931
- }
1932
- c .logs = append (c .logs , logs .Logs ... )
1933
- return nil
1934
- }
1935
-
1936
1795
// tempDirUnixSocket returns a temporary directory that can safely hold unix
1937
1796
// sockets (probably).
1938
1797
//
0 commit comments