Skip to content

Commit 55828b9

Browse files
authored
[ios][tests] Run functional tests with Mono and Native AOT on Helix (#87773)
This PR adds support for Native AOT compilation on Helix. It improves test coverage for Mono and Native AOT by running functional tests on Helix. The proxy project is updated with Native AOT props and apple build targets are updated to support Native AOT compilation. Additionally, it simplifies the sample app by utilizing the shared Apple targets.
1 parent 0916f7b commit 55828b9

26 files changed

+299
-147
lines changed

eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,39 @@ jobs:
8989
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
9090
extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
9191

92+
#
93+
# iOS/tvOS devices
94+
# Build the whole product using Native AOT and run libraries tests
95+
#
96+
- template: /eng/pipelines/common/platform-matrix.yml
97+
parameters:
98+
jobTemplate: /eng/pipelines/common/global-build-job.yml
99+
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
100+
buildConfig: Release
101+
runtimeFlavor: coreclr
102+
isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }}
103+
isiOSLikeOnlyBuild: ${{ parameters.isiOSLikeOnlyBuild }}
104+
platforms:
105+
- ios_arm64
106+
- tvos_arm64
107+
variables:
108+
# map dependencies variables to local variables
109+
- name: librariesContainsChange
110+
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
111+
- name: coreclrContainsChange
112+
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'] ]
113+
jobParameters:
114+
testGroup: innerloop
115+
nameSuffix: AllSubsets_NativeAOT
116+
buildArgs: --cross -s clr.alljits+clr.tools+clr.nativeaotruntime+clr.nativeaotlibs+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=true /p:DevTeamProvisioning=- /p:BuildTestsOnHelix=true /p:UseNativeAOTRuntime=true /p:RunAOTCompilation=false /p:ContinuousIntegrationBuild=true
117+
timeoutInMinutes: 180
118+
# extra steps, run tests
119+
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
120+
extraStepsParameters:
121+
creator: dotnet-bot
122+
testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig)
123+
extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
124+
92125
#
93126
# Build the whole product using NativeAOT for iOS/tvOS and run runtime tests with iOS/tvOS devices
94127
#

eng/pipelines/runtime.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,48 @@ extends:
598598
eq(variables['monoContainsChange'], true),
599599
eq(variables['isRollingBuild'], true))
600600
601+
#
602+
# iOS/tvOS devices
603+
# Build the whole product using Native AOT and run libraries tests
604+
#
605+
- template: /eng/pipelines/common/platform-matrix.yml
606+
parameters:
607+
jobTemplate: /eng/pipelines/common/global-build-job.yml
608+
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
609+
buildConfig: Release
610+
runtimeFlavor: coreclr
611+
platforms:
612+
- ios_arm64
613+
- tvos_arm64
614+
variables:
615+
# map dependencies variables to local variables
616+
- name: librariesContainsChange
617+
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
618+
- name: coreclrContainsChange
619+
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'] ]
620+
jobParameters:
621+
testGroup: innerloop
622+
nameSuffix: AllSubsets_NativeAOT
623+
buildArgs: --cross -s clr.alljits+clr.tools+clr.nativeaotruntime+clr.nativeaotlibs+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=true /p:DevTeamProvisioning=- /p:BuildTestsOnHelix=true /p:UseNativeAOTRuntime=true /p:RunAOTCompilation=false /p:ContinuousIntegrationBuild=true
624+
timeoutInMinutes: 180
625+
condition: >-
626+
or(
627+
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
628+
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
629+
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
630+
eq(variables['isRollingBuild'], true))
631+
# extra steps, run tests
632+
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
633+
extraStepsParameters:
634+
creator: dotnet-bot
635+
testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig)
636+
extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
637+
condition: >-
638+
or(
639+
eq(variables['librariesContainsChange'], true),
640+
eq(variables['coreclrContainsChange'], true),
641+
eq(variables['isRollingBuild'], true))
642+
601643
#
602644
# MacCatalyst interp - requires AOT Compilation and Interp flags
603645
# Build the whole product using Mono and run libraries tests

eng/testing/tests.ioslike.targets

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,22 @@
1616
<!-- running aot-helix tests locally, so we can test with the same project file as CI -->
1717
<_AOTBuildCommand Condition="'$(ContinuousIntegrationBuild)' != 'true'">$(_AOTBuildCommand) /p:RuntimeSrcDir=$(RepoRoot) /p:RuntimeConfig=$(Configuration)</_AOTBuildCommand>
1818

19-
<_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR=&quot;$XHARNESS_EXECUTION_DIR&quot; /p:RunAOTCompilation=$(RunAOTCompilation) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:MonoEnableLLVM=true /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration)</_AOTBuildCommand>
19+
<_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR=&quot;$XHARNESS_EXECUTION_DIR&quot; /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration)</_AOTBuildCommand>
2020
<_AOTBuildCommand>$(_AOTBuildCommand) </_AOTBuildCommand>
2121

2222
<_ResetSimulatorSwitch Condition="'$(TargetOS)' == 'iossimulator' or '$(TargetOS)' == 'tvossimulator'">--reset-simulator</_ResetSimulatorSwitch>
2323
<_SignalAppEndSwitch>--signal-app-end</_SignalAppEndSwitch>
2424
<_AppleSignCommand Condition="'$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvos'">sign &quot;$app&quot;</_AppleSignCommand>
2525

26+
<IncludesTestRunner Condition="'$(IncludesTestRunner)' == ''">true</IncludesTestRunner>
27+
28+
<_AppleBuildCommand Condition="'$(IncludesTestRunner)' == 'true'">apple test</_AppleBuildCommand>
29+
<_AppleBuildCommand Condition="'$(IncludesTestRunner)' != 'true'">apple run</_AppleBuildCommand>
30+
<_AppleExpectedExitCode Condition="'$(ExpectedExitCode)' != ''">--expected-exit-code $(ExpectedExitCode)</_AppleExpectedExitCode>
2631
<_AfterBuildCommands>
2732
mv $XHARNESS_OUT/AOTBuild.binlog &quot;$HELIX_WORKITEM_UPLOAD_ROOT&quot;
2833
$(_AppleSignCommand)
29-
xharness apple test --app &quot;$app&quot; --output-directory &quot;$output_directory&quot; --target &quot;$target&quot; --timeout &quot;$timeout&quot; --xcode &quot;$xcode_path&quot; -v --launch-timeout &quot;$launch_timeout&quot; $(_ResetSimulatorSwitch) $(_SignalAppEndSwitch) -- </_AfterBuildCommands>
34+
xharness $(_AppleBuildCommand) --app &quot;$app&quot; --output-directory &quot;$output_directory&quot; --target &quot;$target&quot; --timeout &quot;$timeout&quot; --xcode &quot;$xcode_path&quot; -v --launch-timeout &quot;$launch_timeout&quot; $(_ResetSimulatorSwitch) $(_SignalAppEndSwitch) $(_AppleExpectedExitCode) -- </_AfterBuildCommands>
3035

3136
<RunScriptCommand>$(_AOTBuildCommand) $(_AfterBuildCommands)</RunScriptCommand>
3237
</PropertyGroup>
@@ -66,11 +71,23 @@
6671
Include="@(AppleAssembliesToBundle)" TargetDir="publish\%(AppleAssembliesToBundle.RecursiveDir)" />
6772
<BundleFiles Include="@(AppleNativeFilesToBundle)" TargetDir="publish\%(AppleNativeFilesToBundle.RecursiveDir)" />
6873
<BundleFiles Include="$(RuntimeConfigFilePath)" TargetDir="publish" />
74+
6975
<BundleFiles Include="$(MonoProjectRoot)\msbuild\apple\data\*" TargetDir="publish" />
7076
<ExtraFiles Condition="'%(AppleAssembliesToBundle._IsNative)' == 'true'"
7177
Include="@(AppleAssembliesToBundle)" TargetDir="extraFiles\%(AppleAssembliesToBundle.RecursiveDir)" />
7278
</ItemGroup>
7379

80+
<ItemGroup Condition="'$(UseNativeAOTRuntime)' == 'true'">
81+
<BundleFiles Include="$(MicrosoftNetCoreAppRuntimePackDir)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/icudt.dat"
82+
TargetDir="publish" />
83+
<BundleFiles Include="$(MicrosoftNetCoreAppRuntimePackDir)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/libicudata.a"
84+
TargetDir="publish" />
85+
<BundleFiles Include="$(MicrosoftNetCoreAppRuntimePackDir)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/libicuuc.a"
86+
TargetDir="publish" />
87+
<BundleFiles Include="$(MicrosoftNetCoreAppRuntimePackDir)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/libicui18n.a"
88+
TargetDir="publish" />
89+
</ItemGroup>
90+
7491
<ItemGroup Condition="'$(DebuggerSupport)' == 'true'">
7592
<!-- Add any pdb files, if available -->
7693
<_BundlePdbFiles Include="$([System.IO.Path]::ChangeExtension('%(AppleAssembliesToBundle.Identity)', '.pdb'))" />
@@ -103,8 +120,10 @@
103120
<_ApplePropertyNames Include="HybridGlobalization" />
104121
<_ApplePropertyNames Include="AssemblyName" />
105122
<_ApplePropertyNames Include="MonoEnableLLVM" />
123+
<_ApplePropertyNames Include="MainLibraryFileName" />
124+
<_ApplePropertyNames Include="UseConsoleUITemplate" />
106125
<_ApplePropertyNames Include="UseRuntimeComponents" />
107-
<_ApplePropertyNames Include="IsRuntimeTests" />
126+
<_ApplePropertyNames Include="IncludesTestRunner" />
108127

109128
<_ApplePropertiesToPass
110129
Include="$(%(_ApplePropertyNames.Identity))"
@@ -138,8 +157,9 @@
138157
<WriteLinesToFile File="$(PublishDir)xunit-excludes.txt" Lines="$(XunitExcludesTxtFileContent)" Overwrite="true" />
139158

140159
<PropertyGroup>
160+
<IncludesTestRunner Condition="'$(IncludesTestRunner)' == ''">true</IncludesTestRunner>
141161
<Optimized Condition="'$(Configuration)' == 'Release'">true</Optimized>
142-
<MainLibraryFileName Condition="'$(MainLibraryFileName)' == '' and '$(IsRuntimeTests)' != 'true'">AppleTestRunner.dll</MainLibraryFileName>
162+
<MainLibraryFileName Condition="'$(MainLibraryFileName)' == '' and '$(IsRuntimeTests)' != 'true' and '$(IncludesTestRunner)' == 'true'">AppleTestRunner.dll</MainLibraryFileName>
143163

144164
<AppleBuildDir>$(PublishDir)</AppleBuildDir>
145165
<AppleBundleDir>$(BundleDir)</AppleBundleDir>

eng/testing/tests.mobile.targets

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
<SkipWorkloadsTestingTargetsImport Condition="'$(SkipWorkloadsTestingTargetsImport)' == ''">true</SkipWorkloadsTestingTargetsImport>
1515
</PropertyGroup>
1616

17-
<PropertyGroup>
18-
<RunAOTCompilation Condition="'$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvos'">true</RunAOTCompilation>
17+
<PropertyGroup Condition="'$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvos'">
18+
<RunAOTCompilation Condition="'$(RuntimeFlavor)' == 'Mono' ">true</RunAOTCompilation>
19+
<UseNativeAOTRuntime Condition="'$(RuntimeFlavor)' == 'CoreCLR'">true</UseNativeAOTRuntime>
1920
</PropertyGroup>
2021

2122
<PropertyGroup>

src/libraries/sendtohelix-mobile.targets

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,27 @@
5858
<_XHarnessAppleCustomCommand Condition="'$(NeedsiOSSDK)' == 'true'">
5959
source build-apple-app.sh
6060
</_XHarnessAppleCustomCommand>
61+
<ILLinkDir>$([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.net.illink.tasks', '$(MicrosoftNETILLinkTasksVersion)'))</ILLinkDir>
6162
</PropertyGroup>
6263

6364
<ItemGroup Condition="'$(NeedsiOSSDK)' == 'true'">
6465
<HelixCorrelationPayload Include="cmake" Uri="$(CMakeUrl)" Destination="build/cmake" />
6566
<HelixCorrelationPayload Include="$(AppleAppBuilderDir)" Destination="build/AppleAppBuilder" />
66-
<HelixCorrelationPayload Include="$(MonoAOTCompilerDir)" Destination="build/MonoAOTCompiler" />
67+
<HelixCorrelationPayload Include="$(MonoAOTCompilerDir)" Condition="'$(RuntimeFlavor)' == 'mono'"
68+
Destination="build/MonoAOTCompiler" />
6769
<HelixCorrelationPayload Include="$(MicrosoftNetCoreAppRuntimePackDir)" Destination="build/microsoft.netcore.app.runtime.$(TargetOS)-$(TargetArchitecture.ToLower())" />
6870
<HelixCorrelationPayload Include="$(iOSLikeBuildTargetsDir)" Destination="build/apple" />
6971
<HelixCorrelationPayload Include="$(iOSLikeLibraryBuilderTargetsDir)" Destination="build/common" />
70-
<HelixCorrelationPayload Include="$(MonoAotCrossDir)" Destination="build/cross" />
72+
<HelixCorrelationPayload Include="$(MonoAotCrossDir)" Condition="'$(RuntimeFlavor)' == 'mono'"
73+
Destination="build/cross" />
7174
<HelixCorrelationPayload Include="$(MonoTargetsTasksDir)" Destination="build/MonoTargetsTasks" />
75+
<HelixCorrelationPayload Include="$(CoreCLRCrossILCompilerDir)" Condition="'$(RuntimeFlavor)' == 'coreclr'"
76+
Destination="build/ilc" />
77+
<HelixCorrelationPayload Include="$(CoreCLRBuildIntegrationDir)" Condition="'$(RuntimeFlavor)' == 'coreclr'"
78+
Destination="build/BuildIntegration" />
79+
<HelixCorrelationPayload Include="$(CoreCLRAotSdkDir)" Condition="'$(RuntimeFlavor)' == 'coreclr'"
80+
Destination="build/aotsdk" />
81+
<HelixCorrelationPayload Include="$(ILLinkDir)" Destination="build/microsoft.net.illink.tasks" />
7282
</ItemGroup>
7383

7484
<ItemGroup Condition="'$(TargetsAppleMobile)' == 'true'">

src/libraries/tests.proj

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,6 @@
240240

241241
<ItemGroup Condition="'$(TargetOS)' == 'ios' and '$(RunDisablediOSTests)' != 'true'">
242242
<ProjectExclusions Include="$(MSBuildThisFileDirectory)*\tests\**\*.Tests.csproj" />
243-
244-
<!-- Functional tests on devices have problems with return codes from mlaunch -->
245-
<ProjectExclusions Include="$(RepoRoot)\src\tests\FunctionalTests\iOS\Device\**\*.Test.csproj" />
246-
</ItemGroup>
247-
248-
<ItemGroup Condition="'$(TargetOS)' == 'iossimulator' and '$(TargetArchitecture)' == 'arm64' and '$(RunDisablediOSTests)' != 'true'">
249-
<!-- Functional tests on arm64 simulator have problems with return codes from mlaunch -->
250-
<ProjectExclusions Include="$(RepoRoot)\src\tests\FunctionalTests\iOS\Simulator\**\*.Test.csproj" />
251243
</ItemGroup>
252244

253245
<ItemGroup Condition="'$(TargetOS)' == 'tvos' and '$(RunDisablediOSTests)' != 'true'">
@@ -284,9 +276,6 @@
284276
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.RegularExpressions\tests\UnitTests\System.Text.RegularExpressions.Tests.csproj" />
285277
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.RegularExpressions\tests\FunctionalTests\System.Text.RegularExpressions.Tests.csproj" />
286278

287-
<!-- Functional tests on devices have problems with return codes from mlaunch -->
288-
<ProjectExclusions Include="$(RepoRoot)\src\tests\FunctionalTests\$(TargetOS)\Device\**\*.Test.csproj" />
289-
290279
<!-- https://github.com/dotnet/runtime/issues/73041 -->
291280
<ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.CSharp\tests\Microsoft.CSharp.Tests.csproj" />
292281
</ItemGroup>
@@ -535,7 +524,7 @@
535524
</ItemGroup>
536525

537526
<ItemGroup>
538-
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.Runtime\tests\System.Runtime.Tests.csproj" />
527+
<SmokeTestProject Condition="'$(UseNativeAOTRuntime)' != 'true'" Include="$(MSBuildThisFileDirectory)System.Runtime\tests\System.Runtime.Tests.csproj" />
539528
<GrpcTestProject Include="$(RepoRoot)\src\tests\FunctionalTests\Android\Device_Emulator\gRPC\Android.Device_Emulator.gRPC.Test.csproj" />
540529
</ItemGroup>
541530

@@ -631,7 +620,7 @@
631620
BuildInParallel="false" />
632621
</ItemGroup>
633622

634-
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(TargetOS)' == 'ios'">
623+
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(TargetOS)' == 'ios' and '$(RunAOTCompilation)' == 'true'">
635624
<!-- Only System.Runtime tests on iOS for now -->
636625
<ProjectReference Include="$(MSBuildThisFileDirectory)System.Runtime\tests\System.Runtime.Tests.csproj" />
637626

@@ -640,15 +629,20 @@
640629
BuildInParallel="false" />
641630
</ItemGroup>
642631

632+
633+
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and ('$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvos') and '$(UseNativeAOTRuntime)' == 'true'">
634+
<ProjectReference Include="$(RepoRoot)\src\tests\FunctionalTests\$(TargetOS)\Device\**\*.Test.csproj"
635+
Exclude="@(ProjectExclusions)"
636+
BuildInParallel="false" />
637+
</ItemGroup>
638+
643639
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(TargetOS)' == 'ios' and '$(IsManualOrRollingBuild)' == 'true'">
644640
<!-- These crash on tvOS, but do not on iOS. Run these only on the rolling builds -->
645641
<ProjectReference Include="$(MSBuildThisFileDirectory)System.IO.MemoryMappedFiles\tests\System.IO.MemoryMappedFiles.Tests.csproj" />
646642
<ProjectReference Include="$(MSBuildThisFileDirectory)System.Runtime.Numerics\tests\System.Runtime.Numerics.Tests.csproj" />
647643
</ItemGroup>
648644

649645
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(RunSmokeTestsOnly)' != 'true' and '$(RunGrpcTestsOnly)' != 'true' and '$(TargetOS)' == 'iossimulator'">
650-
<ProjectReference Include="$(MonoProjectRoot)sample\iOS\Program.csproj"
651-
BuildInParallel="false" />
652646
<ProjectReference Include="$(RepoRoot)\src\tests\FunctionalTests\iOS\Simulator\**\*.Test.csproj"
653647
Exclude="@(ProjectExclusions)"
654648
BuildInParallel="false" />
@@ -661,8 +655,6 @@
661655
</ItemGroup>
662656

663657
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(RunSmokeTestsOnly)' != 'true' and '$(RunGrpcTestsOnly)' != 'true' and '$(TargetOS)' == 'maccatalyst'">
664-
<ProjectReference Include="$(MonoProjectRoot)sample\iOS\Program.csproj"
665-
BuildInParallel="false" />
666658
<ProjectReference Include="$(RepoRoot)\src\tests\FunctionalTests\iOS\Simulator\**\*.Test.csproj"
667659
Exclude="@(ProjectExclusions)"
668660
BuildInParallel="false" />

src/mono/msbuild/apple/build/AppleBuild.InTree.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<Import Project="$(MSBuildThisFileDirectory)AppleBuild.targets" />
1414

1515
<!-- Use local runtime pack -->
16-
<Target Name="UpdateRuntimePack" AfterTargets="ResolveFrameworkReferences">
16+
<Target Name="UpdateRuntimePack" AfterTargets="ResolveFrameworkReferences" Condition="'$(PublishAotUsingRuntimePack)' != 'true'">
1717
<PropertyGroup>
1818
<_LocalMicrosoftNetCoreAppRuntimePackDir>$(MicrosoftNetCoreAppRuntimePackDir)</_LocalMicrosoftNetCoreAppRuntimePackDir>
1919
</PropertyGroup>

0 commit comments

Comments
 (0)