@@ -70,6 +70,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
70
70
71
71
t .Run ("SignedTokenQueryParameter" ,func (t * testing.T ) {
72
72
t .Parallel ()
73
+
73
74
if appHostIsPrimary {
74
75
t .Skip ("Tickets are not used for terminal requests on the primary." )
75
76
}
@@ -101,8 +102,6 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
101
102
t .Run ("WorkspaceAppsProxyPath" ,func (t * testing.T ) {
102
103
t .Parallel ()
103
104
104
- appDetails := setupProxyTest (t ,nil )
105
-
106
105
t .Run ("Disabled" ,func (t * testing.T ) {
107
106
t .Parallel ()
108
107
@@ -132,6 +131,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
132
131
t .Skip ("This test only applies when testing apps on the primary." )
133
132
}
134
133
134
+ appDetails := setupProxyTest (t ,nil )
135
135
unauthedClient := appDetails .AppClient (t )
136
136
unauthedClient .SetSessionToken ("" )
137
137
@@ -148,7 +148,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
148
148
require .NoError (t ,err )
149
149
require .True (t ,loc .Query ().Has ("message" ))
150
150
require .True (t ,loc .Query ().Has ("redirect" ))
151
- assertWorkspaceLastUsedAtUpdated (t ,appDetails )
151
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
152
152
})
153
153
154
154
t .Run ("LoginWithoutAuthOnProxy" ,func (t * testing.T ) {
@@ -158,6 +158,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
158
158
t .Skip ("This test only applies when testing apps on workspace proxies." )
159
159
}
160
160
161
+ appDetails := setupProxyTest (t ,nil )
161
162
unauthedClient := appDetails .AppClient (t )
162
163
unauthedClient .SetSessionToken ("" )
163
164
@@ -186,12 +187,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
186
187
// request is getting stripped.
187
188
require .Equal (t ,u .Path ,redirectURI .Path + "/" )
188
189
require .Equal (t ,u .RawQuery ,redirectURI .RawQuery )
189
- assertWorkspaceLastUsedAtUpdated (t ,appDetails )
190
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
190
191
})
191
192
192
193
t .Run ("NoAccessShould404" ,func (t * testing.T ) {
193
194
t .Parallel ()
194
195
196
+ appDetails := setupProxyTest (t ,nil )
195
197
userClient ,_ := coderdtest .CreateAnotherUser (t ,appDetails .SDKClient ,appDetails .FirstUser .OrganizationID ,rbac .RoleMember ())
196
198
userAppClient := appDetails .AppClient (t )
197
199
userAppClient .SetSessionToken (userClient .SessionToken ())
@@ -210,6 +212,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
210
212
t .Run ("RedirectsWithSlash" ,func (t * testing.T ) {
211
213
t .Parallel ()
212
214
215
+ appDetails := setupProxyTest (t ,nil )
213
216
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
214
217
defer cancel ()
215
218
@@ -226,6 +229,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
226
229
t .Run ("RedirectsWithQuery" ,func (t * testing.T ) {
227
230
t .Parallel ()
228
231
232
+ appDetails := setupProxyTest (t ,nil )
229
233
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
230
234
defer cancel ()
231
235
@@ -245,6 +249,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
245
249
t .Run ("Proxies" ,func (t * testing.T ) {
246
250
t .Parallel ()
247
251
252
+ appDetails := setupProxyTest (t ,nil )
248
253
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
249
254
defer cancel ()
250
255
@@ -333,6 +338,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
333
338
t .Run ("BlocksMe" ,func (t * testing.T ) {
334
339
t .Parallel ()
335
340
341
+ appDetails := setupProxyTest (t ,nil )
336
342
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
337
343
defer cancel ()
338
344
@@ -347,13 +353,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
347
353
body ,err := io .ReadAll (resp .Body )
348
354
require .NoError (t ,err )
349
355
require .Contains (t ,string (body ),"must be accessed with the full username, not @me" )
350
- // TODO(cian): A blocked request should not count as workspace usage.
351
- // assertWorkspaceLastUsedAtNotUpdated(t, appDetails.AppClient(t), appDetails)
356
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
352
357
})
353
358
354
359
t .Run ("ForwardsIP" ,func (t * testing.T ) {
355
360
t .Parallel ()
356
361
362
+ appDetails := setupProxyTest (t ,nil )
357
363
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
358
364
defer cancel ()
359
365
@@ -373,6 +379,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
373
379
t .Run ("ProxyError" ,func (t * testing.T ) {
374
380
t .Parallel ()
375
381
382
+ appDetails := setupProxyTest (t ,nil )
376
383
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
377
384
defer cancel ()
378
385
@@ -388,6 +395,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
388
395
t .Run ("NoProxyPort" ,func (t * testing.T ) {
389
396
t .Parallel ()
390
397
398
+ appDetails := setupProxyTest (t ,nil )
391
399
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
392
400
defer cancel ()
393
401
@@ -397,7 +405,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
397
405
// TODO(@deansheather): This should be 400. There's a todo in the
398
406
// resolve request code to fix this.
399
407
require .Equal (t ,http .StatusInternalServerError ,resp .StatusCode )
400
- assertWorkspaceLastUsedAtUpdated (t ,appDetails )
408
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
401
409
})
402
410
})
403
411
@@ -636,6 +644,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
636
644
_ = resp .Body .Close ()
637
645
require .Equal (t ,http .StatusOK ,resp .StatusCode )
638
646
require .Equal (t ,resp .Header .Get ("X-Got-Host" ),u .Host )
647
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
639
648
})
640
649
641
650
t .Run ("WorkspaceAppsProxySubdomainHostnamePrefix/Different" ,func (t * testing.T ) {
@@ -686,6 +695,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
686
695
require .NoError (t ,err )
687
696
_ = resp .Body .Close ()
688
697
require .NotEqual (t ,http .StatusOK ,resp .StatusCode )
698
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
689
699
})
690
700
691
701
// This test ensures that the subdomain handler does nothing if
@@ -754,11 +764,10 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
754
764
t .Run ("WorkspaceAppsProxySubdomain" ,func (t * testing.T ) {
755
765
t .Parallel ()
756
766
757
- appDetails := setupProxyTest (t ,nil )
758
-
759
767
t .Run ("NoAccessShould401" ,func (t * testing.T ) {
760
768
t .Parallel ()
761
769
770
+ appDetails := setupProxyTest (t ,nil )
762
771
userClient ,_ := coderdtest .CreateAnotherUser (t ,appDetails .SDKClient ,appDetails .FirstUser .OrganizationID ,rbac .RoleMember ())
763
772
userAppClient := appDetails .AppClient (t )
764
773
userAppClient .SetSessionToken (userClient .SessionToken ())
@@ -770,11 +779,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
770
779
require .NoError (t ,err )
771
780
defer resp .Body .Close ()
772
781
require .Equal (t ,http .StatusNotFound ,resp .StatusCode )
782
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
773
783
})
774
784
775
785
t .Run ("RedirectsWithSlash" ,func (t * testing.T ) {
776
786
t .Parallel ()
777
787
788
+ appDetails := setupProxyTest (t ,nil )
778
789
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
779
790
defer cancel ()
780
791
@@ -789,11 +800,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
789
800
loc ,err := resp .Location ()
790
801
require .NoError (t ,err )
791
802
require .Equal (t ,appDetails .SubdomainAppURL (appDetails .Apps .Owner ).Path ,loc .Path )
803
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
792
804
})
793
805
794
806
t .Run ("RedirectsWithQuery" ,func (t * testing.T ) {
795
807
t .Parallel ()
796
808
809
+ appDetails := setupProxyTest (t ,nil )
797
810
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
798
811
defer cancel ()
799
812
@@ -807,11 +820,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
807
820
loc ,err := resp .Location ()
808
821
require .NoError (t ,err )
809
822
require .Equal (t ,appDetails .SubdomainAppURL (appDetails .Apps .Owner ).RawQuery ,loc .RawQuery )
823
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
810
824
})
811
825
812
826
t .Run ("Proxies" ,func (t * testing.T ) {
813
827
t .Parallel ()
814
828
829
+ appDetails := setupProxyTest (t ,nil )
815
830
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
816
831
defer cancel ()
817
832
@@ -848,6 +863,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
848
863
require .NoError (t ,err )
849
864
require .Equal (t ,proxyTestAppBody ,string (body ))
850
865
require .Equal (t ,http .StatusOK ,resp .StatusCode )
866
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
851
867
})
852
868
853
869
t .Run ("ProxiesHTTPS" ,func (t * testing.T ) {
@@ -892,11 +908,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
892
908
require .NoError (t ,err )
893
909
require .Equal (t ,proxyTestAppBody ,string (body ))
894
910
require .Equal (t ,http .StatusOK ,resp .StatusCode )
911
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
895
912
})
896
913
897
914
t .Run ("ProxiesPort" ,func (t * testing.T ) {
898
915
t .Parallel ()
899
916
917
+ appDetails := setupProxyTest (t ,nil )
900
918
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
901
919
defer cancel ()
902
920
@@ -907,23 +925,27 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
907
925
require .NoError (t ,err )
908
926
require .Equal (t ,proxyTestAppBody ,string (body ))
909
927
require .Equal (t ,http .StatusOK ,resp .StatusCode )
928
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
910
929
})
911
930
912
931
t .Run ("ProxyError" ,func (t * testing.T ) {
913
932
t .Parallel ()
914
933
934
+ appDetails := setupProxyTest (t ,nil )
915
935
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
916
936
defer cancel ()
917
937
918
938
resp ,err := appDetails .AppClient (t ).Request (ctx ,http .MethodGet ,appDetails .SubdomainAppURL (appDetails .Apps .Fake ).String (),nil )
919
939
require .NoError (t ,err )
920
940
defer resp .Body .Close ()
921
941
require .Equal (t ,http .StatusBadGateway ,resp .StatusCode )
942
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
922
943
})
923
944
924
945
t .Run ("ProxyPortMinimumError" ,func (t * testing.T ) {
925
946
t .Parallel ()
926
947
948
+ appDetails := setupProxyTest (t ,nil )
927
949
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
928
950
defer cancel ()
929
951
@@ -939,6 +961,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
939
961
err = json .NewDecoder (resp .Body ).Decode (& resBody )
940
962
require .NoError (t ,err )
941
963
require .Contains (t ,resBody .Message ,"Coder reserves ports less than" )
964
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
942
965
})
943
966
944
967
t .Run ("SuffixWildcardOK" ,func (t * testing.T ) {
@@ -961,6 +984,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
961
984
require .NoError (t ,err )
962
985
require .Equal (t ,proxyTestAppBody ,string (body ))
963
986
require .Equal (t ,http .StatusOK ,resp .StatusCode )
987
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
964
988
})
965
989
966
990
t .Run ("WildcardPortOK" ,func (t * testing.T ) {
@@ -993,16 +1017,19 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
993
1017
require .NoError (t ,err )
994
1018
require .Equal (t ,proxyTestAppBody ,string (body ))
995
1019
require .Equal (t ,http .StatusOK ,resp .StatusCode )
1020
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
996
1021
})
997
1022
998
1023
t .Run ("SuffixWildcardNotMatch" ,func (t * testing.T ) {
999
1024
t .Parallel ()
1000
1025
1001
- appDetails := setupProxyTest (t ,& DeploymentOptions {
1002
- AppHost :"*-suffix.test.coder.com" ,
1003
- })
1004
-
1005
1026
t .Run ("NoSuffix" ,func (t * testing.T ) {
1027
+ t .Parallel ()
1028
+
1029
+ appDetails := setupProxyTest (t ,& DeploymentOptions {
1030
+ AppHost :"*-suffix.test.coder.com" ,
1031
+ })
1032
+
1006
1033
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
1007
1034
defer cancel ()
1008
1035
@@ -1020,11 +1047,16 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
1020
1047
// It's probably rendering the dashboard or a 404 page, so only
1021
1048
// ensure that the body doesn't match.
1022
1049
require .NotContains (t ,string (body ),proxyTestAppBody )
1050
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
1023
1051
})
1024
1052
1025
1053
t .Run ("DifferentSuffix" ,func (t * testing.T ) {
1026
1054
t .Parallel ()
1027
1055
1056
+ appDetails := setupProxyTest (t ,& DeploymentOptions {
1057
+ AppHost :"*-suffix.test.coder.com" ,
1058
+ })
1059
+
1028
1060
ctx ,cancel := context .WithTimeout (context .Background (),testutil .WaitLong )
1029
1061
defer cancel ()
1030
1062
@@ -1042,6 +1074,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
1042
1074
// It's probably rendering the dashboard, so only ensure that the body
1043
1075
// doesn't match.
1044
1076
require .NotContains (t ,string (body ),proxyTestAppBody )
1077
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
1045
1078
})
1046
1079
})
1047
1080
})
@@ -1062,6 +1095,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
1062
1095
require .NoError (t ,err )
1063
1096
defer resp .Body .Close ()
1064
1097
require .Equal (t ,http .StatusNotFound ,resp .StatusCode )
1098
+ assertWorkspaceLastUsedAtNotUpdated (t ,appDetails )
1065
1099
})
1066
1100
1067
1101
t .Run ("AuthenticatedOK" ,func (t * testing.T ) {
@@ -1090,6 +1124,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
1090
1124
require .NoError (t ,err )
1091
1125
defer resp .Body .Close ()
1092
1126
require .Equal (t ,http .StatusOK ,resp .StatusCode )
1127
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
1093
1128
})
1094
1129
1095
1130
t .Run ("PublicOK" ,func (t * testing.T ) {
@@ -1117,6 +1152,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
1117
1152
require .NoError (t ,err )
1118
1153
defer resp .Body .Close ()
1119
1154
require .Equal (t ,http .StatusOK ,resp .StatusCode )
1155
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
1120
1156
})
1121
1157
1122
1158
t .Run ("HTTPS" ,func (t * testing.T ) {
@@ -1145,6 +1181,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
1145
1181
require .NoError (t ,err )
1146
1182
defer resp .Body .Close ()
1147
1183
require .Equal (t ,http .StatusOK ,resp .StatusCode )
1184
+ assertWorkspaceLastUsedAtUpdated (t ,appDetails )
1148
1185
})
1149
1186
})
1150
1187
@@ -1719,26 +1756,33 @@ func testReconnectingPTY(ctx context.Context, t *testing.T, client *codersdk.Cli
1719
1756
}
1720
1757
1721
1758
// Accessing an app should update the workspace's LastUsedAt.
1722
- // NOTE: Despite our efforts with the flush channel, this is inherently racy.
1759
+ // NOTE: Despite our efforts with the flush channel, this is inherently racy when used with
1760
+ // parallel tests on the same workspace/app.
1723
1761
func assertWorkspaceLastUsedAtUpdated (t testing.TB ,details * Details ) {
1724
1762
t .Helper ()
1725
1763
1764
+ require .NotNil (t ,details .Workspace ,"can't assert LastUsedAt on a nil workspace!" )
1765
+ before ,err := details .SDKClient .Workspace (context .Background (),details .Workspace .ID )
1766
+ require .NoError (t ,err )
1726
1767
// Wait for stats to fully flush.
1768
+ details .FlushStats ()
1727
1769
require .Eventually (t ,func ()bool {
1728
- details .FlushStats ()
1729
- ws ,err := details .SDKClient .Workspace (context .Background (),details .Workspace .ID )
1730
- assert .NoError (t ,err )
1731
- return ws .LastUsedAt .After (details .Workspace .LastUsedAt )
1732
- },testutil .WaitShort ,testutil .IntervalMedium ,"workspace LastUsedAt not updated when it should have been" )
1770
+ after ,err := details .SDKClient .Workspace (context .Background (),details .Workspace .ID )
1771
+ return assert .NoError (t ,err )&& after .LastUsedAt .After (before .LastUsedAt )
1772
+ },testutil .WaitShort ,testutil .IntervalMedium )
1733
1773
}
1734
1774
1735
1775
// Except when it sometimes shouldn't (e.g. no access)
1736
- // NOTE: Despite our efforts with the flush channel, this is inherently racy.
1776
+ // NOTE: Despite our efforts with the flush channel, this is inherently racy when used with
1777
+ // parallel tests on the same workspace/app.
1737
1778
func assertWorkspaceLastUsedAtNotUpdated (t testing.TB ,details * Details ) {
1738
1779
t .Helper ()
1739
1780
1781
+ require .NotNil (t ,details .Workspace ,"can't assert LastUsedAt on a nil workspace!" )
1782
+ before ,err := details .SDKClient .Workspace (context .Background (),details .Workspace .ID )
1783
+ require .NoError (t ,err )
1740
1784
details .FlushStats ()
1741
- ws ,err := details .SDKClient .Workspace (context .Background (),details .Workspace .ID )
1785
+ after ,err := details .SDKClient .Workspace (context .Background (),details .Workspace .ID )
1742
1786
require .NoError (t ,err )
1743
- require .Equal (t ,ws .LastUsedAt ,details . Workspace .LastUsedAt ,"workspace LastUsedAt updated when it should not have been" )
1787
+ require .Equal (t ,before .LastUsedAt ,after .LastUsedAt ,"workspace LastUsedAt updated when it should not have been" )
1744
1788
}