Misc fixes.
This commit is contained in:
Родитель
6a514490e0
Коммит
ec81cc6aa9
|
@ -167,8 +167,19 @@
|
|||
|
||||
<!-- Directory to store project specific stamp files used by certain targets for incremental builds -->
|
||||
<_MaciOSStampDirectory>$(IntermediateOutputPath)stamp\</_MaciOSStampDirectory>
|
||||
|
||||
<!-- Our own runtime features -->
|
||||
|
||||
<!-- Set default DisposeTaggedPointers value, we stop disposing them by default in .NET 10 -->
|
||||
<!-- The default logic here must match the default logic in NSObject.DisposeTaggedPointers -->
|
||||
<DisposeTaggedPointers Condition="'$(DisposeTaggedPointers)' == '' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 10.0))">false</DisposeTaggedPointers>
|
||||
<DisposeTaggedPointers Condition="'$(DisposeTaggedPointers)' == ''">true</DisposeTaggedPointers>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<RuntimeHostConfigurationOption Include="Foundation.NSObject.DisposeTaggedPointers" Condition="'$(DisposeTaggedPointers)' != ''" Value="$(DisposeTaggedPointers)" Trim="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetPlatformSupported Condition=" '$(TargetPlatformIdentifier)' == '$(_PlatformName)' ">true</TargetPlatformSupported>
|
||||
</PropertyGroup>
|
||||
|
@ -573,9 +584,6 @@
|
|||
<!-- Set default ValidateObjectPointers value -->
|
||||
<_ValidateObjectPointers Condition="'$(_ValidateObjectPointers)' == ''">false</_ValidateObjectPointers>
|
||||
|
||||
<!-- Set default DisposeTaggedPointers value -->
|
||||
<_DisposeTaggedPointers Condition="'$(_DisposeTaggedPointers)' == ''">true</_DisposeTaggedPointers>
|
||||
|
||||
<_CustomLinkerOptions>
|
||||
AreAnyAssembliesTrimmed=$(_AreAnyAssembliesTrimmed)
|
||||
AssemblyName=$(AssemblyName).dll
|
||||
|
@ -690,7 +698,6 @@
|
|||
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsManagedStaticRegistrar" Value="$(_IsManagedStaticRegistrarFeature)" Trim="true" />
|
||||
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsNativeAOT" Value="$(_IsNativeAOTFeature)" Trim="true" />
|
||||
<RuntimeHostConfigurationOption Include="ObjCRuntime.Class.ValidateObjectPointers" Value="$(_ValidateObjectPointers)" Trim="true" />
|
||||
<RuntimeHostConfigurationOption Include="ObjCRuntime.NSObject.DisposeTaggedPointers" Value="$(_DisposeTaggedPointers)" Trim="true" />
|
||||
|
||||
<!-- Mark all assemblies to be copied if we're not linking any assemblies -->
|
||||
<ResolvedFileToPublish
|
||||
|
|
|
@ -998,11 +998,24 @@ namespace Foundation {
|
|||
handle = NativeHandle.Zero;
|
||||
}
|
||||
|
||||
// This option is turned on by setting _DisposeTaggedPointers property to true in the project file.
|
||||
static bool dispose_tagged_pointers;
|
||||
// This option is changed by setting the DisposeTaggedPointers MSBuild property in the project file.
|
||||
static bool? dispose_tagged_pointers;
|
||||
static bool DisposeTaggedPointers {
|
||||
get => dispose_tagged_pointers;
|
||||
set => dispose_tagged_pointers = value;
|
||||
get {
|
||||
if (!dispose_tagged_pointers.HasValue) {
|
||||
if (AppContext.TryGetSwitch ("Foundation.NSObject.DisposeTaggedPointers", out var dtp)) {
|
||||
dispose_tagged_pointers = dtp;
|
||||
} else {
|
||||
// The default logic here must match how we set the default value for the DisposeTaggedPointers MSBuild property.
|
||||
#if NET10_0_OR_GREATER
|
||||
dispose_tagged_pointers = false;
|
||||
#else
|
||||
dispose_tagged_pointers = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return dispose_tagged_pointers.Value;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
|
@ -1011,34 +1024,37 @@ namespace Foundation {
|
|||
return;
|
||||
disposed = true;
|
||||
|
||||
/* Tagged pointer is limited to 64bit, which is all we support anyway.
|
||||
*
|
||||
* The tagged pointer bit is:
|
||||
*
|
||||
* Arm64: most significant bit
|
||||
* Simulators (both on arm64 and x64 desktops): most significant bit
|
||||
* Desktop/x64 (macOS + Mac Catalyst): least significant bit
|
||||
* Ref: https://github.com/apple-oss-distributions/objc4/blob/89543e2c0f67d38ca5211cea33f42c51500287d5/runtime/objc-internal.h#L603-L672
|
||||
*/
|
||||
var isTaggedPointerThatShouldNotBeDisposed = false;
|
||||
if (!DisposeTaggedPointers) {
|
||||
/* Tagged pointer is limited to 64bit, which is all we support anyway.
|
||||
*
|
||||
* The bit that identifies if a pointer is a tagged pointer is:
|
||||
*
|
||||
* Arm64 (everywhere): most significant bit
|
||||
* Simulators (both on arm64 and x64 desktops): most significant bit
|
||||
* Desktop/x64 (macOS + Mac Catalyst): least significant bit
|
||||
*
|
||||
* Ref: https://github.com/apple-oss-distributions/objc4/blob/89543e2c0f67d38ca5211cea33f42c51500287d5/runtime/objc-internal.h#L603-L672
|
||||
*/
|
||||
#if __MACOS__ || __MACCATALYST__
|
||||
ulong _OBJC_TAG_MASK;
|
||||
if (Runtime.IsARM64CallingConvention) {
|
||||
_OBJC_TAG_MASK = 1UL << 63;
|
||||
} else {
|
||||
_OBJC_TAG_MASK = 1UL;
|
||||
}
|
||||
ulong _OBJC_TAG_MASK;
|
||||
if (Runtime.IsARM64CallingConvention) {
|
||||
_OBJC_TAG_MASK = 1UL << 63;
|
||||
} else {
|
||||
_OBJC_TAG_MASK = 1UL;
|
||||
}
|
||||
#else
|
||||
const ulong _OBJC_TAG_MASK = 1UL << 63;
|
||||
const ulong _OBJC_TAG_MASK = 1UL << 63;
|
||||
#endif
|
||||
|
||||
bool isTaggedPointer;
|
||||
unchecked {
|
||||
var ulongHandle = (ulong) (IntPtr) handle;
|
||||
isTaggedPointer = (ulongHandle & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
|
||||
unchecked {
|
||||
var ulongHandle = (ulong) (IntPtr) handle;
|
||||
var isTaggedPointer = (ulongHandle & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
|
||||
isTaggedPointerThatShouldNotBeDisposed = isTaggedPointer;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DisposeTaggedPointers && isTaggedPointer) {
|
||||
// don't dispose tagged pointers.
|
||||
if (isTaggedPointerThatShouldNotBeDisposed) {
|
||||
FreeData (); // still need to do this though.
|
||||
} else if (handle != NativeHandle.Zero) {
|
||||
if (disposing) {
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<linker>
|
||||
<assembly fullname="Microsoft.MacCatalyst">
|
||||
<type fullname="Foundation.NSObject">
|
||||
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="false" value="false" />
|
||||
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="true" value="true" />
|
||||
</type>
|
||||
<type fullname="ObjCRuntime.Dlfcn">
|
||||
<method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
|
||||
</type>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<linker>
|
||||
<assembly fullname="Microsoft.iOS">
|
||||
<type fullname="Foundation.NSObject">
|
||||
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="false" value="false" />
|
||||
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="true" value="true" />
|
||||
</type>
|
||||
<type fullname="ObjCRuntime.Dlfcn">
|
||||
<method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
|
||||
</type>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<linker>
|
||||
<assembly fullname="Microsoft.tvOS">
|
||||
<type fullname="Foundation.NSObject">
|
||||
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="false" value="false" />
|
||||
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="true" value="true" />
|
||||
</type>
|
||||
<type fullname="ObjCRuntime.Dlfcn">
|
||||
<method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
|
||||
</type>
|
||||
|
|
|
@ -73,7 +73,7 @@ PLATFORM=$(shell basename "$(CURDIR)")
|
|||
endif
|
||||
|
||||
ifneq ($(RUNTIMEIDENTIFIERS)$(RUNTIMEIDENTIFIER),)
|
||||
$(error "Don't set RUNTIMEIDENTIFIER or RUNTIMEIDENTIFIERS, set RID instead")
|
||||
$(error "Don't set RUNTIMEIDENTIFIER or RUNTIMEIDENTIFIERS, set RID instead (RUNTIMEIDENTIFIER=$(RUNTIMEIDENTIFIER), RUNTIMEIDENTIFIERS=$(RUNTIMEIDENTIFIERS))")
|
||||
endif
|
||||
|
||||
ifeq ($(RID),)
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Foundation;
|
||||
|
||||
namespace DisposeTaggedPointersTestApp {
|
||||
public class Program {
|
||||
static int Main (string [] args)
|
||||
{
|
||||
var testCaseString = Environment.GetEnvironmentVariable ("TEST_CASE");
|
||||
if (string.IsNullOrEmpty (testCaseString)) {
|
||||
Console.WriteLine ($"The environment variable TEST_CASE wasn't set.");
|
||||
return 2;
|
||||
}
|
||||
#if NET10_0_OR_GREATER
|
||||
var taggedPointersDisposedByDefault = false;
|
||||
#else
|
||||
var taggedPointersDisposedByDefault = true;
|
||||
#endif
|
||||
switch (testCaseString) {
|
||||
case "DisableWithAppContext":
|
||||
AppContext.SetSwitch ("Foundation.NSObject.DisposeTaggedPointers", false);
|
||||
if (ThrowsObjectDisposedExceptions ()) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: unexpected ObjectDisposedException when DisposeTaggedPointers=false");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
case "EnableWithAppContext":
|
||||
AppContext.SetSwitch ("Foundation.NSObject.DisposeTaggedPointers", true);
|
||||
if (!ThrowsObjectDisposedExceptions ()) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: unexpected lack of ObjectDisposedException when DisposeTaggedPointers=true");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
case "DisableWithMSBuildPropertyTrimmed":
|
||||
if (ThrowsObjectDisposedExceptions ()) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: unexpected ObjectDisposedException when DisposeTaggedPointers=false");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
case "EnableWithMSBuildPropertyTrimmed":
|
||||
if (!ThrowsObjectDisposedExceptions ()) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: unexpected lack of ObjectDisposedException when DisposeTaggedPointers=true");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
case "DisableWithMSBuildPropertyUntrimmed": {
|
||||
var throws = ThrowsObjectDisposedExceptions ();
|
||||
if (throws == taggedPointersDisposedByDefault) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: unexpected ObjectDisposedException when DisposeTaggedPointers=false");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
}
|
||||
case "EnableWithMSBuildPropertyUntrimmed": {
|
||||
var throws = ThrowsObjectDisposedExceptions ();
|
||||
if (throws != taggedPointersDisposedByDefault) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: unexpected lack of ObjectDisposedException when DisposeTaggedPointers=true");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
}
|
||||
case "Default": {
|
||||
var throws = ThrowsObjectDisposedExceptions ();
|
||||
if (throws != taggedPointersDisposedByDefault) {
|
||||
Console.WriteLine ($"❌ {testCaseString}: Failure: Expected ObjectDisposedException: {taggedPointersDisposedByDefault} Threw ObjectDisposedException: {throws}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine ($"✅ {testCaseString}: Success");
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
Console.WriteLine ($"❌ Unknown test case: {testCaseString }");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ThrowsObjectDisposedExceptions () => MonoTouchFixtures.ObjCRuntime.TaggedPointerTest.ThrowsObjectDisposedExceptions ();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(SetAppendRuntimeIdentifierToOutputPathToFalse)' == 'true'">
|
||||
<!-- Used by the AppendRuntimeIdentifierToOutputPath_* tests -->
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildThisFileDirectory)../../Directory.Build.props" />
|
||||
</Project>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-maccatalyst</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\shared.csproj" />
|
||||
</Project>
|
|
@ -0,0 +1 @@
|
|||
include ../shared.mk
|
|
@ -0,0 +1,2 @@
|
|||
TOP=../../..
|
||||
include $(TOP)/tests/common/shared-dotnet-test.mk
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-ios</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\shared.csproj" />
|
||||
</Project>
|
|
@ -0,0 +1 @@
|
|||
include ../shared.mk
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-macos</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\shared.csproj" />
|
||||
</Project>
|
|
@ -0,0 +1 @@
|
|||
include ../shared.mk
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
||||
<ApplicationTitle>DisposeTaggedPointersTestApp</ApplicationTitle>
|
||||
<ApplicationId>com.xamarin.disposetaggedpointerstestapp</ApplicationId>
|
||||
|
||||
<UseInterpreter>true</UseInterpreter> <!-- to speed up the test run -->
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="../../common/shared-dotnet.csproj" />
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="../*.cs" />
|
||||
<Compile Include="../../../monotouch-test/ObjCRuntime/TaggedPointerTest.Shared.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,44 @@
|
|||
TOP=../../../..
|
||||
TESTNAME=DisposeTaggedPointersTestApp
|
||||
include $(TOP)/tests/common/shared-dotnet.mk
|
||||
|
||||
export RUNTIMEIDENTIFIER=
|
||||
export RUNTIMEIDENTIFIERS=
|
||||
|
||||
.stamp-restore:
|
||||
$(Q) $(DOTNET) restore
|
||||
$(Q) touch $@
|
||||
|
||||
define Test
|
||||
clean-$(2):
|
||||
$(Q) rm -f .stamp-build-$(2)
|
||||
$(Q) rm -rf bin/$(1) obj/$(1)
|
||||
CLEAN_TARGETS+=clean-$(2)
|
||||
|
||||
.stamp-build-$(2): .stamp-restore
|
||||
$(MAKE) build CONFIG=$(1) BUILD_ARGUMENTS="/tl:off $(3)"
|
||||
$(Q) touch $$@
|
||||
BUILD_TARGETS+=.stamp-build-$(2)
|
||||
|
||||
run-$(2): export TEST_CASE=$(1)
|
||||
run-$(2): .stamp-build-$(2)
|
||||
$(MAKE) run-bare CONFIG=$(1)
|
||||
RUN_TARGETS+=run-$(2)
|
||||
|
||||
test-$(2): run-$(2)
|
||||
endef
|
||||
|
||||
$(eval $(call Test,Default,default))
|
||||
$(eval $(call Test,DisableWithAppContext,disablewithappcontext))
|
||||
$(eval $(call Test,EnableWithAppContext,enablewithappcontext))
|
||||
$(eval $(call Test,DisableWithMSBuildPropertyUntrimmed,disablewithmsbuildpropertyuntrimmed,/p:DisposeTaggedPointers=false /p:_LinkMode=None))
|
||||
$(eval $(call Test,EnableWithMSBuildPropertyUntrimmed,enablewithmsbuildpropertyuntrimmed,/p:DisposeTaggedPointers=true /p:_LinkMode=None))
|
||||
$(eval $(call Test,DisableWithMSBuildPropertyTrimmed,disablewithmsbuildpropertytrimmed,/p:DisposeTaggedPointers=false /p:_LinkMode=SdkOnly))
|
||||
$(eval $(call Test,EnableWithMSBuildPropertyTrimmed,enablewithmsbuildpropertytrimmed,/p:DisposeTaggedPointers=true /p:_LinkMode=SdkOnly))
|
||||
|
||||
build-all: $(BUILD_TARGETS)
|
||||
clean-all:: $(CLEAN_TARGETS)
|
||||
$(Q) rm -f .stamp-* *.binlog
|
||||
test-all run-tests run-all run: $(RUN_TARGETS)
|
||||
|
||||
.PHONY: $(TEST_CASES)
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-tvos</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\shared.csproj" />
|
||||
</Project>
|
|
@ -0,0 +1 @@
|
|||
include ../shared.mk
|
|
@ -2864,5 +2864,29 @@ namespace Xamarin.Tests {
|
|||
var errors = BinLog.GetBuildLogErrors (rv.BinLogPath).ToArray ();
|
||||
AssertErrorMessages (errors, $"The SupportedOSPlatformVersion value '{version}' in the project file is lower than the minimum value '{minVersion}'.");
|
||||
}
|
||||
|
||||
[TestCase (ApplePlatform.MacOSX)]
|
||||
[TestCase (ApplePlatform.MacCatalyst)]
|
||||
public void DisposeTaggedPointersTest (ApplePlatform platform)
|
||||
{
|
||||
var project = "DisposeTaggedPointersTestApp";
|
||||
Configuration.IgnoreIfIgnoredPlatform (platform);
|
||||
|
||||
var project_path = GetProjectPath (project, platform: platform);
|
||||
Clean (project_path);
|
||||
|
||||
var arguments = new string [] {
|
||||
"-C", Path.GetDirectoryName (project_path)!,
|
||||
"clean-all"
|
||||
};
|
||||
AssertExecute ("make", arguments, out var _);
|
||||
|
||||
arguments = new string [] {
|
||||
"-C", Path.GetDirectoryName (project_path)!,
|
||||
"test-all",
|
||||
"-j",
|
||||
};
|
||||
AssertExecute ("make", arguments, out var _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
|
||||
using Foundation;
|
||||
|
||||
namespace MonoTouchFixtures.ObjCRuntime {
|
||||
public partial class TaggedPointerTest {
|
||||
public static bool ThrowsObjectDisposedExceptions ()
|
||||
{
|
||||
try {
|
||||
var notificationData =
|
||||
"""
|
||||
{
|
||||
action = "action";
|
||||
aps =
|
||||
{
|
||||
category = "ee";
|
||||
"content-available" = dd;
|
||||
"mutable-content" = cc;
|
||||
sound = bb;
|
||||
"thread-id" = "aa";
|
||||
};
|
||||
"em-account" = "a";
|
||||
"em-account-id" = "b";
|
||||
"em-body" = "c";
|
||||
"em-date" = "d";
|
||||
"em-from" = "e";
|
||||
"em-from-address" = "f";
|
||||
"em-notification" = g;
|
||||
"em-notification-id" = h;
|
||||
"em-subject" = "i";
|
||||
"gcm.message_id" = j;
|
||||
"google.c.a.e" = k;
|
||||
"google.c.fid" = l;
|
||||
"google.c.sender.id" = m;
|
||||
}
|
||||
""";
|
||||
|
||||
var data = NSData.FromString (notificationData);
|
||||
var fmt = NSPropertyListFormat.OpenStep;
|
||||
var userInfo = (NSMutableDictionary) NSPropertyListSerialization.PropertyListWithData (data, NSPropertyListReadOptions.Immutable, ref fmt, out var error);
|
||||
var apsKey = new NSString ("aps");
|
||||
// Iteration here should not throw ObjectDisposedExceptions
|
||||
foreach (var kv in userInfo) {
|
||||
apsKey.Dispose ();
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (ObjectDisposedException) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using Foundation;
|
||||
|
||||
|
@ -8,47 +10,34 @@ namespace MonoTouchFixtures.ObjCRuntime {
|
|||
|
||||
[TestFixture]
|
||||
[Preserve (AllMembers = true)]
|
||||
public class TaggedPointerTest {
|
||||
public partial class TaggedPointerTest {
|
||||
|
||||
[Test]
|
||||
public void TaggedPointersArentDisposed ()
|
||||
{
|
||||
var notificationData =
|
||||
"""
|
||||
{
|
||||
action = "action";
|
||||
aps =
|
||||
{
|
||||
category = "ee";
|
||||
"content-available" = dd;
|
||||
"mutable-content" = cc;
|
||||
sound = bb;
|
||||
"thread-id" = "aa";
|
||||
};
|
||||
"em-account" = "a";
|
||||
"em-account-id" = "b";
|
||||
"em-body" = "c";
|
||||
"em-date" = "d";
|
||||
"em-from" = "e";
|
||||
"em-from-address" = "f";
|
||||
"em-notification" = g;
|
||||
"em-notification-id" = h;
|
||||
"em-subject" = "i";
|
||||
"gcm.message_id" = j;
|
||||
"google.c.a.e" = k;
|
||||
"google.c.fid" = l;
|
||||
"google.c.sender.id" = m;
|
||||
}
|
||||
""";
|
||||
#if NET10_0_OR_GREATER
|
||||
var taggedPointersDisposedByDefault = false;
|
||||
#else
|
||||
var taggedPointersDisposedByDefault = true;
|
||||
#endif
|
||||
Assert.AreEqual (taggedPointersDisposedByDefault, ThrowsObjectDisposedExceptions (), "Default behavior");
|
||||
}
|
||||
|
||||
var data = NSData.FromString (notificationData);
|
||||
var fmt = NSPropertyListFormat.OpenStep;
|
||||
var userInfo = (NSMutableDictionary) NSPropertyListSerialization.PropertyListWithData (data, NSPropertyListReadOptions.Immutable, ref fmt, out var error);
|
||||
var apsKey = new NSString ("aps");
|
||||
// Iteration here should not throw ObjectDisposedExceptions
|
||||
foreach (var kv in userInfo) {
|
||||
apsKey.Dispose ();
|
||||
[Test]
|
||||
public void MemoryUsage ()
|
||||
{
|
||||
var taggedStringValue = "a";
|
||||
var objA = new NSString (taggedStringValue);
|
||||
var objB = new NSString (taggedStringValue);
|
||||
Assert.AreEqual (objA.Handle, objB.Handle, "Pointer equality for tagged pointers");
|
||||
|
||||
var cwt = new ConditionalWeakTable<string, NSObject> ();
|
||||
var count = 1000;
|
||||
for (var i = 0; i < count; i++) {
|
||||
cwt.Add (i.ToString (), new NSString (taggedStringValue));
|
||||
}
|
||||
GC.Collect ();
|
||||
Assert.That (cwt.Count (), Is.LessThan (count), "At least some objects should have gotten garbage collected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче