1- using Ipfs ;
1+ using System . Diagnostics ;
2+ using Ipfs ;
3+ using OwlCore . Diagnostics ;
4+ using OwlCore . Kubo ;
5+ using OwlCore . Nomad . Kubo ;
6+ using OwlCore . Nomad . Kubo . Events ;
7+ using OwlCore . Storage ;
8+ using OwlCore . Storage . System . IO ;
9+ using WindowsAppCommunity . Sdk . Models ;
10+ using WindowsAppCommunity . Sdk . Nomad ;
211
312namespace WindowsAppCommunity . Sdk . Tests ;
413
514[ TestClass ]
615public partial class BasicTests
716{
17+ private void LoggerOnMessageReceived ( object ? sender , LoggerMessageEventArgs args ) => Debug . WriteLine ( args . Message ) ;
18+
819 [ TestMethod ]
9- public void TestPeerIdToCid ( )
20+ public async Task BasicTestAsync ( )
1021 {
11- var keyId = "12D3KooWHTJs5AGsyVqosX15r2UwUXwU3XnDb6RFPka3EMeVhhJr" ;
12-
13- var peer = new Peer { Id = keyId } ;
22+ Logger . MessageReceived += LoggerOnMessageReceived ;
23+ var cancellationToken = CancellationToken . None ;
1424
15- Cid peerCid = new Cid { Hash = keyId } ;
16-
17- Console . WriteLine ( "Success" ) ;
25+ var temp = new SystemFolder ( Path . GetTempPath ( ) ) ;
26+ var testTempFolder = await SafeCreateFolderAsync ( temp , $ "{ nameof ( BasicTests ) } .{ nameof ( BasicTestAsync ) } ", cancellationToken ) ;
27+
28+ var kubo = await BootstrapKuboAsync ( testTempFolder , 5012 , 8012 , cancellationToken ) ;
29+ var kuboOptions = new KuboOptions
30+ {
31+ IpnsLifetime = TimeSpan . FromDays ( 1 ) ,
32+ ShouldPin = false ,
33+ UseCache = false ,
34+ } ;
35+
36+ var client = kubo . Client ;
37+ var projectRoamingKeyName = "TestProject.Roaming" ;
38+ var projectLocalKeyName = "TestProject.Local" ;
39+ var publisherRoamingKeyName = "TestPublisher.Roaming" ;
40+ var publisherLocalKeyName = "TestPublisher.Local" ;
41+ var userRoamingKeyName = "TestUser.Roaming" ;
42+ var userLocalKeyName = "TestUser.Local" ;
43+
44+ NomadKuboRepository < ModifiableProject , IReadOnlyProject , Project , ValueUpdateEvent > projectRepository = null ! ;
45+ NomadKuboRepository < ModifiablePublisher , IReadOnlyPublisher , Publisher , ValueUpdateEvent > publisherRepository = null ! ;
46+ NomadKuboRepository < ModifiableUser , IReadOnlyUser , User , ValueUpdateEvent > userRepository = null ! ;
47+
48+ projectRepository = new NomadKuboRepository < ModifiableProject , IReadOnlyProject , Project , ValueUpdateEvent >
49+ {
50+ DefaultEventStreamLabel = "Test Project" ,
51+ Client = kubo . Client ,
52+ KuboOptions = kuboOptions ,
53+ GetEventStreamHandlerConfigAsync = async ( roamingId , cancellationToken ) =>
54+ {
55+ var ( localKey , roamingKey , foundRoamingId ) = await NomadKeyHelpers . RoamingIdToNomadKeysAsync ( roamingId , projectRoamingKeyName , projectLocalKeyName , client , cancellationToken ) ;
56+ return new NomadKuboEventStreamHandlerConfig < Project >
57+ {
58+ RoamingId = roamingKey ? . Id ?? ( foundRoamingId is not null ? Cid . Decode ( foundRoamingId ) : null ) ,
59+ RoamingKey = roamingKey ,
60+ RoamingKeyName = projectRoamingKeyName ,
61+ LocalKey = localKey ,
62+ LocalKeyName = projectLocalKeyName ,
63+ } ;
64+ } ,
65+ GetDefaultRoamingValue = ( localKey , roamingKey ) => new Project
66+ {
67+ Name = "Test Project" ,
68+ Description = "This is a test project." ,
69+ ExtendedDescription = "This is a test project. It is used to test the Windows App Community SDK." ,
70+ Category = "Test" ,
71+ Sources = [ localKey . Id ] ,
72+ } ,
73+ ModifiableFromHandlerConfig = config => ModifiableProject . FromHandlerConfig ( config , projectRepository , publisherRepository , userRepository , client , kuboOptions ) ,
74+ ReadOnlyFromHandlerConfig = config => ReadOnlyProject . FromHandlerConfig ( config , projectRepository , publisherRepository , userRepository , client , kuboOptions ) ,
75+ } ;
76+
77+ publisherRepository = new NomadKuboRepository < ModifiablePublisher , IReadOnlyPublisher , Publisher , ValueUpdateEvent >
78+ {
79+ DefaultEventStreamLabel = "Test Publisher" ,
80+ Client = kubo . Client ,
81+ KuboOptions = kuboOptions ,
82+ GetEventStreamHandlerConfigAsync = async ( roamingId , cancellationToken ) =>
83+ {
84+ var ( localKey , roamingKey , foundRoamingId ) = await NomadKeyHelpers . RoamingIdToNomadKeysAsync ( roamingId , publisherRoamingKeyName , publisherLocalKeyName , client , cancellationToken ) ;
85+ return new NomadKuboEventStreamHandlerConfig < Publisher >
86+ {
87+ RoamingId = roamingKey ? . Id ?? ( foundRoamingId is not null ? Cid . Decode ( foundRoamingId ) : null ) ,
88+ RoamingKey = roamingKey ,
89+ RoamingKeyName = publisherRoamingKeyName ,
90+ LocalKey = localKey ,
91+ LocalKeyName = publisherLocalKeyName ,
92+ } ;
93+ } ,
94+ GetDefaultRoamingValue = ( localKey , roamingKey ) => new Publisher
95+ {
96+ Name = "Test Publisher" ,
97+ Description = "This is a test publisher." ,
98+ ExtendedDescription = "This is a test publisher. It is used to test the Windows App Community SDK." ,
99+ Sources = [ localKey . Id ] ,
100+ } ,
101+ ModifiableFromHandlerConfig = config => ModifiablePublisher . FromHandlerConfig ( config , projectRepository , publisherRepository , userRepository , client , kuboOptions ) ,
102+ ReadOnlyFromHandlerConfig = config => ReadOnlyPublisher . FromHandlerConfig ( config , projectRepository , publisherRepository , userRepository , client , kuboOptions ) ,
103+ } ;
104+
105+ userRepository = new NomadKuboRepository < ModifiableUser , IReadOnlyUser , User , ValueUpdateEvent >
106+ {
107+ DefaultEventStreamLabel = "Test User" ,
108+ Client = kubo . Client ,
109+ KuboOptions = kuboOptions ,
110+ GetEventStreamHandlerConfigAsync = async ( roamingId , cancellationToken ) =>
111+ {
112+ var ( localKey , roamingKey , foundRoamingId ) = await NomadKeyHelpers . RoamingIdToNomadKeysAsync ( roamingId , userRoamingKeyName , userLocalKeyName , client , cancellationToken ) ;
113+ return new NomadKuboEventStreamHandlerConfig < User >
114+ {
115+ RoamingId = roamingKey ? . Id ?? ( foundRoamingId is not null ? Cid . Decode ( foundRoamingId ) : null ) ,
116+ RoamingKey = roamingKey ,
117+ RoamingKeyName = userRoamingKeyName ,
118+ LocalKey = localKey ,
119+ LocalKeyName = userLocalKeyName ,
120+ } ;
121+ } ,
122+ GetDefaultRoamingValue = ( localKey , roamingKey ) => new User
123+ {
124+ Name = "Test User" ,
125+ Description = "This is a test user." ,
126+ ExtendedDescription = "This is a test user. It is used to test the Windows App Community SDK." ,
127+ Sources = [ localKey . Id ] ,
128+ } ,
129+ ModifiableFromHandlerConfig = config => ModifiableUser . FromHandlerConfig ( config , projectRepository , publisherRepository , client , kuboOptions ) ,
130+ ReadOnlyFromHandlerConfig = config => ReadOnlyUser . FromHandlerConfig ( config , projectRepository , publisherRepository , client , kuboOptions ) ,
131+ } ;
132+
133+ var project = await projectRepository . CreateAsync ( cancellationToken ) ;
134+ var publisher = await publisherRepository . CreateAsync ( cancellationToken ) ;
135+ var user = await userRepository . CreateAsync ( cancellationToken ) ;
136+
137+ await kubo . Client . ShutdownAsync ( ) ;
138+ kubo . Dispose ( ) ;
139+ await SetAllFileAttributesRecursive ( testTempFolder , attributes => attributes & ~ FileAttributes . ReadOnly ) ;
140+ await temp . DeleteAsync ( testTempFolder , cancellationToken ) ;
141+ Logger . MessageReceived -= LoggerOnMessageReceived ;
142+ }
143+
144+ /// <summary>
145+ /// Creates a temp folder for the test fixture to work in, safely unlocking and removing existing files if needed.
146+ /// </summary>
147+ /// <returns>The folder that was created.</returns>
148+ public static async Task < SystemFolder > SafeCreateFolderAsync ( SystemFolder rootFolder , string name , CancellationToken cancellationToken )
149+ {
150+ // When Kubo is stopped unexpectedly, it may leave some files with a ReadOnly attribute.
151+ // Since this folder is created every time tests are run, we need to clean up any files leftover from prior runs.
152+ // To do that, we need to remove the ReadOnly file attribute.
153+ var testTempRoot = ( SystemFolder ) await rootFolder . CreateFolderAsync ( name , overwrite : false , cancellationToken : cancellationToken ) ;
154+ await SetAllFileAttributesRecursive ( testTempRoot , attributes => attributes & ~ FileAttributes . ReadOnly ) ;
155+
156+ // Delete and recreate the folder.
157+ return ( SystemFolder ) await rootFolder . CreateFolderAsync ( name , overwrite : true , cancellationToken : cancellationToken ) ;
158+ }
159+
160+ /// <summary>
161+ /// Changes the file attributes of all files in all subfolders of the provided <see cref="SystemFolder"/>.
162+ /// </summary>
163+ /// <param name="rootFolder">The folder to set file permissions in.</param>
164+ /// <param name="transform">This function is provided the current file attributes, and should return the new file attributes.</param>
165+ public static async Task SetAllFileAttributesRecursive ( SystemFolder rootFolder , Func < FileAttributes , FileAttributes > transform )
166+ {
167+ await foreach ( var childFile in rootFolder . GetFilesAsync ( ) )
168+ {
169+ var file = ( SystemFile ) childFile ;
170+ file . Info . Attributes = transform ( file . Info . Attributes ) ;
171+ }
172+
173+ await foreach ( var childFolder in rootFolder . GetFoldersAsync ( ) )
174+ {
175+ var folder = ( SystemFolder ) childFolder ;
176+ await SetAllFileAttributesRecursive ( folder , transform ) ;
177+ }
178+ }
179+
180+ private static async Task < KuboBootstrapper > BootstrapKuboAsync ( SystemFolder kuboRepo , int apiPort , int gatewayPort , CancellationToken cancellationToken )
181+ {
182+ var kubo = new KuboBootstrapper ( kuboRepo . Path )
183+ {
184+ ApiUri = new Uri ( $ "http://127.0.0.1:{ apiPort } ") ,
185+ GatewayUri = new Uri ( $ "http://127.0.0.1:{ gatewayPort } ") ,
186+ RoutingMode = DhtRoutingMode . None ,
187+ LaunchConflictMode = BootstrapLaunchConflictMode . Attach ,
188+ ApiUriMode = ConfigMode . OverwriteExisting ,
189+ GatewayUriMode = ConfigMode . OverwriteExisting ,
190+ } ;
191+
192+ await kubo . StartAsync ( cancellationToken ) ;
193+ return kubo ;
18194 }
19195}
0 commit comments