@@ -135,6 +135,11 @@ public void NativeAOT ()
135
135
proj . SetProperty ( "PublishAot" , "true" ) ;
136
136
proj . SetProperty ( "PublishAotUsingRuntimePack" , "true" ) ;
137
137
proj . SetProperty ( "AndroidNdkDirectory" , AndroidNdkPath ) ;
138
+ proj . SetProperty ( "_ExtraTrimmerArgs" , "--verbose" ) ;
139
+
140
+ // Required for java/util/ArrayList assertion below
141
+ proj . MainActivity = proj . DefaultMainActivity
142
+ . Replace ( "//${AFTER_ONCREATE}" , "new Android.Runtime.JavaList (); new Android.Runtime.JavaList<int> ();" ) ;
138
143
139
144
using var b = CreateApkBuilder ( ) ;
140
145
Assert . IsTrue ( b . Build ( proj ) , "Build should have succeeded." ) ;
@@ -165,6 +170,43 @@ public void NativeAOT ()
165
170
Assert . IsNotNull ( method , $ "{ linkedMonoAndroidAssembly } should contain { typeName } .{ methodName } ") ;
166
171
}
167
172
173
+ var typemap = new Dictionary < string , TypeReference > ( ) ;
174
+ var linkedRuntimeAssembly = Path . Combine ( intermediate , "linked" , "Microsoft.Android.Runtime.NativeAOT.dll" ) ;
175
+ FileAssert . Exists ( linkedRuntimeAssembly ) ;
176
+ using ( var assembly = AssemblyDefinition . ReadAssembly ( linkedRuntimeAssembly ) ) {
177
+ var type = assembly . MainModule . Types . FirstOrDefault ( t => t . Name == "NativeAotTypeManager" ) ;
178
+ Assert . IsNotNull ( type , $ "{ linkedRuntimeAssembly } should contain NativeAotTypeManager") ;
179
+ var method = type . Methods . FirstOrDefault ( m => m . Name == "InitializeTypeMappings" ) ;
180
+ Assert . IsNotNull ( method , "NativeAotTypeManager should contain InitializeTypeMappings" ) ;
181
+
182
+ foreach ( var i in method . Body . Instructions ) {
183
+ if ( i . OpCode != Mono . Cecil . Cil . OpCodes . Ldstr )
184
+ continue ;
185
+ if ( i . Operand is not string javaName )
186
+ continue ;
187
+ if ( i . Next . Operand is not TypeReference t )
188
+ continue ;
189
+ typemap . Add ( javaName , t ) ;
190
+ }
191
+
192
+ // Basic types
193
+ AssertTypeMap ( "java/lang/Object" , "Java.Lang.Object" ) ;
194
+ AssertTypeMap ( "java/lang/String" , "Java.Lang.String" ) ;
195
+ AssertTypeMap ( "[Ljava/lang/Object;" , "Java.Interop.JavaArray`1" ) ;
196
+ AssertTypeMap ( "java/util/ArrayList" , "Android.Runtime.JavaList" ) ;
197
+ AssertTypeMap ( "android/app/Activity" , "Android.App.Activity" ) ;
198
+ AssertTypeMap ( "android/widget/Button" , "Android.Widget.Button" ) ;
199
+ Assert . IsFalse ( StringAssertEx . ContainsText ( b . LastBuildOutput ,
200
+ "Duplicate typemap entry for java/util/ArrayList => Android.Runtime.JavaList`1" ) ,
201
+ "Should get log message about duplicate Android.Runtime.JavaList`1!" ) ;
202
+
203
+ // Special *Invoker case
204
+ AssertTypeMap ( "android/view/View$OnClickListener" , "Android.Views.View/IOnClickListener" ) ;
205
+ Assert . IsFalse ( StringAssertEx . ContainsText ( b . LastBuildOutput ,
206
+ "Duplicate typemap entry for android/view/View$OnClickListener => Android.Views.View/IOnClickListenerInvoker" ) ,
207
+ "Should get log message about duplicate IOnClickListenerInvoker!" ) ;
208
+ }
209
+
168
210
var dexFile = Path . Combine ( intermediate , "android" , "bin" , "classes.dex" ) ;
169
211
FileAssert . Exists ( dexFile ) ;
170
212
foreach ( var className in mono_classes ) {
@@ -180,6 +222,15 @@ public void NativeAOT ()
180
222
foreach ( var nativeaot_file in nativeaot_files ) {
181
223
Assert . IsTrue ( zip . ContainsEntry ( nativeaot_file , caseSensitive : true ) , $ "APK must contain `{ nativeaot_file } `.") ;
182
224
}
225
+
226
+ void AssertTypeMap ( string javaName , string managedName )
227
+ {
228
+ if ( typemap . TryGetValue ( javaName , out var reference ) ) {
229
+ Assert . AreEqual ( managedName , reference . ToString ( ) ) ;
230
+ } else {
231
+ Assert . Fail ( $ "InitializeTypeMappings should contain Ldstr \" { javaName } \" !") ;
232
+ }
233
+ }
183
234
}
184
235
185
236
[ Test ]
0 commit comments