1+ using System . Net ;
2+ using System . Net . Http . Json ;
3+ using Microsoft . AspNetCore . Hosting ;
4+ using Microsoft . EntityFrameworkCore ;
5+ using Microsoft . Extensions . DependencyInjection ;
6+ using Newtonsoft . Json ;
7+ using OpenShock . API . Models . Response ;
8+ using OpenShock . Common . Models ;
9+ using OpenShock . Common . OpenShockDb ;
10+ using OpenShock . Common . Redis ;
11+ using OpenShock . Common . Utils ;
12+ using Redis . OM . Contracts ;
13+ using JsonSerializer = System . Text . Json . JsonSerializer ;
14+
15+ namespace OpenShock . API . IntegrationTests . Tests ;
16+
17+ public sealed class LcgAssignmentTests
18+ {
19+ [ ClassDataSource < WebApplicationFactory > ( Shared = SharedType . PerTestSession ) ]
20+ public required WebApplicationFactory WebApplicationFactory { get ; init ; }
21+
22+ private static readonly Guid UserId = Guid . Parse ( "11111111-1111-1111-1111-111111111111" ) ;
23+ private static readonly Guid HubId = Guid . Parse ( "11111111-1111-1111-1111-111111111111" ) ;
24+ private const string HubToken = "test" ;
25+
26+ [ Before ( Test ) ]
27+ public async Task Setup ( )
28+ {
29+ await using var context = WebApplicationFactory . Services . CreateAsyncScope ( ) ;
30+ var db = context . ServiceProvider . GetRequiredService < OpenShockContext > ( ) ;
31+
32+ var user = new User
33+ {
34+ Id = UserId ,
35+ Name = "TestUser" ,
36+ Email = "test@test.org" ,
37+ PasswordHash = HashingUtils . HashPassword ( "password" ) ,
38+ CreatedAt = DateTime . UtcNow ,
39+ ActivatedAt = DateTime . UtcNow
40+ } ;
41+
42+ db . Users . Add ( user ) ;
43+
44+ var hub = new Device
45+ {
46+ Id = HubId ,
47+ Name = "TestHub" ,
48+ OwnerId = UserId ,
49+ Token = HubToken ,
50+ CreatedAt = DateTime . UtcNow
51+ } ;
52+
53+ db . Devices . Add ( hub ) ;
54+
55+ await db . SaveChangesAsync ( ) ;
56+ }
57+
58+ [ After ( Test ) ]
59+ public async Task Teardown ( )
60+ {
61+ await using var context = WebApplicationFactory . Services . CreateAsyncScope ( ) ;
62+ var db = context . ServiceProvider . GetRequiredService < OpenShockContext > ( ) ;
63+ await db . Devices . Where ( x => x . Id == HubId ) . ExecuteDeleteAsync ( ) ;
64+ await db . Users . Where ( x => x . Id == UserId ) . ExecuteDeleteAsync ( ) ;
65+
66+ var redisConnectionProvider = context . ServiceProvider . GetRequiredService < IRedisConnectionProvider > ( ) ;
67+ var webHostEnvironment = context . ServiceProvider . GetRequiredService < IWebHostEnvironment > ( ) ;
68+ var lcgNodesCollection = redisConnectionProvider . RedisCollection < LcgNode > ( false ) ;
69+
70+ var allLcg = await lcgNodesCollection . ToArrayAsync ( ) ;
71+ await lcgNodesCollection . DeleteAsync ( allLcg ) ;
72+ }
73+
74+ [ Test ]
75+ [ NotInParallel ]
76+ [ Arguments ( "US" , "us1.example.com" , new [ ] { "US|us1.example.com" , "DE|de1.example.com" , "AS|as1.example.com" } ) ]
77+ [ Arguments ( "DE" , "de1.example.com" , new [ ] { "US|us1.example.com" , "DE|de1.example.com" , "AS|as1.example.com" } ) ]
78+ [ Arguments ( "CA" , "us1.example.com" , new [ ] { "US|us1.example.com" , "DE|de1.example.com" , "AS|as1.example.com" } ) ]
79+ [ Arguments ( "CA" , "us1.example.com" , new [ ] { "US|us1.example.com" , "DE|de1.example.com" , "AS|as1.example.com" } ) ]
80+ [ Arguments ( "AT" , "de1.example.com" , new [ ] { "US|us1.example.com" , "DE|de1.example.com" , "AS|as1.example.com" } ) ]
81+ [ Arguments ( "FR" , "de1.example.com" , new [ ] { "US|us1.example.com" , "DE|de1.example.com" , "AS|as1.example.com" } ) ]
82+ public async Task GetLcgAssignment ( string requesterCountry , string expectedHost , string [ ] availableGateways )
83+ {
84+ using var client = WebApplicationFactory . CreateClient ( ) ;
85+
86+ await using var context = WebApplicationFactory . Services . CreateAsyncScope ( ) ;
87+ var redisConnectionProvider = context . ServiceProvider . GetRequiredService < IRedisConnectionProvider > ( ) ;
88+ var webHostEnvironment = context . ServiceProvider . GetRequiredService < IWebHostEnvironment > ( ) ;
89+ var lcgNodesCollection = redisConnectionProvider . RedisCollection < LcgNode > ( false ) ;
90+
91+ var testGateways = availableGateways . Select ( x =>
92+ {
93+ var split = x . Split ( '|' ) ;
94+ if ( split . Length != 2 )
95+ throw new ArgumentException ( "Invalid gateway format" ) ;
96+
97+ return new LcgNode
98+ {
99+ Country = split [ 0 ] ,
100+ Fqdn = split [ 1 ] ,
101+ Load = 0 ,
102+ Environment = webHostEnvironment . EnvironmentName
103+ } ;
104+ } ) ;
105+
106+ await lcgNodesCollection . InsertAsync ( testGateways ) ;
107+
108+ var httpRequest = new HttpRequestMessage ( HttpMethod . Get , "/2/device/assignLCG?version=1" ) ;
109+ httpRequest . Headers . Add ( "Device-Token" , HubToken ) ;
110+ httpRequest . Headers . Add ( "CF-IPCountry" , requesterCountry ) ;
111+ var response = await client . SendAsync ( httpRequest ) ;
112+
113+ await Assert . That ( response . StatusCode ) . IsEqualTo ( HttpStatusCode . OK ) ;
114+
115+ var mediaType = response . Content . Headers . ContentType ? . MediaType ;
116+ await Assert . That ( mediaType ) . IsEqualTo ( "application/json" ) ;
117+
118+ var data = await response . Content . ReadFromJsonAsync < LcgNodeResponseV2 > ( ) ;
119+ await Assert . That ( data ) . IsNotNull ( ) ;
120+ await Assert . That ( data . Host ) . IsEqualTo ( expectedHost ) ;
121+ }
122+
123+
124+ }
0 commit comments