diff --git a/tests/.gitignore b/tests/.gitignore index 323d1973fafa..aa989f0701ba 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,4 +1,26 @@ -*-tvos.csproj -*-watchos.csproj -*-unified.csproj +index.html +*.log +*-unified.sln +TestResult.xml +build +*-tvos.?sproj +*-tvos.sln +*-watchos.?sproj +*-watchos-app.?sproj +*-watchos-extension.?sproj +*-watchos.sln +*-tvos.plist +*-watchos.plist +*-unified.?sproj +*-unifiedXM45.?sproj +*-unifiedXM45.sln +Makefile-mac.inc +.stamp* +Info-*.plist +*.zip +Makefile.inc +*.stamp +test.config +mac-test-package +.nuget diff --git a/tests/BundledResources/BundledResources.csproj b/tests/BundledResources/BundledResources.csproj new file mode 100644 index 000000000000..18d9fd56b62c --- /dev/null +++ b/tests/BundledResources/BundledResources.csproj @@ -0,0 +1,54 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + BundledResources + Resources + BundledResources + MonoTouch + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + False + + + none + True + bin\Release + prompt + 4 + False + DO_NOT_REMOVE + + + + + + + + + + + basn3p08.png + + + xamvideotest.mp4 + + + + + + + \ No newline at end of file diff --git a/tests/BundledResources/ResourcesTest.cs b/tests/BundledResources/ResourcesTest.cs new file mode 100644 index 000000000000..5bd5d98fd27a --- /dev/null +++ b/tests/BundledResources/ResourcesTest.cs @@ -0,0 +1,49 @@ +// +// Resource Bundling Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace BundledResources { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ResourcesTest { + + [Test] + public void Bundled () + { + // files are extracted (by MonoDevelop) so we can see them in the file system + // that's true for simulator or devices and whatever the linker settings are + var dir = NSBundle.MainBundle.BundlePath; + Assert.True (File.Exists (Path.Combine (dir, "basn3p08.png")), "file-basn3p08.png"); + Assert.True (File.Exists (Path.Combine (dir, "xamvideotest.mp4")), "xamvideotest.mp4"); + + // resources are removed by the linker or an extra step (e.g. "link sdk" or "don't link") but that + // extra step is done only on device (to keep the simulator builds as fast as possible) + var resources = typeof(ResourcesTest).Assembly.GetManifestResourceNames (); + if (Runtime.Arch == Arch.DEVICE) { + Assert.That (resources.Length, Is.EqualTo (0), "No resources"); + } else { + Assert.That (resources.Length, Is.GreaterThanOrEqualTo (2), "Resources"); + Assert.That (resources, Contains.Item ("__monotouch_content_basn3p08.png"), "res-basn3p08.png"); + Assert.That (resources, Contains.Item ("__monotouch_content_xamvideotest.mp4"), "res-xamvideotest.mp4"); + } + } + } +} \ No newline at end of file diff --git a/tests/EmbeddedResources/EmbeddedResources.csproj b/tests/EmbeddedResources/EmbeddedResources.csproj new file mode 100644 index 000000000000..4e737dfe798a --- /dev/null +++ b/tests/EmbeddedResources/EmbeddedResources.csproj @@ -0,0 +1,53 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {676F527D-3352-42EA-9DE2-181C45003568} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + EmbeddedResources + Resources + EmbeddedResources + true + ..\..\..\xamarin-macios\product.snk + MonoTouch + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + False + + + none + True + bin\Release + prompt + 4 + False + DO_NOT_REMOVE + + + + + + + + + + + + + + + + + + diff --git a/tests/EmbeddedResources/ResourcesTest.cs b/tests/EmbeddedResources/ResourcesTest.cs new file mode 100644 index 000000000000..df3728d192c4 --- /dev/null +++ b/tests/EmbeddedResources/ResourcesTest.cs @@ -0,0 +1,40 @@ +// +// Resource Bundling Tests +// +// Authors: +// Rolf Bjarne Kvinge (rolf@xamarin.com) +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Resources; +using System.Globalization; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace EmbeddedResources { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ResourcesTest { + + [Test] + public void Embedded () + { + var manager = new ResourceManager ("EmbeddedResources.Welcome", typeof(ResourcesTest).Assembly); + + Assert.AreEqual ("Welcome", manager.GetString ("String1", new CultureInfo ("en")), "en"); + Assert.AreEqual ("Willkommen", manager.GetString ("String1", new CultureInfo ("de")), "de"); + Assert.AreEqual ("Bienvenido", manager.GetString ("String1", new CultureInfo ("es")), "es"); + } + } +} \ No newline at end of file diff --git a/tests/EmbeddedResources/Welcome.de.resx b/tests/EmbeddedResources/Welcome.de.resx new file mode 100755 index 000000000000..73b49728033d --- /dev/null +++ b/tests/EmbeddedResources/Welcome.de.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Willkommen + + \ No newline at end of file diff --git a/tests/EmbeddedResources/Welcome.es.resx b/tests/EmbeddedResources/Welcome.es.resx new file mode 100755 index 000000000000..4adb75c3c1f6 --- /dev/null +++ b/tests/EmbeddedResources/Welcome.es.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bienvenido + + \ No newline at end of file diff --git a/tests/EmbeddedResources/Welcome.resx b/tests/EmbeddedResources/Welcome.resx new file mode 100755 index 000000000000..b1b776a53a30 --- /dev/null +++ b/tests/EmbeddedResources/Welcome.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Welcome + + \ No newline at end of file diff --git a/tests/Makefile b/tests/Makefile index c934fc6de10c..d7b0849d3269 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,342 @@ -TOP=.. +TOP = ../../xamarin-macios + +ifdef INCLUDE_MAC +SUBDIRS += no-mmp +endif +# disabled for now: mac-test + include $(TOP)/Make.config +include $(TOP)/mk/rules.mk + +MTOUCH=$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/mtouch +UNIT_SERVER_DIR=$(TOUCH_UNIT_PATH)/Touch.Server +UNIT_SERVER=$(UNIT_SERVER_DIR)/bin/Debug/Touch.Server.exe +TEST_SUITES=monotouch-test link\ sdk link\ all dont\ link framework-test mini +BCL_TEST_SUITES=mscorlib System System.Core System.Data System.Net.Http System.Numerics System.Runtime.Serialization System.Transactions System.Web.Services System.Xml System.Xml.Linq Mono.Security System.ComponentModel.DataAnnotations System.Json System.ServiceModel.Web Mono.Data.Sqlite +ALL_TEST_SUITES=$(TEST_SUITES) $(BCL_TEST_SUITES) +EXEC_UNIT_SERVER=XCODE_DEVELOPER_ROOT=$(XCODE_DEVELOPER_ROOT) MONOTOUCH_ROOT=$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX) $(SYSTEM_MONO) --debug $(UNIT_SERVER) + +export MD_APPLE_SDK_ROOT=$(abspath $(XCODE_DEVELOPER_ROOT)/../..) +export MD_MTOUCH_SDK_ROOT=$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX) +export XBUILD_FRAMEWORK_FOLDERS_PATH=$(IOS_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks +export MSBuildExtensionsPath=$(IOS_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild +export XAMMAC_FRAMEWORK_PATH=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current +export XamarinMacFrameworkRoot=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current + +ifneq ($(RELEASE),) +CONFIG=Release +else +CONFIG=Debug +endif + +ifeq ($(V),) +ifeq ($(BUILD_REVISION),) +# non-verbose local build +XHARNESS_VERBOSITY= +else +# wrench build +XHARNESS_VERBOSITY=--verbose +endif +else +# verbose build +XHARNESS_VERBOSITY=--verbose +endif + +# +# To run all the tests, just do: +# +# make run-tests +# +# and go take a long tea break. +# +# For faster turnaround there are specific targets that can be used +# to run specific test suites. For more information read the README.md. +# + +all-local:: qa-test-dependencies.zip mac-test-package.zip + +test.config: Makefile $(TOP)/Make.config + @rm -f $@ + @echo "MONOTOUCH_PREFIX=$(abspath $(MONOTOUCH_PREFIX))" >> $@ + @echo "IOS_DESTDIR=$(abspath $(IOS_DESTDIR))" >> $@ + @echo "MAC_DESTDIR=$(abspath $(MAC_DESTDIR))" >> $@ + @echo "WATCH_MONO_PATH=$(abspath $(WATCH_MONO_PATH))" >> $@ + +clean-local:: + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhoneSimulator /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhone /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhoneSimulator /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests-unified.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhone /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests-unified.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhoneSimulator /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests-tvos.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhoneSimulator /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests-tvos.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhone /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests-watchos.sln + $(Q) $(SYSTEM_XBUILD) /t:Clean /p:Platform=iPhone /p:Configuration=$(CONFIG) $(XBUILD_VERBOSITY) tests-watchos.sln + +## run targets = build + [install] + exec + +run run-all run-tests run-test: + $(Q) for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir run || exit 1; \ + done + $(Q) $(MAKE) run-local + +# separate build-dev-* entries because some of them are build with debug other (llvm) with release +build-dev-bots: build-test-libraries + # test LLVM armv6, this is Classic only because arm64 doesn't have llvm support. + $(MAKE) "build-ios-devclassic-dont link" CONFIG=Release + # test LLVM armv7, this is Classic only because arm64 doesn't have llvm support. + $(MAKE) "build-ios-devclassic-link all" CONFIG=Release + # test LLVM armv6 arm7 (fat), this is Classic only because arm64 doesn't have llvm support. + $(MAKE) "build-ios-devclassic-link sdk" CONFIG=Release + # test LLVM arm7 w/thumb2, this is Classic only because arm64 doesn't have llvm support. + $(MAKE) build-ios-devclassic-monotouch-test CONFIG=Release + # test BCL mscorlib + $(MAKE) build-ios-dev-mscorlib CONFIG=Release + # test BCL System.Core + $(MAKE) build-ios-dev-System.Core CONFIG=Release + # run any other scripted tests + $(MAKE) -C scripted + +build-% run-% exec-% install-%: + @echo "" + @echo "\033[0;31mUnknown target: $@\033[0m" + @echo "" + @echo "Syntax is: ---" + @echo " Action: build, install (only for device), exec, run (= build + install + exec)." + @echo " Platform: ios, tvos, watchos (can be skipped, in which case all platforms are executed)" + @echo " Where: " + @echo " ios: sim = [simclassic + simunified = [sim32, sim64]]; dev = [devclassic + devunified]" + @echo " tvos/watchos: sim, dev" + @echo " What: The test project to run (BCL tests do not need to be treated specially anymore, just use test project's name)" + @echo "" + @echo "Example:" + @echo "" + @echo " # this will run monotouch-test on an Apple TV device" + @echo " $ make run-tvos-dev-monotouch-test" + @echo "" + @echo "For more info read README.md." + @echo "" + @exit 1 + +check-result: + @test -z "$(BUILD_REVISION)" || echo "@MonkeyWrench: AddFile: $(abspath $(FILE))" + @if grep "Tests run" "$(FILE)"; then \ + if grep FAIL "$(FILE)"; then \ + test "x" == "x$(BUILD_REVISION)" -o "x" == "x$(TESTNAME)" || echo "@MonkeyWrench: AddSummary: $(TESTNAME) failed: `grep "Tests run:" "$(FILE)" | sed 's/Tests run: //'`
"; \ + echo Test run failed; \ + exit 1; \ + else \ + test "x" == "x$(BUILD_REVISION)" -o "x" == "x$(TESTNAME)" || echo "@MonkeyWrench: AddSummary: $(TESTNAME) succeeded: `grep "Tests run:" "$(FILE)" | sed 's/Tests run: //'`
"; \ + echo Test run succeeded; \ + fi; \ + else \ + test "x" == "x$(BUILD_REVISION)" -o "x" == "x$(TESTNAME)" || echo "@MonkeyWrench: AddSummary: $(TESTNAME) crashed
"; \ + echo Test run crashed; \ + exit 1; \ + fi + +logdev: + $(MTOUCH) --logdev + +$(UNIT_SERVER): $(wildcard $(UNIT_SERVER_DIR)/*.cs) + (cd $(UNIT_SERVER_DIR) && $(SYSTEM_XBUILD)) + +build-test-libraries: + @$(MAKE) -C $(TOP)/tests/test-libraries + +Makefile.inc: xharness/xharness.exe + $(Q_GEN) $(SYSTEM_MONO) --debug $< $(XHARNESS_VERBOSITY) --configure --autoconf --rootdir $(CURDIR) + +-include Makefile.inc + +$(GUI_UNIT_PATH)/bin/net_4_5/GuiUnit.exe: + XBUILD_FRAMEWORK_FOLDERS_PATH=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks MSBuildExtensionsPath=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild XamarinMacFrameworkRoot=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current xbuild $(GUI_UNIT_PATH)/src/framework/GuiUnit_NET_4_5.csproj + +$(GUI_UNIT_PATH)/bin/xammac_mobile/GuiUnit.exe: + XBUILD_FRAMEWORK_FOLDERS_PATH=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks MSBuildExtensionsPath=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild XamarinMacFrameworkRoot=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current xbuild $(GUI_UNIT_PATH)/src/framework/GuiUnit_xammac_mobile.csproj + +Makefile-mac.inc: xharness/xharness.exe + $(Q_GEN) $(SYSTEM_MONO) --debug $< $(XHARNESS_VERBOSITY) --configure --autoconf --mac --rootdir $(CURDIR) + +-include Makefile-mac.inc + +$(TOP)/tools/mtouch/SdkVersions.cs: $(TOP)/tools/mtouch/SdkVersions.cs.in + @$(MAKE) -C $(TOP)/tools/mtouch SdkVersions.cs + +.stamp-src-project-files: + @$(MAKE) -C $(TOP)/src project-files + @touch $@ + +xharness/xharness.exe: $(wildcard xharness/*.cs) xharness/xharness.csproj $(TOP)/tools/mtouch/SdkVersions.cs test.config .stamp-src-project-files + $(Q_GEN) $(SYSTEM_XBUILD) $(XBUILD_VERBOSITY_QUIET) xharness/xharness.csproj + +killall: + @killall "iPhone Simulator" >/dev/null 2>&1 || true + @killall "iOS Simulator" >/dev/null 2>&1 || true + @killall Touch.Server >/dev/null 2>&1 || true + +NUNIT_MSBUILD_DIR=$(TOP)/msbuild/packages/NUnit.Runners.2.6.4/tools/lib +test-ios-tasks: + $(SYSTEM_XBUILD) $(TOP)/msbuild/Xamarin.MacDev.Tasks.sln + cd $(NUNIT_MSBUILD_DIR) && $(SYSTEM_MONO) ../nunit-console.exe ../../../../tests/bin/Xamarin.iOS.Tasks.Tests.dll -xml=TestResults_Xamarin.iOS.Tasks.Tests.xml -labels $(TEST_FIXTURE) || touch .failed-stamp + @[[ -z "$$BUILD_REPOSITORY" ]] || ( xsltproc $(TOP)/tests/HtmlTransform.xslt $(NUNIT_MSBUILD_DIR)/TestResults_Xamarin.iOS.Tasks.Tests.xml > $(TOP)/tests/index.html && echo "@MonkeyWrench: AddFile: $$PWD/index.html" ) + @if test -e $(NUNIT_MSBUILD_DIR)/.failed-stamp; then rm $(NUNIT_MSBUILD_DIR)/.failed-stamp; exit 1; fi + +ifdef ENABLE_XAMARIN +ifdef INCLUDE_IOS +qa-test-dependencies.zip: + @$(MAKE) build-test-libraries + @# Make sure we start from a clean slate + $(Q) rm -rf $@ $@.tmpdir +ifdef INCLUDE_TVOS + @# TVOS + $(Q) mkdir -p $@.tmpdir/tvos + $(Q) cp $(TOP)/src/build/tvos/reference/MonoTouch.Dialog-1.dll* $@.tmpdir/tvos + $(Q) cp $(TOP)/src/build/tvos/reference/MonoTouch.NUnitLite.dll* $@.tmpdir/tvos + $(Q) cp $(TOP)/tests/test-libraries/.libs/tvos/libtest.a $@.tmpdir/tvos + $(Q) cp $(TOP)/tests/test-libraries/.libs/tvos/libtest.dylib $@.tmpdir/tvos + $(Q) cp -a $(TOP)/tests/test-libraries/.libs/tvos/XTest.framework $@.tmpdir/tvos +endif + @# iOS + $(Q) mkdir -p $@.tmpdir/ios + $(Q) cp $(TOP)/tests/test-libraries/.libs/ios/libtest.a $@.tmpdir/ios + $(Q) cp $(TOP)/tests/test-libraries/.libs/ios/libtest.dylib $@.tmpdir/ios + $(Q) cp -a $(TOP)/tests/test-libraries/.libs/ios/XTest.framework $@.tmpdir/ios + $(Q) cp $(MACCORE_PATH)/tools/mlaunch/mlaunch $@.tmpdir + @# Generate zip + $(Q_GEN) cd $@.tmpdir && zip -9r $(abspath $@) . + @# Cleanup + $(Q) rm -rf $@.tmpdir +else +qa-test-dependencies.zip: + @echo Not enabled +endif +else +qa-test-dependencies.zip: + @echo Xamarin build not enabled +endif + +ifdef INCLUDE_MAC +mac-test-package.zip: + ./package-mac-tests.sh +else +mac-test-package.zip: + @echo Not enabled +endif + +#XI +ifdef INCLUDE_IOS +wrench-mtouch: + cd mtouch && $(MAKE) + git clean -xfdq + +wrench-btouch: + cd generator && $(MAKE) + cd generator && git clean -xfdq + +wrench-build-unit-test-dev: + $(MAKE) build-dev-bots + git clean -xfdq + +wrench-sim-linksdk: + $(Q) $(MAKE) wrench-sim-link\ sdk + +wrench-sim-linkall: + $(Q) $(MAKE) wrench-sim-link\ all + +wrench-sim-dontlink: + $(Q) $(MAKE) wrench-sim-dont\ link + +else +wrench-mtouch wrench-btouch wrench-build-unit-test-dev: + @echo "iOS tests have been disabled [$@]" +endif + +## XM +ifdef INCLUDE_MAC +wrench-mac-dontlink: + $(Q) $(MAKE) run-mac-dontlink + $(Q) $(MAKE) clean-mac-dontlink + +wrench-mac-mmp: + @echo Now part of wrench-mac-mmptest + +wrench-mac-misc: + @echo Tests mac-misc tests removed + +wrench-mac-apidiff: + @echo This is done in the normal api-diff target now. + +wrench-mac-drm: + @echo "The DRM tests have all been removed." + +wrench-mac-api: + $(Q) $(MAKE) run-mac-apitest + $(Q) $(MAKE) clean-mac-apitest + +wrench-mac-mmptest: + $(Q) $(MAKE) run-mac-mmptest + $(Q) $(MAKE) clean-mac-mmptest + $(Q) $(MAKE) -C mmptest/regression + +wrench-mac-msbuild: + $(Q) $(MAKE) run-mac-msbuild + $(Q) $(MAKE) clean-mac-msbuild + +wrench-mac-binding-project: + cd mac-binding-project && $(MAKE) + cd mac-binding-project && git clean -xfdq + +else +wrench-mac-%: + @echo "Mac tests have been disabled [$@]" +endif + +wrench-msbuild: + $(MAKE) -C $(TOP)/msbuild test-xml +ifdef INCLUDE_IOS + $(MAKE) test-ios-tasks +else + @echo "iOS tests have been disabled [$@]" +endif + cd $(TOP)/msbuild && git clean -xfdq + +wrench-docs: +ifdef ENABLE_XAMARIN +ifdef INCLUDE_IOS + $(MAKE) -C $(MACCORE_PATH) update-docs +else + @echo "iOS tests have been disabled [$@]" +endif +else + @echo "Docs have been disabled [$@]" +endif + +# the wrenchhelper-* targets are generated. +wrench-sim-%: + git clean -xfdq +ifdef INCLUDE_IOS + unset LD_LIBRARY_PATH && script -q /dev/null $(MAKE) "wrenchhelper-$*" +else + @echo "iOS tests have been disabled [$@]" +endif + +wrench-bcl-sim-%: + git clean -xfdq +ifdef INCLUDE_IOS + unset LD_LIBRARY_PATH && script -q /dev/null $(MAKE) "wrenchhelper-$*" +else + @echo "iOS tests have been disabled [$@]" +endif + +wrench-%: + git clean -xfdq +ifdef INCLUDE_IOS + touch "exec-$*.log" + echo "@MonkeyWrench: AddFile: $(PWD)/exec-$*.log" + unset LD_LIBRARY_PATH && script -q /dev/null $(MAKE) "run-$*" + echo "Test succeeded" +else + @echo "iOS tests have been disabled [$@]" +endif -%: - $(MAKE) -C $(MACCORE_PATH)/tests $@ diff --git a/tests/README.md b/tests/README.md index 66cf824d879f..f83b5688c9ea 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,4 +1,181 @@ -README.md +# Various tests to be executed prior to releases + +## Test solutions + +Many of the test solutions and test projects are generated, and will +only be available after running `make` once. + +* tests.sln: This is the base test solution, which targets iOS using the Classic API. _Not_ generated. +* tests-unified.sln: All the iOS test projects using the Unified API. Generated. +* tests-tvos.sln: All the TVOS test projects. Generated. +* tests-watchos.sln: All the WatchOS test projects. Generated. + +### Test solution/project generation + +The tool that generates the test solutions / projects is called xharness, +and lives in the xharness subdirectory. + +## Types of Tests + +### Unit Tests + +Most of the projects are using NUnit[Lite] and looks like unit tests. +They are meant to be executed on the target: simulator, devices, OSX. + +In reality most of them are regression tests - but that does not change +the need to execute and continually expand them to cover new code. + + +### Introspection Tests + +Introspection tests are executed on target (both simulator and device for +iOS) or a specific version of OSX. The application proceed to analyze itself +using: + +* `System.Reflection` for managed code; and +* the ObjectiveC runtime library for native code + +and compare the results. E.g. if using .NET reflection it can see a binding +for a `NSBundle` type then it should be able to find a native `NSBundle` +type using the ObjC runtime functions. Otherwise an error is raised... + +Since the application analyze itself it must contains everything we wish +to test. That's why the introspection tests are part of the `dontlink.app` +application (for iOS) and the dontlink-mac project (for OSX). + +Pros + +* They always tell the truth, which can differ from documentation + +Cons + +* Incomplete - Not everything is encoded in the metadata / executable; +* Too complete - Not every truth is good to be known (or published) + + +### Extrospection Tests ### + +Extrospection tests takes data from some outside sources and see if our +implementation match the information, e.g. + +* Header files from the SDK; +* Rules, like Gendarme or FxCop; + +Since this is done externally there's no need to run them on the devices, +simulator or even a specific version of OSX. + +Pro + +* There is more data available, e.g. information lost when compiling + +Con + +* The data might not represent the truth (errors, false positives...) + + + +# Test Suites + +## *-tests : where * is the assembly name, e.g. monotouch + +Use the project defaults for linking, i.e. + +* "Don't link" for simulator + +* "Link SDK assemblies only" for devices + +## dontlink + +* regression testing without using the linker + +* both simulator and devices are set to "Don't link" + +## linkall + +* regression testing using the linker on the all assemblies + +* "Link all assemblies" for both simulator/devices + +## linksdk + +* regression testing using the linker on the SDK assemblies + +* "Link SDK assemblies only" for both simulator/devices + +## bcl-test + +These are the Mono BCL test suite tweaked to run on the mobile profile. +It reuse the files directly from mono's repository (linking, not copying). + +As other unit tests the configuration is set to mimick normal apps, e.g. + +* "Don't link" for simulator + +* "Link SDK assemblies only" for devices + + +# Common make targets + +Run every test in both the simulator and on device, using both the compat and the new profile (for the simulator both in 32 and 64bit mode). + + $ make run + +Run every test in the simulator, using both the compat and the new profile (both 32 and 64bit simulators). + + $ make run-all-sim + +Run every test on device, using both the compat and the new profile + + $ make run-all-dev + +# Detailed make targets + +* Main target + + * run-*what*-*where*-*project*: Builds, installs (if applicable) and runs the specified test project on the specified platform. This is the most common target to use. + * build-*what*-*where*-*project*: Will build the specified test project for the specified platform and target. + * install-*what*-*where*-*project*: Will install the specified test project on a connected device. There's currently no way to select the device, so ensure you've only one connected (if many devices are connected, it's random which will used). + * exec-*what*-*where*-*project*: Will run the specified test project in the simulator or on a device. + +* What + + * -ios-: iOS. + * -tvos-: TVOS. + * -watchos-: WatchOS + + If "What" is skipped, all variations are executed sequentially. + +* Where + + * -simclassic-: Simulator using the Classic API. Only applicable when platform is iOS. + * -simunified-: Simulator using Unified API. The build will contain both an i386 and an x86_64 binary. Only applicable to the build-* target, while the -sim32- and -sim64- are only applicable to the exec-* targets. Only applicable when the platform is iOS. + * -sim32-: 32bits iOS simulator using the Unified API. Not applicable to other platforms. + * -sim64-: 64bits iOS simulator using the Unified API. Not applicable to other platforms. + * -sim-: + * iOS: Both the -simclassic- and -simunified- versions. + * WatchOS/TVOS: The WatchOS/TVOS simulator. + * -devclassic-: Device using the Classic API. Only applicable when the platform is iOS. + * -devunified-: Device using the Unified API. The build will contain both an armv7 and an arm64 binary. It's not possible to select a 32/64bit version, you'll run what your device supports. Only applicable when the platform is iOS. + * -dev-: + * iOS: Both the -devclassic- and -devunified- versions. + * WatchOS/TVOS: A Watch or TV device. + +* Examples + + $ make run-ios-sim32-monotouchtest: This will run `monotouch-test` using the Unified API in a 32-bit simulator. + $ make run-tvos-dev-dont\ link: This will run `dont link` on an Apple TV device. + +# Utility run-* targets + +These targets will build, install (if applicable) and run the specified project(s). + +* Simulator + * run-sim-*project*: Builds and runs the specified test project in the simulator in compat, 32 and 64bit mode. + * run-sim: Builds and runs all the non-bcl test projects in the simulator in compat, 32 and 64bit mode. + +* Device + * run-dev-*project*: Builds and runs the specified non-bcl test project on a device in compat and native mode (if it's 32 and 64bit depends on the device; 64bit devices will run in 64bit mode and the same for 32bit devices). + * run-devcompat: Run all the non-bcl test projects on device, in compat mode. + * run-devdual: Run all the non-bcl test projects on device, in native mode (if it's 32 and 64bit depends on the device; 64bit devices will run in 64bit mode and the same for 32bit devices). + * run-dev: Run all the non-bcl test projects on device, in both compat and native mode. -Our test suites are presently being re-worked to work without external, -non public, dependencies. They will be added here shortly. diff --git a/tests/api-shared/CoreFoundation/CFNotificationCenterTest.cs b/tests/api-shared/CoreFoundation/CFNotificationCenterTest.cs new file mode 100644 index 000000000000..c8c82ea15844 --- /dev/null +++ b/tests/api-shared/CoreFoundation/CFNotificationCenterTest.cs @@ -0,0 +1,91 @@ +// +// Unit tests for CFNotificationCenter +// +// Authors: +// Miguel de Icaza (miguel@xamarin.com) +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; + +#if XAMCORE_2_0 +using Foundation; +using CoreFoundation; +#else +#if MONOMAC +using MonoMac.CoreFoundation; +using MonoMac.Foundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +#endif +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class CFNotificationCenterTest + { + [Test] + public void TestObservers () + { + var target = new NSObject (); + var d = CFNotificationCenter.Local; + int count = 0; + int count2 = 0; + CFNotificationObserverToken o2 = null; + var o1 = d.AddObserver ("hello", target, (x,dd)=>{ + count++; +// Console.WriteLine ("Here"); + + if (count == 1) + o2 = d.AddObserver ("hello", target, (y,ee)=> { +// Console.WriteLine ("There"); + count2++; + }); + }); + d.PostNotification ("hello", target, null, deliverImmediately:true); + Assert.AreEqual (1, count); + d.PostNotification ("hello", target, null, deliverImmediately:true); + Assert.AreEqual (2, count); + Assert.AreEqual (1, count2); + + // Remove the first observer, count should not be updated + d.RemoveObserver (o1); + d.PostNotification ("hello", target, null); + Assert.AreEqual (2, count); + Assert.AreEqual (2, count2); + + // Remove the last observer, there should be no change in count + d.RemoveObserver (o2); + d.PostNotification ("hello", target, null); + Assert.AreEqual (2, count); + Assert.AreEqual (2, count2); + + // Test removing all observers + count = 0; + o1 = d.AddObserver ("hello", target, (x,dd)=>{ + count++; + Console.WriteLine ("Here"); + }); + o2 = d.AddObserver ("hello", target, (y,ee)=> {count++;}); + d.RemoveEveryObserver (); + d.PostNotification ("hello", target, null); + Assert.AreEqual (0, count); + + // Test removing from a callback + count = 0; + o2 = d.AddObserver ("hello", target, (y,ee)=> {count++; d.RemoveObserver (o2); }); + d.PostNotification ("hello", target, null); + Assert.AreEqual (1, count); + d.PostNotification ("hello", target, null); + Assert.AreEqual (1, count); + } + + } +} + diff --git a/tests/api-shared/ObjCRuntime/RegistrarTest.cs b/tests/api-shared/ObjCRuntime/RegistrarTest.cs new file mode 100644 index 000000000000..596cfbffd3d8 --- /dev/null +++ b/tests/api-shared/ObjCRuntime/RegistrarTest.cs @@ -0,0 +1,69 @@ +// +// Unit tests for the registrars. +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif __IOS__ +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace XamarinTests.ObjCRuntime { + [TestFixture] + public class RegistrarSharedTest { + public static Registrars CurrentRegistrar { + get { + return Registrar.CurrentRegistrar; + } + } + + [Test] + public void IntPtrCtor () + { + IntPtr ptr = IntPtr.Zero; + try { + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (IntPtrCtorTestClass)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init")); + var ex = Assert.Throws (() => Messaging.bool_objc_msgSend_IntPtr (ptr, Selector.GetHandle ("conformsToProtocol:"), IntPtr.Zero)); + var msg = string.Format ("Failed to marshal the Objective-C object 0x{0} (type: IntPtrCtorTestClass). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'XamarinTests.ObjCRuntime.RegistrarSharedTest+IntPtrCtorTestClass' does not have a constructor that takes one IntPtr argument).", ptr.ToString ("x")); + if (CurrentRegistrar == Registrars.Static || CurrentRegistrar == Registrars.OldStatic) { + msg += "\nAdditional information:\n\tSelector: conformsToProtocol:\n\tMethod: "; +#if !XAMCORE_2_0 +#if __IOS__ + msg += "MonoTouch."; +#else + msg += "MonoMac."; +#endif +#endif + msg += "Foundation.NSObject:InvokeConformsToProtocol (intptr)\n"; + } + Assert.AreEqual (msg, ex.Message, "#message"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + } + + [Register ("IntPtrCtorTestClass")] + class IntPtrCtorTestClass : NSObject { + [Export ("initWithFoo:")] + public IntPtrCtorTestClass (int foo) + { + Console.WriteLine ("foo1"); + } + } + } +} diff --git a/tests/apitest/.gitignore b/tests/apitest/.gitignore new file mode 100644 index 000000000000..0cef782ba01b --- /dev/null +++ b/tests/apitest/.gitignore @@ -0,0 +1,2 @@ +TestResult* +build/ diff --git a/tests/apitest/Info.plist b/tests/apitest/Info.plist new file mode 100644 index 000000000000..803c7af5e180 --- /dev/null +++ b/tests/apitest/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleDisplayName + apitest + CFBundleIdentifier + com.xamarin.apitest + CFBundleName + apitest + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSPrincipalClass + NSApplication + + diff --git a/tests/apitest/apitest.csproj b/tests/apitest/apitest.csproj new file mode 100644 index 000000000000..2cbc657ad2ae --- /dev/null +++ b/tests/apitest/apitest.csproj @@ -0,0 +1,155 @@ + + + + Debug + x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + apitest + apitest + v4.5 + Resources + + + true + full + false + bin\x86\Debug + DEBUG;MONOMAC + prompt + 4 + false + false + Mac Developer + false + false + false + false + x86 + + + true + bin\x86\Debug + MONOMAC + prompt + 4 + false + true + Developer ID Application + true + false + true + false + SdkOnly + x86 + + + + + + + + + + ..\..\..\xamarin-macios\external\guiunit\bin\net_4_5\GuiUnit.exe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + shared\ObjCRuntime\RegistrarTest.cs + + + shared\ObjCRuntime\Registrar.cs + + + src\CoreFoundation\CFNotificationCenterTest.cs + + + shared\PlatformInfo.cs + + + shared\MacTestMain.cs + + + + + + + diff --git a/tests/apitest/src/AVFoundation/AVAudioIONode.cs b/tests/apitest/src/AVFoundation/AVAudioIONode.cs new file mode 100644 index 000000000000..f31e4fab8e4c --- /dev/null +++ b/tests/apitest/src/AVFoundation/AVAudioIONode.cs @@ -0,0 +1,35 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.AudioUnit; +using MonoMac.AVFoundation; +using AUUnit = MonoMac.AudioUnit.AudioUnit; +#else +using AppKit; +using Foundation; +using AudioUnit; +using AUUnit = AudioUnit.AudioUnit; +using AVFoundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class AVAudioIONodeTests + { + [Test] + public void AVAudioIONodeTests_AudioUnitTest () + { + Asserts.EnsureYosemite (); + + AVAudioEngine eng = new AVAudioEngine(); + AVAudioIONode node = eng.OutputNode; + AUUnit unit = node.AudioUnit; + unit.GetElementCount (AudioUnitScopeType.Global); + // Make sure this doens't crash. + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AVFoundation/AVPlayerLayerTest.cs b/tests/apitest/src/AVFoundation/AVPlayerLayerTest.cs new file mode 100644 index 000000000000..4525a5227470 --- /dev/null +++ b/tests/apitest/src/AVFoundation/AVPlayerLayerTest.cs @@ -0,0 +1,33 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.AudioUnit; +using MonoMac.AVFoundation; +#else +using AppKit; +using Foundation; +using AudioUnit; +using AVFoundation; +using AUUnit = AudioUnit.AudioUnit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class AVPlayerLayerTests + { + [Test] + public void AVPlayerLayer_VideoGravity () + { + AVPlayerLayer layer = new AVPlayerLayer (); +#if XAMCORE_2_0 + Assert.IsNotNull (layer.VideoGravity); +#else + Assert.IsNotNull (layer.LayerVideoGravity); +#endif + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSAppearance.cs b/tests/apitest/src/AppKit/NSAppearance.cs new file mode 100644 index 000000000000..1218984110fb --- /dev/null +++ b/tests/apitest/src/AppKit/NSAppearance.cs @@ -0,0 +1,58 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +using nfloat = System.Single; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSAppearanceTests + { + [Test] + public void NSAppearanceShouldLoadAppearanceNamed () + { + Asserts.EnsureYosemite (); + + var appearance = NSAppearance.GetAppearance (NSAppearance.NameVibrantDark); + Assert.IsNotNull (appearance, "NSAppearanceShouldLoadAppearanceNamed - Failed to initialize appearance VibrantDark"); + Assert.AreEqual (appearance.Name, NSAppearance.NameVibrantDark.ToString (), "NSAppearanceShouldLoadAppearanceNamed - Appearance initialized with incorrect name."); + } + +#if FALSE // Test failing, exception doesn't appear to be thrown during test, throw correctly running in an app. + [Test] + public void NSAppearanceConstructorShouldFailWithInvalidName () + { + bool exceptionHit = false; + + try { + var appearance = new NSAppearance ("InvalidNameTest", null); + } catch (ArgumentException e) { + exceptionHit = true; + } + + Assert.IsTrue (exceptionHit, "NSAppearanceConstructorShouldFailWithInvalidName - No exception thrown while initializing appearance with invalid name."); + } +#endif + + [Test] + public void NSAppearanceShouldChangeCurrentAppearance () + { + Asserts.EnsureYosemite (); + + var appearance = NSAppearance.CurrentAppearance; + + NSAppearance.CurrentAppearance = NSAppearance.GetAppearance (NSAppearance.NameVibrantDark); + + Assert.AreNotEqual (appearance, NSAppearance.CurrentAppearance, "NSAppearanceShouldChangeCurrentAppearance - Failed to change appearance."); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSApplication.cs b/tests/apitest/src/AppKit/NSApplication.cs new file mode 100644 index 000000000000..80f661476a4e --- /dev/null +++ b/tests/apitest/src/AppKit/NSApplication.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSApplicationTests + { + [Test] + public void NSApplication_SendActionNullTest () + { + NSApplication.SharedApplication.SendAction(new Selector("undo:"), null, new NSObject ()); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSCellTest.cs b/tests/apitest/src/AppKit/NSCellTest.cs new file mode 100644 index 000000000000..fb8e947132cb --- /dev/null +++ b/tests/apitest/src/AppKit/NSCellTest.cs @@ -0,0 +1,95 @@ +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using AppKit; +using Foundation; +using ObjCRuntime; +#else +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +using NUnit.Framework; + +namespace MonoMacFixtures.AppKit +{ + [TestFixture] + public class CellTest + { + [Test] + public void CopyTest () + { + using (var cell = new CustomCell ()) + Check (cell.Handle); + } + + [Test] + public void CopyDerivedTest () + { + using (var cell = new DerivedCell ()) + Check (cell.Handle); + } + + void Check (IntPtr cell_handle) + { + var clone_ptr = IntPtr_objc_msgSend (cell_handle, Selector.GetHandle ("copyWithZone:"), IntPtr.Zero); +// Console.WriteLine ("Created cell 0x{0} (GCHandle: 0x{2}) with clone 0x{1} (GCHandle: 0x{3})", cell_handle.ToString ("x"), clone_ptr.ToString ("x"), GetGCHandle (cell_handle).ToString ("x"), GetGCHandle (clone_ptr).ToString ("x")); + + Assert.AreNotEqual (GetGCHandle (cell_handle), GetGCHandle (clone_ptr), "gchandle #1"); + CustomCell.expectedHandle = cell_handle; + objc_msgSend (Class.GetHandle (typeof (CustomCell)), Selector.GetHandle ("foo:"), cell_handle); + + Assert.AreNotEqual (GetGCHandle (cell_handle), GetGCHandle (clone_ptr), "gchandle #2"); + CustomCell.expectedHandle = clone_ptr; + objc_msgSend (Class.GetHandle (typeof (CustomCell)), Selector.GetHandle ("foo:"), clone_ptr); + + Assert.AreNotEqual (GetGCHandle (cell_handle), GetGCHandle (clone_ptr), "gchandle #3"); + + objc_msgSend (clone_ptr, Selector.GetHandle ("release")); + } + + [DllImport ("__Internal", EntryPoint = "xamarin_get_gchandle")] + extern static int GetGCHandle (IntPtr ptr); + + const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib"; + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector, IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void objc_msgSend (IntPtr receiver, IntPtr selector, IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB)] + internal extern static IntPtr object_getInstanceVariable (IntPtr cls, string name, out IntPtr value); + } + + class CustomCell : NSCell { + public static IntPtr expectedHandle; + + public CustomCell (IntPtr ptr) : base (ptr) { } + public CustomCell () { } + + [Export ("foo:")] + public static void Foo (CustomCell mySelf) + { + Assert.AreEqual (expectedHandle, mySelf.Handle, "Handle"); + } + } + + class DerivedCell : CustomCell + { + public DerivedCell (IntPtr ptr) : base (ptr) { } + public DerivedCell () { } + + public override NSObject Copy (NSZone zone) + { + return base.Copy (zone); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSClipView.cs b/tests/apitest/src/AppKit/NSClipView.cs new file mode 100644 index 000000000000..ee77bdd975ef --- /dev/null +++ b/tests/apitest/src/AppKit/NSClipView.cs @@ -0,0 +1,33 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using CoreGraphics; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSClipViewTests + { + [Test] + public void NSClipViewConstrainBoundsRect () + { + Asserts.EnsureMavericks (); + + var clipView = new NSClipView (new CGRect (0, 0, 50, 50)); + var rect = clipView.ConstrainBoundsRect (new CGRect (10, 10, 30, 30)); + + Assert.IsTrue (rect.X == 0, "NSClipViewConstrainBoundsRect - X value was not 0"); + Assert.IsTrue (rect.Y == 0, "NSClipViewConstrainBoundsRect - Y value was not 0"); + Assert.IsTrue (rect.Width == 30, "NSClipViewConstrainBoundsRect - Width value was not 30"); + Assert.IsTrue (rect.Height == 30, "NSClipViewConstrainBoundsRect - Height value was not 30"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSColor.cs b/tests/apitest/src/AppKit/NSColor.cs new file mode 100644 index 000000000000..95b8a4603e1e --- /dev/null +++ b/tests/apitest/src/AppKit/NSColor.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using nfloat = System.Single; +#else +using AppKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSColorTests + { + [Test] + public void NSColor_ComponentTests () + { + NSColor c = NSColor.Blue; + nfloat [] components; + c.GetComponents (out components); + Assert.IsTrue (0f == components[0], "Red"); + Assert.IsTrue (0f == components[1], "Green"); + Assert.IsTrue (1f == components[2], "Blue"); + } + + [Test] + public void SingleComponents () + { + var c = NSColor.Red; + nfloat[] components; + c.GetComponents (out components); + Assert.AreEqual (c.RedComponent, components [0], "Red"); + Assert.AreEqual (c.GreenComponent, components [1], "Green"); + Assert.AreEqual (c.BlueComponent, components [2], "Blue"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSControl.cs b/tests/apitest/src/AppKit/NSControl.cs new file mode 100644 index 000000000000..46b8063cb576 --- /dev/null +++ b/tests/apitest/src/AppKit/NSControl.cs @@ -0,0 +1,91 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +#else +using AppKit; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSControlTests + { + [Test] + public void NSControlShouldChangeControlSize () + { + Asserts.EnsureYosemite (); + var control = new NSButton (); + var size = control.ControlSize; + control.ControlSize = NSControlSize.Mini; + + Assert.IsFalse (size == control.ControlSize); + Assert.IsTrue (control.ControlSize == NSControlSize.Mini); + } + + [Test] + public void NSControlShouldChangeHighlighted () + { + Asserts.EnsureYosemite (); + + var control = new NSButton (); + var highlighted = control.Highlighted; + control.Highlighted = !highlighted; + + Assert.IsFalse (highlighted == control.Highlighted); + } + + [Test] + public void NSControlShouldChangeLineBreakMode () + { + Asserts.EnsureYosemite (); + + var control = new NSButton (); + var lineBreak = control.LineBreakMode; + control.LineBreakMode = NSLineBreakMode.Clipping; + + Assert.IsTrue (control.LineBreakMode == NSLineBreakMode.Clipping); + Assert.IsFalse (lineBreak == control.LineBreakMode); + } + + [Test] + public void NSControlShouldAddMultipleActivatedEventHandlers () + { + var control = new NSButton (); + + int firstHitCount = 0; + int secondHitCount = 0; + + control.Activated += (sender, e) => firstHitCount++; + control.Activated += (sender, e) => secondHitCount++; + + control.PerformClick (control); + + Assert.IsTrue (firstHitCount == 1, "NSControlShouldAddMultipleActivatedEventHandlers - Did not call first EventHandler"); + Assert.IsTrue (secondHitCount == 1, "NSControlShouldAddMultipleActivatedEventHandlers - Did not call second EventHandler"); + } + + [Test] + public void NSControlShouldRemoveAndAddActivatedEventHandlers () + { + var control = new NSButton (); + + int firstHitCount = 0; + int secondHitCount = 0; + + EventHandler firstDelegate = (object sender, EventArgs e) => firstHitCount++; + + control.Activated += firstDelegate; + control.Activated -= firstDelegate; + control.Activated += (sender, e) => secondHitCount++; + + control.PerformClick (control); + + Assert.IsTrue (firstHitCount == 0, "NSControlShouldRemoveAndAddActivatedEventHandlers - Called first EventHandler after it was removed"); + Assert.IsTrue (secondHitCount == 1, "NSControlShouldRemoveAndAddActivatedEventHandlers - Did not call second EventHandler"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSDraggingItem.cs b/tests/apitest/src/AppKit/NSDraggingItem.cs new file mode 100644 index 000000000000..c5f962a474b3 --- /dev/null +++ b/tests/apitest/src/AppKit/NSDraggingItem.cs @@ -0,0 +1,46 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSDraggingItemTests + { + [Test] + public void NSDraggingItemConstructorTests () + { +#pragma warning disable 0219 + NSDraggingItem item = new NSDraggingItem ((NSString)"Testing"); + item = new NSDraggingItem (new MyPasteboard ()); +#pragma warning restore 0219 + } + + class MyPasteboard : NSPasteboardWriting + { + public override NSObject GetPasteboardPropertyListForType (string type) + { + return new NSObject (); + } + + public override string[] GetWritableTypesForPasteboard (NSPasteboard pasteboard) + { + return new string [] {}; + } + + public override NSPasteboardWritingOptions GetWritingOptionsForType (string type, NSPasteboard pasteboard) + { + return NSPasteboardWritingOptions.WritingPromised; + } + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSGradient.cs b/tests/apitest/src/AppKit/NSGradient.cs new file mode 100644 index 000000000000..f6377670d64a --- /dev/null +++ b/tests/apitest/src/AppKit/NSGradient.cs @@ -0,0 +1,58 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using nfloat = System.Single; +#else +using AppKit; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSGradientTests + { + [Test] + public void NSGradientConstructorTests () + { + NSColorSpace colorSpace = NSColorSpace.GenericRGBColorSpace; + NSGradient g = new NSGradient (new[] { NSColor.Black, NSColor.White, NSColor.Black }, new[] { 0f, .5f, 1.0f }, colorSpace); + Assert.IsNotNull (g); + Assert.AreEqual (colorSpace, g.ColorSpace); + Assert.AreEqual (3, g.ColorStopsCount); + + // Since we are asking for colors on a gradient, there will be some color blending, even with just black and white. + const float closeEnough = .05f; + NSColor black = NSColor.Black.UsingColorSpace (NSColorSpace.CalibratedRGB); + NSColor white = NSColor.White.UsingColorSpace (NSColorSpace.CalibratedRGB); + + NSColor color; + nfloat location; + + g.GetColor (out color, out location, 0); + color = color.UsingColorSpace (NSColorSpace.CalibratedRGB); + Assert.IsTrue (black.RedComponent - color.RedComponent < closeEnough); + Assert.IsTrue (black.BlueComponent - color.BlueComponent < closeEnough); + Assert.IsTrue (black.GreenComponent - color.GreenComponent < closeEnough); + Assert.AreEqual (0.0f, (float)location); + + g.GetColor (out color, out location, 1); + color = color.UsingColorSpace (NSColorSpace.CalibratedRGB); + Assert.IsTrue (white.RedComponent - color.RedComponent < closeEnough); + Assert.IsTrue (white.BlueComponent - color.BlueComponent < closeEnough); + Assert.IsTrue (white.GreenComponent - color.GreenComponent < closeEnough); + Assert.AreEqual (0.5f, (float)location); + + g.GetColor (out color, out location, 2); + color = color.UsingColorSpace (NSColorSpace.CalibratedRGB); + Assert.IsTrue (black.RedComponent - color.RedComponent < closeEnough); + Assert.IsTrue (black.BlueComponent - color.BlueComponent < closeEnough); + Assert.IsTrue (black.GreenComponent - color.GreenComponent < closeEnough); + Assert.AreEqual (1.0f, (float)location); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSImage.cs b/tests/apitest/src/AppKit/NSImage.cs new file mode 100644 index 000000000000..0116836a27b6 --- /dev/null +++ b/tests/apitest/src/AppKit/NSImage.cs @@ -0,0 +1,55 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using CGSize = System.Drawing.SizeF; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +#else +using AppKit; +using CoreGraphics; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSImageTests + { + [Test] + public void ImageWithSize () + { + Asserts.EnsureMountainLion (); + var image = NSImage.ImageWithSize (new CGSize (50, 50), false, rect => { + return true; + }); + Assert.IsNotNull (image); + } + + [Test] + public void NSImageCapInsets () + { + Asserts.EnsureYosemite (); + + var image = new NSImage (); + image.CapInsets = new NSEdgeInsets (5f, 6f, 7f, 8f); + + Assert.IsNotNull (image.CapInsets); + Assert.IsTrue (image.CapInsets.Top == 5f, "NSImageCapInsets - Top value was not 5"); + Assert.IsTrue (image.CapInsets.Left == 6f, "NSImageCapInsets - Left value was not 6"); + Assert.IsTrue (image.CapInsets.Bottom == 7f, "NSImageCapInsets - Bottom value was not 7"); + Assert.IsTrue (image.CapInsets.Right == 8f, "NSImageCapInsets - Right value was not 8"); + } + + [Test] + public void NSImageResizingModeShouldChange () + { + Asserts.EnsureYosemite (); + + var image = new NSImage (); + image.ResizingMode = NSImageResizingMode.Stretch; + Assert.AreEqual (image.ResizingMode, NSImageResizingMode.Stretch, "NSImageResizingMode - Was not equal to Stretch"); + Assert.AreNotEqual (image.ResizingMode, NSImageResizingMode.Tile, "NSImageResizingMode - Was incorrectly equal to Tile"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSLayoutManagerTests.cs b/tests/apitest/src/AppKit/NSLayoutManagerTests.cs new file mode 100644 index 000000000000..20b03d9c9361 --- /dev/null +++ b/tests/apitest/src/AppKit/NSLayoutManagerTests.cs @@ -0,0 +1,67 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +using CGPoint = System.Drawing.PointF; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +using CoreGraphics; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSLayoutManagerTests + { + NSLayoutManager manager; + + [SetUp] + public void CreateManager () + { + // This sets up the global context so our drawing doesn't produce error messages + NSBitmapImageRep bitmap = new NSBitmapImageRep (IntPtr.Zero, 1000, 1000, 16, 4, true, false, NSColorSpace.DeviceRGB, 0, 0); + NSGraphicsContext.CurrentContext = NSGraphicsContext.FromBitmap (bitmap); + + NSTextStorage storage = new NSTextStorage ("Hello World"); + NSTextContainer container = new NSTextContainer (); + manager = new NSLayoutManager (); + + manager.AddTextContainer (container); + storage.AddLayoutManager (manager); + } + + [Test] + public void NSLayoutManager_DrawBackgroundForGlyphRange () + { + manager.DrawBackgroundForGlyphRange (new NSRange (0, 4), new CGPoint (10, 10)); + } + + [Test] + public void NSLayoutManager_DrawGlyphsForGlyphRange () + { + manager.DrawGlyphsForGlyphRange (new NSRange (0, 4), new CGPoint (10, 10)); + } + + [Test] + public void NSLayoutManager_CharacterRangeForGlyphRange () + { + NSRange pnt; + NSRange range = manager.CharacterRangeForGlyphRange (new NSRange (0, 4), out pnt); + Assert.IsNotNull (range); + } + + [Test] + public void NSLayoutManager_GlyphRangeForCharacterRange () + { + NSRange pnt; + NSRange range = manager.GlyphRangeForCharacterRange (new NSRange (0, 4), out pnt); + Assert.IsNotNull (range); + } + } +} diff --git a/tests/apitest/src/AppKit/NSOutlineView.cs b/tests/apitest/src/AppKit/NSOutlineView.cs new file mode 100644 index 000000000000..f8ae10450931 --- /dev/null +++ b/tests/apitest/src/AppKit/NSOutlineView.cs @@ -0,0 +1,42 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +#else +using AppKit; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSOutlineViewTests + { + [Test] + public void NSOutlineView_InsertNull () + { + NSOutlineView v = new NSOutlineView (); + v.BeginUpdates (); // We do this to prevent a crash: Insert/remove/move only works within a -beginUpdates/-endUpdates block or a View Based TableView +#if !XAMCORE_2_0 + v.InsertItems (new NSIndexSet (0), null, NSTableViewAnimationOptions.EffectFade); +#else + v.InsertItems (new NSIndexSet (0), null, NSTableViewAnimation.None); +#endif + v.EndUpdates (); + } + + [Test] + public void NSOutlineView_DelegateDataSourceNull () + { + NSOutlineView v = new NSOutlineView (); + v.WeakDelegate = null; + v.Delegate = null; + v.WeakDataSource = null; + v.DataSource = null; + } + } +} + diff --git a/tests/apitest/src/AppKit/NSPasteboard.cs b/tests/apitest/src/AppKit/NSPasteboard.cs new file mode 100644 index 000000000000..e88c664d113f --- /dev/null +++ b/tests/apitest/src/AppKit/NSPasteboard.cs @@ -0,0 +1,57 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSPasteboardTests + { + [Test] + public void NSPasteboardTests_WriteObjectTests () + { + NSPasteboard b = NSPasteboard.CreateWithUniqueName(); + b.WriteObjects (new INSPasteboardWriting [] { (NSString)"asfd" }); + b.WriteObjects (new NSPasteboardWriting [] { new MyPasteboard () }); +#if !XAMCORE_2_0 + // Awesome backwards compat API + b.WriteObjects (new NSPasteboardReading [] { new MyPasteboard2 () }); +#endif + } + + class MyPasteboard2 : NSPasteboardReading + { + public override NSObject InitWithPasteboardPropertyList (NSObject propertyList, string type) + { + return new NSObject (); + } + } + + class MyPasteboard : NSPasteboardWriting + { + public override NSObject GetPasteboardPropertyListForType (string type) + { + return new NSObject (); + } + + public override string[] GetWritableTypesForPasteboard (NSPasteboard pasteboard) + { + return new string [] {}; + } + + public override NSPasteboardWritingOptions GetWritingOptionsForType (string type, NSPasteboard pasteboard) + { + return NSPasteboardWritingOptions.WritingPromised; + } + } + } +} diff --git a/tests/apitest/src/AppKit/NSPathControl.cs b/tests/apitest/src/AppKit/NSPathControl.cs new file mode 100644 index 000000000000..f1e18b30828c --- /dev/null +++ b/tests/apitest/src/AppKit/NSPathControl.cs @@ -0,0 +1,79 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSPathControlTests + { + [Test] + public void NSPathControlShouldSetEditable () + { + Asserts.EnsureYosemite (); + + var control = new NSPathControl (); + var editable = control.Editable; + control.Editable = !editable; + + Assert.IsTrue (control.Editable != editable, "NSPathControlShouldSetEditable - Failed to change the Editable property"); + } + + [Test] + public void NSPathControlShouldSetAllowedTypes () + { + Asserts.EnsureYosemite (); + + var control = new NSPathControl (); + var allowedTypes = control.AllowedTypes; + control.AllowedTypes = new [] { (NSString)"exe", (NSString)"jpg" }; + + Assert.IsTrue (control.AllowedTypes != allowedTypes, "NSPathControlShouldSetAllowedTypes - Failed to change AllowedTypes property"); + } + + [Test] + public void NSPathControlShouldSetPlaceholderString () + { + Asserts.EnsureYosemite (); + + var control = new NSPathControl (); + var placeholderString = control.PlaceholderString; + control.PlaceholderString = "Test Placeholder"; + + Assert.IsTrue (control.PlaceholderString != placeholderString, "NSPathControlShouldSetPlaceholderString - Failed to change PlaceholderString property"); + } + + [Test] + public void NSPathControlShouldSetPlaceholderAttributedString () + { + Asserts.EnsureYosemite (); + + var control = new NSPathControl (); + var placeholderAttributedString = control.PlaceholderAttributedString; + control.PlaceholderAttributedString = new NSAttributedString ("Test Placeholder"); + + Assert.IsTrue (control.PlaceholderAttributedString != placeholderAttributedString, "NSPathControlShouldSetPlaceholderAttributedString - Failed to change PlaceholderAttributedString property"); + } + + [Test] + public void NSPathControlShouldSetPathItems () + { + Asserts.EnsureYosemite (); + + var control = new NSPathControl (); + var pathItems = control.PathItems; + control.PathItems = new [] { new NSPathControlItem () }; + + Assert.IsTrue (control.PathItems != pathItems, "NSPathControlShouldSetPathItems - Failed to set PathItems property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSPathControlItem.cs b/tests/apitest/src/AppKit/NSPathControlItem.cs new file mode 100644 index 000000000000..bd459ad5431a --- /dev/null +++ b/tests/apitest/src/AppKit/NSPathControlItem.cs @@ -0,0 +1,56 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSPathControlItemTests + { + [SetUp] + public void Setup () + { + Asserts.EnsureYosemite (); + } + + [Test] + public void NSPathControlItemShouldSetTitle () + { + var item = new NSPathControlItem (); + var title = item.Title; + item.Title = "Test"; + + Assert.IsTrue (item.Title != title, "NSPathControlShouldSetTitle - Title value did not change."); + } + + [Test] + public void NSPathControlItemShouldSetAttributedTitle () + { + var item = new NSPathControlItem (); + var attributedTitle = item.AttributedTitle; + item.AttributedTitle = new NSAttributedString ("Test"); + + Assert.IsTrue (item.AttributedTitle != attributedTitle, "NSPathControlShouldSetAttributedTitle - AttributedTitle value did not change."); + + } + + [Test] + public void NSPathControlItemShouldSetImage () + { + var item = new NSPathControlItem (); + Assert.IsTrue (item.Image == null, "NSPathControlItemShouldSetImage - Image did not start as null"); + + item.Image = new NSImage (); + Assert.IsTrue (item.Image != null, "NSPathControlItemShouldSetImage - Failed to set Image property"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSSearchField.cs b/tests/apitest/src/AppKit/NSSearchField.cs new file mode 100644 index 000000000000..9d16c3da3c9b --- /dev/null +++ b/tests/apitest/src/AppKit/NSSearchField.cs @@ -0,0 +1,71 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSSearchFieldTests + { + [Test] + public void NSSearchFieldShouldSetSearchMenuTemplate () + { + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) < Platform.Mac_10_10) + return; + + var searchField = new NSSearchField (); + var searchMenuTemplate = searchField.SearchMenuTemplate; + searchField.SearchMenuTemplate = new NSMenu ("Test"); + + Assert.IsTrue (searchField.SearchMenuTemplate != searchMenuTemplate, "NSSearchFieldShouldSetSearchMenuTemplate - Failed to set the SearchMenuTemplate property."); + } + + [Test] + public void NSSearchFieldShouldSetSendsWholeSearchString () + { + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) < Platform.Mac_10_10) + return; + + var searchField = new NSSearchField (); + var sendsWholeSearchString = searchField.SendsWholeSearchString; + searchField.SendsWholeSearchString = !sendsWholeSearchString; + + Assert.IsTrue (searchField.SendsWholeSearchString != sendsWholeSearchString, "NSSearchFieldShouldSetSendsWholeSearchString - Failed to set the SendsWholeSearchString property."); + } + + [Test] + public void NSSearchFieldShouldSetMaximumRecents () + { + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) < Platform.Mac_10_10) + return; + + var searchField = new NSSearchField (); + var maximumRecents = searchField.MaximumRecents; + searchField.MaximumRecents = maximumRecents + 3; + + Assert.IsTrue (searchField.MaximumRecents != maximumRecents, "NSSearchFieldShouldSetMaximumRecents - Failed to set the MaximumRecents property."); + } + + [Test] + public void NSSearchFieldShouldSetSendsSearchStringImmediately () + { + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) < Platform.Mac_10_10) + return; + + var searchField = new NSSearchField (); + var sendsSearchStringImmediately = searchField.SendsSearchStringImmediately; + searchField.SendsSearchStringImmediately = !sendsSearchStringImmediately; + + Assert.IsTrue (searchField.SendsSearchStringImmediately != sendsSearchStringImmediately, "NSSearchFieldShouldSetSendsSearchStringImmediately - Failed to set the SendsSearchStringImmediately property."); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSSplitViewController.cs b/tests/apitest/src/AppKit/NSSplitViewController.cs new file mode 100644 index 000000000000..458349a88c27 --- /dev/null +++ b/tests/apitest/src/AppKit/NSSplitViewController.cs @@ -0,0 +1,99 @@ +using System; +using NUnit.Framework; +using System.Linq; + +#if !XAMCORE_2_0 +using System.Drawing; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; + +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSSplitViewControllerTests + { + NSSplitViewController controller; + + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + + controller = new NSSplitViewController (); + } + + [Test] + public void NSSplitViewControllerShouldChangeSplitView () + { + var splitView = controller.SplitView; + controller.SplitView = new NSSplitView (); + + Assert.IsFalse (controller.SplitView == splitView, "NSSplitViewControllerShouldChangeSplitView - Failed to set the SplitView property"); + } + + [Test] + public void NSSplitViewControllerShouldChangeSplitViewItems () + { + var items = controller.SplitViewItems; + controller.SplitViewItems = new NSSplitViewItem [] { new NSSplitViewItem { ViewController = new NSViewController () } }; + + Assert.IsFalse (controller.SplitViewItems == items, "NSSplitViewControllerShouldChangeSplitViewItems - Failed to set the SplitViewItems property"); + } + + [Test] + public void NSSplitViewControllerShouldAddSplitViewItem () + { + var item = new NSSplitViewItem { ViewController = new NSViewController () }; + controller.AddSplitViewItem (item); + + Assert.IsTrue (controller.SplitViewItems.Contains (item), "NSSplitViewControllerShouldAddSplitViewItem - Failed to add item"); + } + + [Test] + public void NSSplitViewControllerShouldRemoveSplitViewItem () + { + var item = new NSSplitViewItem { ViewController = new NSViewController () }; + controller.AddSplitViewItem (item); + + Assert.IsTrue (controller.SplitViewItems.Contains (item), "NSSplitViewControllerShouldRemoveSplitViewItem - Failed to add item"); + + controller.RemoveSplitViewItem (item); + + Assert.IsFalse (controller.SplitViewItems.Contains (item), "NSSplitViewControllerShouldRemoveSplitViewItem - Failed to remove item"); + } + + [Test] + public void NSSplitViewControllerShouldInsertSplitViewItem () + { + controller.AddSplitViewItem (new NSSplitViewItem { ViewController = new NSViewController () }); + controller.AddSplitViewItem (new NSSplitViewItem { ViewController = new NSViewController () }); + controller.AddSplitViewItem (new NSSplitViewItem { ViewController = new NSViewController () }); + var item = new NSSplitViewItem { ViewController = new NSViewController () }; + controller.InsertSplitViewItem (item, 1); + + Assert.IsTrue (controller.SplitViewItems [1] == item, "NSSplitViewControllerShouldInsertSplitViewItem - Failed to insert the item at the given position."); + Assert.IsFalse (controller.SplitViewItems [0] == item, "NSSplitViewControllerShouldInsertSplitViewItem - Inserted the item in the wrong position."); + } + + [Test] + public void NSSplitViewControllerShouldGetSplitViewItem () + { + controller.AddSplitViewItem (new NSSplitViewItem { ViewController = new NSViewController () }); + controller.AddSplitViewItem (new NSSplitViewItem { ViewController = new NSViewController () }); + controller.AddSplitViewItem (new NSSplitViewItem { ViewController = new NSViewController () }); + var viewController = new NSViewController (); + var item = new NSSplitViewItem { ViewController = viewController }; + controller.InsertSplitViewItem (item, 1); + + var retrievedItem = controller.GetSplitViewItem (viewController); + + Assert.IsTrue (retrievedItem == item, "NSSplitViewControllerShouldGetSplitViewItem - Failed to get SplitViewItem from ViewController"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSSplitViewItem.cs b/tests/apitest/src/AppKit/NSSplitViewItem.cs new file mode 100644 index 000000000000..b58497a00061 --- /dev/null +++ b/tests/apitest/src/AppKit/NSSplitViewItem.cs @@ -0,0 +1,77 @@ +using System; +using NUnit.Framework; +using System.Linq; + +#if !XAMCORE_2_0 +using System.Drawing; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; + +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSSplitViewItemTests + { + NSSplitViewItem item; + + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + + item = new NSSplitViewItem (); + } + + [Test] + public void NSSplitViewItemShouldCreateFromViewController () + { + var viewController = new NSViewController (); + var splitViewItem = NSSplitViewItem.FromViewController (viewController); + + Assert.IsFalse (splitViewItem == null, "NSSplitViewItemShouldCreateFromViewController - Returned null"); + Assert.IsTrue (splitViewItem.ViewController == viewController, "NSSplitViewItemShouldCreateFromViewController - ViewController property not set correctly"); + } + + [Test] + public void NSSplitViewItemShouldChangeViewController () + { + var viewController = item.ViewController; + item.ViewController = new NSViewController (); + + Assert.IsFalse (item.ViewController == viewController, "NSSplitViewItemShouldChangeViewController - Failed to set the ViewController property"); + } + + [Test] + public void NSSplitViewItemShouldChangeCollapsed () + { + var collapsed = item.Collapsed; + item.Collapsed = !collapsed; + + Assert.IsFalse (item.Collapsed == collapsed, "NSSplitViewItemShouldChangeCollapsed - Failed to set the Collapsed property"); + } + + [Test] + public void NSSplitViewItemShouldChangeCanCollapse () + { + var canCollapse = item.CanCollapse; + item.CanCollapse = !canCollapse; + + Assert.IsFalse (item.CanCollapse == canCollapse, "NSSplitViewItemShouldChangeCanCollapse - Failed to set the CanCollapse property"); + } + + [Test] + public void NSSplitViewItemShouldChangeHoldingPriority () + { + var holdingPriority = item.HoldingPriority; + item.HoldingPriority = 0.35f; + + Assert.IsFalse (item.HoldingPriority == holdingPriority, "NSSplitViewItemShouldChangeHoldingPriority - Failed to set the HoldingPriority property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSStackView.cs b/tests/apitest/src/AppKit/NSStackView.cs new file mode 100644 index 000000000000..85f29b5d68e4 --- /dev/null +++ b/tests/apitest/src/AppKit/NSStackView.cs @@ -0,0 +1,193 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSStackViewTests + { + NSStackView view; + NSView first; + NSView second; + NSView third; + + [SetUp] + public void SetUp () + { + Asserts.EnsureMavericks (); + + view = new NSStackView (); + + first = new NSView (); + second = new NSView (); + third = new NSView (); + } + + [Test] + public void NSStackViewShouldCreateWithEmptyConstructor () + { + Assert.IsNotNull (view, "NSStackViewCreateWithEmptyConstructor - Failed to create view"); + } + + [Test] + public void NSStackViewShouldCreateWithViews () + { + view = NSStackView.FromViews (new [] { first, second }); + + Assert.IsNotNull (view, "NSStackViewCreateWithViews - Failed to create view"); + Assert.IsTrue (view.Views.Length == 2, "NSStackViewShouldCreateWithViews - StackView does not have 2 views"); + } + + [Test] + public void NSStackViewShouldAddView () + {view.AddView (new NSView (), NSStackViewGravity.Bottom); + + Assert.IsTrue (view.Views.Length == 1, "NSStackViewShouldAddView - Failed to add view - length was 0"); + } + + [Test] + public void NSStackViewShouldInsertView () + { + view.AddView (first, NSStackViewGravity.Trailing); + view.AddView (second, NSStackViewGravity.Trailing); + + view.InsertView (third, 1, NSStackViewGravity.Trailing); + + Assert.IsTrue (view.Views.Length == 3, "NSStackViewShouldInsertView - Wrong number of views"); + Assert.IsTrue (view.Views [1] == third, "NSStackViewShouldInsertView - New view not inserted at the correct location"); + } + + [Test] + public void NSStackViewShouldRemoveView () + { + view = NSStackView.FromViews (new [] { first, second }); + + view.RemoveView (second); + + Assert.IsTrue (view.Views.Length == 1, "NSStackViewShouldRemoveView - Failed to remove view"); + } + + [Test] + public void NSStackViewShouldSetViews () + { + view.SetViews (new [] { first, second }, NSStackViewGravity.Leading); + + Assert.IsTrue (view.Views.Length == 2, "NSStackViewShouldSetViews - Views length was not 0"); + Assert.IsTrue (view.ViewsInGravity (NSStackViewGravity.Leading).Length == 2, "NSStackViewShouldSetViews - ViewsInGravity Leading was not 2"); + Assert.IsTrue (view.ViewsInGravity (NSStackViewGravity.Trailing).Length == 0, "NSStackViewShouldSetViews - ViewsInGravity Trailing was not 0"); + } + + [Test] + public void NSStackViewShouldChangeAlignment () + { + var alignment = view.Alignment; + view.Alignment = NSLayoutAttribute.Right; + + Assert.IsFalse (view.Alignment == alignment, "NSStackViewShouldChangeAlignment - Failed to change Alignment property"); + } + + [Test] + public void NSStackViewShouldChangeOrientation () + { + var orientation = view.Orientation; + view.Orientation = NSUserInterfaceLayoutOrientation.Vertical; + + Assert.IsFalse (view.Orientation == orientation, "NSStackViewShouldChangeOrientation - Failed to change Orientation property"); + } + + [Test] + public void NSStackViewShouldChangeSpacing () + { + var spacing = view.Spacing; + view.Spacing = spacing + 3; + + Assert.IsFalse (view.Spacing == spacing, "NSStackViewShouldChangeSpacing - Failed to change Spacing property"); + } + + [Test] + public void NSStackViewShouldChangeEdgeInsets () + { + var edgeInsets = view.EdgeInsets; + view.EdgeInsets = new NSEdgeInsets (20, 20, 20, 20); + + Assert.IsFalse (view.EdgeInsets.Left == edgeInsets.Left, "NSStackViewShouldChangeEdgeInsets - Failed to change EdgeInsets property"); + Assert.IsFalse (view.EdgeInsets.Right == edgeInsets.Right, "NSStackViewShouldChangeEdgeInsets - Failed to change EdgeInsets property"); + Assert.IsFalse (view.EdgeInsets.Top == edgeInsets.Top, "NSStackViewShouldChangeEdgeInsets - Failed to change EdgeInsets property"); + Assert.IsFalse (view.EdgeInsets.Bottom == edgeInsets.Bottom, "NSStackViewShouldChangeEdgeInsets - Failed to change EdgeInsets property"); + } + + [Test] + public void NSStackViewShouldChangeHasEqualSpacing () + { + var hasEqualSpacing = view.HasEqualSpacing; + view.HasEqualSpacing = !hasEqualSpacing; + + Assert.IsFalse (view.HasEqualSpacing == hasEqualSpacing, "NSStackViewShouldChangeHasEqualSpacing - Failed to change HasEqualSpacing property"); + } + +// [Test] +// public void NSStackViewShouldSetDelegate () +// { +// var view = new NSStackView (); +// view.Delegate = new NSStackViewDelegate (); +// +// Assert.IsNotNull (view.Delegate, "NSStackViewShouldSetDelegate - Delegate property returned null"); +// } + + [Test] + public void NSStackViewShouldChangeClippingResistance () + { + var clippingResistance = view.ClippingResistancePriorityForOrientation (NSLayoutConstraintOrientation.Vertical); + view.SetClippingResistancePriority (clippingResistance + 3, NSLayoutConstraintOrientation.Vertical); + + Assert.IsFalse (view.ClippingResistancePriorityForOrientation (NSLayoutConstraintOrientation.Vertical) == clippingResistance, + "NSStackViewShouldChangeClippingResistance - Failed to set ClippingResistance"); + } + + [Test] + public void NSStackViewShouldChangeHuggingPriority () + { + var huggingPriority = view.HuggingPriority (NSLayoutConstraintOrientation.Horizontal); + view.SetHuggingPriority (huggingPriority + 10, NSLayoutConstraintOrientation.Horizontal); + + Assert.IsFalse (view.HuggingPriority (NSLayoutConstraintOrientation.Horizontal) == huggingPriority, + "NSStackViewShouldChangeHuggingPriority - Failed to set HuggingPriority"); + } + + [Test] + public void NSStackViewShouldChangeCustomSpacing () + { + view.AddView (first, NSStackViewGravity.Trailing); + view.AddView (second, NSStackViewGravity.Trailing); + + var customSpacing = view.CustomSpacingAfterView (first); + view.SetCustomSpacing (10, first); + + Assert.IsFalse (view.CustomSpacingAfterView (first) == customSpacing, + "NSStackViewShouldChangeCustomSpacing - Failed to set CustomSpacing"); + } + + [Test] + public void NSStackViewShouldChangeVisibilityPriority () + { + view.AddView (first, NSStackViewGravity.Trailing); + view.AddView (second, NSStackViewGravity.Trailing); + + var visibilityPriority = view.VisibilityPriority (first); + view.SetVisibilityPriority (10, first); + + Assert.IsFalse (view.VisibilityPriority (first) == visibilityPriority, + "NSStackViewShouldChangeVisibilityPriority - Failed to set VisibilityPriority"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSStepperCell.cs b/tests/apitest/src/AppKit/NSStepperCell.cs new file mode 100644 index 000000000000..54d9a059c0a5 --- /dev/null +++ b/tests/apitest/src/AppKit/NSStepperCell.cs @@ -0,0 +1,66 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +#else +using AppKit; +#endif + +namespace apitest +{ + [TestFixture] + public class NSStepperCellTests + { + NSStepperCell cell; + + [SetUp] + public void SetUp () + { + cell = new NSStepperCell (); + } + + [Test] + public void NSStepperCell_ShouldSetMinValue () + { + var minValue = cell.MinValue; + cell.MinValue = 3.14159; + + Assert.IsTrue (cell.MinValue != minValue, "NSStepperCell_ShouldSetMinValue - Failed to set the MinValue property"); + } + + [Test] + public void NSStepperCell_ShouldSetMaxValue () + { + var maxValue = cell.MaxValue; + cell.MaxValue = 3.14159; + + Assert.IsTrue (cell.MinValue != maxValue, "NSStepperCell_ShouldSetMaxValue - Failed to set the MaxValue property"); + } + [Test] + public void NSStepperCell_ShouldSetIncrement () + { + var increment = cell.Increment; + cell.Increment = 3.14159; + + Assert.IsTrue (cell.Increment != increment, "NSStepperCell_ShouldSetIncrement - Failed to set the Increment property"); + } + [Test] + public void NSStepperCell_ShouldSetValueWraps () + { + var valueWraps = cell.ValueWraps; + cell.ValueWraps = !valueWraps; + + Assert.IsTrue (cell.ValueWraps != valueWraps, "NSStepperCell_ShouldSetValueWraps - Failed to set the ValueWraps property"); + } + [Test] + public void NSStepperCell_ShouldSetAutoRepeat () + { + var autoRepeat = cell.Autorepeat; + cell.Autorepeat = !autoRepeat; + + Assert.IsTrue (cell.Autorepeat != autoRepeat, "NSStepperCell_ShouldSetAutoRepeat - Failed to set the Autorepeat property"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSStoryboardSegue.cs b/tests/apitest/src/AppKit/NSStoryboardSegue.cs new file mode 100644 index 000000000000..a547f598e279 --- /dev/null +++ b/tests/apitest/src/AppKit/NSStoryboardSegue.cs @@ -0,0 +1,69 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSStoryboardSegueTests + { + NSStoryboardSegue segue; + NSViewController source; + NSViewController destination; + + [SetUp] + public void Setup () + { + Asserts.EnsureYosemite (); + + source = new NSViewController (); + destination = new NSViewController (); + segue = new NSStoryboardSegue ("Test", source, destination); + } + + [Test] + public void NSStoryboardSegueShouldCreateSegueWithConstructor () + { + Assert.IsNotNull (segue, "NSStoryboardSegueShouldCreateSegueWithConstructor - Failed to create segue, value is null"); + } + + [Test] + public void NSStoryboardSegueShouldGetIdentifier () + { + Assert.IsFalse (string.IsNullOrEmpty (segue.Identifier), "NSStoryboardSegueShouldGetIdentifier - Identifier property was empty or null"); + } + + [Test] + public void NSStoryboardSegueShouldGetSourceController () + { + Assert.IsNotNull (segue.SourceController, "NSStoryboardSegueShouldGetSourceController - Source controller was null"); + Assert.IsTrue (segue.SourceController == source, "NSStoryboardSegueShouldGetSourceController - Source controller did not match the source controller passed into the segue."); + } + + [Test] + public void NSStoryboardSegueShouldGetDestinationController () + { + Assert.IsNotNull (segue.DestinationController, "NSStoryboardSegueShouldGetDestinationController - Destination controller was null"); + Assert.IsTrue (segue.DestinationController == destination, "NSStoryboardSegueShouldGetDestinationController - Destination controller did not mass the destination controller passed into the segue."); + } + +#if false // Crashes when run in test from command line, works from an actual app + [Test] + public void NSStoryboardSegueShouldCreateSegueWithStaticMethod () + { + var segue = NSStoryboardSegue.FromIdentifier ("Test", new NSViewController (), new NSViewController (), () => { + }); + Assert.IsNotNull (segue); + } +#endif + } +} + diff --git a/tests/apitest/src/AppKit/NSTabViewController.cs b/tests/apitest/src/AppKit/NSTabViewController.cs new file mode 100644 index 000000000000..4c388d5c416a --- /dev/null +++ b/tests/apitest/src/AppKit/NSTabViewController.cs @@ -0,0 +1,154 @@ +using System; +using NUnit.Framework; +using System.Linq; + +#if !XAMCORE_2_0 +using System.Drawing; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; + +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSTabViewControllerTests + { + NSTabViewController controller; + + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + + controller = new NSTabViewController (); + } + + [Test] + public void NSTabViewControllerShouldChangeTabStyle () + { + var tabStyle = controller.TabStyle; + controller.TabStyle = NSTabViewControllerTabStyle.Toolbar; + + Assert.IsFalse (controller.TabStyle == tabStyle, "NSTabViewControllerShouldChangeTabStyle - Failed to set the TabStyle property"); + } + +// [Test] +// public void NSTabViewControllerShouldChangeTabView () +// { +// var tabView = controller.TabView; +// controller.TabView = new NSTabView (); +// +// Assert.IsFalse (controller.TabView == tabView, "NSTabViewControllerShouldChangeTabView - Failed to set the TabView property"); +// } + + [Test] + public void NSTabViewControllerShouldChangeSegmentedControl () + { + // This API was removed in 10.11 + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) >= Platform.Mac_10_11) + return; + + var segmentedControl = controller.SegmentedControl; + controller.SegmentedControl = new NSSegmentedControl (); + + Assert.IsFalse (controller.SegmentedControl == segmentedControl, "NSTabViewControllerShouldChangeSegmentedControl - Failed to set the SegmentedControl property"); + } + + [Test] + public void NSTabViewControllerShouldChangeTransitionOptions () + { + var options = controller.TransitionOptions; + controller.TransitionOptions = NSViewControllerTransitionOptions.Crossfade | NSViewControllerTransitionOptions.SlideRight; + + Assert.IsFalse (controller.TransitionOptions == options, "NSTabViewControllerShouldChangeTransitionOptions - Failed to set the TransitionOptions property"); + } + + [Test] + public void NSTabViewControllerShouldChangeCanPropagateSelectedChildViewControllerTitle () + { + var canPropogate = controller.CanPropagateSelectedChildViewControllerTitle; + controller.CanPropagateSelectedChildViewControllerTitle = !canPropogate; + + Assert.IsFalse (controller.CanPropagateSelectedChildViewControllerTitle == canPropogate, "NSTabViewControllerShouldChangeCanPropagateSelectedChildViewControllerTitle - Failed to set the CanPropagateSelectedChildViewControllerTitle property"); + } + + [Test] + public void NSTabViewControllerShouldChangeTabViewItems () + { + var items = controller.TabViewItems; + controller.TabViewItems = new NSTabViewItem [] { new NSTabViewItem { ViewController = new NSViewController () } }; + + Assert.IsFalse (controller.TabViewItems == items, "NSTabViewControllerShouldChangeTabViewItems - Failed to set the TabViewItems property"); + } + + [Test] + public void NSTabViewControllerShouldChangeSelectedTabViewItemIndex () + { + controller.TabViewItems = new NSTabViewItem [] { + new NSTabViewItem { ViewController = new NSViewController () }, + new NSTabViewItem { ViewController = new NSViewController () }, + new NSTabViewItem { ViewController = new NSViewController () } + }; + + var index = controller.SelectedTabViewItemIndex; + controller.SelectedTabViewItemIndex = (index + 1) % 3; + + Assert.IsFalse (controller.SelectedTabViewItemIndex == index, "NSTabViewControllerShouldChangeSelectedTabViewItemIndex - Failed to set the SelectedTabViewItemIndex property"); + } + + [Test] + public void NSTabViewControllerShouldAddTabViewItem () + { + var item = new NSTabViewItem { ViewController = new NSViewController () }; + controller.AddTabViewItem (item); + + Assert.IsTrue (controller.TabViewItems.Contains (item), "NSTabViewControllerShouldAddTabViewItem - Failed to add TabViewItem"); + } + + [Test] + public void NSTabViewControllerShouldRemoveTabViewItem () + { + var item = new NSTabViewItem { ViewController = new NSViewController () }; + controller.AddTabViewItem (item); + + Assert.IsTrue (controller.TabViewItems.Contains (item), "NSTabViewControllerShouldRemoveTabViewItem - Failed to add item"); + + controller.RemoveTabViewItem (item); + + Assert.IsFalse (controller.TabViewItems.Contains (item), "NSTabViewControllerShouldRemoveTabViewItem - Failed to remove item"); + } + + [Test] + public void NSTabViewControllerShouldInsertTabViewItem () + { + controller.AddTabViewItem (new NSTabViewItem { ViewController = new NSViewController () }); + controller.AddTabViewItem (new NSTabViewItem { ViewController = new NSViewController () }); + controller.AddTabViewItem (new NSTabViewItem { ViewController = new NSViewController () }); + var item = new NSTabViewItem { ViewController = new NSViewController () }; + controller.InsertTabViewItem (item, 1); + + Assert.IsTrue (controller.TabViewItems [1] == item, "NSTabViewControllerShouldInsertTabViewItem - Failed to insert the item at the given position."); + Assert.IsFalse (controller.TabViewItems [0] == item, "NSTabViewControllerShouldInsertTabViewItem - Inserted the item in the wrong position."); + } + + [Test] + public void NSTabViewControllerShouldGetTabViewItem () + { + controller.AddTabViewItem (new NSTabViewItem { ViewController = new NSViewController () }); + controller.AddTabViewItem (new NSTabViewItem { ViewController = new NSViewController () }); + controller.AddTabViewItem (new NSTabViewItem { ViewController = new NSViewController () }); + var viewController = new NSViewController (); + var item = new NSTabViewItem { ViewController = viewController }; + controller.InsertTabViewItem (item, 1); + + var retrievedItem = controller.GetTabViewItem (viewController); + + Assert.IsTrue (retrievedItem == item, "NSTabViewControllerShouldGetTabViewItem - Failed to get TabViewItem from ViewController"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSTabViewItem.cs b/tests/apitest/src/AppKit/NSTabViewItem.cs new file mode 100644 index 000000000000..e4ed6bd78571 --- /dev/null +++ b/tests/apitest/src/AppKit/NSTabViewItem.cs @@ -0,0 +1,49 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSTabViewItemTests + { + NSTabViewItem item; + + [SetUp] + public void SetUp () + { + item = new NSTabViewItem (); + } + + [Test] + public void NSTabViewItemShouldChangeImage () + { + Asserts.EnsureYosemite (); + + var image = item.Image; + item.Image = new NSImage (); + + Assert.IsFalse (item.Image == image, "NSTabViewItemShouldChangeImage - Failed to set the Image property"); + } + + [Test] + public void NSTabViewItemShouldChangeViewController () + { + Asserts.EnsureYosemite (); + + var vc = item.ViewController; + item.ViewController = new NSViewController (); + + Assert.IsFalse (item.ViewController == vc, "NSTabViewItemShouldChangeViewController - Failed to set the ViewController property"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSTableColumn.cs b/tests/apitest/src/AppKit/NSTableColumn.cs new file mode 100644 index 000000000000..a13fa483fdac --- /dev/null +++ b/tests/apitest/src/AppKit/NSTableColumn.cs @@ -0,0 +1,38 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSTableColumnTests + { + NSTableColumn column; + + [SetUp] + public void SetUp () + { + column = new NSTableColumn (); + } + + [Test] + public void NSTableColumnShouldChangeTitle () + { + Asserts.EnsureYosemite (); + + var title = column.Title; + column.Title = "Test"; + + Assert.IsFalse (column.Title == title, "NSTableColumnShouldChangeTitle - Failed to set the Title property"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSTableRowView.cs b/tests/apitest/src/AppKit/NSTableRowView.cs new file mode 100644 index 000000000000..a03b012ee1c3 --- /dev/null +++ b/tests/apitest/src/AppKit/NSTableRowView.cs @@ -0,0 +1,49 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSTableRowViewTests + { + NSTableRowView view; + + [SetUp] + public void SetUp () + { + view = new NSTableRowView (); + } + + [Test] + public void NSTableRowViewShouldChangePreviousRowSelected () + { + Asserts.EnsureYosemite (); + + var selected = view.PreviousRowSelected; + view.PreviousRowSelected = !selected; + + Assert.IsFalse (view.PreviousRowSelected == selected, "NSTableRowViewShouldChangePreviousRowSelected - Failed to set the PreviousRowSelected property"); + } + + [Test] + public void NSTableRowViewShouldChangeNextRowSelected () + { + Asserts.EnsureYosemite (); + + var selected = view.NextRowSelected; + view.NextRowSelected = !selected; + + Assert.IsFalse (view.NextRowSelected == selected, "NSTableRowViewShouldChangeNextRowSelected - Failed to set the NextRowSelected property"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSTableView.cs b/tests/apitest/src/AppKit/NSTableView.cs new file mode 100644 index 000000000000..db3477ec6a1d --- /dev/null +++ b/tests/apitest/src/AppKit/NSTableView.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +#else +using AppKit; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSTableViewTests + { + [Test] + public void NSTableView_DelegateDataSourceNull () + { + NSTableView v = new NSTableView (); + v.WeakDelegate = null; + v.Delegate = null; + v.WeakDataSource = null; + v.DataSource = null; + } + } +} + diff --git a/tests/apitest/src/AppKit/NSTextField.cs b/tests/apitest/src/AppKit/NSTextField.cs new file mode 100644 index 000000000000..391f4eb3c127 --- /dev/null +++ b/tests/apitest/src/AppKit/NSTextField.cs @@ -0,0 +1,48 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSTextFieldTests + { + NSTextField textField; + + [SetUp] + public void SetUp () + { + textField = new NSTextField (); + } + + [Test] + public void NSTextFieldShouldChangePlaceholderString () + { + Asserts.EnsureYosemite (); + + var placeholder = textField.PlaceholderString; + textField.PlaceholderString = "Test"; + + Assert.IsFalse (textField.PlaceholderString == placeholder, "NSTextFieldShouldChangePlaceholderString - Failed to set the PlaceholderString property"); + } + + [Test] + public void NSTextFieldShouldChangePlaceholderAttributedString () + { + Asserts.EnsureYosemite (); + + var placeholder = textField.PlaceholderAttributedString; + textField.PlaceholderAttributedString = new NSAttributedString ("Test"); + + Assert.IsFalse (textField.PlaceholderAttributedString == placeholder, "NSTextFieldShouldChangePlaceholderAttributedString - Failed to set the PlaceholderAttributedString property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSTextFinder.cs b/tests/apitest/src/AppKit/NSTextFinder.cs new file mode 100644 index 000000000000..4bca3e89f0d9 --- /dev/null +++ b/tests/apitest/src/AppKit/NSTextFinder.cs @@ -0,0 +1,92 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.AudioUnit; +using MonoMac.AudioToolbox; +using MonoMac.Foundation; +using nuint = System.UInt32; +#else +using AppKit; +using AudioUnit; +using AudioToolbox; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSTextFinderTests + { + [Test] + public void NSTextFinderConstructor () + { + NSTextFinder f = new NSTextFinder (); + Assert.IsNotNull (f); + + FinderClient client = new FinderClient (); + f.Client = client; + } + + class FinderClient : NSTextFinderClient + { + public override bool AllowsMultipleSelection { get { return true; } } + + public override bool Editable { get { return true; } } + + public override string String { get { return "Testing One Two Three"; } } + + public override NSRange FirstSelectedRange { get { return new NSRange(); } } + + public override NSArray SelectedRanges { get; set; } + + public override NSArray VisibleCharacterRanges { get { return new NSArray(); } } + + public override bool Selectable { get { return true; } } + + public override string StringAtIndexeffectiveRangeendsWithSearchBoundary (nuint characterIndex, ref NSRange outRange, bool outFlag) + { + return String; + } + + public override nuint StringLength () + { + return (nuint)String.Length; + } + + public override void ScrollRangeToVisible (NSRange range) + { + } + + public override bool ShouldReplaceCharactersInRangeswithStrings (NSArray ranges, NSArray strings) + { + return false; + } + + public override void ReplaceCharactersInRangewithString (NSRange range, string str) + { + } + + public override void DidReplaceCharacters () + { + } + + public override NSView ContentViewAtIndexeffectiveCharacterRange (nuint index, ref NSRange outRange) + { + return null; + } + + public override NSArray RectsForCharacterRange (NSRange range) + { + return null; + } + + public override void DrawCharactersInRangeforContentView (NSRange range, NSView view) + { + } + } + } +} + diff --git a/tests/apitest/src/AppKit/NSTextInputClient.cs b/tests/apitest/src/AppKit/NSTextInputClient.cs new file mode 100644 index 000000000000..f07d71bb2d97 --- /dev/null +++ b/tests/apitest/src/AppKit/NSTextInputClient.cs @@ -0,0 +1,117 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using CGPoint = System.Drawing.PointF; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using CoreGraphics; +using Foundation; +#endif + +namespace apitest +{ + [TestFixture] + public class NSTextInputClient + { + NSTextView textView; + + [SetUp] + public void SetUp () + { + textView = new NSTextView (new CGRect (0, 0, 37, 120)); + textView.Value = "This is a new string"; + Assert.AreEqual (textView.Value, "This is a new string", "NSTextInputClientSetup - Failed to set value"); + } + + [Test] + public void NSTextInputClient_ShouldInsertText () + { + textView.InsertText ((NSString)"Test", new NSRange (5, 4)); + + Assert.AreEqual (textView.Value, "This Test new string", "NSTextInputClient_ShouldInsertText - Failed to insert text"); + } + + [Test] + public void NSTextInputClient_ShouldMarkText () + { + textView.SetMarkedText ((NSString)"Testing", new NSRange (0, 10), new NSRange (5, 4)); + + Assert.IsTrue (textView.HasMarkedText, "NSTextInputClient_ShouldMarkText - Failed to mark text"); + Assert.AreEqual (textView.MarkedRange, new NSRange (5, 7)); + } + + [Test] + public void NSTextInputClient_ShouldGetValidAttributesForMarkedText () + { + Assert.IsTrue (textView.ValidAttributesForMarkedText.Length > 0, "NSTextInputClient_ShouldGetValidAttributesForMarkedTExt - No valid attributes"); + } + + [Test] + public void NSTextInputClient_ShouldUnmarkText () + { + textView.SetMarkedText ((NSString)"Testing", new NSRange (0, 10), new NSRange (5, 4)); + + Assert.IsTrue (textView.HasMarkedText, "NSTextInputClient_ShouldUnMarkText - Failed to mark text"); + + textView.UnmarkText (); + + Assert.IsFalse (textView.HasMarkedText, "NSTextInputClient_ShouldUnmarkText - Failed to Unmark text"); + Assert.IsTrue (textView.MarkedRange.Length == 0, "NSTextInputClient_ShouldUnmarkText - MarkedRange is not 0"); + } + + [Test] + public void NSTextInputClient_ShouldGetAttributedSubstring () + { + NSRange range; + var attributedString = textView.GetAttributedSubstring (new NSRange (10, 15), out range); + + Assert.AreEqual (attributedString.Value, "new string", "NSTextInputClient_ShouldGetAttributedSubstring - Failed to get the correct string"); + Assert.AreEqual (range, new NSRange (10, 10), "NSTextInputClient_ShouldGetAttributedSubstring - Wrong range value returned"); + } + + [Test] + public void NSTextInputClient_ShouldGetFirstRect () + { + NSRange range; + var rect = textView.GetFirstRect (new NSRange (12, 18), out range); + + Assert.AreEqual (rect, new CGRect (0, 0, 12, 14), "NSTextInputClient_ShouldGetFirstRect - Returned wrong rect"); + Assert.AreEqual (range, new NSRange (10, 4), "NSTextInputClient_ShouldGetFirstRect - Returned wrong Range"); + } + + [Test] + public void NSTextInputClient_ShouldGetAttributedString () + { + Assert.AreEqual (textView.AttributedString.Value, "This is a new string", "NSTextInputClient_ShouldGetAttributedString - Returned the wrong attributed string"); + } + + [Test] + public void NSTextInputClient_ShouldGetFractionofDistanceThroughGlyph () + { + Assert.IsTrue (textView.GetFractionOfDistanceThroughGlyph (new CGPoint (1, 2)) == 0, "NSTextInputClient_ShouldGetFractionofDistanceThroughGlyph - Returned wrong fraaction value"); + } + + [Test] + public void NSTextInputClient_ShouldGetBaselineDelta () + { + Assert.IsTrue (textView.GetBaselineDelta (4) == 11, "NSTextInputClient_ShouldGetBaselineDelta - Returned wrong baseline delta value"); + } + + [Test] + public void NSTextInputClient_ShouldGetDrawsVertically () + { + Assert.IsFalse (textView.DrawsVertically (4), "NSTextInputClient_ShouldGetDrawsVertically - Returned wrong value"); + } + + [Test] + public void NSTextInputClient_ShouldGetWindowLevel () + { + Assert.AreEqual (textView.WindowLevel, NSWindowLevel.Normal, "NSTextInputClient_ShouldGetWindowLevel - WindowLevel returned the wrong value"); + } + } +} + diff --git a/tests/apitest/src/AppKit/NSTextView.cs b/tests/apitest/src/AppKit/NSTextView.cs new file mode 100644 index 000000000000..94ea69c06096 --- /dev/null +++ b/tests/apitest/src/AppKit/NSTextView.cs @@ -0,0 +1,37 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSTextViewTests + { + NSTextView view; + + [SetUp] + public void SetUp () + { + view = new NSTextView (); + } + + [Test] + public void NSTextViewShouldChangeUsesRolloverButtonForSelection () + { + Asserts.EnsureYosemite (); + + var usesRollover = view.UsesRolloverButtonForSelection; + view.UsesRolloverButtonForSelection = !usesRollover; + + Assert.IsFalse (view.UsesRolloverButtonForSelection == usesRollover, "NSTextViewShouldChangeUsesRolloverButtonForSelection - Failed to set the UsesRolloverButtonForSelection property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSToolbar.cs b/tests/apitest/src/AppKit/NSToolbar.cs new file mode 100644 index 000000000000..9b6ecbcaff4c --- /dev/null +++ b/tests/apitest/src/AppKit/NSToolbar.cs @@ -0,0 +1,37 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSToolbarTests + { + NSToolbar toolbar; + + [SetUp] + public void SetUp () + { + toolbar = new NSToolbar (NSToolbar.NSToolbarSeparatorItemIdentifier); + } + + [Test] + public void NSToolbarShouldChangeAllowsExtensionItems () + { + Asserts.EnsureYosemite (); + + var allows = toolbar.AllowsExtensionItems; + toolbar.AllowsExtensionItems = !allows; + + Assert.IsFalse (toolbar.AllowsExtensionItems == allows, "NSToolbarShouldChangeAllowsExtensionItems - Failed to set the AllowsExtensionItems property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSUserDefaultsController.cs b/tests/apitest/src/AppKit/NSUserDefaultsController.cs new file mode 100644 index 000000000000..04ca2ae69f84 --- /dev/null +++ b/tests/apitest/src/AppKit/NSUserDefaultsController.cs @@ -0,0 +1,77 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSUserDefaultsControllerTests + { + NSUserDefaultsController controller; + + [Test] + public void NSUserDefaultsControllerShouldGetSharedController () + { + controller = NSUserDefaultsController.SharedUserDefaultsController; + + Assert.IsNotNull (controller, "NSUserDefaultsControllerShouldGetDefaultController - SharedUserDefaultsController returned null"); + } + + [Test] + public void NSUserDefaultsControllerShouldCreateNewControllerWithDefaultConstructor () + { + controller = new NSUserDefaultsController (); + + Assert.IsNotNull (controller, "NSUserDefaultsControllerShouldCreateNewControllerWithDefaultConstructor - Constructor returned null"); + } + + [Test] + public void NSUserDefaultsControllerShouldCreateNewControllerWithNullParameters () + { + controller = new NSUserDefaultsController (null, null); + + Assert.IsTrue (controller.Defaults == NSUserDefaults.StandardUserDefaults); + Assert.IsTrue (controller.InitialValues == null); + Assert.IsNotNull (controller, "NSUserDefaultsControllerShouldCreateNewControllerWithNullParameters - Constructor returned null"); + } + + [Test] + public void NSUserDefaultsControllerShouldCreateNewControllerWithParameters () + { + var initialValues = new NSDictionary (); + controller = new NSUserDefaultsController (NSUserDefaults.StandardUserDefaults, initialValues); + + Assert.IsTrue (controller.Defaults == NSUserDefaults.StandardUserDefaults); + Assert.IsTrue (controller.InitialValues == initialValues); + Assert.IsNotNull (controller, "NSUserDefaultsControllerShouldCreateNewControllerWithParameters - Constructor returned null"); + } + + [Test] + public void NSUserDefaultsControllerShouldChangeInitialValues () + { + controller = new NSUserDefaultsController (NSUserDefaults.StandardUserDefaults, null); + var initialValues = controller.InitialValues; + controller.InitialValues = new NSDictionary (); + + Assert.IsFalse (controller.InitialValues == initialValues, "NSUserDefaultsControllerShouldChangeInitialValues - Failed to set the InitialValues property"); + } + + [Test] + public void NSUserDefaultsControllerShouldChangeAppliesImmediately () + { + controller = new NSUserDefaultsController (NSUserDefaults.StandardUserDefaults, null); + var appliesImmediately = controller.AppliesImmediately; + controller.AppliesImmediately = !appliesImmediately; + + Assert.IsFalse (controller.AppliesImmediately == appliesImmediately, "NSUserDefaultsControllerShouldChangeAppliesImmediately - Failed to set the AppliesImmediately property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSView.cs b/tests/apitest/src/AppKit/NSView.cs new file mode 100644 index 000000000000..595e20ce390a --- /dev/null +++ b/tests/apitest/src/AppKit/NSView.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSViewTests + { + NSView view; + + [SetUp] + public void SetUp () + { + view = new NSView (); + } + + [Test] + public void NSViewShouldAddGestureRecognizer () + { + Asserts.EnsureYosemite (); + + var length = 0; + if (view.GestureRecognizers != null) + length = view.GestureRecognizers.Length; + view.AddGestureRecognizer (new NSGestureRecognizer ()); + + Assert.IsTrue (view.GestureRecognizers.Length == length + 1, "NSViewShouldAddGestureRecognizer - Failed to add recognizer, count didn't change."); + } + + [Test] + public void NSViewShouldRemoveGestureRecognizer () + { + Asserts.EnsureYosemite (); + + var recognizer = new NSClickGestureRecognizer (); + view.AddGestureRecognizer (recognizer); + + Assert.IsTrue (view.GestureRecognizers.Length != 0, "NSViewShouldRemoveGestureRecognizer - Failed to add gesture recognizer"); + + view.RemoveGestureRecognizer (recognizer); + + Assert.IsTrue (view.GestureRecognizers.Length == 0, "NSViewShouldRemoveGestureRecognizer - Failed to remove gesture recognizer"); + } + + [Test] + public void NSViewShouldChangeGestureRecognizers () + { + Asserts.EnsureYosemite (); + + var recognizers = view.GestureRecognizers; + view.GestureRecognizers = new NSGestureRecognizer [] { new NSClickGestureRecognizer (), new NSPanGestureRecognizer () }; + + Assert.IsFalse (view.GestureRecognizers == recognizers); + } + + [Test] + public void AllItemsWithNSMenuShouldAllowNull () + { + // Can't test typeof (NSResponder) since it is abstract + List types = new List { typeof (NSCell), typeof (NSMenuItem), typeof (NSPathControl), + typeof (NSPopUpButton), typeof (NSPopUpButtonCell) }; + if (IntPtr.Size == 4) + types.Add (typeof (NSMenuView)); // NSMenuView is 32-bit only + + foreach (Type t in types) { + object o = Activator.CreateInstance (t); + PropertyInfo prop = t.GetProperty("Menu", BindingFlags.Public | BindingFlags.Instance); + prop.SetValue (o, null, null); + } + + // NSStateBarItem can't be created via default constructor + NSStatusBar.SystemStatusBar.CreateStatusItem (10).Menu = null; + } + } +} diff --git a/tests/apitest/src/AppKit/NSViewController.cs b/tests/apitest/src/AppKit/NSViewController.cs new file mode 100644 index 000000000000..ef791df70917 --- /dev/null +++ b/tests/apitest/src/AppKit/NSViewController.cs @@ -0,0 +1,70 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using System.Drawing; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSViewControllerTests + { + NSViewController controller; + + [SetUp] + public void SetUp () + { + controller = new NSViewController (); + } + + [Test] + public void NSViewControllerShouldAddChildViewController () + { + Asserts.EnsureYosemite (); + + var child = new NSViewController (); + controller.AddChildViewController (child); + + Assert.IsTrue (controller.ChildViewControllers.Length == 1, "NSViewControllerShouldAddChildViewControllers - Failed to add child view controller"); + } + + [Test] + public void NSViewControllerShouldRemoveChildViewController () + { + Asserts.EnsureYosemite (); + + var child = new NSViewController (); + controller.AddChildViewController (child); + + Assert.IsTrue (controller.ChildViewControllers.Length == 1, "NSViewControllerShouldRemoveChildViewControllers - Failed to add child view controller"); + + controller.RemoveChildViewController (0); + + Assert.IsTrue (controller.ChildViewControllers.Length == 0, "NSViewControllerShouldRemoveChildViewController - Failed to remove child view controller"); + } + + [Test] + public void NSViewControllerShouldInsertChildViewController () + { + Asserts.EnsureYosemite (); + + controller.AddChildViewController (new NSViewController ()); + controller.AddChildViewController (new NSViewController ()); + + Assert.IsTrue (controller.ChildViewControllers.Length == 2, "NSViewControllerShouldInsertChildViewController - Failed to add child view controller"); + + var child = new NSViewController (); + controller.InsertChildViewController (child, 1); + + Assert.IsTrue (controller.ChildViewControllers.Length == 3, "NSViewControllerShouldInsertChildViewController - Failed to insert child view controller"); + Assert.IsTrue (controller.ChildViewControllers [1] == child, "NSViewControllerShouldInsertChildViewController - Inserted child view controller at the wrong index."); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSVisualEffectView.cs b/tests/apitest/src/AppKit/NSVisualEffectView.cs new file mode 100644 index 000000000000..d3c66251e60a --- /dev/null +++ b/tests/apitest/src/AppKit/NSVisualEffectView.cs @@ -0,0 +1,64 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSVisualEffectViewTests + { + NSVisualEffectView view; + + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + + view = new NSVisualEffectView (); + } + + [Test] + public void NSVisualEffectViewShouldChangeMaterial () + { + var material = view.Material; + view.Material = NSVisualEffectMaterial.Titlebar; + + Assert.IsFalse (view.Material == material, "NSVisualEffectViewShouldChangeMaterial - Failed to set the Material property"); + } + + [Test] + public void NSVisualEffectViewShouldChangeBlendingMode () + { + var blendingMode = view.BlendingMode; + view.BlendingMode = NSVisualEffectBlendingMode.WithinWindow; + + Assert.IsFalse (view.BlendingMode == blendingMode, "NSVisualEffectViewShouldChangeBlendingMode - Failed to set the BlendingMode property"); + } + + [Test] + public void NSVisualEffectViewShouldChangeState () + { + var state = view.State; + view.State = NSVisualEffectState.Inactive; + + Assert.IsFalse (view.State == state, "NSVisualEffectViewShouldChangeState - Failed to set the State property"); + } + + [Test] + public void NSVisualEffectViewShouldChangeMaskImage () + { + var image = view.MaskImage; + view.MaskImage = new NSImage (); + + Assert.IsFalse (view.MaskImage == image, "NSVisualEffectViewShouldChangeMaskImage - Failed to set the MaskImage property"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AppKit/NSWindowController.cs b/tests/apitest/src/AppKit/NSWindowController.cs new file mode 100644 index 000000000000..91ec5232b772 --- /dev/null +++ b/tests/apitest/src/AppKit/NSWindowController.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public class NSWindowControllerTests + { + [Test] + public void NSWindowController_ShowWindowTest () + { + NSWindowController c = new NSWindowController (); + c.ShowWindow (null); + } + } +} diff --git a/tests/apitest/src/AppKit/NSWorkspace.cs b/tests/apitest/src/AppKit/NSWorkspace.cs new file mode 100644 index 000000000000..a71a56aa6abd --- /dev/null +++ b/tests/apitest/src/AppKit/NSWorkspace.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +#else +using AppKit; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSWorkspaceTests + { + [Test] + public void NSWorkspaceConstantTests () + { + Assert.IsNotNull (NSWorkspace.LaunchConfigurationAppleEvent); + Assert.IsNotNull (NSWorkspace.LaunchConfigurationArguments); + Assert.IsNotNull (NSWorkspace.LaunchConfigurationEnvironment); + Assert.IsNotNull (NSWorkspace.LaunchConfigurationArchitecture); + } + } +} diff --git a/tests/apitest/src/Asserts.cs b/tests/apitest/src/Asserts.cs new file mode 100644 index 000000000000..40c5f7e3898b --- /dev/null +++ b/tests/apitest/src/Asserts.cs @@ -0,0 +1,62 @@ +using System; +using System.Reflection; + +using NUnit.Framework; +using TouchUnit.Bindings; + +#if !XAMCORE_2_0 +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using ObjCRuntime; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + public static class Asserts + { + public static bool IsAtLeastYosemite { + get { + return PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) >= Platform.Mac_10_10; + } + } + + public static bool IsAtLeastElCapitan { + get { + return PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) >= Platform.Mac_10_11; + } + } + + public static void EnsureYosemite () + { + if (!IsAtLeastYosemite) + Assert.Pass ("This test requires Yosemite. Skipping"); + } + + public static void EnsureMavericks () + { + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) < Platform.Mac_10_9) + Assert.Pass ("This test requires Mavericks. Skipping"); + } + + public static void EnsureMountainLion () + { + if (PlatformHelper.ToMacVersion (PlatformHelper.GetHostApiPlatform ()) < Platform.Mac_10_8) + Assert.Pass ("This test requires Mountain Lion. Skipping"); + } + + public static void Ensure64Bit () + { + if (IntPtr.Size == 4) + Assert.Pass ("This test requires 64-bit. Skipping"); + } + + public static bool SkipDueToAvailabilityAttribute (ICustomAttributeProvider member) + { + if (member == null) + return false; + return !member.IsAvailableOnHostPlatform (); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/AudioUnit/AUGraphTest.cs b/tests/apitest/src/AudioUnit/AUGraphTest.cs new file mode 100644 index 000000000000..b0b5fa186274 --- /dev/null +++ b/tests/apitest/src/AudioUnit/AUGraphTest.cs @@ -0,0 +1,117 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.AudioUnit; +using MonoMac.AudioToolbox; +#else +using AppKit; +using AudioUnit; +using AudioToolbox; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class AUGraphTests + { + int graphRenderCallbackCount = 0; + int mixerRenderCallbackCount = 0; + AUGraph graph; +#if XAMCORE_2_0 + AudioUnit.AudioUnit mMixer; +#else + AudioUnit mMixer; +#endif + + void SetupAUGraph () + { + graph = new AUGraph (); + + AudioComponentDescription mixerDescription = new AudioComponentDescription (); + mixerDescription.ComponentType = AudioComponentType.Mixer; + mixerDescription.ComponentSubType = (int)AudioTypeMixer.MultiChannel; + mixerDescription.ComponentFlags = 0; + mixerDescription.ComponentFlagsMask = 0; + mixerDescription.ComponentManufacturer = AudioComponentManufacturerType.Apple; + + AudioComponentDescription outputDesciption = new AudioComponentDescription (); + outputDesciption.ComponentType = AudioComponentType.Output; + outputDesciption.ComponentSubType = (int)AudioTypeOutput.System; + outputDesciption.ComponentFlags = 0; + outputDesciption.ComponentFlagsMask = 0; + outputDesciption.ComponentManufacturer = AudioComponentManufacturerType.Apple; + + int mixerNode = graph.AddNode (mixerDescription); + int outputNode = graph.AddNode (outputDesciption); + + AUGraphError error = graph.ConnnectNodeInput (mixerNode, 0, outputNode, 0); + Assert.AreEqual (AUGraphError.OK, error); + + graph.Open (); + + mMixer = graph.GetNodeInfo (mixerNode); + + AudioUnitStatus status = mMixer.SetElementCount (AudioUnitScopeType.Input, 0); + Assert.AreEqual (AudioUnitStatus.OK, status); + } + + [Test] + public async Task DoTest () + { + SetupAUGraph (); + + // One of these has to be commented out depending on old\new build + graph.AddRenderNotify (GraphRenderCallback); + //graph.RenderCallback += HandleRenderCallback; + + AudioUnitStatus status = mMixer.SetRenderCallback (MixerRenderCallback); + Assert.AreEqual (AudioUnitStatus.OK, status ); + + await WaitOnGraphAndMixerCallbacks (); + } + +#if !XAMCORE_2_0 +#pragma warning disable 0612 + void HandleRenderCallback (object sender, AudioGraphEventArgs e) + { + graphRenderCallbackCount++; + } +#pragma warning restore 0612 +#endif + + AudioUnitStatus GraphRenderCallback (AudioUnitRenderActionFlags actionFlags, AudioTimeStamp timeStamp, uint busNumber, uint numberFrames, AudioBuffers data) + { + graphRenderCallbackCount++; + return AudioUnitStatus.NoError; + } + + AudioUnitStatus MixerRenderCallback (AudioUnitRenderActionFlags actionFlags, AudioTimeStamp timeStamp, uint busNumber, uint numberFrames, AudioBuffers data) + { + mixerRenderCallbackCount++; + return AudioUnitStatus.NoError; + } + + async Task WaitOnGraphAndMixerCallbacks () + { + graph.Initialize (); + graph.Start (); + + // Wait for 1 second, then give up + try { + for (int i = 0; i < 100; ++i) { + if (graphRenderCallbackCount > 0 && mixerRenderCallbackCount > 0) + return; + await Task.Delay (10); + } + Assert.Fail ("Did not see events after 1 second"); + } + finally { + graph.Stop (); + } + } + } +} + diff --git a/tests/apitest/src/AudioUnit/AudioUnit.cs b/tests/apitest/src/AudioUnit/AudioUnit.cs new file mode 100644 index 000000000000..b46f8b43da6a --- /dev/null +++ b/tests/apitest/src/AudioUnit/AudioUnit.cs @@ -0,0 +1,90 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.AudioUnit; +using theUnit = MonoMac.AudioUnit.AudioUnit; // Namespace fun +#else +using AppKit; +using AudioUnit; +using theUnit = AudioUnit.AudioUnit; + +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class AudioUnitTests + { + theUnit GetAudioUnitForTest () + { + AudioComponentDescription desc = new AudioComponentDescription (); + desc.ComponentType = AudioComponentType.Output; + desc.ComponentSubType = 1634230636; // 'ahal' + desc.ComponentFlags = 0; + desc.ComponentFlagsMask = 0; + desc.ComponentManufacturer = AudioComponentManufacturerType.Apple; + + AudioComponent comp = AudioComponent.FindNextComponent (null, ref desc); + theUnit unit = new theUnit (comp); + return unit; + } + + [Test] + public void GetCurrentDevice_Test () + { + theUnit unit = GetAudioUnitForTest (); + + uint device = unit.GetCurrentDevice (AudioUnitScopeType.Global); + Assert.IsTrue (device != 0); + } + + [Test] + public void AudioObjectPropertySelector4CCTest () + { + Assert.That (FourCC ((int) AudioObjectPropertySelector.Devices), Is.EqualTo ("dev#"), "dev#"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.DefaultInputDevice), Is.EqualTo ("dIn "), "dIn "); + Assert.That (FourCC ((int) AudioObjectPropertySelector.DefaultOutputDevice), Is.EqualTo ("dOut"), "dOut"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.DefaultSystemOutputDevice), Is.EqualTo ("sOut"), "sOut"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.TranslateUIDToDevice), Is.EqualTo ("uidd"), "uidd"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.MixStereoToMono), Is.EqualTo ("stmo"), "stmo"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.PlugInList), Is.EqualTo ("plg#"), "plg#"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.TranslateBundleIDToPlugIn), Is.EqualTo ("bidp"), "bidp"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.TransportManagerList), Is.EqualTo ("tmg#"), "tmg#"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.TranslateBundleIDToTransportManager), Is.EqualTo ("tmbi"), "tmbi"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.BoxList), Is.EqualTo ("box#"), "box#"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.TranslateUIDToBox), Is.EqualTo ("uidb"), "uidb"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.ProcessIsMaster), Is.EqualTo ("mast"), "mast"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.IsInitingOrExiting), Is.EqualTo ("inot"), "inot"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.UserIDChanged), Is.EqualTo ("euid"), "euid"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.ProcessIsAudible), Is.EqualTo ("pmut"), "pmut"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.SleepingIsAllowed), Is.EqualTo ("slep"), "slep"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.UnloadingIsAllowed), Is.EqualTo ("unld"), "unld"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.HogModeIsAllowed), Is.EqualTo ("hogr"), "hogr"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.UserSessionIsActiveOrHeadless), Is.EqualTo ("user"), "user"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.ServiceRestarted), Is.EqualTo ("srst"), "srst"); + Assert.That (FourCC ((int) AudioObjectPropertySelector.PowerHint), Is.EqualTo ("powh"), "powh"); + } + + [Test] + public void AudioObjectPropertyScope4CCTest () + { + Assert.That (FourCC ((int) AudioObjectPropertyScope.Global), Is.EqualTo ("glob"), "glob"); + Assert.That (FourCC ((int) AudioObjectPropertyScope.Input), Is.EqualTo ("inpt"), "inpt"); + Assert.That (FourCC ((int) AudioObjectPropertyScope.Output), Is.EqualTo ("outp"), "outp"); + Assert.That (FourCC ((int) AudioObjectPropertyScope.PlayThrough), Is.EqualTo ("ptru"), "ptru"); + } + + string FourCC (int value) + { + return new string (new char [] { + (char) (byte) (value >> 24), + (char) (byte) (value >> 16), + (char) (byte) (value >> 8), + (char) (byte) value }); + } + } +} + diff --git a/tests/apitest/src/CoreAnimation/CABasicAnimation.cs b/tests/apitest/src/CoreAnimation/CABasicAnimation.cs new file mode 100644 index 000000000000..2383b79cb4ac --- /dev/null +++ b/tests/apitest/src/CoreAnimation/CABasicAnimation.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.CoreAnimation; +using MonoMac.CoreGraphics; +using MonoMac.Foundation; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using CoreAnimation; +using CoreGraphics; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class CABasicAnimationTests + { + [Test] + public void CABasicAnimation_FromToBy_INativeTests () + { + CABasicAnimation test = CABasicAnimation.FromKeyPath ("bounds"); + NSNumber number = new NSNumber (10); + test.From = number; + Assert.AreEqual (test.From, number, "NSObject from"); + test.To = number; + Assert.AreEqual (test.To, number, "NSObject to"); + test.By = number; + Assert.AreEqual (test.By, number, "NSObject by"); + + CGColor color = new CGColor (.5f, .5f, .5f); + test = CABasicAnimation.FromKeyPath ("color"); + test.SetFrom (color); + Assert.AreEqual (test.GetFromAs (), color, "INativeObject from"); + test.SetTo (color); + Assert.AreEqual (test.GetToAs (), color, "INativeObject to"); + test.SetBy (color); + Assert.AreEqual (test.GetByAs (), color, "INativeObject by"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/CoreAnimation/CAKeyFrameAnimation.cs b/tests/apitest/src/CoreAnimation/CAKeyFrameAnimation.cs new file mode 100644 index 000000000000..1ea8000fa544 --- /dev/null +++ b/tests/apitest/src/CoreAnimation/CAKeyFrameAnimation.cs @@ -0,0 +1,42 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.CoreAnimation; +using MonoMac.CoreGraphics; +using MonoMac.Foundation; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using CoreAnimation; +using CoreGraphics; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class CAKeyFrameAnimationTests + { + [Test] + public void CAKeyFrameAnimation_ValuesTests () + { + CAKeyFrameAnimation keyFrameAni = new CAKeyFrameAnimation(); + keyFrameAni.Values = new NSObject [] { new NSNumber (5) }; + Assert.AreEqual (1, keyFrameAni.Values.Length); + NSNumber arrayNumber = (NSNumber)keyFrameAni.Values[0]; + Assert.AreEqual (5, arrayNumber.Int32Value); + + CGRect frame = new CGRect (10, 10, 0, 0); + CGImage image = CGImage.ScreenImage (0, frame); + + keyFrameAni.SetValues (new CGImage [] {image, image}); + Assert.AreEqual (2, keyFrameAni.Values.Length); + CGImage arrayImage = (CGImage)keyFrameAni.GetValuesAs ()[1]; + Assert.AreEqual (image.Handle, arrayImage.Handle); + } + } +} + diff --git a/tests/apitest/src/CoreAnimation/CALayer.cs b/tests/apitest/src/CoreAnimation/CALayer.cs new file mode 100644 index 000000000000..4e247cbf08ed --- /dev/null +++ b/tests/apitest/src/CoreAnimation/CALayer.cs @@ -0,0 +1,44 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.CoreAnimation; +using MonoMac.CoreGraphics; +using MonoMac.Foundation; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using CoreAnimation; +using CoreGraphics; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class CALayerTests + { + [Test] + public void CALayer_ValuesTests () + { + CALayer layer = new CALayer (); + CGRect frame = new CGRect (10, 10, 0, 0); + CGImage image = CGImage.ScreenImage (0, frame); + NSImage NSImage = new NSImage (); + + layer.Contents = image; + CGImage arrayImage = layer.Contents; + Assert.AreEqual (image.Handle, arrayImage.Handle); + + layer.SetContents (NSImage); + NSImage arrayNSImage = layer.GetContentsAs (); + Assert.AreEqual (NSImage.Handle, arrayNSImage.Handle); + + layer.SetContents (null); // Should not throw + layer.Contents = null; // Should not throw + } + } +} + diff --git a/tests/apitest/src/CoreAnimation/CAOpenGLLayer.cs b/tests/apitest/src/CoreAnimation/CAOpenGLLayer.cs new file mode 100644 index 000000000000..083343a2907f --- /dev/null +++ b/tests/apitest/src/CoreAnimation/CAOpenGLLayer.cs @@ -0,0 +1,46 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.CoreAnimation; +using MonoMac.OpenGL; +using MonoMac.ObjCRuntime; +#else +using AppKit; +using Foundation; +using CoreAnimation; +using OpenGL; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class CAOpenGLLayerTest + { + [Test] + public void SubclassedTest () + { + using (var layer = new OpenGLLayer ()) { + Messaging.IntPtr_objc_msgSend (layer.Handle, Selector.GetHandle ("copyCGLPixelFormatForDisplayMask:")); + } + } + } + + public partial class OpenGLLayer : CAOpenGLLayer + { + public override CGLPixelFormat CopyCGLPixelFormatForDisplayMask (uint mask) + { + var attribs = new object [] { + CGLPixelFormatAttribute.Accelerated, + CGLPixelFormatAttribute.DoubleBuffer, + CGLPixelFormatAttribute.ColorSize, 24, + CGLPixelFormatAttribute.DepthSize, 16 }; + + CGLPixelFormat pixelFormat = new CGLPixelFormat (attribs); + return pixelFormat; + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/CoreImage/CIFilter.cs b/tests/apitest/src/CoreImage/CIFilter.cs new file mode 100644 index 000000000000..caee32142eca --- /dev/null +++ b/tests/apitest/src/CoreImage/CIFilter.cs @@ -0,0 +1,42 @@ +using NUnit.Framework; +using System; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.CoreImage; +using MonoMac.CoreGraphics; +using CGSize = System.Drawing.SizeF; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using ObjCRuntime; +using CoreImage; +using CoreGraphics; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class CIFilterTests + { + [Test] + public void CIFilterOutputImageTest () + { + NSImage nsImg = new NSImage (new CGSize (400, 400)); + nsImg.LockFocus (); + NSColor.Red.SetFill (); + NSBezierPath.FillRect (new CGRect (0, 0, 400, 400)); + nsImg.UnlockFocus (); + + CIImage img = CIImage.FromCGImage (nsImg.CGImage); + var gloom = new CIGloom () { + Image = img, + Intensity = 5, + Radius = 1 + }; + var output = gloom.OutputImage; + Assert.IsNotNull (output, "CIFilterOutputImageTest - output was null"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/DelegateAndDataSourceTest.cs b/tests/apitest/src/DelegateAndDataSourceTest.cs new file mode 100644 index 000000000000..c1f6b75479cb --- /dev/null +++ b/tests/apitest/src/DelegateAndDataSourceTest.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NUnit.Framework; +using System.Runtime.CompilerServices; + + +#if !XAMCORE_2_0 +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +#else +using Foundation; +using AppKit; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + static class TypeExtension { + public static PropertyInfo GetMostDerivedProperty (this Type t, string name) + { + while (t != null && t != t.BaseType) { + var rv = t.GetProperty (name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + if (rv != null) + return rv; + t = t.BaseType; + } + return null; + } + } + + [TestFixture] + public class DelegateAndDataSourceTest + { + [Test] + public void DelegateAndDataSourceAllowsNull () + { + var failingTypes = new Dictionary (); + + // Get our binding assembly + var xamMac = typeof (NSObject).Assembly; + + // Walk all non abstract types, looking for things with zero param constructors + foreach (Type t in xamMac.GetTypes ().Where (t => !t.IsAbstract)) { + // Check availability attributes. + if (Asserts.SkipDueToAvailabilityAttribute (t) || skip (t)) + continue; + + var ctor = t.GetConstructor (BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null); + + // If they have one of the properites we are testing + if (ctor != null) { + PropertyInfo weakDelegate = t.GetMostDerivedProperty("WeakDelegate"); + PropertyInfo del = t.GetMostDerivedProperty("Delegate"); + PropertyInfo weakDataSource = t.GetMostDerivedProperty("WeakDataSource"); + PropertyInfo dataSource = t.GetMostDerivedProperty("DataSource"); + if (isValidToTest (weakDelegate) || isValidToTest (del) || + isValidToTest (weakDataSource) || isValidToTest (dataSource) ) { + try { + // Create an instance and try to set null + using (var instance = (IDisposable) ctor.Invoke (null)) { + if (isValidToTest (weakDelegate)) { + weakDelegate.SetValue (instance, null, null); + } + if (isValidToTest (del)) { + del.SetValue (instance, null, null); + } + if (isValidToTest (weakDataSource)) { + weakDataSource.SetValue (instance, null, null); + } + if (isValidToTest (dataSource)) { + dataSource.SetValue (instance, null, null); + } + } + } + catch (TargetInvocationException e) { + failingTypes.Add (t, e.InnerException.Message); + } + catch (Exception e) { + Assert.Fail ("Unexpected exception {0} while testing {1}", e, t); + } + } + } + } + + GC.Collect (2); // Flush out random failures. Some classes only act badly when disposed + if (failingTypes.Count > 0) { + Console.WriteLine ("{0} failing types:", failingTypes.Count); + foreach (var kvp in failingTypes) + Console.WriteLine ("{0}: {1}", kvp.Key, kvp.Value); + Assert.Fail ("{0} failing types", failingTypes.Count); + } + } + + bool skip (Type t) + { + switch (t.Name) { + case "AVAssetResourceLoader": + case "AVAssetResourceLoadingRequest": + case "AVAssetResourceLoadingContentInformationRequest": + case "SCNRenderer": + case "NSStream": + case "NSSharingServicePicker": + case "NSCache": + case "NSToolbar": + case "NSComboBox": + case "NSComboBoxCell": + case "IKScannerDeviceView": + case "NSUserActivity": + case "NSFontPanel": + case "AVAudioRecorder": + case "MKMapView": + case "SKScene": + case "NSSpeechRecognizer": + case "NSClickGestureRecognizer": + // These classes don't do well when you instance them without support + return true; + case "SCNLayer": + case "SCNProgram": + if (Asserts.IsAtLeastElCapitan && IntPtr.Size == 4) + return true; + break; + } + + return false; + } + +// Based on bug 28505 - NSTabView wasn't holding a reference to the Delegate property under new ref count. +// An ArgumentSemantic (Strong, Retain, etc) is required to keep the reference around so the app doesn't crash after a GC. +// This test scans all bindings looking for instances where bindings don't have the correct ArgumentSemantic + [Test] + public void DelegateAndDataSourceHaveArgumentSemanticAttribute () + { + var failingTypes = new Dictionary (); + + // Get our binding assembly + var xamMac = typeof (NSObject).Assembly; + + foreach (Type t in xamMac.GetTypes ().Where (t => !t.IsAbstract)) { + // Check availability attributes. + if (Asserts.SkipDueToAvailabilityAttribute (t)) + continue; + + PropertyInfo weakDelegate = t.GetMostDerivedProperty ("WeakDelegate"); + PropertyInfo del = t.GetMostDerivedProperty ("Delegate"); + + MethodInfo[] accessors = null; + + if (del != null) { + if (weakDelegate != null) { + if (!weakDelegate.CanWrite) + continue; + + accessors = weakDelegate.GetAccessors (); + } else { + if (!del.CanWrite) + continue; + + accessors = del.GetAccessors (); + } + + foreach (var accessor in accessors) { + var attr = accessor.GetCustomAttributes ().FirstOrDefault (a => a.Selector == "delegate"); + if (attr == null) + continue; + + if (attr.ArgumentSemantic == ArgumentSemantic.None) { + failingTypes.Add (t, "Delegate has no ArgumentSemantic set"); + break; + } + } + } + + PropertyInfo weakDataSource = t.GetMostDerivedProperty ("WeakDataSource"); + PropertyInfo dataSource = t.GetMostDerivedProperty ("DataSource"); + + if (dataSource != null) { + accessors = null; + if (weakDataSource != null) { + if (!weakDataSource.CanWrite) + continue; + + accessors = weakDataSource.GetAccessors (); + } else { + if (!dataSource.CanWrite) + continue; + + accessors = dataSource.GetAccessors (); + } + + foreach (var accessor in accessors) { + var attr = accessor.GetCustomAttributes ().FirstOrDefault (a => a.Selector == "dataSource"); + if (attr == null) + continue; + + if (attr.ArgumentSemantic == ArgumentSemantic.None) { + failingTypes.Add (t, "Data Source has no ArgumentSemantic set"); + break; + } + } + } + } + + if (failingTypes.Count > 0) { + Console.WriteLine ("{0} failing types:", failingTypes.Count); + foreach (var kvp in failingTypes) + Console.WriteLine ("{0}: {1}", kvp.Key, kvp.Value); + Assert.Fail ("{0} failing types", failingTypes.Count); + } + } + + [Test] + public void TargetArgumentSemanticAttribute () + { + var failingTypes = new Dictionary (); + + // Get our binding assembly + var xamMac = typeof (NSObject).Assembly; + + foreach (Type t in xamMac.GetTypes ().Where (t => !t.IsAbstract)) { + // Check availability attributes. + if (Asserts.SkipDueToAvailabilityAttribute (t)) + continue; + + PropertyInfo target = t.GetMostDerivedProperty ("Target"); + if (target != null && target.PropertyType == typeof (NSObject)) { + MethodInfo[] accessors = target.GetAccessors (); + foreach (var accessor in accessors) { + var attr = accessor.GetCustomAttributes ().FirstOrDefault (a => a.Selector == "target"); + if (attr == null) + continue; + + if (attr.ArgumentSemantic == ArgumentSemantic.None) { + failingTypes.Add (t, "Target has no ArgumentSemantic set"); + break; + } + } + } + } + + if (failingTypes.Count > 0) { + Console.WriteLine ("{0} failing types:", failingTypes.Count); + foreach (var kvp in failingTypes) + Console.WriteLine ("{0}: {1}", kvp.Key, kvp.Value); + Assert.Fail ("{0} failing types", failingTypes.Count); + } + } + + bool isValidToTest (PropertyInfo p) + { + return p != null && p.CanWrite && !Asserts.SkipDueToAvailabilityAttribute (p); + } + } +} + diff --git a/tests/apitest/src/DerivedEventTest.cs b/tests/apitest/src/DerivedEventTest.cs new file mode 100644 index 000000000000..271c0d441aa7 --- /dev/null +++ b/tests/apitest/src/DerivedEventTest.cs @@ -0,0 +1,80 @@ +#if XAMCORE_2_0 +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using NUnit.Framework; + +using Foundation; +using AppKit; +using CoreGraphics; + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class DerivedEventTest + { + [Test] + public void DerivedEvents_DontStompEachOther () + { + NSComboBox b = new NSComboBox (new CGRect (0, 0, 200, 25)); + + b.SelectionChanged += (sender, e) => Console.WriteLine ("Change"); + TestDelegates (b); + b.EditingEnded += (sender, e) => Console.WriteLine ("Edit"); + TestDelegates (b); + b.Delegate = null; + + b.EditingEnded += (sender, e) => Console.WriteLine ("Edit"); + TestDelegates (b); + b.SelectionChanged += (sender, e) => Console.WriteLine ("Change"); + TestDelegates (b); + } + + void TestDelegates (NSComboBox b) + { + NSTextField f = (NSTextField)b; + Assert.IsNotNull (b.Delegate, "NSComboBox delegate null"); + Assert.IsNotNull (f.Delegate, "NSTextField delegate null"); + Assert.AreEqual (b.Delegate.GetHashCode (), f.Delegate.GetHashCode (), "Delegates are not equal"); + } + + [Test] + public void DerivedEvents_OverwriteThrows () + { + TestOverrideThrow (false, true); + TestOverrideThrow (true, true); +#if MONOMAC + NSApplication.CheckForEventAndDelegateMismatches = false; +#else + UIApplication.CheckForEventAndDelegateMismatches = false; +#endif + TestOverrideThrow (false, false); + TestOverrideThrow (true, false); + } + + void TestOverrideThrow (bool eventFirst, bool shouldThrow) + { + NSComboBox b = new NSComboBox (new CGRect (0, 0, 200, 25)); + if (eventFirst) + b.SelectionChanged += (sender, e) => Console.WriteLine ("Change"); + else + b.Delegate = new NSComboBoxDelegate (); + + bool didThrow = false; + try { + if (eventFirst) + b.Delegate = new NSComboBoxDelegate (); + else + b.SelectionChanged += (sender, e) => Console.WriteLine ("Change"); + } + catch (System.InvalidOperationException) { + didThrow = true; + } + if (shouldThrow != didThrow) + Assert.Fail ("TestOverrideThrow ({0}, {1}) did not have expected thrown status", eventFirst, shouldThrow); + } + } +} +#endif \ No newline at end of file diff --git a/tests/apitest/src/EveryFrameworkSmokeTest.cs b/tests/apitest/src/EveryFrameworkSmokeTest.cs new file mode 100644 index 000000000000..ba16756d060e --- /dev/null +++ b/tests/apitest/src/EveryFrameworkSmokeTest.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac; +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using AppKit; +using Foundation; +using ObjCRuntime; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class EveryFrameworkSmokeTests + { + enum LoadStatus { FailTest, Acceptable }; + + LoadStatus CheckLoadFailure (string libraryName, string path) + { + // Easy pass if the library doesn't even exist on the system... + if (!File.Exists (path)) + return LoadStatus.Acceptable; + + // No bindings for any of these yet + switch (libraryName) { + case "CryptoTokenKitLibrary": + case "FinderSyncLibrary": + case "HypervisorLibrary": + return LoadStatus.Acceptable; + } + + // These libraries only have 64-bit version + bool is64Bit = IntPtr.Size == 8; + if (!is64Bit) { + switch (libraryName) { + case "AVKitLibrary": + case "AccountsLibrary": + case "CloudKitLibrary": + case "ContactsLibrary": + case "ContactsUILibrary": + case "CryptoTokenKitLibrary": + case "EventKitLibrary": + case "FinderSyncLibrary": + case "GLKitLibrary": + case "GameControllerLibrary": + case "GameplayKitLibrary": + case "HypervisorLibrary": + case "LocalAuthenticationLibrary": + case "MapKitLibrary": + case "MediaLibraryLibrary": + case "MetalKitLibrary": + case "ModelIOLibrary": + case "MultipeerConnectivityLibrary": + case "NetworkExtensionLibrary": + case "NotificationCenterLibrary": + case "SceneKitLibrary": + case "SocialLibrary": + case "SpriteKitLibrary": + return LoadStatus.Acceptable; + } + } + + return LoadStatus.FailTest; + } + + [Test] + public void ExpectedLibrariesAreLoaded () + { + List failures = new List (); + + // In the past, we've missed frameworks in NSObject.mac.cs and shipped brokeness + // This test tries to verify every framework listed in Constants either is loaded or expected to not be + foreach (FieldInfo info in typeof(Constants).GetFields ().Where (x => x.Name.EndsWith ("Library")) ) { + string path = (string)info.GetRawConstantValue (); + // Use RTLD_NOLOAD (0x10) so we don't load, just check to see if it is in memory + IntPtr handle = Dlfcn.dlopen (path, 0x10); + if (handle == IntPtr.Zero && CheckLoadFailure (info.Name, path) == LoadStatus.FailTest) + failures.Add (string.Format ("{0} ({1}) failed to load but this was not expected", info.Name, path)); + } + + if (failures.Count > 0) + Assert.Fail (string.Join ("\n", failures)); + } + } +} diff --git a/tests/apitest/src/Foundation/AppleScript.cs b/tests/apitest/src/Foundation/AppleScript.cs new file mode 100644 index 000000000000..9b15cd13bad7 --- /dev/null +++ b/tests/apitest/src/Foundation/AppleScript.cs @@ -0,0 +1,36 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +#else +using AppKit; +using Foundation; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class AppleScriptTests + { + [Test] + public void AppleScript_BasicTest () + { +#pragma warning disable 0219 + const string script = @"tell application ""Finder"" +end tell"; + NSAppleScript s = new NSAppleScript (script); + + NSDictionary errorInfo; + bool success = s.CompileAndReturnError(out errorInfo); + Assert.IsTrue (success); + Assert.IsNull (errorInfo); + Assert.IsTrue (s.Compiled); + + NSAppleEventDescriptor descriptor = s.ExecuteAndReturnError (out errorInfo); + Assert.IsNull (errorInfo); +#pragma warning restore 0219 + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/Foundation/NSFormatter.cs b/tests/apitest/src/Foundation/NSFormatter.cs new file mode 100644 index 000000000000..c3f7490045e3 --- /dev/null +++ b/tests/apitest/src/Foundation/NSFormatter.cs @@ -0,0 +1,63 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.Foundation; +using MonoMac.AppKit; +#else +using Foundation; +using AppKit; +#endif + +namespace apitest +{ + [TestFixture] + public class NSFormatterTests + { + NSNumberFormatter formatter; + + [SetUp] + public void SetUp () + { + formatter = new NSNumberFormatter (); + formatter.NumberStyle = NSNumberFormatterStyle.Currency; + formatter.Locale = NSLocale.FromLocaleIdentifier ("en-US"); + } + + [Test] + public void NSFormatter_ShouldGetString () + { + var str = formatter.StringFor (NSNumber.FromFloat (0.12f)); + + Assert.AreEqual (str, "$0.12"); + } + + [Test] + public void NSFormatter_ShouldGetAttributedString () + { + var str = formatter.GetAttributedString (NSNumber.FromFloat (3.21f), new NSStringAttributes () { Font = NSFont.SystemFontOfSize (8) }); + + Assert.AreEqual (str.Value, "$3.21"); + } + + [Test] + public void NSFormatter_ShouldGetEditingString () + { + var str = formatter.EditingStringFor (NSNumber.FromInt32 (14)); + + Assert.AreEqual (str, "$14.00"); + } + + [Test] + public void NSFormatter_IsPartialStringValid () + { + string newstr; + NSString error; + formatter.PartialStringValidationEnabled = true; + var valid = formatter.IsPartialStringValid ("valid string", out newstr, out error); + + Assert.IsTrue (valid); + } + } +} + diff --git a/tests/apitest/src/Foundation/NSIndexSet.cs b/tests/apitest/src/Foundation/NSIndexSet.cs new file mode 100644 index 000000000000..96ab0e5a40db --- /dev/null +++ b/tests/apitest/src/Foundation/NSIndexSet.cs @@ -0,0 +1,52 @@ +using System; +using System.Linq; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +using nint = System.Int32; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +using CoreGraphics; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSIndexSetTests + { + [Test] + public void NSIndexSet_ConstructorTest () + { +#pragma warning disable 0219 + NSIndexSet a = new NSIndexSet ((int)5); +#if XAMCORE_2_0 + NSIndexSet b = new NSIndexSet ((uint)5); + NSIndexSet c = new NSIndexSet ((nint)5); +#endif +#pragma warning restore 0219 + } + + [Test] + public void NSIndexSet_EmptyToList () + { + NSIndexSet a = new NSIndexSet (); +#pragma warning disable 0219 + var b = a.ToList (); +#pragma warning restore 0219 + } + + [Test] + public void NSIndexSet_EmptyToArray () + { + NSIndexSet a = new NSIndexSet (); +#pragma warning disable 0219 + var b = a.ToArray (); +#pragma warning restore 0219 + } + } +} diff --git a/tests/apitest/src/Foundation/NSLayoutConstraint.cs b/tests/apitest/src/Foundation/NSLayoutConstraint.cs new file mode 100644 index 000000000000..8df3b63bee99 --- /dev/null +++ b/tests/apitest/src/Foundation/NSLayoutConstraint.cs @@ -0,0 +1,70 @@ +#if !XAMCORE_2_0 +using MonoMac.AppKit; +#else +using AppKit; +#endif +using NUnit.Framework; + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSLayoutConstraintTest + { + [Test] + public void FromVisualFormat () + { + using (var testView = new TestView ()) { + var constraints = NSLayoutConstraint.FromVisualFormat ("[firstLabel]-[secondLabel]-|", + NSLayoutFormatOptions.DirectionLeadingToTrailing, + "firstLabel", testView.FirstLabel, + "secondLabel", testView.SecondLabel + ); + + const int expectedNumberOfConstraints = 2; + + Assert.That (constraints != null, + "'NSLayoutConstraint.FromVisualFormat' method returned no constraints"); + + Assert.That (constraints.Length == expectedNumberOfConstraints, + string.Format ("Expected number of constraints is {0}. Actual number is {1}", expectedNumberOfConstraints, constraints.Length)); + + Assert.That (constraints [0].FirstItem == testView.SecondLabel, + "First item of constraints[0] is not testView.SecondLabel"); + Assert.That (constraints [0].SecondItem == testView.FirstLabel, + "Second item of constraints[0] is not testView.FirstLabel"); + Assert.That (constraints [0].Relation == NSLayoutRelation.Equal, + string.Format ("Relation between views of constraints[0] must be `NSLayoutRelation.Equal`. Actual realtion is {0}", constraints [0].Relation)); + + Assert.That (constraints [1].FirstItem == testView, + "First item of constraints[1] is not testView"); + Assert.That (constraints [1].SecondItem == testView.SecondLabel, + "Second item of constraints[1] is not testView.SecondLabel"); + Assert.That (constraints [1].Relation == NSLayoutRelation.Equal, + string.Format ("Relation between views of constraints[1] must be `NSLayoutRelation.Equal`. Actual realtion is {0}", constraints [1].Relation)); + } + } + } + + public class TestView : NSView + { + public NSTextView FirstLabel { get; private set; } + + public NSTextView SecondLabel { get; private set; } + + public TestView () + { + FirstLabel = new NSTextView { + TranslatesAutoresizingMaskIntoConstraints = false + }; + + AddSubview (FirstLabel); + + SecondLabel = new NSTextView { + TranslatesAutoresizingMaskIntoConstraints = false + }; + + AddSubview (SecondLabel); + } + } +} + diff --git a/tests/apitest/src/Foundation/NSObject.cs b/tests/apitest/src/Foundation/NSObject.cs new file mode 100644 index 000000000000..764fe7b24397 --- /dev/null +++ b/tests/apitest/src/Foundation/NSObject.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +using nint = System.Int32; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +using CoreGraphics; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSObjectTests + { + [Test] + async public Task NSObjectTests_InvokeTest () + { + bool hit = false; + NSApplication.SharedApplication.Invoke (() => hit = true, 1); + // Wait for 10 second, then give up + for (int i = 0; i < 1000; ++i) { + if (hit) + return; + await Task.Delay (10); + } + Assert.Fail ("Did not see events after 10 second"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/Foundation/NSScriptCommandArgumentDescriptionTest.cs b/tests/apitest/src/Foundation/NSScriptCommandArgumentDescriptionTest.cs new file mode 100644 index 000000000000..82895f7a4482 --- /dev/null +++ b/tests/apitest/src/Foundation/NSScriptCommandArgumentDescriptionTest.cs @@ -0,0 +1,88 @@ +// Copyright 2015 Xamarin, Inc. + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSScriptCommandArgumentDescriptionKeysTest { + [Test] + public void TestAppleEventCodeKey () + { + Assert.IsNotNull (NSScriptCommandArgumentDescriptionKeys.AppleEventCodeKey); + Assert.AreEqual ("AppleEventCode", NSScriptCommandArgumentDescriptionKeys.AppleEventCodeKey?.ToString ()); + } + + [Test] + public void TestTypeKey () + { + Assert.AreEqual ("Type", NSScriptCommandArgumentDescriptionKeys.TypeKey.ToString ()); + } + + [Test] + public void TestOptionalKey () + { + Assert.AreEqual ("Optional", NSScriptCommandArgumentDescriptionKeys.OptionalKey.ToString ()); + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSScriptCommandArgumentDescriptionTest { + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestConstructorNameNullOrEmpty (string name) + { + new NSScriptCommandArgumentDescription (name, "eeee", "NSString", false); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestConstructorEventCodeNullOrEmpty (string eventCode) + { + new NSScriptCommandArgumentDescription ("name", eventCode, "NSString", false); + } + + [TestCase ("srf")] + [TestCase ("TooLong")] + [ExpectedException (typeof (ArgumentException))] + public void TestConstructorEventCodeWrongLength (string eventCode) + { + new NSScriptCommandArgumentDescription ("name", eventCode, "NSString", false); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestConstructorTypeNullOrEmpty (string type) + { + new NSScriptCommandArgumentDescription ("name", "****", type, false); + } + + [TestCase ("name", "cdfd", "NSString", true)] + [TestCase ("name", "cdfd", "NSNumber", false)] + [TestCase ("name", "****", "NSNumber", true)] + [TestCase ("otherName", "****", "NSNumber", false)] + public void TestDescription (string name, string code, string type, bool isOptional) + { + var arg = new NSScriptCommandArgumentDescription (name, code, type, isOptional); + var description = arg.Dictionary; + + Assert.AreEqual (code, description [new NSString ("AppleEventCode")].ToString ()); + Assert.AreEqual (type, description [new NSString ("Type")].ToString ()); + Assert.AreEqual (isOptional? "Yes" : "No", description [ new NSString ("Optional")].ToString ()); + } + } +} diff --git a/tests/apitest/src/Foundation/NSScriptCommandDescriptionTest.cs b/tests/apitest/src/Foundation/NSScriptCommandDescriptionTest.cs new file mode 100644 index 000000000000..33692bf1eb56 --- /dev/null +++ b/tests/apitest/src/Foundation/NSScriptCommandDescriptionTest.cs @@ -0,0 +1,212 @@ +// Copyright 2015 Xamarin, Inc. + +using System; +using System.Collections.Generic; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSScriptCommandDescriptionTest { + + NSScriptCommandDescription scriptDescription = null; + Dictionary args; + NSScriptCommandDescriptionDictionary dict = null; + string suiteName, commandName, cmdClass, eventCode, eventClass, returnType, resultAppleEvent = null; + + [SetUp] + public void Init () + { + args = new Dictionary { + {"firstArg", new NSScriptCommandArgumentDescription {Name="firstArg", AppleEventCode="fArg", Type="integer", IsOptional=true}}, + {"secondArg", new NSScriptCommandArgumentDescription {Name="secondArg", AppleEventCode="sArg", Type="NSNumber"}}, + {"thirdArg", new NSScriptCommandArgumentDescription {Name="thirdArg", AppleEventCode="tArg", Type="integer"}} + }; + + suiteName = "Chromium Suite"; + commandName = "Exec Python"; + cmdClass = "NSScriptCommand"; + eventCode = "ExPy"; + eventClass = "CrSu"; + returnType = "NSString"; + resultAppleEvent = "text"; + dict = new NSScriptCommandDescriptionDictionary { + CommandClass = cmdClass, + AppleEventCode = eventCode, + AppleEventClassCode = eventClass, + Type = returnType, + ResultAppleEventCode = resultAppleEvent + }; + + foreach(var arg in args.Values) { + dict.Add (arg); + } + scriptDescription = NSScriptCommandDescription.Create (suiteName, commandName, dict); + } + + [TearDown] + public void Dispose () + { + if (scriptDescription != null) + scriptDescription.Dispose (); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateWithDictWrongArgDescription () + { + var description = new NSScriptCommandDescriptionDictionary (); + NSScriptCommandDescription.Create (suiteName, commandName, description); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateWithDictNullOrEmptySuitName (string code) + { + var description = new NSScriptCommandDescriptionDictionary (); + NSScriptCommandDescription.Create (code, commandName, description); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateWithDictNullOrEmptyCommandName (string code) + { + var description = new NSScriptCommandDescriptionDictionary (); + NSScriptCommandDescription.Create (suiteName, code, description); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestCreateWithDictNullDict () + { + NSScriptCommandDescriptionDictionary dict = null; + NSScriptCommandDescription.Create (suiteName, commandName, dict); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateSuiteNameNullOrEmpty (string code) + { + NSScriptCommandDescription.Create (code, commandName, dict); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateCommandNameNullOrEmpty (string code) + { + NSScriptCommandDescription.Create (suiteName, code, dict); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateCmdClassNullOrEmpty (string code) + { + dict.CommandClass = code; + NSScriptCommandDescription.Create (suiteName, commandName, dict); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateEventCodeNullOrEmpty (string code) + { + dict.AppleEventCode = code; + NSScriptCommandDescription.Create (suiteName, commandName, dict); + } + + [TestCase ("TooLong")] + [TestCase ("srt")] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateEventCodeWrongLength (string code) + { + dict.AppleEventCode = code; + NSScriptCommandDescription.Create (suiteName, commandName, dict); + } + + [TestCase ("TooLong")] + [TestCase ("srt")] + [ExpectedException (typeof (ArgumentException))] + public void TestCreateResultAppleEventWrongLength (string code) + { + dict.ResultAppleEventCode = code; + NSScriptCommandDescription.Create (suiteName, commandName, dict); + } + + [Test] + public void TestClassName () + { + Assert.AreEqual (cmdClass, scriptDescription.ClassName); + } + + [Test] + public void TestName () + { + Assert.AreEqual (commandName, scriptDescription.Name); + } + + [Test] + public void TestSuiteName () + { + Assert.AreEqual (suiteName, scriptDescription.SuitName); + } + + [Test] + public void TestArgumentsNames () + { + Assert.AreEqual (args.Keys.Count, scriptDescription.ArgumentNames.Length); + foreach (var argName in scriptDescription.ArgumentNames) { + Assert.IsTrue (args.Keys.Contains (argName), "Arg {0} is missing", argName); + } + } + + [Test] + public void TestAppleEventClassCode () + { + Assert.AreEqual (eventClass, scriptDescription.AppleEventClassCode); + } + + [Test] + public void TestAppleEventCode () + { + Assert.AreEqual (eventCode, scriptDescription.AppleEventCode); + } + + [Test] + public void TestIsOptionalArgument () + { + foreach (KeyValuePair kvp in args) { + Assert.AreEqual (kvp.Value.IsOptional, scriptDescription.IsOptionalArgument (kvp.Key), + "Wrong apple event code for arg {0}", kvp.Key); + } + } + + [Test] + public void TestGetAppleEventCodeForArgument () + { + foreach (KeyValuePair kvp in args) { + Assert.AreEqual (kvp.Value.AppleEventCode, scriptDescription.GetAppleEventCodeForArgument (kvp.Key), + "Wrong apple event code for arg {0}", kvp.Key); + } + } + + [Test] + public void TestReturnType () + { + Assert.AreEqual (returnType, scriptDescription.ReturnType); + } + } +} diff --git a/tests/apitest/src/Foundation/NSString.cs b/tests/apitest/src/Foundation/NSString.cs new file mode 100644 index 000000000000..d7a6857ad5e1 --- /dev/null +++ b/tests/apitest/src/Foundation/NSString.cs @@ -0,0 +1,85 @@ +using System; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +using nuint = System.UInt32; +using nint = System.Int32; +using CGRect = System.Drawing.RectangleF; +using CGSize = System.Drawing.SizeF; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +using CoreGraphics; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSStringTests + { + [Test] + public void NSString_LineRangeForRange () + { + // Test from http://stackoverflow.com/questions/1085524/how-to-count-the-number-of-lines-in-an-objective-c-string-nsstring + NSString input = new NSString("Hey\nHow\nYou\nDoing"); + int stringLength = (int)input.Length; + int numberOfLines = 0; + for (int index = 0 ; index < stringLength ; numberOfLines++) { + NSRange range = input.LineRangeForRange (new NSRange(index, 0)); + index = (int)(range.Location + range.Length); + } + Assert.AreEqual (4, numberOfLines); + } + + [Test] + public void NSString_GetLineStart () + { + NSString input = new NSString("Hey\nHow\nYou\nDoing"); + nuint start, lineEnd, contentsEnd; + input.GetLineStart (out start, out lineEnd, out contentsEnd, new NSRange (5, 11)); + Assert.AreEqual (4, start); + Assert.AreEqual (17, lineEnd); + Assert.AreEqual (17, contentsEnd); + } + + [Test] + public void NSString_BoundingRectWithSize () + { + NSString input = new NSString("Hey\nHow\nYou\nDoing"); + CGRect rect = input.BoundingRectWithSize (new CGSize (20, 30), NSStringDrawingOptions.UsesLineFragmentOrigin | NSStringDrawingOptions.UsesFontLeading, new NSDictionary ()); + Assert.IsTrue (rect.Width > 0); + Assert.IsTrue (rect.Height > 0); + } + } + + [TestFixture] + public class NSAttributedStringTests + { + [Test] + public void NSAttributedString_BoundingRectWithSize () + { + NSFont font = NSFont.FromFontName ("Arial", 40); + NSAttributedString str = new NSAttributedString("Hello World", font); + CGRect rect = str.BoundingRectWithSize (new CGSize (20, 30), NSStringDrawingOptions.UsesLineFragmentOrigin | NSStringDrawingOptions.UsesFontLeading); + Assert.IsTrue (rect.Width > 0); + Assert.IsTrue (rect.Height > 0); + } + + [Test] + public void NSAttributedString_GetUrl () + { + NSRange range; + var str = new NSAttributedString ("Test string with url: http://www.google.com"); + var url = str.GetUrl (42, out range); + + Assert.IsNotNull (url); + Assert.IsTrue (url.AbsoluteString == "http://www.google.com"); + Assert.IsTrue (range.Location == 22); + Assert.IsTrue (range.Length == 21); + } + } +} diff --git a/tests/apitest/src/Foundation/NSThread.cs b/tests/apitest/src/Foundation/NSThread.cs new file mode 100644 index 000000000000..0f0d59f9ba31 --- /dev/null +++ b/tests/apitest/src/Foundation/NSThread.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +using nint = System.Int32; +#else +using AppKit; +using ObjCRuntime; +using Foundation; +using CoreGraphics; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class NSThreadTests + { + [Test] + public void NSThread_CallStack_Test() + { + string [] stack = NSThread.NativeCallStack; + Assert.IsNotNull (stack); + Assert.IsTrue (stack.Length > 0); + } + } +} diff --git a/tests/apitest/src/MonoMac/AssemblyTest.cs b/tests/apitest/src/MonoMac/AssemblyTest.cs new file mode 100644 index 000000000000..fe9cf7fcbf95 --- /dev/null +++ b/tests/apitest/src/MonoMac/AssemblyTest.cs @@ -0,0 +1,32 @@ +// +// Unit tests for the assembly itself +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoMac.Foundation; +#endif +using NUnit.Framework; + +namespace MonoMacFixtures { + + [TestFixture] + public class AssemblyTest { + + static byte[] pkt = { 0x84, 0xe0, 0x4f, 0xf9, 0xcf, 0xb7, 0x90, 0x65 }; + + [Test] + public void PublicKeyToken () + { + Assert.AreEqual (pkt, typeof (NSObject).Assembly.GetName ().GetPublicKeyToken (), "GetPublicKeyToken"); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/MonoMac/CBUUID.cs b/tests/apitest/src/MonoMac/CBUUID.cs new file mode 100644 index 000000000000..02a690e6f2e7 --- /dev/null +++ b/tests/apitest/src/MonoMac/CBUUID.cs @@ -0,0 +1,139 @@ +// +// Unit tests for CBUUID +// +// Authors: +// Aaron Bockover +// +// Copyright 2013 Xamarin, Inc. +// + +using System; + +#if XAMCORE_2_0 +using Foundation; +using CoreBluetooth; +#else +using MonoMac.Foundation; +using MonoMac.CoreBluetooth; +#endif + +using NUnit.Framework; + +namespace MonoMacFixtures.CoreBluetooth +{ + [TestFixture] + public class CBUUIDTest + { + [Test] + public void Roundtrip_16bits () + { + using (CBUUID uuid = CBUUID.FromString ("1234")) { + Assert.That (uuid.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.IsNotNull (uuid.Data, "Data"); + Assert.That (uuid.Description, Is.EqualTo ("Unknown (<1234>)"), "Description"); + Assert.That (uuid.ToString (false), Is.EqualTo ("1234"), "ToString(false)"); + Assert.That (uuid.ToString (true), Is.EqualTo ("00001234-0000-1000-8000-00805f9b34fb"), "ToString(true)"); + using (CBUUID u2 = CBUUID.FromString (uuid.ToString ())) { + Assert.That (u2.ToString (), Is.EqualTo (uuid.ToString ()), "Roundtrip"); + } + } + } + + [Test] + public void Roundtrip_128bits () + { + using (CBUUID uuid = CBUUID.FromString ("12345678-90AB-CDEF-cafe-c80c20443d0b")) { + Assert.That (uuid.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.IsNotNull (uuid.Data, "Data"); + Assert.That (uuid.Description, Is.EqualTo ("Unknown (<12345678 90abcdef cafec80c 20443d0b>)"), "Description"); + Assert.That (uuid.ToString (false), Is.EqualTo (uuid.ToString (true)), "ToString"); + using (CBUUID u2 = CBUUID.FromString (uuid.ToString ())) { + Assert.That (u2.ToString (), Is.EqualTo (uuid.ToString ()), "Roundtrip"); + } + } + } + + static CBUUID MakeFull (byte a, byte b) + { + return MakeFull (0, 0, a, b); + } + + static CBUUID MakeFull (byte a, byte b, byte c, byte d) + { + return CBUUID.FromBytes (new byte [] { + a, b, c, d, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb + }); + } + + [Test] + public void Null () + { + Assert.That (null as CBUUID, Is.Null); + Assert.That (null as CBUUID, Is.EqualTo (null as CBUUID)); + } + + [Test] + public void FullRandomEquals () + { + var guid = Guid.NewGuid (); + Assert.That (CBUUID.FromBytes (guid.ToByteArray ()), + Is.EqualTo (CBUUID.FromBytes (guid.ToByteArray ()))); + } + + [Test] + public void FullRandomNotEqual () + { + Assert.That (CBUUID.FromBytes (Guid.NewGuid ().ToByteArray ()), + Is.Not.EqualTo (CBUUID.FromBytes (Guid.NewGuid ().ToByteArray ()))); + } + + [Test] + public void PartialEquals () + { + var guid = new byte [] { 0xaa, 0xbb }; + Assert.That (CBUUID.FromBytes (guid), + Is.EqualTo (CBUUID.FromBytes (guid))); + + // ObjC exception: Data does not represent a valid UUID +// guid = new byte [] { 0xaa, 0xbb, 0xcc, 0xdd }; +// Assert.That (CBUUID.FromBytes (guid), +// Is.EqualTo (CBUUID.FromBytes (guid))); + + Assert.That (CBUUID.FromPartial (0x1234), + Is.EqualTo (CBUUID.FromPartial (0x1234))); + + Assert.That (CBUUID.FromString ("1234"), + Is.EqualTo (CBUUID.FromBytes (new byte [] { 0x12, 0x34 }))); + + // ObjC exception: Data <12345678> does not represent a valid UUID +// Assert.That (CBUUID.FromString ("12345678"), +// Is.EqualTo (CBUUID.FromBytes (new byte [] { 0x12, 0x34, 0x56, 0x78 }))); + } + + [Test] + public void PartialEqualsFull () + { + Assert.That (CBUUID.FromPartial (0x0127), Is.EqualTo (MakeFull (0x01, 0x27))); + + // ObjC exception: Data does not represent a valid UUID +// Assert.That (CBUUID.FromBytes (new byte [] { 0xab, 0xcd, 0xef, 0x12 }), +// Is.EqualTo (MakeFull (0xab, 0xcd, 0xef, 0x12))); + + Assert.That (CBUUID.FromString ("1234"), + Is.EqualTo (CBUUID.FromString ("00001234-0000-1000-8000-00805f9b34fb"))); + + // ObjC exception: Data <12345678> does not represent a valid UUID +// Assert.That (CBUUID.FromString ("12345678"), +// Is.EqualTo (CBUUID.FromString ("12345678-0000-1000-8000-00805f9b34fb"))); + } + + [Test] + public void PartialsOfDifferentSizeNotEqual () + { + // ObjC exception: Data <12345678> does not represent a valid UUID + Assert.That (CBUUID.FromPartial (0x1234), Is.Not.EqualTo ( + CBUUID.FromString ("12345678-0000-1000-8000-00805f9b34fb"))); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/NSScriptCommandDescriptionDictionaryTest.cs b/tests/apitest/src/NSScriptCommandDescriptionDictionaryTest.cs new file mode 100644 index 000000000000..c1283499f92e --- /dev/null +++ b/tests/apitest/src/NSScriptCommandDescriptionDictionaryTest.cs @@ -0,0 +1,95 @@ + +// Copyright 2015 Xamarin, Inc. + +using System; +using System.Collections.Generic; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSScriptCommandDescriptionDictionaryTest { + [Test] + public void TestAddNullArgument () + { + var arg = new NSScriptCommandArgumentDescription () { AppleEventCode="frgt", Type="text", Name="Foo"}; + var desc = new NSScriptCommandDescriptionDictionary (); + // no exception should happen + desc.Add (arg); + using (var argKey = new NSString ("Arguments")) + using (var nsName = new NSString (arg.Name)) { + Assert.IsTrue (desc.Dictionary.ContainsKey (argKey)); + var argDict = desc.Dictionary [argKey] as NSDictionary; + Assert.IsNotNull (argDict); + Assert.IsTrue (argDict.ContainsKey (nsName)); + } + } + + [Test] + public void TestAddArgument () + { + var arg = new NSScriptCommandArgumentDescription () { AppleEventCode="frgt", Type="text", Name="Foo"}; + var desc = new NSScriptCommandDescriptionDictionary () {Arguments = new NSMutableDictionary ()}; + // no exception should happen + desc.Add (arg); + using (var argKey = new NSString ("Arguments")) + using (var nsName = new NSString (arg.Name)) { + Assert.IsTrue (desc.Dictionary.ContainsKey (argKey)); + var argDict = desc.Dictionary [argKey] as NSDictionary; + Assert.IsNotNull (argDict); + Assert.IsTrue (argDict.ContainsKey (nsName)); + } + } + + [Test] + public void TestRemoveNoArguments () + { + var arg = new NSScriptCommandArgumentDescription () { AppleEventCode="frgt", Type="text", Name="Foo"}; + var desc = new NSScriptCommandDescriptionDictionary (); + // no exception should happen + Assert.IsFalse (desc.Remove (arg)); + } + + [Test] + public void TestRemoveMissingArgument () + { + var arg = new NSScriptCommandArgumentDescription () { AppleEventCode="frgt", Type="text", Name="Foo"}; + var desc = new NSScriptCommandDescriptionDictionary () {Arguments = new NSMutableDictionary ()}; + // no exception should happen + Assert.IsFalse (desc.Remove (arg)); + } + + [Test] + public void RemoveArgument () + { + var arg = new NSScriptCommandArgumentDescription () { AppleEventCode="frgt", Type="text", Name="Foo"}; + var desc = new NSScriptCommandDescriptionDictionary () {Arguments = new NSMutableDictionary ()}; + // no exception should happen + desc.Add (arg); + using (var argKey = new NSString ("Arguments")) + using (var nsName = new NSString (arg.Name)) { + Assert.IsTrue (desc.Dictionary.ContainsKey (argKey)); + var argDict = desc.Dictionary [argKey] as NSDictionary; + Assert.IsNotNull (argDict); + Assert.IsTrue (argDict.ContainsKey (nsName)); + } + desc.Remove (arg); + using (var argKey = new NSString ("Arguments")) + using (var nsName = new NSString (arg.Name)) { + Assert.IsTrue (desc.Dictionary.ContainsKey (argKey)); + var argDict = desc.Dictionary [argKey] as NSDictionary; + Assert.IsNotNull (argDict); + Assert.IsFalse (argDict.ContainsKey (nsName)); + } + } + } +} diff --git a/tests/apitest/src/ObjCRuntime/ClassTest.cs b/tests/apitest/src/ObjCRuntime/ClassTest.cs new file mode 100644 index 000000000000..89a5ea6ccc63 --- /dev/null +++ b/tests/apitest/src/ObjCRuntime/ClassTest.cs @@ -0,0 +1,51 @@ +// +// Unit tests for Class +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoMacFixtures.ObjCRuntime { + + [TestFixture] + public class ClassTest { + [Test] + public void ThrowOnMissingNativeClassTest () + { + bool saved = Class.ThrowOnInitFailure; + + Class.ThrowOnInitFailure = true; + try { + new InexistentClass (); + Assert.Fail ("a"); + } catch { + // OK + } finally { + Class.ThrowOnInitFailure = saved; + } + } + + [Register ("Inexistent", true)] + public class InexistentClass : NSObject { + public override IntPtr ClassHandle { + get { + return Class.GetHandle (GetType ().Name); + } + } + } + } +} diff --git a/tests/apitest/src/ObjCRuntime/Messaging.cs b/tests/apitest/src/ObjCRuntime/Messaging.cs new file mode 100644 index 000000000000..b3be5b134461 --- /dev/null +++ b/tests/apitest/src/ObjCRuntime/Messaging.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.InteropServices; + +public class Messaging +{ + const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib"; + + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static bool bool_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend (IntPtr receiver, IntPtr selector); +} + diff --git a/tests/apitest/src/SceneKit/SCNGeometrySource.cs b/tests/apitest/src/SceneKit/SCNGeometrySource.cs new file mode 100644 index 000000000000..8714154970e7 --- /dev/null +++ b/tests/apitest/src/SceneKit/SCNGeometrySource.cs @@ -0,0 +1,78 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.Foundation; +using MonoMac.SceneKit; +#else +using Foundation; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SCNGeometrySourceTests + { + [SetUp] + public void SetUp () + { + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNGeometrySourceSemanticTest () + { + Asserts.EnsureMountainLion (); + Assert.IsNotNull (SCNGeometrySourceSemantic.Color, "Color"); + } + + private bool isValidEnumForPlatform (SCNGeometrySourceSemantics value) + { + if (Asserts.IsAtLeastYosemite) + return true; + + switch (value) { + case SCNGeometrySourceSemantics.Color: + case SCNGeometrySourceSemantics.Normal: + case SCNGeometrySourceSemantics.Texcoord: + case SCNGeometrySourceSemantics.Vertex: + return true; + + case SCNGeometrySourceSemantics.BoneIndices: + case SCNGeometrySourceSemantics.BoneWeights: + case SCNGeometrySourceSemantics.EdgeCrease: + case SCNGeometrySourceSemantics.VertexCrease: + default: // this might need updating with 10.11 + return Asserts.IsAtLeastYosemite; + } + } + + [Test] + public void SCNGeometrySource_FromDataTest () + { + Asserts.EnsureMountainLion (); +#pragma warning disable 0219 + SCNGeometrySource d = SCNGeometrySource.FromData (new NSData (), SCNGeometrySourceSemantic.Color, 1, false, 1, 1, 1, 1); + foreach (SCNGeometrySourceSemantics s in Enum.GetValues (typeof (SCNGeometrySourceSemantics))) { + if (!isValidEnumForPlatform (s)) + continue; + d = SCNGeometrySource.FromData (new NSData (), s, 1, false, 1, 1, 1, 1); + } +#pragma warning restore 0219 + } + + [Test] + public void SCNGeometrySource_BoneStringTests () // These were radar://17782603 + { + Asserts.EnsureYosemite (); + +#pragma warning disable 0219 + SCNGeometrySource d = SCNGeometrySource.FromData (new NSData (), SCNGeometrySourceSemantic.BoneWeights, 1, false, 1, 1, 1, 1); + d = SCNGeometrySource.FromData (new NSData (), SCNGeometrySourceSemantic.BoneIndices, 1, false, 1, 1, 1, 1); +#pragma warning restore 0219 + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SceneKit/SCNMaterial.cs b/tests/apitest/src/SceneKit/SCNMaterial.cs new file mode 100644 index 000000000000..9cb425d3a7af --- /dev/null +++ b/tests/apitest/src/SceneKit/SCNMaterial.cs @@ -0,0 +1,48 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.SceneKit; +#else +using AppKit; +using Foundation; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SCNMaterialTests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureMavericks (); + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNMaterial_ShaderModifierTest_Weak () + { + if (IntPtr.Size == 8) // API is 64-bit only + { + SCNMaterial m = new SCNMaterial (); + m.WeakShaderModifiers = new NSDictionary (); + } + } + + [Test] + public void SCNMaterial_ShaderModifierTest () + { + if (IntPtr.Size == 8) // API is 64-bit only + { + SCNMaterial m = new SCNMaterial (); + m.ShaderModifiers = new SCNShaderModifiers (); + } + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SceneKit/SCNNode.cs b/tests/apitest/src/SceneKit/SCNNode.cs new file mode 100644 index 000000000000..56a206a553ba --- /dev/null +++ b/tests/apitest/src/SceneKit/SCNNode.cs @@ -0,0 +1,70 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.CoreAnimation; +using MonoMac.SceneKit; +#else +using AppKit; +using Foundation; +using CoreAnimation; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SCNNodeTests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureMavericks (); + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNNode_AddAnimation () + { + SCNNode c = new SCNNode (); + CABasicAnimation a = CABasicAnimation.FromKeyPath ("hidden"); + NSString key = new NSString("MyKey"); + c.AddAnimation (a, key); + CAPropertyAnimation cur = (CAPropertyAnimation)c.GetAnimation (key); + Assert.IsNotNull (cur); + Assert.AreEqual (cur.KeyPath, "hidden"); + c.RemoveAnimation (key); + cur = (CAPropertyAnimation)c.GetAnimation (key); + Assert.IsNull (cur); + } + + [Test] + public void SCNNode_SetPhysicsBodyTest () + { + Asserts.EnsureYosemite (); + + if (IntPtr.Size == 8) + { + // Create a new empty scene + var Scene = new SCNScene (); + + var floorNode = SCNNode.Create (); + Scene.RootNode.AddChildNode (floorNode); + + floorNode.PhysicsBody = SCNPhysicsBody.CreateStaticBody (); + Scene.PhysicsWorld.Speed = 0; + } + } + + [Test] + public void SCNNode_GeometryNullTest () + { + var floorNode = SCNNode.Create (); + floorNode.Geometry = null; + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SceneKit/SCNScene.cs b/tests/apitest/src/SceneKit/SCNScene.cs new file mode 100644 index 000000000000..b1b35ad3461e --- /dev/null +++ b/tests/apitest/src/SceneKit/SCNScene.cs @@ -0,0 +1,52 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.Foundation; +using MonoMac.SceneKit; + +#else +using Foundation; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SCNSceneTests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNSceneLoadingOptions_AnimationImportPolicyTest () + { + SCNSceneLoadingOptions o = new SCNSceneLoadingOptions (); + RoundTrip (o, SCNAnimationImportPolicy.Play); + RoundTrip (o, SCNAnimationImportPolicy.PlayRepeatedly); + RoundTrip (o, SCNAnimationImportPolicy.DoNotPlay); + RoundTrip (o, SCNAnimationImportPolicy.PlayUsingSceneTimeBase); + } + + [Test] + public void SCNSceneLoadingOptions_AnimationImportPolicyTestKeysNonNull () + { + Assert.IsNotNull (SCNSceneSourceLoading.AnimationImportPolicyPlay); + Assert.IsNotNull (SCNSceneSourceLoading.AnimationImportPolicyPlayRepeatedly); + Assert.IsNotNull (SCNSceneSourceLoading.AnimationImportPolicyDoNotPlay); + Assert.IsNotNull (SCNSceneSourceLoading.AnimationImportPolicyPlayUsingSceneTimeBase); + } + + void RoundTrip (SCNSceneLoadingOptions o, SCNAnimationImportPolicy policy) + { + o.AnimationImportPolicy = policy; + Assert.IsTrue (o.AnimationImportPolicy == policy); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SceneKit/SCNView.cs b/tests/apitest/src/SceneKit/SCNView.cs new file mode 100644 index 000000000000..9828d574e579 --- /dev/null +++ b/tests/apitest/src/SceneKit/SCNView.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.CoreAnimation; +using MonoMac.SceneKit; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using Foundation; +using CoreAnimation; +using CoreGraphics; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SCNViewTests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNView_TechniqueSetterTest () + { + SCNView v = new SCNView (new CGRect (), (NSDictionary) null); + SCNTechnique t = SCNTechnique.Create (new NSDictionary ()); + v.Technique = t; + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SceneKit/SCNWorld.cs b/tests/apitest/src/SceneKit/SCNWorld.cs new file mode 100644 index 000000000000..18af5764e563 --- /dev/null +++ b/tests/apitest/src/SceneKit/SCNWorld.cs @@ -0,0 +1,41 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.CoreAnimation; +using MonoMac.SceneKit; +#else +using AppKit; +using Foundation; +using CoreAnimation; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SCNWorldTests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureMavericks (); + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNNode_BackfaceCulling () + { + Asserts.EnsureYosemite (); + + if (IntPtr.Size == 8) + { + Assert.IsNotNull (SCNPhysicsTestKeys.BackfaceCullingKey); + } + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SceneKit/SceneKit.cs b/tests/apitest/src/SceneKit/SceneKit.cs new file mode 100644 index 000000000000..e15e0865a8d0 --- /dev/null +++ b/tests/apitest/src/SceneKit/SceneKit.cs @@ -0,0 +1,53 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.CoreAnimation; +using MonoMac.SceneKit; +using CGRect = System.Drawing.RectangleF; +#else +using AppKit; +using Foundation; +using CoreAnimation; +using CoreGraphics; +using SceneKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SceneKitTests // Generic one off tests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureYosemite (); + if (Asserts.IsAtLeastElCapitan) + Asserts.Ensure64Bit (); + } + + [Test] + public void SCNGeometrySourceSemantic_ColorKeyTest () + { + NSString s = SCNGeometrySourceSemantic.Color; + Assert.IsTrue (s != null && s != (NSString)(string.Empty)); + } + + [Test] + public void SCNPhysicsTestKeys_SearchModeKeyTest () + { + NSString s = SCNPhysicsTestKeys.SearchModeKey; + Assert.IsTrue (s != null && s != (NSString)(string.Empty)); + } + + [Test] + public void SCNSceneSourceLoading_AnimationImportPolicyKeyTest () + { + NSString s = SCNSceneSourceLoading.AnimationImportPolicyKey; + Assert.IsTrue (s != null && s != (NSString)(string.Empty)); + } + } +} \ No newline at end of file diff --git a/tests/apitest/src/SearchKit/SearchKitTest.cs b/tests/apitest/src/SearchKit/SearchKitTest.cs new file mode 100644 index 000000000000..0f7611d2130f --- /dev/null +++ b/tests/apitest/src/SearchKit/SearchKitTest.cs @@ -0,0 +1,154 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using SearchKit; + +namespace apitest { + + [TestFixture] + public class SearchKitTests { + string path = "/tmp/my.index"; + + [SetUp] + public void Setup () + { + SKIndex.LoadDefaultExtractorPlugIns (); + if (File.Exists (path)) + File.Delete (path); + + } + + [Test] + public void TestCreate () + { + var idx = SKIndex.CreateWithUrl (new NSUrl ("file://" + path), "myIndex", SKIndexType.InvertedVector, null); + if (idx == null) + throw new Exception (); + + + var d1 = new SKDocument (new NSUrl ("file:///etc/passwd")); + var d2 = new SKDocument (new NSUrl ("file:///etc/fstab")); + idx.AddDocument (d1, "text/plain", true); + + idx.AddDocumentWithText (d2, "This file contains some text like an Apple and an Orange", true); + + const int max = 10; + nint [] ids = new nint [max]; + float[] scores = new float[max]; + nint nfound; + bool more; + + using (var search = idx.Search ("some", SKSearchOptions.SpaceMeansOr)) { + more = search.FindMatches (max, ref ids, ref scores, 1, out nfound); + Assert.IsFalse (more); + + for (nint i = 0; i < nfound; i++) { + var doc = idx.GetDocument (ids [i]); + Assert.IsNotNull (doc, "TestCreate - GetDocument returned null"); + } + } + + using (var search = idx.Search ("some", SKSearchOptions.SpaceMeansOr)) { + more = search.FindMatches (max, ref ids, 1, out nfound); + for (nint i = 0; i < nfound; i++) { + var doc = idx.GetDocument (ids [i]); + Console.WriteLine ("Got {0}", doc); + } + } + + idx.Compact (); + idx.Flush (); + idx.Close (); + + // Now open + idx = SKIndex.FromUrl (new NSUrl ("file://" + path), "myIndex", true); + Assert.NotNull (idx); + + } + + [Test] + public void TestInMemory () + { + var m = new NSMutableData (); + var idx = SKIndex.CreateWithMutableData (m, "indexName", SKIndexType.Inverted, null); + Assert.NotNull (idx); + idx.AddDocumentWithText (new SKDocument (new NSUrl ("file:///etc/passwd")), "These are the contents of the passwd file, well, not really", true); + idx.Flush (); + idx.Compact (); + idx.Close (); + + idx = SKIndex.FromMutableData (m, "indexName"); + Assert.NotNull (idx); + idx.Close (); + } + + [Test] + public void TestTextAnalysis () + { + var m = new NSMutableData (); + var properties = new SKTextAnalysis () { + StartTermChars = "", + EndTermChars = "", + TermChars = "\"-_@.'", + MinTermLength = 3, + StopWords = new NSSet ("all", "and", "its", "it's", "the") + }; + + var idx = SKIndex.CreateWithMutableData (m, "indexName", SKIndexType.Inverted, properties); + Assert.NotNull (idx); + + } + + [Test] + public void TestSummary () + { + var sum = SKSummary.Create ( + "Once upon a time, there was a dog that loved to take long walks in the park and enjoyed jumping all around (maybe more so on hot days).\n\n" + + "One day he ran into a solid rock in the park and was puzzled by it.\n\n" + + "If I cook this rock enough, it will be soft and tasty. I might even get lucky and find some salt."); + + Assert.NotNull (sum); + var rankOrder = new nint[10]; + var sentenceIndex = new nint[10]; + var paragraphIndex = new nint [10]; + + nint n; + n = sum.GetSentenceSummaryInfo (10, rankOrder, sentenceIndex, paragraphIndex); + Assert.AreEqual (4, n); + Assert.AreEqual (2, paragraphIndex[3]); // 4th sentence (index 3) is on the 3rd (index 2) paragraph + n = sum.GetSentenceSummaryInfo (10, null, sentenceIndex, paragraphIndex); + Assert.AreEqual (4, n); + n = sum.GetSentenceSummaryInfo (10, rankOrder, null, paragraphIndex); + Assert.AreEqual (4, n); + n = sum.GetSentenceSummaryInfo (10, rankOrder, sentenceIndex, null); + Assert.AreEqual (4, n); + n = sum.GetSentenceSummaryInfo (10, null, null, paragraphIndex); + Assert.AreEqual (4, n); + n = sum.GetSentenceSummaryInfo (10, null, sentenceIndex, null); + Assert.AreEqual (4, n); + n = sum.GetSentenceSummaryInfo (10, rankOrder, null, null); + Assert.AreEqual (4, n); + n = sum.GetSentenceSummaryInfo (10, null, null, null); + Assert.AreEqual (4, n); + + n = sum.GetParagraphSummaryInfo (10, rankOrder, paragraphIndex); + n = sum.GetParagraphSummaryInfo (10, null, paragraphIndex); + n = sum.GetParagraphSummaryInfo (10, rankOrder, null); + n = sum.GetParagraphSummaryInfo (10, null, null); + var sentence = sum.GetSentence (3); + Assert.AreEqual ("I might even get lucky and find some salt.", sentence); + var par = sum.GetParagraph (1); + Assert.AreEqual ("One day he ran into a solid rock in the park and was puzzled by it.\n", par); + var ssum = sum.GetSentenceSummary (1); + Assert.NotNull (ssum); + var psum = sum.GetParagraphSummary (1); + Assert.NotNull (psum); + } + } +} +#endif diff --git a/tests/apitest/src/SpriteKit/SKPaymentTests.cs b/tests/apitest/src/SpriteKit/SKPaymentTests.cs new file mode 100644 index 000000000000..5aa414a52592 --- /dev/null +++ b/tests/apitest/src/SpriteKit/SKPaymentTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +#if !XAMCORE_2_0 +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.StoreKit; +using nuint = System.UInt32; +#else +using AppKit; +using Foundation; +using StoreKit; +#endif + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SKPaymentTests + { + [Test] + public void SKPayment_PaymentWithProduct () + { + SKProduct product = new SKProduct(); + SKPayment payment = SKPayment.PaymentWithProduct (product); + Assert.IsNotNull (payment); + } + } +} + diff --git a/tests/apitest/src/SpriteKit/SKScene.cs b/tests/apitest/src/SpriteKit/SKScene.cs new file mode 100644 index 000000000000..1468bff902f9 --- /dev/null +++ b/tests/apitest/src/SpriteKit/SKScene.cs @@ -0,0 +1,52 @@ +#if XAMCORE_2_0 +using System; +using System.Threading.Tasks; +using NUnit.Framework; + +using AppKit; +using Foundation; +using CoreAnimation; +using CoreGraphics; +using SpriteKit; + +namespace Xamarin.Mac.Tests +{ + [TestFixture] + public class SKSceneTests + { + [SetUp] + public void SetUp () + { + Asserts.EnsureMavericks (); + } + + [Test] + public void SKScene_InitWithSize () + { + if (IntPtr.Size != 8) // SpriteKit is 64-bit only on mac + return; + + SKNode c = new SKNode (); + //SKScene c = new SKScene (new CGSize (50, 50)); + Assert.IsNotNull (c); + } + + [Test] + public void SKScene_InitWithSizeSuper () + { + if (IntPtr.Size != 8) // SpriteKit is 64-bit only on mac + return; + + MyScene c = new MyScene (new CGSize (50, 50)); + Assert.IsNotNull (c); + } + + class MyScene : SKScene + { + public MyScene (CGSize size) : base (size) + { + } + } + } +} +#endif \ No newline at end of file diff --git a/tests/bcl-test/.gitignore b/tests/bcl-test/.gitignore new file mode 100644 index 000000000000..6e4386e149a3 --- /dev/null +++ b/tests/bcl-test/.gitignore @@ -0,0 +1,3 @@ +*/*.csproj +*/*.sln +*.exe \ No newline at end of file diff --git a/tests/bcl-test/AppDelegate.cs b/tests/bcl-test/AppDelegate.cs new file mode 100644 index 000000000000..3e84e45aefad --- /dev/null +++ b/tests/bcl-test/AppDelegate.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; +using NUnit.Framework.Internal.Filters; + +#if !__WATCHOS__ + +namespace BCL.Tests +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + UIWindow window; + TouchRunner runner; + + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + // create a new window instance based on the screen size + window = new UIWindow (UIScreen.MainScreen.Bounds); + runner = new TouchRunner (window); + runner.Filter = new NotFilter (new CategoryExpression ("MobileNotWorking,NotOnMac,NotWorking,ValueAdd,CAS,InetAccess,NotWorkingInterpreter").Filter); + + // register every tests included in the main application/assembly + runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); + + window.RootViewController = new UINavigationController (runner.GetViewController ()); + + // make the window visible + window.MakeKeyAndVisible (); + + return true; + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/bcl-test/Info.plist b/tests/bcl-test/Info.plist new file mode 100644 index 000000000000..38994b08cb21 --- /dev/null +++ b/tests/bcl-test/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDisplayName + BclTest + CFBundleIdentifier + com.xamarin.bcl-test + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + + diff --git a/tests/bcl-test/Main.cs b/tests/bcl-test/Main.cs new file mode 100644 index 000000000000..81470ec2ca7f --- /dev/null +++ b/tests/bcl-test/Main.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +#endif + +namespace BCL.Tests +{ +#if !__WATCHOS__ + public class Application + { + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } + } +#endif + + public class TestRuntime + { + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + static extern IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport ("/usr/lib/system/libdyld.dylib")] + static extern int dyld_get_program_sdk_version (); + + public const string BuildVersion_iOS7_DP3 = "11D5134c"; + public const string BuildVersion_iOS8_Beta1 = "12A4265u"; + + public static string GetiOSBuildVersion () + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS build version on watchOS"); +#else + return NSString.FromHandle (IntPtr_objc_msgSend (UIDevice.CurrentDevice.Handle, Selector.GetHandle ("buildVersion"))); +#endif + } + + public static Version GetSDKVersion () + { + var v = dyld_get_program_sdk_version (); + var major = v >> 16; + var minor = (v >> 8) & 0xFF; + var build = v & 0xFF; + return new Version (major, minor, build); + } + + // This method returns true if: + // system version >= specified version + // AND + // sdk version >= specified version + public static bool CheckSystemAndSDKVersion (int major, int minor) + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS System/SDK version on watchOS"); +#else + if (!UIDevice.CurrentDevice.CheckSystemVersion (major, minor)) + return false; +#endif + + // Check if the SDK version we're built includes the version we're checking for + // We don't want to execute iOS7 tests on an iOS7 device when built with the iOS6 SDK. + return CheckSDKVersion (major, minor); + } + + public static bool CheckSystemVersion (int major, int minor) + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS System/SDK version on watchOS"); +#else + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#endif + } + + public static bool CheckSDKVersion (int major, int minor) + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS SDK version on watchOS"); +#else + if (Runtime.Arch == Arch.SIMULATOR || !CheckSystemVersion (6, 0)) { + // dyld_get_program_sdk_version was introduced with iOS 6.0, so don't do the SDK check on older deviecs. + return true; // dyld_get_program_sdk_version doesn't return what we're looking for on the mac. + } +#endif + + var sdk = GetSDKVersion (); + if (sdk.Major > major) + return true; + if (sdk.Major == major && sdk.Minor >= minor) + return true; + return false; + } + } +} diff --git a/tests/bcl-test/Make.frag b/tests/bcl-test/Make.frag new file mode 100644 index 000000000000..9282a04c0b7d --- /dev/null +++ b/tests/bcl-test/Make.frag @@ -0,0 +1,43 @@ + +ifneq ($(RELEASE),) +CONFIG=Release +else +CONFIG=Debug +endif + +all: build-dev + +build-dev: + $(MAKE) -C ../.. build-ios-devunified-$(LIB) + +clean-dev: + $(MAKE) -C ../.. clean-ios-devunified-$(LIB) + +install-dev: + $(MAKE) -C ../.. install-ios-devunified-$(LIB) + +exec-dev: + $(MAKE) -C ../.. exec-ios-devunified-$(LIB) + +debug-dev: + fruitstrap debug --bundle bin/iPhone/$(CONFIG)/$(shell echo $(LIB) | sed 's/-//g' | sed 's/\.//g').app --args "-app-arg:-autostart" + +build: build-dev +clean: clean-dev +install: install-dev +exec: exec-dev +run: debug-dev + +logdev: + $(MAKE) -C ../.. logdev + +build-%: + $(MAKE) -C ../.. $@-$(LIB) +run-%: + $(MAKE) -C ../.. $@-$(LIB) +exec-%: + $(MAKE) -C ../.. $@-$(LIB) +install-%: + $(MAKE) -C ../.. $@-$(LIB) +clean-%: + $(MAKE) -C ../.. $@-$(LIB) diff --git a/tests/bcl-test/Mono.Data.Sqlite/Info.plist b/tests/bcl-test/Mono.Data.Sqlite/Info.plist new file mode 100644 index 000000000000..9a97f56e3156 --- /dev/null +++ b/tests/bcl-test/Mono.Data.Sqlite/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.monodatasqlitetests + + diff --git a/tests/bcl-test/Mono.Data.Sqlite/Mono.Data.Sqlite.csproj.template b/tests/bcl-test/Mono.Data.Sqlite/Mono.Data.Sqlite.csproj.template new file mode 100644 index 000000000000..4ab1869aff7c --- /dev/null +++ b/tests/bcl-test/Mono.Data.Sqlite/Mono.Data.Sqlite.csproj.template @@ -0,0 +1,140 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {1ADF4F27-7610-4501-A62E-1157273AED7E} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + MonoDataSqliteTests + 168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + cjk + ARMv7 + + + none + True + bin\iPhone\Release + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + cjk + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + + + Resources\Resources.es-ES.resx + Resources.es-ES.resources + + + Resources\Resources.nn-NO.resx + Resources.nn-NO.resources + + + Resources\Resources.resx + Resources.resources + + + diff --git a/tests/bcl-test/Mono.Security/Info.plist b/tests/bcl-test/Mono.Security/Info.plist new file mode 100644 index 000000000000..7f61d7e108fa --- /dev/null +++ b/tests/bcl-test/Mono.Security/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.monosecuritytests + + diff --git a/tests/bcl-test/Mono.Security/Makefile b/tests/bcl-test/Mono.Security/Makefile new file mode 100644 index 000000000000..a8a75083e94c --- /dev/null +++ b/tests/bcl-test/Mono.Security/Makefile @@ -0,0 +1,4 @@ + +LIB=Mono.Security + +include ../Make.frag diff --git a/tests/bcl-test/Mono.Security/Mono.Security.csproj.template b/tests/bcl-test/Mono.Security/Mono.Security.csproj.template new file mode 100644 index 000000000000..3fc411d9c6ba --- /dev/null +++ b/tests/bcl-test/Mono.Security/Mono.Security.csproj.template @@ -0,0 +1,126 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {5023D584-1A32-4917-90C5-A641C800230C} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + MonoSecurityTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + Assert.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.ComponentModel.DataAnnotations/Info.plist b/tests/bcl-test/System.ComponentModel.DataAnnotations/Info.plist new file mode 100644 index 000000000000..745c339435c9 --- /dev/null +++ b/tests/bcl-test/System.ComponentModel.DataAnnotations/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemcomponentmodeldataannotationstests + + diff --git a/tests/bcl-test/System.ComponentModel.DataAnnotations/Makefile b/tests/bcl-test/System.ComponentModel.DataAnnotations/Makefile new file mode 100644 index 000000000000..01e08c068e45 --- /dev/null +++ b/tests/bcl-test/System.ComponentModel.DataAnnotations/Makefile @@ -0,0 +1,4 @@ + +LIB=System.ComponentModel.DataAnnotations + +include ../Make.frag diff --git a/tests/bcl-test/System.ComponentModel.DataAnnotations/System.ComponentModel.DataAnnotations.csproj.template b/tests/bcl-test/System.ComponentModel.DataAnnotations/System.ComponentModel.DataAnnotations.csproj.template new file mode 100644 index 000000000000..9e111572341f --- /dev/null +++ b/tests/bcl-test/System.ComponentModel.DataAnnotations/System.ComponentModel.DataAnnotations.csproj.template @@ -0,0 +1,124 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemComponentModelDataAnnotationsTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + ..\..\..\..\..\usr\lib\mono\2.1\System.ComponentModel.DataAnnotations.dll + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Core/Info.plist b/tests/bcl-test/System.Core/Info.plist new file mode 100644 index 000000000000..4936a373aa3c --- /dev/null +++ b/tests/bcl-test/System.Core/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemcoretests + + diff --git a/tests/bcl-test/System.Core/Makefile b/tests/bcl-test/System.Core/Makefile new file mode 100644 index 000000000000..132099123f30 --- /dev/null +++ b/tests/bcl-test/System.Core/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Core + +include ../Make.frag diff --git a/tests/bcl-test/System.Core/System.Core.csproj.template b/tests/bcl-test/System.Core/System.Core.csproj.template new file mode 100644 index 000000000000..062b42d8ada2 --- /dev/null +++ b/tests/bcl-test/System.Core/System.Core.csproj.template @@ -0,0 +1,122 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {FBC970AA-8234-4905-B559-BD3F32A63C04} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemCoreTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Data/Info.plist b/tests/bcl-test/System.Data/Info.plist new file mode 100644 index 000000000000..8232dc8bd8eb --- /dev/null +++ b/tests/bcl-test/System.Data/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemdatatests + + diff --git a/tests/bcl-test/System.Data/Makefile b/tests/bcl-test/System.Data/Makefile new file mode 100644 index 000000000000..caeea80d1e3f --- /dev/null +++ b/tests/bcl-test/System.Data/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Data + +include ../Make.frag diff --git a/tests/bcl-test/System.Data/System.Data.csproj.template b/tests/bcl-test/System.Data/System.Data.csproj.template new file mode 100644 index 000000000000..9884de12caa1 --- /dev/null +++ b/tests/bcl-test/System.Data/System.Data.csproj.template @@ -0,0 +1,269 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {BEF0140A-A6A6-4074-B55F-03856A6B5862} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemDataTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + west + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + west + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + west + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + west + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + west + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + west + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + Assert.cs + + + +#FILES# + + + + + Test\System.Data\binserialize\BS-tb1.bin + + + Test\System.Data\binserialize\BS-tb2.bin + + + Test\System.Data\binserialize\BS-tb3.bin + + + Test\System.Data\binserialize\BS-tb4.bin + + + Test\System.Data\binserialize\BS-tb5.bin + + + Test\System.Data\store.xsd + + + Test\System.Data\store2.xsd + + + Test\System.Data\store3.xsd + + + Test\System.Data\store4.xsd + + + Test\System.Data\schemas\b582732.xml + + + Test\System.Data\schemas\bug77248.xsd + + + Test\System.Data\schemas\Items.xsd + + + Test\System.Data\schemas\test001.xsd + + + Test\System.Data\schemas\test002.xsd + + + Test\System.Data\schemas\test003.xsd + + + Test\System.Data\schemas\test004.xsd + + + Test\System.Data\schemas\test005.xsd + + + Test\System.Data\schemas\test006.xsd + + + Test\System.Data\schemas\test007.xsd + + + Test\System.Data\schemas\test008.xsd + + + Test\System.Data\schemas\test009.xsd + + + Test\System.Data\schemas\test010.xsd + + + Test\System.Data\schemas\test011.xsd + + + Test\System.Data\schemas\test012.xsd + + + Test\System.Data\schemas\test013.xsd + + + Test\System.Data\schemas\test014.xsd + + + Test\System.Data\schemas\test015.xsd + + + Test\System.Data\schemas\test016.xsd + + + Test\System.Data\schemas\test017.xsd + + + Test\System.Data\schemas\test101.xsd + + + Test\System.Data\schemas\test102.xsd + + + Test\System.Data\schemas\test103.xsd + + + Test\System.Data\region.xml + + + Test\System.Data\own_schema.xsd + + + Test\System.Data\own_schema1.xsd + + + Test\System.Data\own_schema2.xsd + + + Test\System.Data\TypedDataSet.xml + + + Test\System.Xml\region.xml + + + Test\System.Xml\region.xsd + + + Test\System.Xml\store.xsd + + + Test\Mono.Data.SqlExpressions\dateComparisonTest.xml + + + Test\System.Data\TestMerge1.xml + + + Test\System.Xml\2books.xml + + + Test\System.Data\TestReadXmlSchema1.xml + + + Test\System.Data\TestReadXml1.xml + + + diff --git a/tests/bcl-test/System.Json/Info.plist b/tests/bcl-test/System.Json/Info.plist new file mode 100644 index 000000000000..608d9fe7e8bf --- /dev/null +++ b/tests/bcl-test/System.Json/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemjsontests + + diff --git a/tests/bcl-test/System.Json/Makefile b/tests/bcl-test/System.Json/Makefile new file mode 100644 index 000000000000..875f7ad410a6 --- /dev/null +++ b/tests/bcl-test/System.Json/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Json + +include ../Make.frag diff --git a/tests/bcl-test/System.Json/System.Json.csproj.template b/tests/bcl-test/System.Json/System.Json.csproj.template new file mode 100644 index 000000000000..91112c091c32 --- /dev/null +++ b/tests/bcl-test/System.Json/System.Json.csproj.template @@ -0,0 +1,123 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemJsonTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Net.Http/Info.plist b/tests/bcl-test/System.Net.Http/Info.plist new file mode 100644 index 000000000000..eb8c2ab014d2 --- /dev/null +++ b/tests/bcl-test/System.Net.Http/Info.plist @@ -0,0 +1,35 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemnethttptests + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + + diff --git a/tests/bcl-test/System.Net.Http/Makefile b/tests/bcl-test/System.Net.Http/Makefile new file mode 100644 index 000000000000..77607fcbba16 --- /dev/null +++ b/tests/bcl-test/System.Net.Http/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Net.Http + +include ../Make.frag diff --git a/tests/bcl-test/System.Net.Http/System.Net.Http.csproj.template b/tests/bcl-test/System.Net.Http/System.Net.Http.csproj.template new file mode 100644 index 000000000000..6250c37953fc --- /dev/null +++ b/tests/bcl-test/System.Net.Http/System.Net.Http.csproj.template @@ -0,0 +1,125 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemNetHttpTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Net.Http/System.Net.Http/CFNetworkHandlerTest.cs b/tests/bcl-test/System.Net.Http/System.Net.Http/CFNetworkHandlerTest.cs new file mode 100644 index 000000000000..ba90d8f02953 --- /dev/null +++ b/tests/bcl-test/System.Net.Http/System.Net.Http/CFNetworkHandlerTest.cs @@ -0,0 +1,754 @@ +// +// CFNetworkHandlerTest.cs +// +// Authors: +// Marek Safar +// +// Copyright (C) 2013 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if !__WATCHOS__ + +using System; +using System.Collections; +using System.Collections.Generic; +using NUnit.Framework; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; +using System.Net; +using System.Linq; +using System.IO; + +namespace MonoTests.System.Net.Http +{ + [TestFixture] + public class CFNetworkHandlerTest + { + class HttpMessageHandlerMock : CFNetworkHandler + { + public Func> OnSend; + public Func> OnSendFull; + + public HttpMessageHandlerMock () + { + } + + protected override Task SendAsync (HttpRequestMessage request, CancellationToken cancellationToken) + { + if (OnSend != null) + return OnSend (request); + + if (OnSendFull != null) + return OnSendFull (request, cancellationToken); + + Assert.Fail ("Send"); + return null; + } + } + + const int WaitTimeout = 2500; + + string port, TestHost, LocalServer; + + HttpClient client; + + [SetUp] + public void SetupFixture () + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) { + port = "810"; + } else { + port = "8810"; + } + + TestHost = "localhost:" + port; + LocalServer = string.Format ("http://{0}/", TestHost); + client = new HttpClient (new CFNetworkHandler ()); + } + + [Test] + public void Ctor_Default () + { + Assert.IsNull (client.BaseAddress, "#1"); + Assert.IsNotNull (client.DefaultRequestHeaders, "#2"); // TODO: full check + Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#3"); + Assert.AreEqual (TimeSpan.FromSeconds (100), client.Timeout, "#4"); + } + + [Test] + public void CancelPendingRequests () + { + var mh = new HttpMessageHandlerMock (); + + var client = new HttpClient (mh); + var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + var mre = new ManualResetEvent (false); + + mh.OnSendFull = (l, c) => { + mre.Set (); + Assert.IsTrue (c.WaitHandle.WaitOne (1000), "#20"); + Assert.IsTrue (c.IsCancellationRequested, "#21"); + mre.Set (); + return Task.FromResult (new HttpResponseMessage ()); + }; + + var t = Task.Factory.StartNew (() => { + client.SendAsync (request).Wait (WaitTimeout); + }); + + Assert.IsTrue (mre.WaitOne (500), "#1"); + mre.Reset (); + client.CancelPendingRequests (); + Assert.IsTrue (t.Wait (500), "#2"); + + request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + mh.OnSendFull = (l, c) => { + Assert.IsFalse (c.IsCancellationRequested, "#30"); + return Task.FromResult (new HttpResponseMessage ()); + }; + + client.SendAsync (request).Wait (WaitTimeout); + } + + [Test] + public void CancelPendingRequests_BeforeSend () + { + var ct = new CancellationTokenSource (); + ct.Cancel (); + var rr = CancellationTokenSource.CreateLinkedTokenSource (new CancellationToken (), ct.Token); + + + var mh = new HttpMessageHandlerMock (); + + var client = new HttpClient (mh); + var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + client.CancelPendingRequests (); + + mh.OnSendFull = (l, c) => { + Assert.IsFalse (c.IsCancellationRequested, "#30"); + return Task.FromResult (new HttpResponseMessage ()); + }; + + client.SendAsync (request).Wait (WaitTimeout); + + request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + client.SendAsync (request).Wait (WaitTimeout); + } + + [Test] + public void Properties () + { + client.BaseAddress = null; + client.MaxResponseContentBufferSize = int.MaxValue; + client.Timeout = Timeout.InfiniteTimeSpan; + + Assert.IsNull (client.BaseAddress, "#1"); + Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#2"); + Assert.AreEqual (Timeout.InfiniteTimeSpan, client.Timeout, "#3"); + } + + [Test] + public void Properties_Invalid () + { + try { + client.MaxResponseContentBufferSize = 0; + Assert.Fail ("#1"); + } catch (ArgumentOutOfRangeException) { + } + + try { + client.Timeout = TimeSpan.MinValue; + Assert.Fail ("#2"); + } catch (ArgumentOutOfRangeException) { + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send () + { + var mh = new HttpMessageHandlerMock (); + + var client = new HttpClient (mh); + client.BaseAddress = new Uri ("http://xamarin.com"); + var request = new HttpRequestMessage (); + var response = new HttpResponseMessage (); + + mh.OnSend = l => { + Assert.AreEqual (l, request, "#2"); + Assert.AreEqual (client.BaseAddress, l.RequestUri, "#2"); + return Task.FromResult (response); + }; + + Assert.AreEqual (response, client.SendAsync (request).Result, "#1"); + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_DefaultRequestHeaders () + { + var mh = new HttpMessageHandlerMock (); + + var client = new HttpClient (mh); + client.DefaultRequestHeaders.Referrer = new Uri ("http://google.com"); + + var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + var response = new HttpResponseMessage (); + + mh.OnSend = l => { + Assert.AreEqual (client.DefaultRequestHeaders.Referrer, l.Headers.Referrer, "#2"); + Assert.IsNotNull (l.Headers.Referrer, "#3"); + return Task.FromResult (response); + }; + + Assert.AreEqual (response, client.SendAsync (request).Result, "#1"); + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_Default () + { + bool? failed = null; + var listener = CreateListener (l => { + try { + var request = l.Request; + + Assert.IsNull (request.AcceptTypes, "#1"); + Assert.AreEqual (0, request.ContentLength64, "#2"); + Assert.IsNull (request.ContentType, "#3"); + Assert.AreEqual (0, request.Cookies.Count, "#4"); + Assert.IsFalse (request.HasEntityBody, "#5"); + Assert.AreEqual (TestHost, request.Headers["Host"], "#6b"); + Assert.AreEqual ("GET", request.HttpMethod, "#7"); + Assert.IsFalse (request.IsAuthenticated, "#8"); + Assert.IsTrue (request.IsLocal, "#9"); + Assert.IsFalse (request.IsSecureConnection, "#10"); + Assert.IsFalse (request.IsWebSocketRequest, "#11"); + Assert.IsTrue (request.KeepAlive, "#12"); + Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13"); + Assert.IsNull (request.ServiceName, "#14"); + Assert.IsNull (request.UrlReferrer, "#15"); + Assert.IsNull (request.UserAgent, "#16"); + Assert.IsNull (request.UserLanguages, "#17"); + failed = false; + } catch { + failed = true; + } + }); + + try { + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100"); + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101"); + Assert.AreEqual (false, failed, "#102"); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_Version_1_0 () + { + bool? failed = null; + + var listener = CreateListener (l => { + try { + var request = l.Request; + + Assert.IsNull (request.AcceptTypes, "#1"); + Assert.AreEqual (0, request.ContentLength64, "#2"); + Assert.IsNull (request.ContentType, "#3"); + Assert.AreEqual (0, request.Cookies.Count, "#4"); + Assert.IsFalse (request.HasEntityBody, "#5"); + Assert.AreEqual (1, request.Headers.Count, "#6"); + Assert.AreEqual (TestHost, request.Headers["Host"], "#6a"); + Assert.AreEqual ("GET", request.HttpMethod, "#7"); + Assert.IsFalse (request.IsAuthenticated, "#8"); + Assert.IsTrue (request.IsLocal, "#9"); + Assert.IsFalse (request.IsSecureConnection, "#10"); + Assert.IsFalse (request.IsWebSocketRequest, "#11"); + Assert.IsFalse (request.KeepAlive, "#12"); + Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13"); + Assert.IsNull (request.ServiceName, "#14"); + Assert.IsNull (request.UrlReferrer, "#15"); + Assert.IsNull (request.UserAgent, "#16"); + Assert.IsNull (request.UserLanguages, "#17"); + failed = false; + } catch { + failed = true; + } + }); + + try { + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + request.Version = HttpVersion.Version10; + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100"); + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101"); + Assert.AreEqual (false, failed, "#102"); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_ClientHandlerSettings () + { + bool? failed = null; + + var listener = CreateListener (l => { + var request = l.Request; + + try { + Assert.IsNull (request.AcceptTypes, "#1"); + Assert.AreEqual (0, request.ContentLength64, "#2"); + Assert.IsNull (request.ContentType, "#3"); + Assert.AreEqual (1, request.Cookies.Count, "#4"); + Assert.AreEqual (new Cookie ("mycookie", "vv"), request.Cookies[0], "#4a"); + Assert.IsFalse (request.HasEntityBody, "#5"); + Assert.AreEqual (4, request.Headers.Count, "#6"); + Assert.AreEqual (TestHost, request.Headers["Host"], "#6a"); + Assert.AreEqual ("gzip", request.Headers["Accept-Encoding"], "#6b"); + Assert.AreEqual ("mycookie=vv", request.Headers["Cookie"], "#6c"); + Assert.AreEqual ("GET", request.HttpMethod, "#7"); + Assert.IsFalse (request.IsAuthenticated, "#8"); + Assert.IsTrue (request.IsLocal, "#9"); + Assert.IsFalse (request.IsSecureConnection, "#10"); + Assert.IsFalse (request.IsWebSocketRequest, "#11"); + Assert.IsTrue (request.KeepAlive, "#12"); + Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13"); + Assert.IsNull (request.ServiceName, "#14"); + Assert.IsNull (request.UrlReferrer, "#15"); + Assert.IsNull (request.UserAgent, "#16"); + Assert.IsNull (request.UserLanguages, "#17"); + failed = false; + } catch { + failed = true; + } + }); + + try { + var chandler = new CFNetworkHandler (); + chandler.AllowAutoRedirect = true; +// chandler.AutomaticDecompression = DecompressionMethods.GZip; +// chandler.MaxAutomaticRedirections = 33; +// chandler.MaxRequestContentBufferSize = 5555; +// chandler.PreAuthenticate = true; +// chandler.CookieContainer.Add (new Uri (LocalServer), new Cookie ( "mycookie", "vv")); +// chandler.UseCookies = true; +// chandler.UseDefaultCredentials = true; +// chandler.Proxy = new WebProxy ("ee"); +// chandler.UseProxy = true; + + var client = new HttpClient (chandler); + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + request.Version = HttpVersion.Version10; + request.Headers.Add ("Keep-Alive", "false"); + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100"); + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101"); + Assert.AreEqual (false, failed, "#102"); + } finally { + listener.Abort (); + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_CustomHeaders () + { + bool? failed = null; + + var listener = CreateListener (l => { + var request = l.Request; + try { + Assert.AreEqual ("vv", request.Headers["aa"], "#1"); + + var response = l.Response; + response.Headers.Add ("rsp", "rrr"); + response.Headers.Add ("upgrade", "vvvvaa"); + response.Headers.Add ("Date", "aa"); + response.Headers.Add ("cache-control", "audio"); + + response.StatusDescription = "test description"; + response.ProtocolVersion = HttpVersion.Version10; + response.SendChunked = true; + response.RedirectLocation = "w3.org"; + + failed = false; + } catch { + failed = true; + } + }); + + try { + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0"); + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100"); + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101"); + + IEnumerable values; + Assert.IsTrue (response.Headers.TryGetValues ("rsp", out values), "#102"); + Assert.AreEqual ("rrr", values.First (), "#102a"); + + Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#103"); + Assert.AreEqual ("chunked", values.First (), "#103a"); + Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#103b"); + + Assert.IsTrue (response.Headers.TryGetValues ("Date", out values), "#104"); + Assert.AreEqual (1, values.Count (), "#104b"); + // .NET overwrites Date, Mono does not + // Assert.IsNotNull (response.Headers.Date, "#104c"); + + Assert.AreEqual (new ProductHeaderValue ("vvvvaa"), response.Headers.Upgrade.First (), "#105"); + + Assert.AreEqual ("audio", response.Headers.CacheControl.Extensions.First ().Name, "#106"); + + Assert.AreEqual ("w3.org", response.Headers.Location.OriginalString, "#107"); + + Assert.AreEqual ("test description", response.ReasonPhrase, "#110"); + Assert.AreEqual (HttpVersion.Version11, response.Version, "#111"); + + Assert.AreEqual (false, failed, "#112"); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_Content () + { + var listener = CreateListener (l => { + var request = l.Request; + l.Response.OutputStream.WriteByte (55); + l.Response.OutputStream.WriteByte (75); + }); + + try { + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0"); + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual ("7K", response.Content.ReadAsStringAsync ().Result, "#100"); + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101"); + + IEnumerable values; + Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#102"); + Assert.AreEqual ("chunked", values.First (), "#102a"); + Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#102b"); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_Content_MaxResponseContentBufferSize () + { + var listener = CreateListener (l => { + var request = l.Request; + var b = new byte[4000]; + l.Response.OutputStream.Write (b, 0, b.Length); + }); + + try { + client.MaxResponseContentBufferSize = 1000; + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual (4000, response.Content.ReadAsStringAsync ().Result.Length, "#100"); + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101"); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_Content_MaxResponseContentBufferSize_Error () + { + var listener = CreateListener (l => { + var request = l.Request; + var b = new byte[4000]; + l.Response.OutputStream.Write (b, 0, b.Length); + }); + + try { + client.MaxResponseContentBufferSize = 1000; + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + + try { + client.SendAsync (request, HttpCompletionOption.ResponseContentRead).Wait (WaitTimeout); + Assert.Fail ("#2"); + } catch (AggregateException e) { + Assert.IsTrue (e.InnerException is HttpRequestException, "#3"); + } + + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Complete_Error () + { + var listener = CreateListener (l => { + var response = l.Response; + response.StatusCode = 500; + }); + + try { + var request = new HttpRequestMessage (HttpMethod.Get, LocalServer); + var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result; + + Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100"); + Assert.AreEqual (HttpStatusCode.InternalServerError, response.StatusCode, "#101"); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Content_Get () + { + var listener = CreateListener (l => { + var request = l.Request; + l.Response.OutputStream.WriteByte (72); + }); + + try { + var r = new HttpRequestMessage (HttpMethod.Get, LocalServer); + var response = client.SendAsync (r).Result; + + Assert.AreEqual ("H", response.Content.ReadAsStringAsync ().Result); + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Content_Put () + { + bool passed = false; + var listener = CreateListener (l => { + var request = l.Request; + passed = 7 == request.ContentLength64; + passed &= request.ContentType == "text/plain; charset=utf-8"; + passed &= request.InputStream.ReadByte () == 'm'; + }); + + try { + var r = new HttpRequestMessage (HttpMethod.Put, LocalServer); + r.Content = new StringContent ("my text"); + var response = client.SendAsync (r).Result; + + Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1"); + Assert.IsTrue (passed, "#2"); + } finally { + listener.Abort (); + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void Send_Timeout () + { + var mh = new HttpMessageHandlerMock (); + + client.Timeout = TimeSpan.FromMilliseconds (100); + var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + var response = new HttpResponseMessage (); + + mh.OnSendFull = (l, c) => { + Assert.IsTrue (c.WaitHandle.WaitOne (500), "#2"); + return Task.FromResult (response); + }; + + Assert.AreEqual (response, client.SendAsync (request).Result, "#1"); + } + + [Test] + public void Send_Invalid () + { + try { + client.SendAsync (null).Wait (WaitTimeout); + Assert.Fail ("#1"); + } catch (ArgumentNullException) { + } + + try { + var request = new HttpRequestMessage (); + client.SendAsync (request).Wait (WaitTimeout); + Assert.Fail ("#2"); + } catch (InvalidOperationException) { + } + } + + [Test] + public void Send_InvalidHandler () + { + var mh = new HttpMessageHandlerMock (); + + var client = new HttpClient (mh); + client.BaseAddress = new Uri ("http://xamarin.com"); + var request = new HttpRequestMessage (); + + mh.OnSend = l => { + Assert.AreEqual (l, request, "#1"); + return null; + }; + + try { + // Broken by design + client.SendAsync (request).Wait (WaitTimeout); + Assert.Fail ("#2"); + } catch (Exception) { + } + } + + [Test] + public void Send_SameMessage () + { + var mh = new HttpMessageHandlerMock (); + + var client = new HttpClient (mh); + var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com"); + + mh.OnSend = l => Task.FromResult (new HttpResponseMessage ()); + + client.SendAsync (request).Wait (WaitTimeout); + try { + client.SendAsync (request).Wait (WaitTimeout); + Assert.Fail ("#1"); + } catch (InvalidOperationException) { + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void GetString_RelativeUri () + { + client.BaseAddress = new Uri ("http://en.wikipedia.org/wiki/"); + var uri = new Uri ("Computer", UriKind.Relative); + + Assert.That (client.GetStringAsync (uri).Result != null); + Assert.That (client.GetStringAsync ("Computer").Result != null); + } + + [Test] + [Ignore ("Blocks main loop")] + public void GetString_Many () + { + var t1 = client.GetStringAsync ("http://www.google.com"); + var t2 = client.GetStringAsync ("http://www.google.com"); + Assert.IsTrue (Task.WaitAll (new [] { t1, t2 }, WaitTimeout)); + } + + [Test] + [Ignore ("Blocks main loop")] + public void GetByteArray_ServerError () + { + var listener = CreateListener (l => { + var response = l.Response; + response.StatusCode = 500; + l.Response.OutputStream.WriteByte (72); + }); + + try { + try { + client.GetByteArrayAsync (LocalServer).Wait (WaitTimeout); + Assert.Fail ("#1"); + } catch (AggregateException e) { + Assert.IsTrue (e.InnerException is HttpRequestException , "#2"); + } + } finally { + listener.Close (); + } + } + + [Test] + [Ignore ("Blocks main loop")] + public void DisallowAutoRedirect () + { + var listener = CreateListener (l => { + var request = l.Request; + var response = l.Response; + + response.StatusCode = (int)HttpStatusCode.Moved; + response.RedirectLocation = "http://xamarin.com/"; + }); + + try { + var chandler = new CFNetworkHandler (); + chandler.AllowAutoRedirect = false; + var client = new HttpClient (chandler); + + try { + client.GetStringAsync (LocalServer).Wait (WaitTimeout); + Assert.Fail ("#1"); + } catch (AggregateException e) { + Assert.IsTrue (e.InnerException is HttpRequestException, "#2"); + } + } finally { + listener.Abort (); + listener.Close (); + } + } + + HttpListener CreateListener (Action contextAssert) + { + var l = new HttpListener (); + l.Prefixes.Add (string.Format ("http://+:{0}/", port)); + l.Start (); + l.BeginGetContext (ar => { + var ctx = l.EndGetContext (ar); + + try { + if (contextAssert != null) + contextAssert (ctx); + } finally { + ctx.Response.Close (); + } + }, null); + + return l; + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/bcl-test/System.Numerics/Info.plist b/tests/bcl-test/System.Numerics/Info.plist new file mode 100644 index 000000000000..b4ca00a106ef --- /dev/null +++ b/tests/bcl-test/System.Numerics/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemnumericstests + + diff --git a/tests/bcl-test/System.Numerics/Makefile b/tests/bcl-test/System.Numerics/Makefile new file mode 100644 index 000000000000..f774e60ecd44 --- /dev/null +++ b/tests/bcl-test/System.Numerics/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Numerics + +include ../Make.frag diff --git a/tests/bcl-test/System.Numerics/System.Numerics.csproj.template b/tests/bcl-test/System.Numerics/System.Numerics.csproj.template new file mode 100644 index 000000000000..a99e8ce87ced --- /dev/null +++ b/tests/bcl-test/System.Numerics/System.Numerics.csproj.template @@ -0,0 +1,123 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemNumericsTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Runtime.Serialization/Info.plist b/tests/bcl-test/System.Runtime.Serialization/Info.plist new file mode 100644 index 000000000000..a546401e4b85 --- /dev/null +++ b/tests/bcl-test/System.Runtime.Serialization/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemruntimeserializationtests + + diff --git a/tests/bcl-test/System.Runtime.Serialization/Makefile b/tests/bcl-test/System.Runtime.Serialization/Makefile new file mode 100644 index 000000000000..54c940f12950 --- /dev/null +++ b/tests/bcl-test/System.Runtime.Serialization/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Runtime.Serialization + +include ../Make.frag diff --git a/tests/bcl-test/System.Runtime.Serialization/System.Runtime.Serialization.csproj.template b/tests/bcl-test/System.Runtime.Serialization/System.Runtime.Serialization.csproj.template new file mode 100644 index 000000000000..12b8b8cc9f17 --- /dev/null +++ b/tests/bcl-test/System.Runtime.Serialization/System.Runtime.Serialization.csproj.template @@ -0,0 +1,125 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {B86D100D-895B-4510-A5BB-E08F11E82C3C} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemRuntimeSerializationTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.ServiceModel.Web/Info.plist b/tests/bcl-test/System.ServiceModel.Web/Info.plist new file mode 100644 index 000000000000..c3488d0db2a8 --- /dev/null +++ b/tests/bcl-test/System.ServiceModel.Web/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemservicemodelwebtests + + diff --git a/tests/bcl-test/System.ServiceModel.Web/Makefile b/tests/bcl-test/System.ServiceModel.Web/Makefile new file mode 100644 index 000000000000..35777353b82e --- /dev/null +++ b/tests/bcl-test/System.ServiceModel.Web/Makefile @@ -0,0 +1,4 @@ + +LIB=System.ServiceModel.Web + +include ../Make.frag diff --git a/tests/bcl-test/System.ServiceModel.Web/System.ServiceModel.Web.csproj.template b/tests/bcl-test/System.ServiceModel.Web/System.ServiceModel.Web.csproj.template new file mode 100644 index 000000000000..1cee0a828d9d --- /dev/null +++ b/tests/bcl-test/System.ServiceModel.Web/System.ServiceModel.Web.csproj.template @@ -0,0 +1,125 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemServiceModelWebTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Transactions/Info.plist b/tests/bcl-test/System.Transactions/Info.plist new file mode 100644 index 000000000000..3677792571b4 --- /dev/null +++ b/tests/bcl-test/System.Transactions/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemtransactionstests + + diff --git a/tests/bcl-test/System.Transactions/Makefile b/tests/bcl-test/System.Transactions/Makefile new file mode 100644 index 000000000000..01e92ceef536 --- /dev/null +++ b/tests/bcl-test/System.Transactions/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Transactions + +include ../Make.frag diff --git a/tests/bcl-test/System.Transactions/System.Transactions.csproj.template b/tests/bcl-test/System.Transactions/System.Transactions.csproj.template new file mode 100644 index 000000000000..f54275325179 --- /dev/null +++ b/tests/bcl-test/System.Transactions/System.Transactions.csproj.template @@ -0,0 +1,121 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {A12ED440-8270-4701-A35D-0C3C9E0AA735} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemTransactionsTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Web.Services/Info.plist b/tests/bcl-test/System.Web.Services/Info.plist new file mode 100644 index 000000000000..6743bb230e3b --- /dev/null +++ b/tests/bcl-test/System.Web.Services/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemwebservicestests + + diff --git a/tests/bcl-test/System.Web.Services/Makefile b/tests/bcl-test/System.Web.Services/Makefile new file mode 100644 index 000000000000..8a09e30f4ef0 --- /dev/null +++ b/tests/bcl-test/System.Web.Services/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Web.Services + +include ../Make.frag diff --git a/tests/bcl-test/System.Web.Services/System.Web.Services.csproj.template b/tests/bcl-test/System.Web.Services/System.Web.Services.csproj.template new file mode 100644 index 000000000000..edf79eb4b3b1 --- /dev/null +++ b/tests/bcl-test/System.Web.Services/System.Web.Services.csproj.template @@ -0,0 +1,130 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {DA061019-04C3-4221-AF04-63F2BFB5DA42} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemWebServicesTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + + + Test\System.Web.Services.Description\test2.wsdl + + + Test\System.Web.Services.Description\test.wsdl + + + diff --git a/tests/bcl-test/System.Xml.Linq/Info.plist b/tests/bcl-test/System.Xml.Linq/Info.plist new file mode 100644 index 000000000000..cd80d0cc6e26 --- /dev/null +++ b/tests/bcl-test/System.Xml.Linq/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemxmllinqtests + + diff --git a/tests/bcl-test/System.Xml.Linq/Makefile b/tests/bcl-test/System.Xml.Linq/Makefile new file mode 100644 index 000000000000..db238304c3ba --- /dev/null +++ b/tests/bcl-test/System.Xml.Linq/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Xml.Linq + +include ../Make.frag diff --git a/tests/bcl-test/System.Xml.Linq/System.Xml.Linq.csproj.template b/tests/bcl-test/System.Xml.Linq/System.Xml.Linq.csproj.template new file mode 100644 index 000000000000..be4494e9877b --- /dev/null +++ b/tests/bcl-test/System.Xml.Linq/System.Xml.Linq.csproj.template @@ -0,0 +1,119 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {DB354193-B05D-471B-BEB8-F6C74DA4C93A} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemXmlLinqTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/System.Xml/Info.plist b/tests/bcl-test/System.Xml/Info.plist new file mode 100644 index 000000000000..6b9a0e1c4f02 --- /dev/null +++ b/tests/bcl-test/System.Xml/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemxmltests + + diff --git a/tests/bcl-test/System.Xml/Makefile b/tests/bcl-test/System.Xml/Makefile new file mode 100644 index 000000000000..c4f01b9b9234 --- /dev/null +++ b/tests/bcl-test/System.Xml/Makefile @@ -0,0 +1,4 @@ + +LIB=System.Xml + +include ../Make.frag diff --git a/tests/bcl-test/System.Xml/System.Xml.csproj.template b/tests/bcl-test/System.Xml/System.Xml.csproj.template new file mode 100644 index 000000000000..6d43039a08a2 --- /dev/null +++ b/tests/bcl-test/System.Xml/System.Xml.csproj.template @@ -0,0 +1,389 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {93268FFB-571C-4402-8899-027A7778D2C0} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemXmlTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + + + Test\XmlFiles\xsd\1.xsd + + + Test\XmlFiles\xsd\2.xsd + + + Test\XmlFiles\xsd\3.xsd + + + Test\XmlFiles\xsd\336625.xsd + + + Test\XmlFiles\xsd\358408.xsd + + + Test\XmlFiles\xsd\361818-2.xsd + + + Test\XmlFiles\xsd\361818-3.xsd + + + Test\XmlFiles\xsd\361818.xsd + + + Test\XmlFiles\xsd\376395.xml + + + Test\XmlFiles\xsd\376395.xsd + + + Test\XmlFiles\xsd\4.xsd + + + Test\XmlFiles\xsd\422581.xml + + + Test\XmlFiles\xsd\422581.xsd + + + Test\XmlFiles\xsd\5.xsd + + + Test\XmlFiles\xsd\584664a.xml + + + Test\XmlFiles\xsd\584664a.xsd + + + Test\XmlFiles\xsd\584664b.xml + + + Test\XmlFiles\xsd\584664b.xsd + + + Test\XmlFiles\xsd\6.xsd + + + Test\XmlFiles\xsd\670945-1.xsd + + + Test\XmlFiles\xsd\670945-2.xsd + + + Test\XmlFiles\xsd\77687.xsd + + + Test\XmlFiles\xsd\77687inc.xsd + + + Test\XmlFiles\xsd\78985.xml + + + Test\XmlFiles\xsd\78985.xsd + + + Test\XmlFiles\xsd\79650.xsd + + + Test\XmlFiles\xsd\81360.xsd + + + Test\XmlFiles\xsd\81360inc1.xsd + + + Test\XmlFiles\xsd\81360inc2.xsd + + + Test\XmlFiles\xsd\82010.xml + + + Test\XmlFiles\xsd\82010.xsd + + + Test\XmlFiles\xsd\82078.xsd + + + Test\XmlFiles\xsd\datatypesTest.xsd + + + Test\XmlFiles\xsd\extension-attr-redefine-1.xsd + + + Test\XmlFiles\xsd\extension-attr-redefine-2.xsd + + + Test\XmlFiles\xsd\extension-attr-redefine-3.xsd + + + Test\XmlFiles\xsd\import-subst-dbr-base.xsd + + + Test\XmlFiles\xsd\import-subst-dbr-ext.xsd + + + Test\XmlFiles\xsd\importNamespaceTest.xsd + + + Test\XmlFiles\xsd\importNamespaceTest2.xsd + + + Test\XmlFiles\xsd\importedNamespace.xsd + + + Test\XmlFiles\xsd\importedNamespace2.xsd + + + Test\XmlFiles\xsd\inter-inc-1.xsd + + + Test\XmlFiles\xsd\inter-inc-2.xsd + + + Test\XmlFiles\xsd\multi-schemaLocation.xml + + + Test\XmlFiles\xsd\resolveUriSchema.xsd + + + Test\XmlFiles\xsd\x-net-config-schema.xsd + + + Test\XmlFiles\xsd\x-net-config-storage-factory-provider-schema.xsd + + + Test\XmlFiles\xsd\xml.xsd + + + Test\XmlFiles\xsd\xsdimporttest.xml + + + Test\XmlFiles\xsl\316238-1.xsl + + + Test\XmlFiles\xsl\316238-2.xsl + + + Test\XmlFiles\xsl\325482.xml + + + Test\XmlFiles\xsl\325482.xsl + + + Test\XmlFiles\xsl\391424.xml + + + Test\XmlFiles\xsl\391424.xsl + + + Test\XmlFiles\xsl\82493.xml + + + Test\XmlFiles\xsl\82493.xsl + + + Test\XmlFiles\xsl\91834.xml + + + Test\XmlFiles\xsl\91834.xsl + + + Test\XmlFiles\xsl\91834a.xml + + + Test\XmlFiles\xsl\current-in-select.ref + + + Test\XmlFiles\xsl\current-in-select.xml + + + Test\XmlFiles\xsl\current-in-select.xsl + + + Test\XmlFiles\xsl\empty.xsl + + + Test\XmlFiles\xsl\stripspace.xml + + + Test\XmlFiles\xsl\stripspace.xsl + + + Test\XmlFiles\XsdValidation\1.xsd + + + Test\XmlFiles\XsdValidation\2.xsd + + + Test\XmlFiles\XsdValidation\3.xsd + + + Test\XmlFiles\XsdValidation\4.xsd + + + Test\XmlFiles\496192.xml + + + Test\XmlFiles\496192.xsd + + + Test\XmlFiles\595947.xsd + + + Test\XmlFiles\676993.xml + + + Test\XmlFiles\676993.xsd + + + Test\XmlFiles\76102.xml + + + Test\XmlFiles\79683.dtd + + + Test\XmlFiles\literal-data.xml + + + Test\XmlFiles\nested-dtd-test.dtd + + + Test\XmlFiles\nested-dtd-test.xml + + + Test\XmlFiles\nested-included.dtd + + + Test\XmlFiles\simple.xml + + + Test\System.Xml\nist_dom\files\noDTDXMLfile.xml + + + Test\System.Xml\nist_dom\files\otherDoc.xml + + + Test\System.Xml\nist_dom\files\staff.dtd + + + Test\System.Xml\nist_dom\files\staff.html + + + Test\System.Xml\nist_dom\files\staff.xml + + + diff --git a/tests/bcl-test/System/Info.plist b/tests/bcl-test/System/Info.plist new file mode 100644 index 000000000000..9d1bc3322d07 --- /dev/null +++ b/tests/bcl-test/System/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.systemtests + + diff --git a/tests/bcl-test/System/Makefile b/tests/bcl-test/System/Makefile new file mode 100644 index 000000000000..37858a94f291 --- /dev/null +++ b/tests/bcl-test/System/Makefile @@ -0,0 +1,4 @@ + +LIB=System + +include ../Make.frag diff --git a/tests/bcl-test/System/System.csproj.template b/tests/bcl-test/System/System.csproj.template new file mode 100644 index 000000000000..4e8038e4d993 --- /dev/null +++ b/tests/bcl-test/System/System.csproj.template @@ -0,0 +1,124 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {EEE20F63-4282-450A-8584-93F640929D13} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + SystemTests + 67,168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + ARMv7 + + + none + True + bin\iPhone\Release + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + Assert.cs + + + +#FILES# + + + diff --git a/tests/bcl-test/mscorlib/Info.plist b/tests/bcl-test/mscorlib/Info.plist new file mode 100644 index 000000000000..3c8865dcff0b --- /dev/null +++ b/tests/bcl-test/mscorlib/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + UIApplicationExitsOnSuspend + + CFBundleIdentifier + com.xamarin.mscorlibtests + + diff --git a/tests/bcl-test/mscorlib/Makefile b/tests/bcl-test/mscorlib/Makefile new file mode 100644 index 000000000000..6179234fa745 --- /dev/null +++ b/tests/bcl-test/mscorlib/Makefile @@ -0,0 +1,5 @@ + +LIB=mscorlib +APP=mscorlib + +include ../Make.frag diff --git a/tests/bcl-test/mscorlib/mscorlib.csproj.template b/tests/bcl-test/mscorlib/mscorlib.csproj.template new file mode 100644 index 000000000000..fffaa18741a7 --- /dev/null +++ b/tests/bcl-test/mscorlib/mscorlib.csproj.template @@ -0,0 +1,138 @@ + + + + Debug + iPhoneSimulator + 10.0.0 + 2.0 + {34CB1751-E445-4E32-BFA7-03E6831C11EE} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BCL.Tests + Resources + mscorlibtests + 168,169,219,414,612,618,649,672 + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + True + None + False + True + i386 + + + none + True + bin\iPhoneSimulator\Release + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + None + True + i386 + + + True + full + False + bin\iPhone\Debug + DEBUG;INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + iPhone Developer + True + False + True + cjk + ARMv7 + + + none + True + bin\iPhone\Release + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Developer + True + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + cjk + ARMv7 + + + none + True + bin\iPhone\Ad-Hoc + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + iPhone Distribution + True + Automatic:AdHoc + True + ARMv7 + + + none + True + bin\iPhone\AppStore + INSIDE_CORLIB;LIBC;NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;MONO_DATACONVERTER_STATIC_METHODS;NET_2_1;MOBILE;MONOTOUCH + prompt + 4 + False + Automatic:AppStore + iPhone Distribution + True + ARMv7 + + + + + + + + + + + + + + + + + Main.cs + + + AppDelegate.cs + + + +#FILES# + + + + + Resources\Resources.es-ES.resx + Resources.es-ES.resources + + + Resources\Resources.nn-NO.resx + Resources.nn-NO.resources + + + Resources\Resources.resx + Resources.resources + + + diff --git a/tests/bindings/ApiBaseTest.cs b/tests/bindings/ApiBaseTest.cs new file mode 100644 index 000000000000..4412763e8c07 --- /dev/null +++ b/tests/bindings/ApiBaseTest.cs @@ -0,0 +1,270 @@ +// +// Base test fixture for introspection tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using NUnit.Framework; +using Xamarin.Utils; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#if MONOTOUCH +using UIKit; +#endif +#else +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +#endif + +namespace TouchUnit.Bindings { + public abstract class ApiBaseTest { + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + protected static extern bool bool_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr arg1); + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + protected static extern IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector); + + private LatchedEnvironmentVariable continueOnFailure = new LatchedEnvironmentVariable ("API_TEST_CONTINUE_ON_FAILURE"); + + StringBuilder error_output = new StringBuilder (); + + protected void AddErrorLine (string line) + { + error_output.AppendLine (line); + Console.Error.WriteLine (line); + Errors++; + } + + protected void AddErrorLine (string format, params object[] parameters) + { + AddErrorLine (string.Format (format, parameters)); + } + + /// + /// Gets or sets a value indicating whether this test fixture will continue after failures. + /// + /// + /// true if continue on failure; otherwise, false. + /// + public bool ContinueOnFailure { + get { return continueOnFailure.Value; } + set { continueOnFailure.Value = value; } + } + + + private LatchedEnvironmentVariable logProgress = new LatchedEnvironmentVariable ("API_TEST_LOG_PROGRESS"); + + /// + /// Gets or sets a value indicating whether this test fixture will log it's progress. + /// + /// + /// true if log progress; otherwise, false. + /// + public bool LogProgress { + get { return logProgress.Value; } + set { logProgress.Value = value; } + } + + protected TextWriter Writer { +#if MONOMAC + get { return Console.Out; } +#elif __WATCHOS__ + get { return Console.Out; } +#else + get { return DontLink.AppDelegate.Runner.Writer; } +#endif + } + + protected int Errors; + protected void ReportError (string s, params object [] parameters) + { + if (!ContinueOnFailure) + Assert.Fail (s, parameters); + else { + Writer.Write ("[FAIL] "); + Writer.WriteLine (s, parameters); + Errors++; + } + } + + protected void AssertIfErrors (string s, params object[] parameters) + { + if (Errors == 0) + return; + + var msg = string.Format (s, parameters); + if (error_output.Length > 0) { + msg += "\n" + error_output.ToString () + "\n"; + error_output.Clear (); + } + Assert.Fail (msg); + } + + static protected Type NSObjectType = typeof (NSObject); + + protected virtual bool Skip (Attribute attribute) + { + return false; + } + + protected virtual bool SkipDueToAttribute (MemberInfo member) + { + if (member == null) + return false; + + return !member.IsAvailableOnHostPlatform () || + SkipDueToAttribute (member.DeclaringType) || + SkipDueToAttributeInProperty (member); + } + + // We need to check Availability info on PropertyInfo attributes too + // due to sometimes the Availability info only exist on the property + // and not on the property Getter or Setter, this complements the fix for bug: + // https://bugzilla.xamarin.com/show_bug.cgi?id=35176 + protected bool SkipDueToAttributeInProperty (MemberInfo member) + { + if (member == null) + return false; + + var m = member as MethodInfo; + + if (m == null || // Skip anything that is not a method + !m.Attributes.HasFlag (MethodAttributes.SpecialName) || + !m.Name.Contains ("get_")) // We want getters with SpecialName Attribute + return false; + + // FIXME: In the future we could cache this to reduce memory requirements + var property = m.DeclaringType + .GetProperties () + .SingleOrDefault (p => p.GetGetMethod () == m); + return property != null && SkipDueToAttribute (property); + } + + /// + /// Gets the assembly on which the test fixture will reflect the NSObject-derived types. + /// The default implementation returns the assembly where NSObject is defined, e.g. + /// monotouch.dll or xammac.dll. + /// You need to override this method to return the binding assembly you wish to test. + /// + /// + /// The assembly on which the fixture will execute it's tests. + /// + protected virtual Assembly Assembly { + get { return NSObjectType.Assembly; } + } + + const string libprefix = "/System/Library/Frameworks"; + static readonly string simprefix = Environment.GetEnvironmentVariable ("IPHONE_SIMULATOR_ROOT"); + + protected virtual string FindLibrary (string libname, bool requiresFullPath = false) + { + string prefix; + if (!String.IsNullOrEmpty (simprefix) && libname.StartsWith (libprefix, StringComparison.Ordinal)) { + libname = simprefix + libname; + prefix = String.Empty; + } else { + prefix = libprefix; // re-root libname + } + + switch (libname) { +#if !MONOMAC + case "AudioUnit": + libname = "AudioToolbox"; + break; +#endif + case "CoreAnimation": + // generated code uses QuartzCore correctly - even if the [Field] property is wrong + libname = "QuartzCore"; + break; + case "CoreMidi": + // generated code uses CoreMIDI correctly + libname = "CoreMIDI"; + break; + default: + if (requiresFullPath && (Path.GetDirectoryName (libname).Length == 0)) + ReportError ("[FAIL] Library '{0}' is specified without a path", libname); + break; + } + + return Path.Combine (prefix, libname + ".framework", libname); + } + + protected bool IsOSX11OrIOS9 { + get { +#if MONOMAC + return MonoMacFixtures.Mac.IsElCapitanOrHigher; +#elif __WATCHOS__ + return false; +#else + return UIDevice.CurrentDevice.CheckSystemVersion (9, 0); +#endif + } + } + + protected bool CheckiOSSystemVersion (int major, int minor) + { +#if __IOS__ + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check iOS system version on iOS."); +#endif + } + + // This only works for API introduced in the same numeric version in both iOS and tvOS. + protected bool CheckiOSOrTVOSSystemVersion (int major, int minor) + { +#if __IOS__ || __TVOS__ + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check iOS or tvOS system version on iOS or tvOS."); +#endif + } + + protected bool CheckWatchOSSystemVersion (int major, int minor) + { +#if __WATCHOS__ + throw new NotImplementedException (); +// return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check watchOS system version on watchOS."); +#endif + } + + protected bool CheckTVOSSystemVersion (int major, int minor) + { +#if __TVOS__ + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check tvOS system version on tvOS."); +#endif + } + } +} diff --git a/tests/bindings/ApiCoreImageFiltersTest.cs b/tests/bindings/ApiCoreImageFiltersTest.cs new file mode 100644 index 000000000000..a3153aa6f63d --- /dev/null +++ b/tests/bindings/ApiCoreImageFiltersTest.cs @@ -0,0 +1,211 @@ +// +// Test the generated API for all CoreImage filters +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013, 2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using CoreImage; +using Foundation; +using ObjCRuntime; +#if !MONOMAC +using UIKit; +#endif +#elif MONOMAC +using MonoMac.CoreImage; +using MonoMac.Foundation; +#else +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +namespace TouchUnit.Bindings { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public abstract class ApiCoreImageFiltersTest : ApiBaseTest { + + static Type CIFilterType = typeof (CIFilter); + + protected virtual bool Skip (Type type) + { + return Skip (type.Name) || SkipDueToAttribute (type); + } + + protected virtual bool Skip (string nativeName) + { + switch (nativeName) { + // Both reported in radar #21548819 + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputPoint2. + case "CIDepthOfField": + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputCropAmount. + case "CISunbeamsGenerator": + return true; + // FIXME: Remove if fixed. Doesn't appear to exist in El Capitan. Reported in radar #22099780 +// case "CIMaskedVariableBlur": +// cd .. return true; + default: + return false; + } + } + + [Test] + // this test checks that all native filters have a managed peer, i.e. against missing filters + public void CheckNativeFilters () + { + List filters = new List (); + int n = 0; + string qname = CIFilterType.AssemblyQualifiedName; + // that will give us only the list of filters supported by the executing version of iOS + foreach (var filter_name in CIFilter.FilterNamesInCategories (null)) { + if (Skip (filter_name)) + continue; + string type_name = qname.Replace ("CIFilter", filter_name); + if (Type.GetType (type_name, false, true) == null) { + filters.Add (filter_name); + // uncomment to generate bindings for any new native filter +// GenerateBinding (CIFilter.FromName (filter_name), Console.Out); + } + n++; + } + Assert.That (filters.Count, Is.EqualTo (0), "{0} native filters missing: {1}", filters.Count, String.Join (", ", filters)); + } + + [Test] + // this test checks that all managed filters have a native peer, i.e. against extra filters + public void CheckManagedFilters () + { + List filters = new List (CIFilter.FilterNamesInCategories (null)); + var nspace = CIFilterType.Namespace; + var types = CIFilterType.Assembly.GetTypes (); + foreach (Type t in types) { + if (t.Namespace != nspace) + continue; + + if (t.IsAbstract || !CIFilterType.IsAssignableFrom (t)) + continue; + + // we need to skip the filters that are not supported by the executing version of iOS + if (Skip (t)) + continue; + + var ctor = t.GetConstructor (Type.EmptyTypes); + if ((ctor == null) || ctor.IsAbstract) + continue; + + NSObject obj = ctor.Invoke (null) as NSObject; + Assert.That (obj.Handle, Is.Not.EqualTo (IntPtr.Zero), t.Name + ".Handle"); +#if false + // check base type - we might have our own base type or different names, so it's debug only (not failure) + var super = new Class (obj.Class.SuperClass).Name; + var bt = t.BaseType.Name; + if ((super != bt) && (bt == "CIFilter")) // check if we should (like Apple) use a non-default base type for filters + Console.WriteLine ("[WARN] {0}.SuperClass == {1} (native) and {2} managed", t.Name, super, bt); +#endif + int result = filters.RemoveAll (s => StringComparer.OrdinalIgnoreCase.Compare (t.Name, s) == 0); + Assert.That (result, Is.GreaterThan (0), t.Name); + } + // in case it's a buggy filter we need to try to remove it from the list too + for (int i = filters.Count - 1; i >= 0; i--) { + if (Skip (filters [i])) + filters.RemoveAt (i); + } + Assert.That (filters.Count, Is.EqualTo (0), "Managed filters not found for {0}", String.Join (", ", filters)); + } + + static void GenerateBinding (NSObject filter, TextWriter writer) + { + NSObject value; + var attributes = (filter as CIFilter).Attributes; + + writer.WriteLine ("[CoreImageFilter]"); + + if (!attributes.TryGetValue ((NSString)"CIAttributeFilterAvailable_iOS", out value)) { + writer.WriteLine ("[NoiOS]"); + } else { + var v = value.ToString (); + // in the (quite common) case we get "5" for iOS 5.0 + if (v.IndexOf ('.') == -1) + v += ".0"; + var ios = Version.Parse (v); + // we only document availability for iOS 6+ + if (ios.Major > 5) + writer.WriteLine ("[iOS ({0},{1})]", ios.Major, ios.Minor); + } + + if (!attributes.TryGetValue ((NSString)"CIAttributeFilterAvailable_Mac", out value)) { + writer.WriteLine ("[NoMac]"); + } else { + try { + var mac = Version.Parse (value.ToString ()); + // we only document availability for 10.7+ + if (mac.Minor > 6) + writer.WriteLine ("[Mac ({0},{1})]", mac.Major, mac.Minor); + } + catch (FormatException) { + // 10.? is not a valid version - we'll assume it was added a long time ago (in a galaxy far away) + writer.WriteLine ("// incorrect version string for OSX: '{0}' Double-check documentation", value); + } + } + writer.WriteLine ("[BaseType (typeof (CIFilter))]"); + var fname = attributes [(NSString)"CIAttributeFilterName"].ToString (); + writer.WriteLine ("interface {0} {{", fname); + foreach (var k in attributes.Keys) { + var key = k.ToString (); + if (key.StartsWith ("CIAttribute", StringComparison.Ordinal)) + continue; + // CIFilter defines it for all filters + if (key == "inputImage") + continue; + + writer.WriteLine (); + var dict = attributes [k] as NSDictionary; + var type = dict [(NSString) "CIAttributeClass"]; + writer.WriteLine ("\t[CoreImageProperty (\"{0}\")]", key); + + // by default we drop the "input" prefix, but keep the "output" prefix to avoid confusion + if (key.StartsWith ("input", StringComparison.Ordinal)) + key = Char.ToUpperInvariant (key [5]) + key.Substring (6); + + var ptype = type.ToString (); + // Too many things ends up in NSNumber but we do a better job in our bindings + if (ptype == "NSNumber") { + ptype = "float"; + writer.WriteLine ("\t// TODO: this was an NSNumber transformed to float, but maybe an int or bool is more appropriate"); + } + writer.WriteLine ("\t{0} {1} {{ get; set; }}", ptype, key); + } + writer.WriteLine ("}"); + writer.WriteLine (); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/bindings/ApiCtorInitTest.cs b/tests/bindings/ApiCtorInitTest.cs new file mode 100644 index 000000000000..2eff40f7f751 --- /dev/null +++ b/tests/bindings/ApiCtorInitTest.cs @@ -0,0 +1,306 @@ +// +// Test the generated API `init` selectors are usable by the binding consumers +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + + public abstract class ApiCtorInitTest : ApiBaseTest { + + string instance_type_name; + + /// + /// Gets or sets a value indicating whether this test fixture will log untested types. + /// + /// true if log untested types; otherwise, false. + public bool LogUntestedTypes { get; set; } + + /// + /// Override this method if you want the test to skip some specific types. + /// By default types decorated with [Model] will be skipped. + /// + /// The Type to be tested + protected virtual bool Skip (Type type) + { + if (type.ContainsGenericParameters) + return true; + + // skip delegate (and other protocol references) + foreach (object ca in type.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) + return true; + if (ca is ModelAttribute) + return true; + } + switch (type.Name) { +#if !XAMCORE_2_0 + case "AVAssetResourceLoader": // We have DisableDefaultCtor in XAMCORE_2_0 but can't change in compat because of backwards compat + case "AVAssetResourceLoadingRequest": + case "AVAssetResourceLoadingContentInformationRequest": +#endif + // on iOS 8.2 (beta 1) we get: NSInvalidArgumentException Caller did not provide an activityType, and this process does not have a NSUserActivityTypes in its Info.plist. + // even if we specify an NSUserActivityTypes in the Info.plist - might be a bug or there's a new (undocumented) requirement + case "NSUserActivity": + return true; + } + return SkipDueToAttribute (type); + } + + /// + /// Checks that the Handle property of the specified NSObject instance is not null (not IntPtr.Zero). + /// + /// NSObject instance to validate + protected virtual void CheckHandle (NSObject obj) + { + if (obj.Handle == IntPtr.Zero) + ReportError ("{0} : Handle", instance_type_name); + } + + /// + /// Checks that ToString does not return null (not helpful for debugging) and that it does not crash. + /// + /// NSObject instance to validate + protected virtual void CheckToString (NSObject obj) + { + if (obj.ToString () == null) + ReportError ("{0} : ToString", instance_type_name); + } + + bool GetIsDirectBinding (NSObject obj) + { +#if XAMCORE_2_0 + int flags = (byte) typeof (NSObject).GetField ("flags", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); + return (flags & 4) == 4; +#else + return (bool) typeof (NSObject).GetField ("IsDirectBinding", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); +#endif + } + + /// + /// Checks that the IsDirectBinding property is identical to the IsWrapper property of the Register attribute. + /// + /// Object. + protected virtual void CheckIsDirectBinding (NSObject obj) + { + var attrib = obj.GetType ().GetCustomAttribute (false); + // only check types that we register - that way we avoid the 118 MonoTouch.CoreImagge.CI* "special" types + if (attrib == null) + return; + var is_wrapper = attrib != null && attrib.IsWrapper; + var is_direct_binding = GetIsDirectBinding (obj); + if (is_direct_binding != is_wrapper) + ReportError ("{0} : IsDirectBinding (expected {1}, got {2})", instance_type_name, is_wrapper, is_direct_binding); + } + + /// + /// Skip, or not, the specified pproperty from being verified. + /// + /// PropertyInfo candidate + protected virtual bool Skip (PropertyInfo pi) + { + // manually bound API can have the attributes only on the property (and not on the getter/setter) + return SkipDueToAttribute (pi); + } + + /// + /// Dispose the specified NSObject instance. In some cases objects cannot be disposed safely. + /// Override this method to keep them alive while the remaining tests execute. + /// + /// NSObject instance to dispose + /// Type of the object, to be used if special logic is required. + protected virtual void Dispose (NSObject obj, Type type) + { + obj.Dispose (); + } + + protected virtual void CheckNSObjectProtocol (NSObject obj) + { + // not documented to allow null, but commonly used this way. OTOH it's not clear what code answer this + // (it might be different implementations) but we can make sure that Apple allows null with this test + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=35924 + var kind_of_null = obj.IsKindOfClass (null); + if (kind_of_null) + ReportError ("{0} : IsKindOfClass(null) failed", instance_type_name); + var is_member_of_null = obj.IsMemberOfClass (null); + if (is_member_of_null) + ReportError ("{0} : IsMemberOfClass(null) failed", instance_type_name); + var respond_to_null = obj.RespondsToSelector (null); + if (respond_to_null) + ReportError ("{0} : RespondToSelector(null) failed", instance_type_name); + var conforms_to_null = obj.ConformsToProtocol (IntPtr.Zero); + if (conforms_to_null) + ReportError ("{0} : ConformsToProtocol(null) failed", instance_type_name); + } + + // if a .ctor is obsolete then it's because it was not usable (nor testable) + protected override bool SkipDueToAttribute (MemberInfo member) + { + if (member == null) + return false; + var ca = member.GetCustomAttribute (); + return ca != null || base.SkipDueToAttribute (member); + } + + [Test] + public void DefaultCtorAllowed () + { + Errors = 0; + int n = 0; + + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsAbstract || !NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t)) + continue; + + var ctor = t.GetConstructor (Type.EmptyTypes); + if (SkipDueToAttribute (ctor)) + continue; + + if ((ctor == null) || ctor.IsAbstract) { + if (LogUntestedTypes) + Console.WriteLine ("[WARNING] {0} was skipped because it had no default constructor", t); + continue; + } + + instance_type_name = t.FullName; + if (LogProgress) + Console.WriteLine ("{0}. {1}", n, instance_type_name); + + NSObject obj = null; + try { + obj = ctor.Invoke (null) as NSObject; + CheckHandle (obj); + CheckToString (obj); + CheckIsDirectBinding (obj); + CheckNSObjectProtocol (obj); + Dispose (obj, t); + } + catch (Exception e) { + // Objective-C exception thrown + if (!ContinueOnFailure) + throw; + + TargetInvocationException tie = (e as TargetInvocationException); + if (tie != null) + e = tie.InnerException; + ReportError ("Default constructor not allowed for {0} : {1}", instance_type_name, e.Message); + } + n++; + } + Assert.AreEqual (0, Errors, "{0} potential errors found in {1} default ctor validated", Errors, n); + } + + // .NET constructors are not virtual, so we need to re-expose the base class .ctor when a subclass is created. + // That's very important for designated initializer since we can end up with no correct/safe way to create + // subclasses of an existing type + [Test] + public void DesignatedInitializer () + { + Errors = 0; + int n = 0; + + foreach (Type t in Assembly.GetTypes ()) { + // we only care for NSObject subclasses that we expose publicly + if (!t.IsPublic || !NSObjectType.IsAssignableFrom (t)) + continue; + + int designated = 0; + foreach (var ctor in t.GetConstructors ()) { + if (ctor.GetCustomAttribute () == null) + continue; + designated++; + } + // that does not mean that inlining is not required, i.e. it might be useful, even needed + // but it's not a showstopper for subclassing so we'll start with those cases + if (designated > 1) + continue; + + var base_class = t.BaseType; + // NSObject ctor requirements are handled by the generator + if (base_class == NSObjectType) + continue; + foreach (var ctor in base_class.GetConstructors ()) { + // if the base ctor is a designated (not a convenience) initializer then we should re-expose it + if (ctor.GetCustomAttribute () == null) + continue; + + // check if this ctor (from base type) is exposed in the current (subclass) type + if (!Match (ctor, t)) + ReportError ("{0} should re-expose {1}::{2}", t, base_class.Name, ctor.ToString ().Replace ("Void ", String.Empty)); + n++; + } + } + Assert.AreEqual (0, Errors, "{0} potential errors found in {1} designated initializer validated", Errors, n); + } + + protected virtual bool Match (ConstructorInfo ctor, Type type) + { + switch (type.Name) { + case "MKTileOverlayRenderer": + // NSInvalidArgumentEception Expected a MKTileOverlay + // looks like Apple has not yet added a DI for this type, but it should be `initWithTileOverlay:` + if (ctor.ToString () == "Void .ctor(IMKOverlay)") + return true; + break; + case "MPSImageHistogram": + // Could not initialize an instance of the type 'MetalPerformanceShaders.MPSImageHistogram': the native 'initWithDevice:' method returned nil. + // make sense: there's a `initWithDevice:histogramInfo:` DI + if (ctor.ToString () == "Void .ctor(IMTLDevice)") + return true; + break; + case "NSDataDetector": + // -[NSDataDetector initWithPattern:options:error:]: Not valid for NSDataDetector + if (ctor.ToString () == "Void .ctor(NSString, NSRegularExpressionOptions, NSError&)") + return true; + break; +#if __TVOS__ + case "UISearchBar": + // - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER __TVOS_PROHIBITED; + return true; +#endif + } + + var expected = ctor.ToString (); + // NonPublic to get `protected` which can be autogenerated for abstract types (subclassing a non-abstract type) + foreach (var candidate in type.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + if (candidate.ToString () == expected) + return true; + } + return false; + } + } +} diff --git a/tests/bindings/ApiFieldTest.cs b/tests/bindings/ApiFieldTest.cs new file mode 100644 index 000000000000..f60721693605 --- /dev/null +++ b/tests/bindings/ApiFieldTest.cs @@ -0,0 +1,187 @@ +// +// Test the generated API fields (e.g. against typos or unexisting values for the platform) +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.IO; +using System.Collections.Generic; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + + [Preserve (AllMembers = true)] + public abstract class ApiFieldTest : ApiBaseTest { +#if XAMCORE_2_0 + const string NSStringType = "Foundation.NSString"; +#elif MONOMAC + const string NSStringType = "MonoMac.Foundation.NSString"; +#else + const string NSStringType = "MonoTouch.Foundation.NSString"; +#endif + + /// + /// Override if you want to skip testing the specified type. + /// + /// Type to be tested + protected virtual bool Skip (Type type) + { + return false; + } + + /// + /// Override if you want to skip testing the specified property. + /// + /// Property to be tested + protected virtual bool Skip (PropertyInfo property) + { + return SkipDueToAttribute (property); + } + + /// + /// Override if you want to skip testing the specified constant. + /// + /// Constant name to ignore. + protected virtual bool Skip (string constantName) + { + return false; + } + + // check generated code, which are static properties, e.g. + // [Field ("kCGImagePropertyIPTCObjectTypeReference")] + // NSString IPTCObjectTypeReference { get; } + bool CheckAgainstNull (PropertyInfo p, out string name) + { + name = String.Empty; + var g = p.GetGetMethod (true); + if (!g.IsStatic) + return true; + + if (Skip (p)) + return true; + + try { + // if it return nulls then it could be a typo... + // or something not available in the executing version of iOS + bool result = g.Invoke (null, null) != null; + if (!result) + name = p.DeclaringType.FullName + "." + p.Name; + return result; + } + catch (Exception e) { + Console.WriteLine ("[FAIL] Exception on '{0}' : {1}", p, e); + name = p.DeclaringType.FullName + "." + p.Name; + return false; + } + } + + [Test] + public void NonNullNSStringFields () + { + var failed_fields = new List (); + + Errors = 0; + int c = 0, n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, t.FullName); + + foreach (var p in t.GetProperties (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { + // looking for properties with getters only + if (p.CanWrite || !p.CanRead) + continue; + + if (p.PropertyType.FullName != NSStringType) + continue; + + if (SkipDueToAttribute (p)) + continue; + + string name; + bool result = CheckAgainstNull (p, out name); + if (!result) { + ReportError (name); + failed_fields.Add (name); + } + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_fields)); + } + + [Test] + public void FieldExists () + { + var failed_fields = new List (); + + Errors = 0; + int c = 0, n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, t.FullName); + + foreach (var p in t.GetProperties (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { + // looking for properties with getters only + if (p.CanWrite || !p.CanRead) + continue; + + if (SkipDueToAttribute (p)) + continue; + + var f = p.GetCustomAttribute (); + if (f == null) + continue; + + string name = f.SymbolName; + if (Skip (name)) + continue; + + string path = FindLibrary (f.LibraryName); + IntPtr lib = Dlfcn.dlopen (path, 0); + if (Dlfcn.GetIndirect (lib, name) == IntPtr.Zero) { + ReportError ("Could not find the field '{0}' in {1}", name, path); + failed_fields.Add (name); + } + Dlfcn.dlclose (lib); + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_fields)); + } + } +} diff --git a/tests/bindings/ApiPInvokeTest.cs b/tests/bindings/ApiPInvokeTest.cs new file mode 100644 index 000000000000..f3869533b02c --- /dev/null +++ b/tests/bindings/ApiPInvokeTest.cs @@ -0,0 +1,259 @@ +// +// ApiPInvokeTest.cs: enforce P/Invoke signatures +// +// Authors: +// Aaron Bockover +// Sebastien Pouliot +// +// Copyright 2013-2014 Xamarin, Inc. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +#elif MONOMAC +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +#endif + +namespace TouchUnit.Bindings +{ + [Preserve (AllMembers = true)] + public abstract class ApiPInvokeTest : ApiBaseTest { + IEnumerable pinvokeQuery; + + public ApiPInvokeTest () + { + ContinueOnFailure = true; + LogProgress = false; + + pinvokeQuery = from type in Assembly.GetTypes () + where !Skip (type) + from mi in type.GetMethods ( + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Static) + let attr = mi.GetCustomAttribute () + where attr != null && !Skip (mi) + select mi; + } + + protected virtual bool Skip (Type type) + { + return SkipDueToAttribute (type); + } + + protected virtual bool Skip (MethodInfo methodInfo) + { + return SkipDueToAttribute (methodInfo); + } + + [Test] + public void Signatures () + { + int totalPInvokes = 0; + int totalErrors = 0; + + foreach (MethodInfo mi in pinvokeQuery) { + totalPInvokes++; + if (!CheckSignature (mi)) { + totalErrors++; + + if (!ContinueOnFailure) + break; + } + } + + AssertIfErrors ( + "{0} errors found in {1} P/Invoke signatures validated", + totalErrors, totalPInvokes); + } + + protected virtual bool CheckSignature (MethodInfo mi) + { + var success = true; + + if (!CheckReturnParameter (mi, mi.ReturnParameter)) + success = false; + + foreach (var pi in mi.GetParameters ()) { + if (!CheckParameter (mi, pi)) + success = false; + } + + return success; + } + + protected virtual bool CheckReturnParameter (MethodInfo mi, ParameterInfo pi) + { + return CheckForEnumParameter (mi, pi); + } + + protected virtual bool CheckParameter (MethodInfo mi, ParameterInfo pi) + { + return CheckForEnumParameter (mi, pi); + } + + protected virtual bool CheckForEnumParameter (MethodInfo mi, ParameterInfo pi) + { + if (pi.ParameterType.IsEnum && pi.ParameterType.GetCustomAttribute () != null) { + AddErrorLine ("{0}.{1} has a [Native] enum parameter in its signature: {2} {3}", + mi.DeclaringType.FullName, mi.Name, pi.ParameterType, pi.Name); + return false; + } + + return true; + } + + protected virtual bool Skip (string symbolName) + { + return false; + } + + protected virtual bool SkipLibrary (string libraryName) + { + return false; + } + + [Test] + public void SymbolExists () + { + var failed_api = new List (); + Errors = 0; + int c = 0, n = 0; + foreach (MethodInfo mi in pinvokeQuery) { + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, mi); + + var dllimport = mi.GetCustomAttribute (); + + string libname = dllimport.Value; + if (libname == "__Internal" || SkipLibrary (libname)) + continue; + + string path = FindLibrary (dllimport.Value, requiresFullPath: true); + + string name = dllimport.EntryPoint ?? mi.Name; + if (Skip (name)) + continue; + + IntPtr lib = Dlfcn.dlopen (path, 0); + if (Dlfcn.GetIndirect (lib, name) == IntPtr.Zero) { + ReportError ("Could not find the field '{0}' in {1}", name, path); + failed_api.Add (name); + } + Dlfcn.dlclose (lib); + n++; + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} functions validated: {2}", Errors, n, string.Join (", ", failed_api)); + } + + // we just want to confirm the symbol exists so `dlsym` can be disabled + protected void Check (Assembly a) + { + Errors = 0; + int n = 0; + foreach (var t in a.GetTypes ()) { + foreach (var m in t.GetMethods (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)) { + if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0) + continue; + + var dllimport = m.GetCustomAttribute (); + + string name = dllimport.EntryPoint ?? m.Name; + switch (name) { + // known not to be present in ARM64 + case "objc_msgSend_stret": + case "objc_msgSendSuper_stret": + // the linker normally removes them (IntPtr.Size optimization) + continue; + } + + string path = dllimport.Value; + switch (path) { + case "__Internal": + // load from executable + path = null; + break; + case "libc": + // we still have some rogue/not-fully-qualified DllImport + path = "/usr/lib/libSystem.dylib"; + break; + } + + var lib = Dlfcn.dlopen (path, 0); + var h = Dlfcn.dlsym (lib, name); + if (h == IntPtr.Zero) + ReportError ("Could not find the symbol '{0}' in {1}", name, path); + Dlfcn.dlclose (lib); + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} symbol lookups", Errors, n); + } + + protected abstract bool SkipAssembly (Assembly a); + + // Note: this looks very similar to the "SymbolExists" test above (and it is) + // except that we never skip based on availability attributes or __Internal... + // since this is a test to ensure thigns will work at native link time (e.g. + // for devices) when dlsym is disabled + + [Test] + public void Product () + { + var a = typeof (NSObject).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + // since we already have non-linked version of the most common assemblies available here + // we can use them to check for missing symbols (from DllImport) + // it's not complete (there's many more SDK assemblies) but we cannot add all of them into a single project anyway + + [Test] + public void Corlib () + { + var a = typeof (int).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + [Test] + public void System () + { + var a = typeof (System.Net.WebClient).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + [Test] + public void SystemCore () + { + var a = typeof (Enumerable).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + [Test] + public void SystemXml () + { + var a = typeof (System.Xml.XmlDocument).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + } +} diff --git a/tests/bindings/ApiProtocolTest.cs b/tests/bindings/ApiProtocolTest.cs new file mode 100644 index 000000000000..3e649a2293cd --- /dev/null +++ b/tests/bindings/ApiProtocolTest.cs @@ -0,0 +1,297 @@ +// +// Test the generated API for common protocol support +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013, 2015 Xamarin Inc. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + + public abstract class ApiProtocolTest : ApiBaseTest { + + static IntPtr conform_to = Selector.GetHandle ("conformsToProtocol:"); + + public ApiProtocolTest () + { + ContinueOnFailure = true; + } + + static bool ConformTo (IntPtr klass, IntPtr protocol) + { + return bool_objc_msgSend_IntPtr (klass, conform_to, protocol); + } + + protected virtual bool Skip (Type type) + { + switch (type.Name) { + // *** NSForwarding: warning: object 0x5cbd078 of class 'JSExport' does not implement methodSignatureForSelector: -- trouble ahead + // *** NSForwarding: warning: object 0x5cbd078 of class 'JSExport' does not implement doesNotRecognizeSelector: -- abort + case "JSExport": + return true; + default: +#if !XAMCORE_2_0 + // in Classic our internal delegates _inherits_ the type with the [Protocol] attribute + // in Unified our internal delegates _implements_ the interface that has the [Protocol] attribute + if (type.GetCustomAttribute (true) != null) + return true; +#endif + return SkipDueToAttribute (type); + } + } + + IntPtr GetClass (Type type) + { + return Class.GetHandle (type); + } + + protected virtual bool Skip (Type type, string protocolName) + { + switch (protocolName) { + case "NSCopying": + switch (type.Name) { + // undocumented conformance (up to 7.0) and conformity varies between iOS versions + case "CAEmitterCell": + case "GKAchievement": + case "GKScore": + // new in iOS8 and 10.0 + case "NSExtensionContext": + return true; // skip + } + break; + case "NSCoding": + switch (type.Name) { + // only documented to support NSCopying - not NSCoding (fails on iOS 7.1 but not 8.0) + case "NSUrlSessionTask": + case "NSUrlSessionDataTask": + case "NSUrlSessionUploadTask": + case "NSUrlSessionDownloadTask": + // + case "NSUrlSessionConfiguration": + case "NSMergeConflict": + // new in iOS8 and 10.0 + case "NSExtensionContext": + case "NSItemProvider": + // undocumented + return true; + } + break; + case "NSSecureCoding": + switch (type.Name) { + case "NSMergeConflict": // undocumented + // only documented to support NSCopying (and OSX side only does that) + case "NSUrlSessionTask": + case "NSUrlSessionDataTask": + case "NSUrlSessionUploadTask": + case "NSUrlSessionDownloadTask": + case "NSUrlSessionConfiguration": + // new in iOS8 and 10.0 + case "NSExtensionContext": + case "NSItemProvider": + case "NSParagraphStyle": //17770106 + case "NSMutableParagraphStyle": //17770106 + return true; // skip + // iOS9 / 10.11 + case "NSPersonNameComponentsFormatter": + return true; // skip + } + break; + } + return false; + } + + void CheckProtocol (string protocolName, Action action) + { + IntPtr protocol = Runtime.GetProtocol (protocolName); + Assert.AreNotEqual (protocol, IntPtr.Zero, protocolName); + + int n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (!NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t) || Skip (t, protocolName)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1} conforms to {2}", ++n, t.FullName, protocolName); + + IntPtr klass = GetClass (t); + action (t, klass, ConformTo (klass, protocol)); + } + } + + [Test] + public void Coding () + { + Errors = 0; + CheckProtocol ("NSCoding", delegate (Type type, IntPtr klass, bool result) { + if (result) { + // `type` conforms to (native) NSCoding so... + if (result) { + // the type should implements INSCoding + if (!typeof (INSCoding).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSCoding but does not implement INSCoding", type.Name); + } + // FIXME: and implement the .ctor(NSCoder) + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSCoding but does not implement INSCoding", Errors); + } + + // [Test] -> iOS 6.0+ and Mountain Lion (10.8) + + public virtual void SecureCoding () + { + Errors = 0; + CheckProtocol ("NSSecureCoding", delegate (Type type, IntPtr klass, bool result) { + if (result) { + // the type should implements INSSecureCoding + if (!typeof (INSSecureCoding).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSSecureCoding but does not implement INSSecureCoding", type.Name); + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSSecureCoding but does not implement INSSecureCoding", Errors); + } + + bool SupportsSecureCoding (Type type) + { + Class cls = new Class (type); + if (!bool_objc_msgSend_IntPtr (cls.Handle, Selector.GetHandle ("respondsToSelector:"), Selector.GetHandle ("supportsSecureCoding"))) + return false; + + return NSSecureCoding.SupportsSecureCoding (type); + } + + + // [Test] -> iOS 6.0+ and Mountain Lion (10.8) + + public virtual void SupportsSecureCoding () + { + Errors = 0; + CheckProtocol ("NSSecureCoding", delegate (Type type, IntPtr klass, bool result) { + bool supports = SupportsSecureCoding (type); + if (result) { + // check that +supportsSecureCoding returns YES + if (!supports) { + ReportError ("{0} conforms to NSSecureCoding but SupportsSecureCoding returned false", type.Name); + } + } else if (type.IsPublic && supports) { + // there are internal types, e.g. DataWrapper : NSData, that subclass NSSecureCoding-types without + // [re-]declaring their allegiance - but we can live with those small betrayals + Assert.IsFalse (NSSecureCoding.SupportsSecureCoding (type), "{0} !SupportsSecureCoding", type.Name); + ReportError ("SupportsSecureCoding returns true but {0} does not conforms to NSSecureCoding", type.Name); + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSCoding but does not implement INSSecureCoding", Errors); + } + + [Test] + public void Copying () + { + Errors = 0; + CheckProtocol ("NSCopying", delegate (Type type, IntPtr klass, bool result) { + // `type` conforms to (native) NSCopying so... + if (result) { + // the type should implements INSCopying + if (!typeof (INSCopying).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSCopying but does not implement INSCopying", type.Name); + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSCopying but does not implement INSCopying", Errors); + } + + [Test] + public void MutableCopying () + { + Errors = 0; + CheckProtocol ("NSMutableCopying", delegate (Type type, IntPtr klass, bool result) { + // `type` conforms to (native) NSMutableCopying so... + if (result) { + // the type should implements INSMutableCopying + if (!typeof (INSMutableCopying).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSMutableCopying but does not implement INSMutableCopying", type.Name); + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSMutableCopying but does not implement INSMutableCopying", Errors); + } + + [Test] + public void GeneralCase () + { + Errors = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (!NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t)) + continue; + + foreach (var intf in t.GetInterfaces ()) { + if (SkipDueToAttribute (intf)) + continue; + + string protocolName = intf.Name.Substring (1); + switch (protocolName) { + case "NSCoding": + case "NSSecureCoding": + case "NSCopying": + case "NSMutableCopying": + // we have special test cases for them + continue; + default: +#if !XAMCORE_2_0 + // in Classic our internal delegates _inherits_ the type with the [Protocol] attribute + // in Unified our internal delegates _implements_ the interface that has the [Protocol] attribute + var pt = Type.GetType (intf.Namespace + "." + protocolName + ", " + intf.Assembly.FullName); + if (SkipDueToAttribute (pt)) + continue; +#endif + if (Skip (t, protocolName)) + continue; + break; + } + + var a = intf.GetCustomAttribute (true); + if (a == null || a.IsInformal) + continue; + + IntPtr protocol = Runtime.GetProtocol (protocolName); + if (protocol == IntPtr.Zero) + continue; // not a protocol + + if (LogProgress) + Console.WriteLine ("{0} conforms to {1}", t.FullName, protocolName); + + var klass = new Class (t); + if (klass.Handle == IntPtr.Zero) { + AddErrorLine ("Could not load {0}", t.FullName); + } else if (t.IsPublic && !ConformTo (klass.Handle, protocol)) { + // note: some internal types, e.g. like UIAppearance subclasses, return false (and there's not much value in changing this) + ReportError ("Type {0} (native: {1}) does not conform {2}", t.FullName, klass.Name, protocolName); + } + } + } + AssertIfErrors ("{0} types do not really conform to the protocol interfaces", Errors); + } + } +} diff --git a/tests/bindings/ApiSelectorTest.cs b/tests/bindings/ApiSelectorTest.cs new file mode 100644 index 000000000000..b0ef3fff96fb --- /dev/null +++ b/tests/bindings/ApiSelectorTest.cs @@ -0,0 +1,406 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Reflection; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + + public abstract class ApiSelectorTest : ApiBaseTest { + + // not everything should be even tried + + protected virtual bool Skip (Type type) + { + if (type.ContainsGenericParameters) + return true; + + // skip delegate (and other protocol references) + foreach (object ca in type.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) + return true; + if (ca is ModelAttribute) + return true; + } + return SkipDueToAttribute (type); + } + + protected virtual bool Skip (Type type, string selectorName) + { +#if !XAMCORE_2_0 + // old binding mistake + if (selectorName == "subscribedCentrals") + return true; +#else + // The MapKit types/selectors are optional protocol members pulled in from MKAnnotation/MKOverlay. + // These concrete (wrapper) subclasses do not implement all of those optional members, but we + // still need to provide a binding for them, so that user subclasses can implement those members. + switch (type.Name) { + case "MKCircle": + case "MKPolygon": + case "MKPolyline": + switch (selectorName) { + case "canReplaceMapContent": + return true; + } + break; + case "MKShape": + switch (selectorName) { + case "setCoordinate:": + return true; + } + break; + case "MKPlacemark": + switch (selectorName) { + case "setCoordinate:": + case "subtitle": + return true; + } + break; + case "MKTileOverlay": + switch (selectorName) { + case "intersectsMapRect:": + return true; + } + break; + // AVAudioChannelLayout and AVAudioFormat started conforming to NSSecureCoding in OSX 10.11 and iOS 9 + case "AVAudioChannelLayout": + case "AVAudioFormat": + switch (selectorName) { + case "encodeWithCoder:": + return true; + } + break; + // SKTransition started conforming to NSCopying in OSX 10.11 and iOS 9 + case "SKTransition": + switch (selectorName) { + case "copyWithZone:": + return true; + } + break; + } +#endif + // This ctors needs to be manually bound + switch (type.Name) { + case "GKPath": + switch (selectorName) { + case "initWithPoints:count:radius:cyclical:": + return true; + } + break; + case "GKPolygonObstacle": + switch (selectorName) { + case "initWithPoints:count:": + return true; + } + break; + case "NSImage": + switch (selectorName) { + case "initByReferencingFile:": + return true; + } + break; + case "SKVideoNode": + switch (selectorName) { + case "initWithFileNamed:": + case "initWithURL:": + case "initWithVideoFileNamed:": + case "initWithVideoURL:": + case "videoNodeWithFileNamed:": + case "videoNodeWithURL:": + return true; + } + break; + } + + // old binding mistake + return (selectorName == "initWithCoder:"); + } + + protected virtual bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + if (value) + return true; + + var mname = method.Name; + // properties getter and setter will be methods in the _Extensions type + if (method.IsSpecialName) + mname = mname.Replace ("get_", "Get").Replace ("set_", "Set"); + + // it's possible that the selector was inlined for an OPTIONAL protocol member + // we do not want those reported (too many false positives) and we have other tests to find such mistakes + foreach (var intf in actualType.GetInterfaces ()) { + if (intf.GetCustomAttributes () == null) + continue; + var ext = Type.GetType (intf.Namespace + "." + intf.Name.Remove (0, 1) + "_Extensions, " + intf.Assembly.FullName); + if (ext == null) + continue; + foreach (var m in ext.GetMethods ()) { + if (mname != m.Name) + continue; + var parameters = method.GetParameters (); + var ext_params = m.GetParameters (); + // first parameters is `this XXX This` + if (parameters.Length == ext_params.Length - 1) { + bool match = true; + for (int i = 1; i < ext_params.Length; i++) { + match |= (parameters [i - 1].ParameterType == ext_params [i].ParameterType); + } + if (match) + return true; + } + } + } + + name = actualType.FullName + " : " + name; + return false; + } + + static IntPtr responds_handle = Selector.GetHandle ("instancesRespondToSelector:"); + + [Test] + public void Protocols () + { + Errors = 0; + int n = 0; + + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsNested || !NSObjectType.IsAssignableFrom (t)) + continue; + + foreach (object ca in t.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) { + foreach (var c in t.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + ProcessProtocolMember (t, c, ref n); + } + foreach (var m in t.GetMethods (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + ProcessProtocolMember (t, m, ref n); + } + } + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} protocol selectors validated", Errors, n); + } + + void ProcessProtocolMember (Type t, MethodBase m, ref int n) + { + if (SkipDueToAttribute (m)) + return; + + foreach (object ca in m.GetCustomAttributes (true)) { + ExportAttribute export = (ca as ExportAttribute); + if (export == null) + continue; + + string name = export.Selector; + if (Skip (t, name)) + continue; + + CheckInit (t, m, name); + n++; + } + } + + protected virtual IntPtr GetClassForType (Type type) + { + var fi = type.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + return IntPtr.Zero; // e.g. *Delegate + return (IntPtr) fi.GetValue (null); + } + + [Test] + public void InstanceMethods () + { + Errors = 0; + int n = 0; + + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsNested || !NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + IntPtr class_ptr = GetClassForType (t); + + if (class_ptr == IntPtr.Zero) + continue; + + foreach (var c in t.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + Process (class_ptr, t, c, ref n); + } + + foreach (var m in t.GetMethods (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + Process (class_ptr, t, m, ref n); + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} instance selector validated", Errors, n); + } + + void Process (IntPtr class_ptr, Type t, MethodBase m, ref int n) + { + if (m.DeclaringType != t || SkipDueToAttribute (m)) + return; + + foreach (object ca in m.GetCustomAttributes (true)) { + ExportAttribute export = (ca as ExportAttribute); + if (export == null) + continue; + + string name = export.Selector; + if (Skip (t, name)) + continue; + + CheckInit (t, m, name); + + bool result = bool_objc_msgSend_IntPtr (class_ptr, responds_handle, Selector.GetHandle (name)); + bool response = CheckResponse (result, t, m, ref name); + if (!response) + ReportError ("Selector not found for {0}", name); + n++; + } + } + + void CheckInit (Type t, MethodBase m, string name) + { + if (SkipInit (name, m)) + return; + + bool init = IsInitLike (name); + if (m is ConstructorInfo) { + if (!init) + ReportError ("Selector {0} used on a constructor (not a method) on {1}", name, t.FullName); + } else { + if (init) + ReportError ("Selector {0} used on a method (not a constructor) on {1}", name, t.FullName); + } + } + + bool IsInitLike (string selector) + { + if (!selector.StartsWith ("init", StringComparison.OrdinalIgnoreCase)) + return false; + return selector.Length < 5 || Char.IsUpper (selector [4]); + } + + protected virtual bool SkipInit (string selector, MethodBase m) + { + switch (selector) { + // NSAttributedString + case "initWithHTML:documentAttributes:": + case "initWithRTF:documentAttributes:": + case "initWithRTFD:documentAttributes:": + case "initWithURL:options:documentAttributes:error:": + case "initWithFileURL:options:documentAttributes:error:": + // AVAudioRecorder + case "initWithURL:settings:error:": + // NSUrlProtectionSpace + case "initWithHost:port:protocol:realm:authenticationMethod:": + case "initWithProxyHost:port:type:realm:authenticationMethod:": + // NSUserDefaults + case "initWithSuiteName:": + case "initWithUser:": + // GKScore + case "initWithCategory:": + case "initWithLeaderboardIdentifier:": + // MCSession + case "initWithPeer:securityIdentity:encryptionPreference:": + // UISegmentedControl + case "initWithItems:": + var mi = m as MethodInfo; + return mi != null && !mi.IsPublic && mi.ReturnType.Name == "IntPtr"; + default: + return false; + } + } + + protected virtual void Dispose (NSObject obj, Type type) + { + obj.Dispose (); + } + + // funny, this is how I envisioned the instance version... before hitting run :| + protected virtual bool CheckStaticResponse (bool value, Type actualType, Type declaredType, ref string name) + { + if (value) + return true; + + name = actualType.FullName + " : " + name; + return false; + } + + [Test] + public void StaticMethods () + { + Errors = 0; + int n = 0; + + IntPtr responds_handle = Selector.GetHandle ("respondsToSelector:"); + + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsNested || !NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + FieldInfo fi = t.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + continue; // e.g. *Delegate + IntPtr class_ptr = (IntPtr) fi.GetValue (null); + + foreach (var m in t.GetMethods (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)) { + if (SkipDueToAttribute (m)) + continue; + + foreach (object ca in m.GetCustomAttributes (true)) { + if (ca is ExportAttribute) { + string name = (ca as ExportAttribute).Selector; + + if (Skip (t, name)) + continue; + + bool result = bool_objc_msgSend_IntPtr (class_ptr, responds_handle, Selector.GetHandle (name)); + bool response = CheckStaticResponse (result, t, m.DeclaringType, ref name); + if (!response) + ReportError (name); + n++; + } + } + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} static selector validated", Errors, n); + } + } +} diff --git a/tests/bindings/ApiSignatureTest.cs b/tests/bindings/ApiSignatureTest.cs new file mode 100644 index 000000000000..7582f2084bf0 --- /dev/null +++ b/tests/bindings/ApiSignatureTest.cs @@ -0,0 +1,760 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Text; +using NUnit.Framework; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + + public abstract class ApiSignatureTest : ApiBaseTest { + + [DllImport ("/usr/lib/libobjc.dylib")] + // note: the returned string is not ours to free + static extern IntPtr objc_getClass (string name); + + [DllImport ("/usr/lib/libobjc.dylib")] + // note: the returned string is not ours to free + static extern IntPtr method_getTypeEncoding (IntPtr method); + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_getClassMethod (IntPtr klass, IntPtr selector); + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_getInstanceMethod (IntPtr klass, IntPtr selector); + + protected string[] Split (string encoded, out int size) + { + List elements = new List (); + int pos = 0; + string s = Next (encoded, ref pos); + int end = pos; + while (Char.IsDigit (encoded [end])) + end++; + + size = Int32.Parse (encoded.Substring (pos, end - pos)); + + if (encoded [end] != '@' || encoded [end + 1] != '0' || encoded [end + 2] != ':') { + if (!ContinueOnFailure) + Assert.Fail ("Unexpected format, missing '@0:', inside '{0}'", encoded); + return null; + } + + pos = end + 3; + + while (s != null) { + elements.Add (s); + s = Next (encoded, ref pos); + } + return elements.ToArray (); + } + + static string Next (string encoded, ref int pos) + { + // skip digits + while (pos < encoded.Length && Char.IsDigit (encoded [pos])) + pos++; + if (pos >= encoded.Length) + return null; + + StringBuilder sb = new StringBuilder (); + int acc = 0; + char c = encoded [pos]; + while (!Char.IsDigit (c) || acc > 0) { + sb.Append (c); + if (c == '{' || c == '(') + acc++; + else if (c == '}' || c == ')') + acc--; + if (++pos >= encoded.Length) + break; + c = encoded [pos]; + } + return sb.ToString (); + } + + int TypeSize (Type t) + { + return TypeSize (t, ref t); + } + + int TypeSize (Type t, ref Type real) + { + real = t; + if (!t.IsValueType) + return IntPtr.Size; // platform + if (t.IsEnum) { + foreach (var ca in t.CustomAttributes) { + if (ca.AttributeType.Name == "NativeAttribute") + return IntPtr.Size; + } + real = Enum.GetUnderlyingType (t); + } + return Marshal.SizeOf (real); + } + + protected virtual int Size (Type t, bool simd = false) + { + switch (t.Name) { + // rdar 21375616 - Breaking change with EventKit[UI] enum base type + // EventKit.EK* enums are anonymous enums in 10.10 and iOS 8, but an NSInteger in 10.11 and iOS 9. + case "EKCalendarType": + case "EKParticipantType": + case "EKParticipantRole": + case "EKParticipantStatus": + case "EKEventStatus": + case "EKSourceType": + case "EKSpan": + case "EKRecurrenceFrequency": + case "EKEventAvailability": + if (!IsOSX11OrIOS9) + return 4; + break; + case "MDLAxisAlignedBoundingBox": + return 32; // struct (Vector3, Vector3) + } + if (simd) { + switch (t.Name) { + case "Vector3i": // sizeof (vector_uint3) + case "Vector3": // sizeof (vector_float3) + return 16; + case "MDLAxisAlignedBoundingBox": + return 32; // struct (Vector3, Vector3) + } + } + int size = TypeSize (t, ref t); + return t.IsPrimitive && size < 4 ? 4 : size; + } + + protected virtual bool Skip (Type type) + { + if (type.ContainsGenericParameters) + return true; + + return false; + } + + protected virtual bool Skip (Type type, MethodBase method, string selector) + { + return SkipDueToAttribute (method); + } + + public int CurrentParameter { get; private set; } + + public MethodBase CurrentMethod { get; private set; } + + public string CurrentSelector { get; private set; } + + public Type CurrentType { get; private set; } + + const BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; + + [Test] + public void Signatures () + { + int n = 0; + Errors = 0; + + foreach (Type t in Assembly.GetTypes ()) { + + var static_type = t.IsSealed && t.IsAbstract; // e.g. [Category] + if (t.IsNested || (!static_type && !NSObjectType.IsAssignableFrom (t))) + continue; + + if (Skip (t)) + continue; + + CurrentType = t; + + FieldInfo fi = null; + if (!static_type) + fi = t.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + IntPtr class_ptr = fi == null ? IntPtr.Zero : (IntPtr) fi.GetValue (null); + + foreach (MethodBase m in t.GetMethods (Flags)) + CheckMemberSignature (m, t, class_ptr, ref n); + foreach (MethodBase m in t.GetConstructors (Flags)) + CheckMemberSignature (m, t, class_ptr, ref n); + } + AssertIfErrors ("{0} errors found in {1} signatures validated", Errors, n); + } + + void CheckMemberSignature (MethodBase m, Type t, IntPtr class_ptr, ref int n) + { + var methodinfo = m as MethodInfo; + var constructorinfo = m as ConstructorInfo; + + if (methodinfo == null && constructorinfo == null) + return; + + if (m.DeclaringType != t) + return; + + CurrentMethod = m; + + foreach (object ca in m.GetCustomAttributes (true)) { + var exportAttribute = ca as ExportAttribute; + if (exportAttribute == null) + continue; + string name = exportAttribute.Selector; + + if (Skip (t, m, name)) + continue; + + CurrentSelector = name; + + // in some cases, e.g. *Delegate, we cannot use introspection but we can still do some checks + if (class_ptr == IntPtr.Zero) { + BasicChecks (m, t, ref n); + } else { + IntrospectionTest (m, methodinfo, t, class_ptr, ref n); + } + } + } + + void BasicChecks (MethodBase m, Type t, ref int n) + { + int native = 0; + int pos = CurrentSelector.IndexOf (':'); + while (pos != -1) { + native++; + pos = CurrentSelector.IndexOf (':', pos + 1); + } + var mp = m.GetParameters (); + int managed = mp.Length; + if (t.IsSealed && t.IsAbstract) { + // static types, e.g. [Category], adds a first 'This' argument for extension methods + // but we also expose static properties this way, e.g. NSUrlUtilities_NSCharacterSet + if ((managed >= 1) && (mp [0].Name == "This")) + managed--; + } + if (LogProgress) + Console.WriteLine ("{0} {1} '{2}' selector {3} : {4} == {5}", ++n, t.Name, m, CurrentSelector, native, managed); + if (native != managed) { + AddErrorLine ("Parameter count mismatch for {0} in {1}:{2} : Native {3} vs Managed {4}", + CurrentSelector, t, m.Name, native, managed); + } + } + + void IntrospectionTest (MethodBase m, MethodInfo methodinfo, Type t, IntPtr class_ptr, ref int n) + { + IntPtr sel = Selector.GetHandle (CurrentSelector); + IntPtr method; + if (methodinfo != null) + method = m.IsStatic ? class_getClassMethod (class_ptr, sel) : class_getInstanceMethod (class_ptr, sel); + else + method = class_getInstanceMethod (class_ptr, sel); + IntPtr tenc = method_getTypeEncoding (method); + string encoded = Marshal.PtrToStringAuto (tenc); + + if (LogProgress) + Console.WriteLine ("{0} {1} '{2} {3}' selector: {4} == {5}", ++n, t.Name, methodinfo != null ? methodinfo.IsStatic ? "static" : "instance" : "ctor", m, CurrentSelector, encoded); + + // NSObject has quite a bit of stuff that's not usable (except by some class that inherits from it) + if (String.IsNullOrEmpty (encoded)) + return; + + int encoded_size = -1; + string [] elements = null; + try { + elements = Split (encoded, out encoded_size); + } + catch { + } + if (elements == null) { + if (LogProgress) + Console.WriteLine ("[WARNING] Could not parse encoded signature for {0} : {1}", CurrentSelector, encoded); + return; + } + + bool result; + CurrentParameter = 0; + + if (methodinfo != null) { + // check return value + + result = Check (elements [CurrentParameter], methodinfo.ReturnType); + if (!result) + AddErrorLine ("Return Value of selector: {0} on type {1}, Type: {2}, Encoded as: {3}", CurrentSelector, t, methodinfo.ReturnType, elements [CurrentParameter]); + } + + int size = 2 * IntPtr.Size; // self + selector (@0:) + + var parameters = m.GetParameters (); + bool simd = (parameters.Length >= elements.Length); + foreach (var p in parameters) { + CurrentParameter++; + var pt = p.ParameterType; + if (CurrentParameter >= elements.Length) { + // SIMD structures are not (ios8 beta2) encoded in the signature, we ignore them + result = IgnoreSimd (CurrentSelector, t, pt); + if (!result) + AddErrorLine ("Selector: {0} on type {1}, Type: {2}, nothing encoded", CurrentSelector, t, pt); + } else { + // skip SIMD/vector parameters (as they are not encoded) + result = IgnoreSimd (CurrentSelector, t, pt); + if (result) + CurrentParameter--; + else + result = Check (elements [CurrentParameter], pt); + if (!result) + AddErrorLine ("Signature failure in {1} {0} Parameter '{4}' (#{5}) is encoded as '{3}' and bound as '{2}'", + CurrentSelector, t, pt, elements [CurrentParameter], p.Name, CurrentParameter); + } + + size += Size (pt, simd); + } + + // also ensure the encoded size match what MT (or XM) provides + // catch API errors (and should catch most 64bits issues as well) + if (size != encoded_size) + AddErrorLine ("Size {0} != {1} for {2} on {3}: {4}", encoded_size, size, CurrentSelector, t, encoded); + } + + static bool IgnoreSimd (string name, Type t, Type pt) + { + switch (pt.Name) { + case "Vector2": + case "Vector2i": + case "Vector3": + case "Vector3i": + case "Vector4": + case "Vector4i": + case "MDLAxisAlignedBoundingBox": // struct { Vector3, Vector3 } + return true; + default: + return false; + } + } + + protected virtual bool IsValidStruct (Type type, string structName) + { + switch (structName) { + // MKPolygon 'static MonoTouch.MapKit.MKPolygon _FromPoints(IntPtr, Int32)' selector: polygonWithPoints:count: == @16@0:4^{?=dd}8I12 + // NSValue 'static MonoTouch.Foundation.NSValue FromCMTime(CMTime)' selector: valueWithCMTime: == @32@0:4{?=qiIq}8 + case "?": + return type.IsValueType; // || (type.FullName == "System.IntPtr"); +#if XAMCORE_2_0 + case "CGRect": + return type.FullName == "CoreGraphics.CGRect"; + case "CGSize": + return type.FullName == "CoreGraphics.CGSize"; + case "CGPoint": + return type.FullName == "CoreGraphics.CGPoint"; +#else + case "CGRect": + return type.FullName == "System.Drawing.RectangleF"; + case "CGSize": + return type.FullName == "System.Drawing.SizeF"; + case "CGPoint": + return type.FullName == "System.Drawing.PointF"; +#endif + case "opaqueCMFormatDescription": + switch (type.Name) { + case "CMFormatDescription": + case "CMVideoFormatDescription": + case "CMAudioFormatDescription": + return true; + } + break; + case "opaqueCMSampleBuffer": + structName = "CMSampleBuffer"; + break; + case "_NSRange": + structName = "NSRange"; + break; + // textureWithContentsOfFile:options:queue:completionHandler: == v24@0:4@8@12^{dispatch_queue_s=}16@?20 + case "dispatch_queue_s": + structName = "DispatchQueue"; + break; + case "OpaqueCMClock": + structName = "CMClock"; + break; + case "OpaqueCMTimebase": + structName = "CMTimebase"; + break; + case "__CFRunLoop": + structName = "CFRunLoop"; + break; + case "_GLKVector4": + structName = "Vector4"; + break; + case "_GLKVector3": + structName = "Vector3"; + break; + case "_GLKVector2": + structName = "Vector2"; + break; + case "_GLKMatrix2": + structName = "Matrix2"; + break; + case "_GLKMatrix3": + structName = "Matrix3"; + break; + case "_GLKMatrix4": + structName = "Matrix4"; + break; + case "__CVPixelBufferPool": + structName = "CVPixelBufferPool"; + break; + case "opaqueMTAudioProcessingTap": + structName = "MTAudioProcessingTap"; + break; + case "OpaqueMIDIEndpoint": + structName = "Int32"; + break; + case "__CFDictionary": + structName = "NSDictionary"; + break; + case "__CFUUID": + // CBAttribute.UUID is defined as a CBUUID but ObjC runtime tell us it's __CFUUID + // which makes it sound like a (undocumented) toll free bridged type + structName = "CBUUID"; + break; + case "__CFString": + if (type.FullName == "System.String") + return true; + break; +#if !MONOMAC + // definition is different on OSX + case "SCNVector4": + switch (type.Name) { + case "SCNVector4": + // typedef SCNVector4 SCNQuaternion; (SceneKitTypes.h) + case "SCNQuaternion": + return true; + } + break; +#endif + case "_CGLContextObject": + structName = "CGLContext"; + break; + case "_CGLPixelFormatObject": + structName = "CGLPixelFormat"; + break; + case "OpaqueSecIdentityRef": + structName = "SecIdentity"; + break; + case "__SecTrust": + structName = "SecTrust"; + break; + case "_NSZone": + structName = "NSZone"; + break; + case "_AVBeatRange": + structName = "AVBeatRange"; + break; + case "AVAudio3DPoint": + structName = "Vector3"; + break; + case "OpaqueMusicSequence": + structName = "MusicSequence"; + break; + case "OpaqueAudioComponentInstance": + structName = "AudioUnit"; + break; + case "OpaqueAudioComponent": + structName = "AudioComponent"; + break; + case "GCQuaternion": + structName = "Quaterniond"; // OpenTK.Quaterniond + break; + case "OpaqueSecAccessControl": // El Capitan + case "__SecAccessControl": + structName = "SecAccessControl"; + break; + case "AudioChannelLayout": + // this is actually an `nint` used as a pointer (to get a unique signature for the .ctor) + // there's custom code in src/AVFoundation/AVAudioChannelLayout.cs to deal with this +#if XAMCORE_2_0 + structName = "nint"; +#else + structName = "Int32"; +#endif + break; +#if !XAMCORE_2_0 + // in compat it's a class (instead of a struct) hence this hack + case "AudioComponentDescription": + structName = "AudioComponentDescriptionNative"; + break; +#endif + } + return type.Name == structName; + } + + static Type inativeobject = typeof (INativeObject); + + protected virtual bool Check (string encodedType, Type type) + { + char c = encodedType [0]; + + if (encodedType.Length == 1) + return Check (c, type); + + switch (c) { + // GLKBaseEffect 'instance Vector4 get_LightModelAmbientColor()' selector: lightModelAmbientColor == (_GLKVector4={?=ffff}{?=ffff}{?=ffff}[4f])8@0:4 + case '(': + case '{': + string struct_name = encodedType.Substring (1, encodedType.IndexOf ('=') - 1); + return IsValidStruct (type, struct_name); + case '@': + switch (encodedType [1]) { + case '?': + return (type.Name == "NSAction") || type.BaseType.FullName == "System.MulticastDelegate"; + default: + return false; + } + case '^': + switch (encodedType [1]) { + case 'v': + // NSOpenGLContext 'instance MonoMac.OpenGL.CGLContext get_CGLContext()' selector: CGLContextObj == ^v8@0:4 + if ((CurrentType.Name == "NSOpenGLContext") && (type.Name == "CGLContext")) + return true; + // NSOpenGLPixelFormat 'instance MonoMac.OpenGL.CGLPixelFormat get_CGLPixelFormat()' selector: CGLPixelFormatObj == ^v8@0:4 + if ((CurrentType.Name == "NSOpenGLPixelFormat") && (type.Name == "CGLPixelFormat")) + return true; + if (type.Name == "ABRecord") { + if ((CurrentType.Name == "EKParticipant") || CurrentType.Name.StartsWith ("PKPayment", StringComparison.OrdinalIgnoreCase)) + return true; + } + if ((type.Name == "ABAddressBook") && (CurrentType.Name == "EKParticipant")) + return true; + return (type.FullName == "System.IntPtr"); + case 'B': + case 'd': + case 'f': + case 'I': + case 'i': + case 'c': + case 'q': + case 'Q': + case 'S': + return (type.FullName == "System.IntPtr") || Check (encodedType.Substring (1), type.GetElementType ()); + // NSInputStream 'instance Boolean GetBuffer(IntPtr ByRef, UInt32 ByRef)' selector: getBuffer:length: == c16@0:4^*8^I12 + case '*': + case '{': + // 10.7 only: NSArray 'static MonoMac.Foundation.NSArray FromObjects(IntPtr, Int32)' selector: arrayWithObjects:count: == @16@0:4^r@8I12 + case 'r': + if (type.FullName == "System.IntPtr") + return true; + return Check (encodedType.Substring (1), type.IsByRef ? type.GetElementType () : type); + case '@': + return Check ('@', type.IsByRef ? type.GetElementType () : type); + case '^': + case '?': + return (type.FullName == "System.IntPtr"); + default: + return false; + } + case 'r': + // const -> ignore + // e.g. vectorWithValues:count: == @16@0:4r^f8L12 + case 'o': + // out -> ignore + // e.g. validateValue:forKey:error: == c20@0:4N^@8@12o^@16 + case 'N': + // inout -> ignore + // e.g. validateValue:forKey:error: == c20@0:4N^@8@12o^@16 + case 'V': + // oneway -> ignore + // e.g. NSObject 'instance Void NativeRelease()' selector: release == Vv8@0:4 + return Check (encodedType.Substring (1), type); + default: + return false; + } + } + + /// + /// Check that specified encodedType match the type and caller. + /// + /// Encoded type from the ObjC signature. + /// Managed type representing the encoded type. + /// Caller's type. Useful to limit any special case. + protected virtual bool Check (char encodedType, Type type) + { + switch (encodedType) { + case '@': + return (type.IsInterface || // protocol + type.IsArray || // NSArray + (type.Name == "NSArray") || // NSArray + (type.FullName == "System.String") || // NSString + (type.FullName == "System.IntPtr") || // unbinded, e.g. internal + (type.BaseType.FullName == "System.MulticastDelegate") || // completion handler -> delegate + NSObjectType.IsAssignableFrom (type)) || // NSObject derived + inativeobject.IsAssignableFrom (type); // e.g. CGImage + case 'B': + // 64 bits only encode this + return type.FullName == "System.Boolean"; + case 'c': // char, used for C# bool + switch (type.FullName) { + case "System.Boolean": + case "System.SByte": + return true; + default: + return type.IsEnum && TypeSize (type) == 1; + } + case 'C': + switch (type.FullName) { + case "System.Byte": + // GLKBaseEffect 'instance Boolean get_ColorMaterialEnabled()' selector: colorMaterialEnabled == C8@0:4 + case "System.Boolean": + return true; + default: + return false; + } + case 'd': + switch (type.FullName) { + case "System.Double": + return true; + case "System.nfloat": + return IntPtr.Size == 8; + default: + return false; + } + case 'f': + switch (type.FullName) { + case "System.Single": + return true; + case "System.nfloat": + return IntPtr.Size == 4; + default: + return false; + } + case 'i': + switch (type.FullName) { + case "System.Int32": + return true; + case "System.nint": + return IntPtr.Size == 4; + case "EventKit.EKSourceType": + case "EventKit.EKCalendarType": + case "EventKit.EKEventAvailability": + case "EventKit.EKEventStatus": + case "EventKit.EKParticipantRole": + case "EventKit.EKParticipantStatus": + case "EventKit.EKParticipantType": + case "EventKit.EKRecurrenceFrequency": + case "EventKit.EKSpan": + case "EventKit.EKAlarmType": + // EventKit.EK* enums are anonymous enums in 10.10 and iOS 8, but an NSInteger in 10.11 and iOS 9. + if (IsOSX11OrIOS9) + goto default; + return true; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'I': + switch (type.FullName) { + case "System.UInt32": + return true; + case "System.nint": // check + case "System.nuint": + return IntPtr.Size == 4; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'l': + switch (type.FullName) { + case "System.Int32": + return true; + case "System.nint": + return IntPtr.Size == 4; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'L': + switch (type.FullName) { + case "System.UInt32": + return true; + case "System.nint": // check + case "System.nuint": + return IntPtr.Size == 4; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'q': + switch (type.FullName) { + case "System.Int64": + return true; + case "System.nint": + return IntPtr.Size == 8; + default: + return type.IsEnum && TypeSize (type) == 8; + } + case 'Q': + switch (type.FullName) { + case "System.UInt64": + return true; + case "System.nint": // check + case "System.nuint": + return IntPtr.Size == 8; + default: + return type.IsEnum && TypeSize (type) == 8; + } + case 's': + return type.FullName == "System.Int16"; + // unsigned 16 bits + case 'S': + switch (type.FullName) { + case "System.UInt16": + // NSString 'instance Char _characterAtIndex(Int32)' selector: characterAtIndex: == S12@0:4I8 + case "System.Char": + return true; + default: + return type.IsEnum && TypeSize (type) == 2; + } + case ':': + return type.Name == "Selector"; + case 'v': + return type.FullName == "System.Void"; + case '?': + return type.BaseType.FullName == "System.MulticastDelegate"; // completion handler -> delegate + case '#': + return type.FullName == "System.IntPtr" || type.Name == "Class"; + // CAMediaTimingFunction 'instance Void GetControlPointAtIndex(Int32, IntPtr)' selector: getControlPointAtIndex:values: == v16@0:4L8[2f]12 + case '[': + return type.FullName == "System.IntPtr"; + // const uint8_t * -> IntPtr + // NSCoder 'instance Void EncodeBlock(IntPtr, Int32, System.String)' selector: encodeBytes:length:forKey: == v20@0:4r*8I12@16 + case '*': + return type.FullName == "System.IntPtr"; + case '^': + return type.FullName == "System.IntPtr"; + } + return false; + } + } +} diff --git a/tests/bindings/ApiStructTest.cs b/tests/bindings/ApiStructTest.cs new file mode 100644 index 000000000000..de06a491f7b8 --- /dev/null +++ b/tests/bindings/ApiStructTest.cs @@ -0,0 +1,95 @@ +// +// ApiStructTest.cs: enforce structure definitions +// +// Authors: +// Aaron Bockover +// +// Copyright 2013 Xamarin, Inc. + +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +#elif MONOMAC +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +#endif + +namespace TouchUnit.Bindings +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class ApiStructTest : ApiBaseTest + { + public ApiStructTest () + { + ContinueOnFailure = true; + LogProgress = true; + } + + protected virtual bool Skip (Type type) + { + return SkipDueToAttribute (type); + } + + [Test] + public void Structs () + { + int totalStructs = 0; + int totalErrors = 0; + + var structQuery = from type in Assembly.GetTypes () + where type.IsValueType && !type.IsPrimitive && !type.IsEnum && !Skip (type) + select type; + + foreach (var type in structQuery) { + totalStructs++; + if (!CheckStruct (type)) { + totalErrors++; + + if (!ContinueOnFailure) + break; + } + } + + Assert.AreEqual (0, totalErrors, + "{0} errors found in {1} structures validated", + totalErrors, totalStructs); + } + + protected virtual bool CheckStruct (Type type) + { + var success = true; + + foreach (var fi in type.GetFields ()) { + if (!CheckField (type, fi)) + success = false; + } + + return success; + } + + protected virtual bool CheckField (Type type, FieldInfo fi) + { +#if XAMCORE_2_0 + if (fi.FieldType.IsEnum && fi.FieldType.GetCustomAttribute () != null) { + if (LogProgress) + Console.Error.WriteLine ("{0} has a [Native] enum field in its definition: {1} {2}", + type.FullName, fi.FieldType, fi.Name); + return false; + } +#endif + return true; + } + } +} + diff --git a/tests/bindings/ApiWeakPropertyTest.cs b/tests/bindings/ApiWeakPropertyTest.cs new file mode 100644 index 000000000000..4c07b26a5d95 --- /dev/null +++ b/tests/bindings/ApiWeakPropertyTest.cs @@ -0,0 +1,110 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + [Preserve (AllMembers = true)] + public abstract class ApiWeakPropertyTest : ApiBaseTest { + + /// + /// Override if you want to skip testing the specified type. + /// + /// Type to be tested + protected virtual bool Skip (Type type) + { + switch (type.Name) { + case "LinkWithAttribute": // LinkWithAttribute.WeakFrameworks + return true; + } + return false; + } + + /// + /// Override if you want to skip testing the specified property. + /// + /// Property candidate. + protected virtual bool Skip (PropertyInfo property) + { + return false; + } + + [Test] + public void WeakPropertiesHaveArgumentSemantic () + { + var failed_properties = new List (); + + Errors = 0; + int c = 0, n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, t.FullName); + + foreach (var p in t.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { + // looking for properties with setters only + if (!p.CanWrite) + continue; + + if (SkipDueToAttribute (p)) + continue; + + if (Skip (p)) + continue; + + string name = p.Name; + if (!name.StartsWith ("Weak")) + continue; + + string error; + if (CheckArgumentSemantic (p.GetMethod, out error)) { + ReportError (error); + failed_properties.Add (p.ToString ()); + } + if (CheckArgumentSemantic (p.SetMethod, out error)) { + ReportError (error); + failed_properties.Add (p.ToString ()); + } + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_properties)); + } + + bool CheckArgumentSemantic (MethodInfo meth, out string error) + { + error = null; + var export = meth.GetCustomAttribute (); + if (export == null) { + error = String.Format ("{0}.{1} has no [Export]", meth.DeclaringType.FullName, meth.Name); + return true; + } + + switch (export.ArgumentSemantic) { + case ArgumentSemantic.Assign: // Also case ArgumentSemantic.UnsafeUnretained: + case ArgumentSemantic.Copy: + case ArgumentSemantic.Retain: // case ArgumentSemantic.Strong: + case ArgumentSemantic.Weak: + return false; + default: + error = String.Format ("{0}.{1} has incorrect ArgumentSemantics: {2}", meth.DeclaringType.FullName, meth.Name, export.ArgumentSemantic); + return true; + } + } + } +} \ No newline at end of file diff --git a/tests/bindings/CoreSelectorTest.cs b/tests/bindings/CoreSelectorTest.cs new file mode 100644 index 000000000000..12204505a3a9 --- /dev/null +++ b/tests/bindings/CoreSelectorTest.cs @@ -0,0 +1,130 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + + public abstract class CoreSelectorTest : ApiSelectorTest { + + protected override bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + if (value) + return true; + + var declaredType = method.DeclaringType; + + switch (name) { + // optional stuff defined in NSObject (but not implemented by every subclasses) + case "encodeWithCoder:": + case "objectDidEndEditing:": + case "commitEditing": + case "commitEditingWithDelegate:didCommitSelector:contextInfo:": + if (declaredType.Name == "NSObject") + return true; + break; + // internal stuff that must be used + case "_setCFClientFlags:callback:context:": + case "_scheduleInCFRunLoop:forMode:": + case "_unscheduleFromCFRunLoop:forMode:": + // init* works (see monotouchtest.app) but does not respond when queried + case "initWithFileAtPath:": + case "initWithData:": + case "initWithURL:": + if (declaredType.Name == "NSInputStream") + return true; + break; + // init* works (see monotouchtest.app) but does not respond when queried + case "initToMemory": + case "initToFileAtPath:append:": + if (declaredType.Name == "NSOutputStream") + return true; + break; + // init* works (see monotouchtest.app) but does not respond when queried + case "initWithFileDescriptor:": + case "initWithFileDescriptor:closeOnDealloc:": + if (declaredType.Name == "NSFileHandle") + return true; + break; + case "initWithString:": + case "initWithString:attributes:": + case "initWithAttributedString:": + if (declaredType.Name == "NSAttributedString" || declaredType.Name == "NSMutableAttributedString") + return true; + break; + } + return base.CheckResponse (value, actualType, method, ref name); + } + + protected override bool Skip (Type type) + { + switch (type.Name) { + case "MTLRenderPassAttachmentDescriptor": + // This is an abstract(-ish...) type, iOS allows creating an instance of it, but the instance doesn't respond to most of the selector in the headers. + return true; + } + + return base.Skip (type); + } + + protected override IntPtr GetClassForType (Type type) + { + switch (type.Namespace) { + case "MonoTouch.Metal": + case "MonoMac.Metal": + case "Metal": + switch (type.Name) { + case "MTLArgument": + case "MTLArrayType": + case "MTLCompileOptions": + case "MTLComputePipelineDescriptor": + case "MTLComputePipelineReflection": + case "MTLDepthStencilDescriptor": + case "MTLRenderPassAttachmentDescriptor": + case "MTLRenderPassColorAttachmentDescriptor": + case "MTLRenderPassDepthAttachmentDescriptor": + case "MTLRenderPassDescriptor": + case "MTLRenderPassStencilAttachmentDescriptor": + case "MTLRenderPipelineColorAttachmentDescriptor": + case "MTLRenderPipelineDescriptor": + case "MTLRenderPipelineReflection": + case "MTLSamplerDescriptor": + case "MTLStencilDescriptor": + case "MTLStructMember": + case "MTLStructType": + case "MTLTextureDescriptor": + case "MTLVertexAttribute": + case "MTLVertexAttributeDescriptor": + case "MTLVertexBufferLayoutDescriptor": + case "MTLVertexDescriptor": + var ctor = type.GetConstructor (Type.EmptyTypes); + using (var obj = ctor.Invoke (null) as NSObject) { + return IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("class")); + } + } + break; + } + + return base.GetClassForType (type); + } + } +} diff --git a/tests/bindings/PlatformInfo.cs b/tests/bindings/PlatformInfo.cs new file mode 100644 index 000000000000..391865f997fd --- /dev/null +++ b/tests/bindings/PlatformInfo.cs @@ -0,0 +1,151 @@ +// +// PlatformInfo.cs: info about the host platform +// and AvailabilityBaseAttribute extensions for tests +// +// Author: +// Aaron Bockover +// +// Copyright 2015 Xamarin Inc. All rights reserved. + +using System; +using System.Linq; +using System.Reflection; +using System.Collections.Generic; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +#if !MONOMAC +using UIKit; +#endif +#elif MONOMAC +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace TouchUnit.Bindings +{ + public sealed class PlatformInfo + { + static PlatformInfo GetHostPlatformInfo () + { + string name; + string version; +#if __TVOS__ || __IOS__ + name = UIDevice.CurrentDevice.SystemName; + version = UIDevice.CurrentDevice.SystemVersion; +#elif __WATCHOS__ + name = WatchKit.WKInterfaceDevice.CurrentDevice.SystemName; + version = WatchKit.WKInterfaceDevice.CurrentDevice.SystemVersion; +#elif MONOMAC + using (var plist = NSDictionary.FromFile ("/System/Library/CoreServices/SystemVersion.plist")) { + name = (NSString)plist ["ProductName"]; + version = (NSString)plist ["ProductVersion"]; + } +#else +#error Unknown platform +#endif + name = name?.Replace (" ", String.Empty)?.ToLowerInvariant (); + + var platformInfo = new PlatformInfo (); + + if (name != null && name.StartsWith ("mac", StringComparison.Ordinal)) + platformInfo.Name = PlatformName.MacOSX; + else if (name != null && (name.StartsWith ("ios", StringComparison.Ordinal) || name.StartsWith ("iphoneos", StringComparison.Ordinal))) + platformInfo.Name = PlatformName.iOS; + else if (name != null && name.StartsWith ("tvos", StringComparison.Ordinal)) + platformInfo.Name = PlatformName.TvOS; + else if (name != null && name.StartsWith ("watchos", StringComparison.Ordinal)) + platformInfo.Name = PlatformName.WatchOS; + else + throw new FormatException ($"Unknown product name: {name}"); + + platformInfo.Version = Version.Parse (version); + + if (IntPtr.Size == 4) + platformInfo.Architecture = PlatformArchitecture.Arch32; + else if (IntPtr.Size == 8) + platformInfo.Architecture = PlatformArchitecture.Arch64; + + return platformInfo; + } + + public static readonly PlatformInfo Host = GetHostPlatformInfo (); + + public PlatformName Name { get; private set; } + public PlatformArchitecture Architecture { get; private set; } + public Version Version { get; private set; } + + public bool IsMac => Name == PlatformName.MacOSX; + public bool IsIos => Name == PlatformName.iOS; + public bool IsArch32 => Architecture.HasFlag (PlatformArchitecture.Arch32); + public bool IsArch64 => Architecture.HasFlag (PlatformArchitecture.Arch64); + + PlatformInfo () + { + } + } + + public static class AvailabilityExtensions + { + public static bool IsAvailableOnHostPlatform (this ICustomAttributeProvider attributeProvider) + { + return attributeProvider.IsAvailable (PlatformInfo.Host); + } + + public static bool IsAvailable (this ICustomAttributeProvider attributeProvider, PlatformInfo targetPlatform) + { + return attributeProvider + .GetCustomAttributes (true) + .OfType () + .IsAvailable (targetPlatform); + } + + public static bool IsAvailableOnHostPlatform (this IEnumerable attributes) + { + return attributes.IsAvailable (PlatformInfo.Host); + } + + public static bool IsAvailable (this IEnumerable attributes, PlatformInfo targetPlatform) + { + // always "available" from a binding perspective if + // there are no explicit annotations saying otherwise + var available = true; + + foreach (var attr in attributes) { + if (attr.Platform != targetPlatform.Name) + continue; + + switch (attr.AvailabilityKind) { + case AvailabilityKind.Introduced: + if (attr.Version != null) + available &= targetPlatform.Version >= attr.Version; + + if (attr.Architecture != PlatformArchitecture.None && + attr.Architecture != PlatformArchitecture.All) + available &= attr.Architecture.HasFlag (targetPlatform.Architecture); + break; + case AvailabilityKind.Deprecated: + case AvailabilityKind.Obsoleted: + if (attr.Version != null) + available &= targetPlatform.Version < attr.Version; + // FIXME: handle architecture-level _un_availability? + // we didn't do this with the old AvailabilityAttribute... + break; + case AvailabilityKind.Unavailable: + available = false; + break; + } + + if (!available) + return false; + } + + return available; + } + } +} diff --git a/tests/bindings/README b/tests/bindings/README new file mode 100644 index 000000000000..47c3f09627c2 --- /dev/null +++ b/tests/bindings/README @@ -0,0 +1 @@ +Unit test helpers for developers of MonoTouch and Xamarin.Mac binding libraries \ No newline at end of file diff --git a/tests/common.mk b/tests/common.mk new file mode 100644 index 000000000000..6b3eecafeaaf --- /dev/null +++ b/tests/common.mk @@ -0,0 +1,76 @@ +MMP=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/bin/mmp $(MMP_VERBOSITY) + +.PRECIOUS: build/mobile-32.app build/mobile-64.app + +check-guiunit-xml: + @if test -f $(FILE); then \ + if grep 'One or more child tests had errors' $(FILE) > /dev/null; then \ + echo Test run failed; \ + exit 1; \ + fi; \ + echo Test run succeeded; \ + else \ + echo Test run crashed; \ + exit 1; \ + fi + +BASE_DLLS = $(TOP)/src/build/mac/compat/XamMac.dll \ + $(TOP)/src/build/mac/mobile-32/Xamarin.Mac.dll \ + $(TOP)/src/build/mac/mobile-64/Xamarin.Mac.dll + +all-local:: build/compat/$(TESTDLL) build/mobile-32/$(TESTDLL) build/mobile-64/$(TESTDLL) + +clean-local:: + rm -rf build TestResult*.xml + +build/%/$(TESTDLL): $(MAC_SOURCES) build/GuiUnit.exe Makefile $(BASE_DLLS) + @mkdir -p $(dir $@) + $(Q_MCS) $(SYSTEM_MCS) -out:$@ -t:library -debug -d:MONOMAC -d:XAMCORE_2_0 \ + -r:build/GuiUnit.exe \ + -r:$(TOP)/src/build/mac/$*/Xamarin.Mac.dll \ + $(MAC_SOURCES) + +build/compat/$(TESTDLL): $(MAC_SOURCES) build/GuiUnit.exe Makefile $(BASE_DLLS) + @mkdir -p $(dir $@) + $(Q_MCS) $(SYSTEM_MCS) -out:$@ -t:library -debug -d:MONOMAC \ + -r:build/GuiUnit.exe \ + -r:System.Drawing \ + -r:$(TOP)/src/build/mac/compat/XamMac.dll \ + $(MAC_SOURCES) + +build/compat.app: build/compat/$(TESTDLL) $(BASE_DLLS) + @rm -Rf $@ + $(Q) DEVELOPER_DIR=$(XCODE_DEVELOPER_ROOT) $(MMP) --output $(abspath build/compat.app) $(abspath build/GuiUnit.exe) -a $(TOP)/src/build/mac/compat/XamMac.dll --nolink --profile 4.5 --cache $(abspath build/compat-mmp-cache) --marshal-objectivec-exceptions=throwmanaged + +build/mobile-%.app: build/mobile-%/$(TESTDLL) $(BASE_DLLS) + @rm -Rf $@ + $(Q) DEVELOPER_DIR=$(XCODE_DEVELOPER_ROOT) $(MMP) --output $(abspath build/mobile-$*.app) $(abspath build/GuiUnit.exe) -a $(TOP)/src/build/mac/mobile-$*/Xamarin.Mac.dll --nolink --profile mobile --arch $(shell test '$*' == '32' && echo i386 || echo x86_64) --cache $(abspath build/mobile-$*-mmp-cache) --marshal-objectivec-exceptions=throwmanaged + +exec-compat: build/compat.app + @rm -f TestResult-compat.xml + build/compat.app/GuiUnit.app/Contents/MacOS/GuiUnit -noheader $(abspath build/compat/$(TESTDLL)) -xml:$(PWD)/TestResult-compat.xml + @test -z "$(BUILD_REVISION)" || echo @"MonkeyWrench: AddFile: $(abspath TestResult-compat.xml)" + @$(MAKE) check-guiunit-xml FILE=TestResult-compat.xml STAMP=.$@-failure.stamp + +exec-mobile-%: build/mobile-%.app + @rm -f TestResult-mobile-$*.xml .$@-failure.stamp + build/mobile-$*.app/GuiUnit.app/Contents/MacOS/GuiUnit -noheader $(abspath build/mobile-$*/$(TESTDLL)) -xml:$(PWD)/TestResult-mobile-$*.xml + @test -z "$(BUILD_REVISION)" || echo @"MonkeyWrench: AddFile: $(abspath TestResult-mobile-$*.xml)" + @$(MAKE) check-guiunit-xml FILE=TestResult-mobile-$*.xml STAMP=.$@-failure.stamp + +run-%: + @rm -f .$@-failure.stamp + @$(MAKE) exec-$* || echo "run-$* failed" >> .$@-failure.stamp + @if test -e .$@-failure.stamp; then cat .$@-failure.stamp; rm .$@-failure.stamp; exit 1; fi + +run run-test run-tests: build/compat.app build/mobile-32.app build/mobile-64.app + @rm -f .$@-failure.stamp + @$(MAKE) exec-compat || echo "run-compat failed" >> .$@-failure.stamp + @$(MAKE) exec-mobile-32 || echo "run-mobile-32 failed" >> .$@-failure.stamp + @$(MAKE) exec-mobile-64 || echo "run-mobile-64 failed" >> .$@-failure.stamp + @if test -e .$@-failure.stamp; then cat .$@-failure.stamp; rm .$@-failure.stamp; exit 1; fi + +build/GuiUnit.exe: $(shell find $(GUI_UNIT_PATH)/src/framework -name \*.cs -or -name \*.csproj) + @mkdir -p build + @$(SYSTEM_XBUILD) $(GUI_UNIT_PATH)/src/framework/GuiUnit_NET_4_5.csproj + @cp $(GUI_UNIT_PATH)/bin/net_4_5/GuiUnit.exe $@ diff --git a/tests/common/Assert.cs b/tests/common/Assert.cs new file mode 100644 index 000000000000..824d01b58152 --- /dev/null +++ b/tests/common/Assert.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Resources; +using System.Runtime.InteropServices; +using System.Diagnostics; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +using NUnit.Framework; +using NUnit.Framework.Constraints; + +namespace MonoTests { +/* + class CategoryAttribute : Attribute + { + public string Category { get; set; } + + public CategoryAttribute (string category) + { + this.Category = category; + } + } +/* + static class Assert + { + public static void AreEqual (object a, object b, string msg) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b), msg); + } + + public static void AreEqual (object a, object b) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b)); + } + + public static void IsNotNull (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.Not.Null, msg); + } + + public static void IsNotNull (object o) + { + NUnit.Framework.Assert.That (o, Is.Not.Null); + } + + public static void IsNull (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.Null, msg); + } + + public static void IsNull (object o) + { + NUnit.Framework.Assert.That (o, Is.Null); + } + + public static void IsTrue (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.True, msg); + } + + public static void IsTrue (object o) + { + NUnit.Framework.Assert.That (o, Is.True); + } + + public static void IsFalse (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.False, msg); + } + + public static void IsFalse (object o) + { + NUnit.Framework.Assert.That (o, Is.False); + } + + public static void AreSame (object a, object b) + { + NUnit.Framework.Assert.That (a, Is.SameAs (b)); + } + + public static void AreSame (object a, object b, string msg) + { + NUnit.Framework.Assert.That (a, Is.SameAs (b), msg); + } + + public static void Fail (string msg) + { + NUnit.Framework.Assert.Fail (msg); + } + } +*/ + // nunit 1.x compatibility + public class TestCase { + protected virtual void SetUp () + { + } + + public static void Assert (string msg, bool condition) + { + NUnit.Framework.Assert.True (condition, msg); + } + + public static void AssertEquals (object a, object b) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b)); + } + + public static void AssertEquals (string msg, object a, object b) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b), msg); + } + + public static void AssertNull (object a) + { + NUnit.Framework.Assert.That (a, Is.Null); + } + + public static void AssertNull (string msg, object a) + { + NUnit.Framework.Assert.That (a, Is.Null, msg); + } + + public static void AssertNotNull (object a) + { + NUnit.Framework.Assert.That (a, Is.Not.Null); + } + + public static void AssertNotNull (string msg, object a) + { + NUnit.Framework.Assert.That (a, Is.Not.Null, msg); + } + + public static void Fail (string msg) + { + NUnit.Framework.Assert.Fail (msg); + } + } + + public class Assertion : TestCase { + } + + public class TestFixtureSetUpAttribute : SetUpAttribute { + } + + public class StringAssert { + #region StartsWith + static public void StartsWith(string expected, string actual, string message, params object[] args) + { + Assert.That(actual, new StartsWithConstraint(expected), message, args); + } + + static public void StartsWith(string expected, string actual, string message) + { + StartsWith(expected, actual, message, null); + } + + static public void StartsWith(string expected, string actual) + { + StartsWith(expected, actual, string.Empty, null); + } + #endregion + + #region Contains + static public void Contains(string expected, string actual, string message, params object[] args) + { + Assert.That(actual, new SubstringConstraint(expected), message, args); + } + + static public void Contains(string expected, string actual, string message) + { + Contains(expected, actual, message, null); + } + + static public void Contains(string expected, string actual) + { + Contains(expected, actual, string.Empty, null); + } + #endregion + } +} + diff --git a/tests/common/AssertHelpers.cs b/tests/common/AssertHelpers.cs new file mode 100644 index 000000000000..35c7ee5ba6e4 --- /dev/null +++ b/tests/common/AssertHelpers.cs @@ -0,0 +1,70 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; + +using NUnit.Framework; + +namespace Xamarin.Tests +{ + public delegate void Action (); + + public static class Asserts + { + public static void Throws (Action action, string expectedExceptionMessage, string message = "") where T: Exception + { + try { + action (); + throw new AssertionException (string.Format ("Expected {0}, but no exception was thrown. {1}.", typeof (T).FullName, message)); + } catch (T ex) { + Assert.AreEqual (expectedExceptionMessage, ex.Message, message); + } + } + + public static void ThrowsPartial (Action action, string [] expectedExceptionMessages, string message = "") where T: Exception + { + try { + action (); + throw new AssertionException (string.Format ("Expected {0}, but no exception was thrown. {1}.", typeof (T).FullName, message)); + } catch (T ex) { + string [] actual = ex.Message.Split (new string [] { Environment.NewLine }, StringSplitOptions.None); + for (int i = 0; i < expectedExceptionMessages.Length; i++) + StartsWith (expectedExceptionMessages [i], actual [i], i.ToString ()); + } + } + + public static void ThrowsPattern (Action action, string expectedExceptionPattern, string message = "") where T: Exception + { + try { + action (); + throw new AssertionException (string.Format ("Expected {0}, but no exception was thrown. {1}.", typeof (T).FullName, message)); + } catch (T ex) { + IsLike (expectedExceptionPattern, ex.Message, message); + } + } + + public static void StartsWith (string expectedStartsWith, string actual, string message) + { + if (!actual.StartsWith (expectedStartsWith)) + throw new AssertionException (string.Format ("Expected '{0}' to start with '{1}'. {2}", actual, expectedStartsWith, message)); + } + + public static void IsLike (string pattern, string actual, string message) + { + if (!Regex.IsMatch (actual, pattern, RegexOptions.CultureInvariant)) + throw new AssertionException (string.Format ("Expected '{0}' to match pattern '{1}'. {2}", actual, pattern, message)); + } + + public static void Contains (string expectedToContain, string actual, string message) + { + if (!actual.Contains (expectedToContain)) + throw new AssertionException (string.Format ("Expected '{0}' to contain '{1}'. {2}", actual, expectedToContain, message)); + } + + public static void DoesNotContain (string expectedToNotContain, string actual, string message) + { + if (actual.Contains (expectedToNotContain)) + throw new AssertionException (string.Format ("Did not expect '{0}' to contain '{1}'. {2}", actual, expectedToNotContain, message)); + } + } +} + diff --git a/tests/common/ExecutionHelper.cs b/tests/common/ExecutionHelper.cs new file mode 100644 index 000000000000..19c1fc2bdbd4 --- /dev/null +++ b/tests/common/ExecutionHelper.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Diagnostics; + +using NUnit.Framework; + +namespace Xamarin.Tests +{ + class ToolMessage + { + public bool IsError; + public bool IsWarning { get { return !IsError; } } + public string Prefix; + public int Number; + public string PrefixedNumber { get { return Prefix + Number.ToString (); } } + public string Message; + // public string Filename; + // public int LineNumber; + } + + class Tool + { + StringBuilder output = new StringBuilder (); + + List output_lines; + + List messages = new List (); + + public Dictionary EnvironmentVariables { get; set; } + public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds (60); + + public IEnumerable Messages { get { return messages; } } + List OutputLines { + get { + if (output_lines == null) { + output_lines = new List (); + output_lines.AddRange (output.ToString ().Split ('\n')); + } + return output_lines; + } + } + + public int Execute (string arguments, params string [] args) + { + output.Clear (); + output_lines = null; + + var rv = ExecutionHelper.Execute (TestTarget.ToolPath, string.Format (arguments, args), EnvironmentVariables, output, output); + + if (rv != 0) { + if (output.Length > 0) + Console.WriteLine (output); + } + + ParseMessages (); + + return rv; + } + + void ParseMessages () + { + messages.Clear (); + + foreach (var l in output.ToString ().Split ('\n')) { + var line = l; + var msg = new ToolMessage (); + if (line.StartsWith ("error ", StringComparison.Ordinal)) { + msg.IsError = true; + line = line.Substring (6); + } else if (line.StartsWith ("warning ", StringComparison.Ordinal)) { + msg.IsError = false; + line = line.Substring (8); + } else { + // something else + continue; + } + if (line.Length < 7) + continue; // something else + msg.Prefix = line.Substring (0, 2); + if (!int.TryParse (line.Substring (2, 4), out msg.Number)) + continue; // something else + msg.Message = line.Substring (8); + + messages.Add (msg); + } + } + + public bool HasErrorPattern (string prefix, int number, string messagePattern) + { + foreach (var msg in messages) { + if (msg.IsError && msg.Prefix == prefix && msg.Number == number && Regex.IsMatch (msg.Message, messagePattern)) + return true; + } + return false; + } + + public bool HasError (string prefix, int number, string message) + { + foreach (var msg in messages) { + if (msg.IsError && msg.Prefix == prefix && msg.Number == number && msg.Message == message) + return true; + } + return false; + } + + public void AssertErrorPattern (int number, string messagePattern) + { + AssertErrorPattern ("MT", number, messagePattern); + } + + public void AssertErrorPattern (string prefix, int number, string messagePattern) + { + if (!messages.Any ((msg) => msg.Prefix == prefix && msg.Number == number)) + Assert.Fail (string.Format ("The error '{0}{1:0000}' was not found in the output.", prefix, number)); + + if (messages.Any ((msg) => Regex.IsMatch (msg.Message, messagePattern))) + return; + + var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && !Regex.IsMatch (msg.Message, messagePattern)).Select ((msg) => string.Format ("\tThe message '{0}' did not match the pattern '{1}'.", msg.Message, messagePattern)); + Assert.Fail (string.Format ("The error '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, messagePattern, string.Join ("\n", details.ToArray ()))); + } + + public void AssertError (int number, string message) + { + AssertError ("MT", number, message); + } + + public void AssertError (string prefix, int number, string message) + { + if (!messages.Any ((msg) => msg.Prefix == prefix && msg.Number == number)) + Assert.Fail (string.Format ("The error '{0}{1:0000}' was not found in the output.", prefix, number)); + + if (messages.Any ((msg) => msg.Message == message)) + return; + + var details = messages.Where ((msg) => msg.Prefix == prefix && msg.Number == number && msg.Message != message).Select ((msg) => string.Format ("\tMessage #{2} did not match:\n\t\tactual: '{0}'\n\t\texpected: '{1}'", msg.Message, message, messages.IndexOf (msg) + 1)); + Assert.Fail (string.Format ("The error '{0}{1:0000}: {2}' was not found in the output:\n{3}", prefix, number, message, string.Join ("\n", details.ToArray ()))); + } + + public bool HasOutput (string line) + { + return OutputLines.Contains (line); + } + + public bool HasOutputPattern (string linePattern) + { + foreach (var line in OutputLines) { + if (Regex.IsMatch (line, linePattern, RegexOptions.CultureInvariant)) + return true; + } + + return false; + } + + public void AssertOutputPattern (string linePattern) + { + if (!HasOutputPattern (linePattern)) + Assert.Fail (string.Format ("The output does not contain the line '{0}'", linePattern)); + } + } + + class XBuild + { + public static string ToolPath { + get + { + return "/Library/Frameworks/Mono.framework/Commands/xbuild"; + } + } + + public static void Build (string project, string configuration = "Debug", string platform = "iPhoneSimulator", string verbosity = null) + { + ExecutionHelper.Execute (ToolPath, string.Format ("/p:Configuration={0} /p:Platform={1} {2} \"{3}\"", configuration, platform, verbosity == null ? string.Empty : "/verbosity:" + verbosity, project)); + } + } + + static class ExecutionHelper { + static int Execute (ProcessStartInfo psi, StringBuilder stdout, StringBuilder stderr, TimeSpan? timeout = null) + { + var watch = new Stopwatch (); + watch.Start (); + + try { + psi.UseShellExecute = false; + psi.RedirectStandardError = true; + psi.RedirectStandardOutput = true; + Console.WriteLine ("{0} {1}", psi.FileName, psi.Arguments); + using (var p = new Process ()) { + p.StartInfo = psi; + // mtouch/mmp writes UTF8 data outside of the ASCII range, so we need to make sure + // we read it in the same format. This also means we can't use the events to get + // stdout/stderr, because mono's Process class parses those using Encoding.Default. + p.StartInfo.StandardOutputEncoding = Encoding.UTF8; + p.StartInfo.StandardErrorEncoding = Encoding.UTF8; + p.Start (); + + var outReader = new Thread (() => + { + string l; + while ((l = p.StandardOutput.ReadLine ()) != null) { + lock (stdout) + stdout.AppendLine (l); + } + }) + { + IsBackground = true, + }; + outReader.Start (); + + var errReader = new Thread (() => + { + string l; + while ((l = p.StandardError.ReadLine ()) != null) { + lock (stderr) + stderr.AppendLine (l); + } + }) + { + IsBackground = true, + }; + errReader.Start (); + + if (timeout == null) + timeout = TimeSpan.FromMinutes (5); + if (!p.WaitForExit ((int) timeout.Value.TotalMilliseconds)) { + Console.WriteLine ("Command didn't finish in {0} minutes:", timeout.Value.TotalMinutes); + Console.WriteLine ("{0} {1}", p.StartInfo.FileName, p.StartInfo.Arguments); + Console.WriteLine ("Will now kill the process"); + kill (p.Id, 9); + if (!p.WaitForExit (1000 /* killing should be fairly quick */)) { + Console.WriteLine ("Kill failed to kill in 1 second !?"); + return 1; + } + } + + outReader.Join (TimeSpan.FromSeconds (1)); + errReader.Join (TimeSpan.FromSeconds (1)); + + return p.ExitCode; + } + } finally { + Console.WriteLine ("{0} Executed in {1}: {2} {3}", DateTime.Now, watch.Elapsed.ToString (), psi.FileName, psi.Arguments); + } + } + + public static int Execute (string fileName, string arguments, out string output, TimeSpan? timeout = null) + { + var sb = new StringBuilder (); + var psi = new ProcessStartInfo (); + psi.FileName = fileName; + psi.Arguments = arguments; + var rv = Execute (psi, sb, sb, timeout); + output = sb.ToString (); + return rv; + } + + public static int Execute (string fileName, string arguments, Dictionary environmentVariables, StringBuilder stdout, StringBuilder stderr, TimeSpan? timeout = null) + { + if (stdout == null) + stdout = new StringBuilder (); + if (stderr == null) + stderr = new StringBuilder (); + + var psi = new ProcessStartInfo (); + psi.FileName = fileName; + psi.Arguments = arguments; + if (environmentVariables != null) { + var envs = psi.EnvironmentVariables; + foreach (var kvp in environmentVariables) { + if (envs.ContainsKey (kvp.Key)) + envs [kvp.Key] += ":" + kvp.Value; + else + envs.Add (kvp.Key, kvp.Value); + } + } + + return Execute (psi, stdout, stderr, timeout); + } + + [DllImport ("libc")] + private static extern void kill (int pid, int sig); + + public static string Execute (string fileName, string arguments, bool throwOnError = true, Dictionary environmentVariables = null, + bool hide_output = false + ) + { + StringBuilder output = new StringBuilder (); + int exitCode = Execute (fileName, arguments, environmentVariables, output, output); + if (!hide_output) { + Console.WriteLine ("{0} {1}", fileName, arguments); + Console.WriteLine (output); + } + if (throwOnError && exitCode != 0) + throw new TestExecutionException (output.ToString ()); + return output.ToString (); + } + } + + class TestExecutionException : Exception { + public TestExecutionException (string output) + : base (output) + { + } + } +} diff --git a/tests/common/mac/ApiDefinition.cs b/tests/common/mac/ApiDefinition.cs new file mode 100644 index 000000000000..049583b57371 --- /dev/null +++ b/tests/common/mac/ApiDefinition.cs @@ -0,0 +1,68 @@ +using System; + +using AppKit; +using Foundation; +using ObjCRuntime; +using CoreGraphics; + +namespace ExampleBinding +{ + // The first step to creating a binding is to add your native library ("libNativeLibrary.a") + // to the project by right-clicking (or Control-clicking) the folder containing this source + // file and clicking "Add files..." and then simply select the native library (or libraries) + // that you want to bind. + // + // When you do that, you'll notice that MonoDevelop generates a code-behind file for each + // native library which will contain a [LinkWith] attribute. MonoDevelop auto-detects the + // architectures that the native library supports and fills in that information for you, + // however, it cannot auto-detect any Frameworks or other system libraries that the + // native library may depend on, so you'll need to fill in that information yourself. + // + // Once you've done that, you're ready to move on to binding the API... + // + // + // Here is where you'd define your API definition for the native Objective-C library. + // + // For example, to bind the following Objective-C class: + // + // @interface Widget : NSObject { + // } + // + // The C# binding would look like this: + // + // [BaseType (typeof (NSObject))] + // interface Widget { + // } + // + // To bind Objective-C properties, such as: + // + // @property (nonatomic, readwrite, assign) CGPoint center; + // + // You would add a property definition in the C# interface like so: + // + // [Export ("center")] + // CGPoint Center { get; set; } + // + // To bind an Objective-C method, such as: + // + // -(void) doSomething:(NSObject *)object atIndex:(NSInteger)index; + // + // You would add a method definition to the C# interface like so: + // + // [Export ("doSomething:atIndex:")] + // void DoSomething (NSObject object, int index); + // + // Objective-C "constructors" such as: + // + // -(id)initWithElmo:(ElmoMuppet *)elmo; + // + // Can be bound as: + // + // [Export ("initWithElmo:")] + // IntPtr Constructor (ElmoMuppet elmo); + // + // For more information, see http://developer.xamarin.com/guides/ios/advanced_topics/binding_objective-c/ + // +%CODE% +} + diff --git a/tests/common/mac/BindingProjectWithNoTag.csproj b/tests/common/mac/BindingProjectWithNoTag.csproj new file mode 100644 index 000000000000..2b10757338ff --- /dev/null +++ b/tests/common/mac/BindingProjectWithNoTag.csproj @@ -0,0 +1,40 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {ED1B29DD-8FCB-48D4-A0E1-BE98446C9C53} + Library + BindingProjectWithNoTag + Resources + BindingProjectWithNoTag + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false +%CODE% + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/ClassicExample.csproj b/tests/common/mac/ClassicExample.csproj new file mode 100644 index 000000000000..3d304c4b3ccc --- /dev/null +++ b/tests/common/mac/ClassicExample.csproj @@ -0,0 +1,49 @@ + + + + Debug + AnyCPU + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {70E29818-C77A-477D-B394-E9F8B03F2C1B} + Exe + ClassicExample + Resources + ClassicExample + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + false + Mac Developer + false + false +%CODE% + + + + + + + + + + + + + + + + + + + + diff --git a/tests/common/mac/Component1.fs b/tests/common/mac/Component1.fs new file mode 100644 index 000000000000..36da391d07be --- /dev/null +++ b/tests/common/mac/Component1.fs @@ -0,0 +1,3 @@ +namespace FSharpXM45Library +type Class1() = + member this.X = "F#" diff --git a/tests/common/mac/FSharpUnifiedExample.fsproj b/tests/common/mac/FSharpUnifiedExample.fsproj new file mode 100644 index 000000000000..10eb5fb828a1 --- /dev/null +++ b/tests/common/mac/FSharpUnifiedExample.fsproj @@ -0,0 +1,48 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{F2A71F9B-5D33-465A-A702-920D77279786} + {517BFCB9-A89A-45E4-810A-4BDCBE451CF7} + Exe + FSharpUnifiedExample + Resources + FSharpUnifiedExample + v2.0 + Xamarin.Mac + + + true + false + bin\Debug + DEBUG + prompt + true + true + true + false + false + false + Mac Developer + false + false + + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/FSharpUnifiedLibrary.fsproj b/tests/common/mac/FSharpUnifiedLibrary.fsproj new file mode 100644 index 000000000000..58625d9e4579 --- /dev/null +++ b/tests/common/mac/FSharpUnifiedLibrary.fsproj @@ -0,0 +1,50 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{F2A71F9B-5D33-465A-A702-920D77279786} + {5318A97A-4738-4BBF-973D-CC6CD93AA973} + Library + FSharpUnifiedLibrary + Resources + FSharpUnifiedLibrary + v2.0 + Xamarin.Mac + + + true + false + bin\Debug + DEBUG + prompt + false + false + false + false + false + false + false + false + + + + + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/FSharpXM45Example.fsproj b/tests/common/mac/FSharpXM45Example.fsproj new file mode 100644 index 000000000000..515f04c53c4b --- /dev/null +++ b/tests/common/mac/FSharpXM45Example.fsproj @@ -0,0 +1,47 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{F2A71F9B-5D33-465A-A702-920D77279786} + {1C0E1136-9F26-4C13-A049-7839D5ABB4FF} + Exe + FSharpXM45Example + Resources + FSharpXM45Example + true + + + true + false + bin\Debug + DEBUG + prompt + true + true + true + false + false + false + Mac Developer + false + false + + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/FSharpXM45Library.fsproj b/tests/common/mac/FSharpXM45Library.fsproj new file mode 100644 index 000000000000..fe498972daa9 --- /dev/null +++ b/tests/common/mac/FSharpXM45Library.fsproj @@ -0,0 +1,49 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{F2A71F9B-5D33-465A-A702-920D77279786} + {3C11EFFC-888C-4D8F-8133-F6B2947EBEE7} + Library + FSharpXM45Library + Resources + FSharpXM45Library + true + + + true + false + bin\Debug + DEBUG + prompt + false + false + false + false + false + false + false + false + + + + + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/Finder/Entitlements.plist b/tests/common/mac/Finder/Entitlements.plist new file mode 100644 index 000000000000..ffef54421f6d --- /dev/null +++ b/tests/common/mac/Finder/Entitlements.plist @@ -0,0 +1,11 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + + diff --git a/tests/common/mac/Finder/FinderExtensionTest.csproj b/tests/common/mac/Finder/FinderExtensionTest.csproj new file mode 100644 index 000000000000..8e5fcb31ae03 --- /dev/null +++ b/tests/common/mac/Finder/FinderExtensionTest.csproj @@ -0,0 +1,64 @@ + + + + Debug + AnyCPU + {B20EB7A2-A5ED-4CB9-95B3-58209092BF69} + {889C2465-30A1-4310-B175-96B1F4D843DE};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + FinderExtensionTest + FinderExtensionTest + v2.0 + Xamarin.Mac + Resources + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + Mac Developer + false + false + false + true + true + true + + + true + bin\Release + prompt + 4 + false + true + Developer ID Application + true + false + true + true + true + SdkOnly + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/common/mac/Finder/FinderSync.cs b/tests/common/mac/Finder/FinderSync.cs new file mode 100644 index 000000000000..b9fdb6c71377 --- /dev/null +++ b/tests/common/mac/Finder/FinderSync.cs @@ -0,0 +1,51 @@ +using AppKit; +using FinderSync; +using Foundation; +using Social; + +namespace FinderExtensionTest +{ + [Register ("FinderSync")] + public partial class FinderSync : FIFinderSync + { + public override void BeginRequestWithExtensionContext (NSExtensionContext context) + { + } + + public override NSMenu GetMenu (FIMenuKind menuKind) + { + NSMenu menu = new NSMenu (""); + menu.AddItem ("Menu Item from C#", new ObjCRuntime.Selector ("sampleAction:"), ""); + return menu; + } + + public override string ToolbarItemName + { + get + { + return "FinderExtension"; + } + } + + public override string ToolbarItemToolTip + { + get + { + return "FinderExtension: Click the toolbar item for a menu."; + } + } + + public override NSImage ToolbarItemImage + { + get + { + return NSImage.ImageNamed (NSImageName.Caution); + } + } + + [Export ("sampleAction:")] + public void Action (NSObject sender) + { + } + } +} diff --git a/tests/common/mac/Finder/Info.plist b/tests/common/mac/Finder/Info.plist new file mode 100644 index 000000000000..f8dba6737849 --- /dev/null +++ b/tests/common/mac/Finder/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + FinderSyncExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.your-company.FinderExtensionTest + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.10 + LSUIElement + + NSExtension + + NSExtensionAttributes + + NSExtensionPointIdentifier + com.apple.FinderSync + NSExtensionPrincipalClass + FinderSync + + NSPrincipalClass + NSApplication + + + diff --git a/tests/common/mac/Info-Classic.plist b/tests/common/mac/Info-Classic.plist new file mode 100644 index 000000000000..0e6cda3d6dd0 --- /dev/null +++ b/tests/common/mac/Info-Classic.plist @@ -0,0 +1,21 @@ + + + + + CFBundleDisplayName + ClassicExample + CFBundleIdentifier + com.your-company.ClassicExample + CFBundleName + ClassicExample + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + + diff --git a/tests/common/mac/Info-Unified.plist b/tests/common/mac/Info-Unified.plist new file mode 100644 index 000000000000..265bfd98045b --- /dev/null +++ b/tests/common/mac/Info-Unified.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDisplayName + UnifiedExample + CFBundleDevelopmentRegion + en + CFBundleIconFile + + CFBundleIdentifier + com.your-company.UnifiedExample + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + UnifiedExample + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSHumanReadableCopyright + donblas + NSPrincipalClass + NSApplication + + diff --git a/tests/common/mac/MacTestMain.cs b/tests/common/mac/MacTestMain.cs index ac20b4908c97..c141ae33b6e9 100644 --- a/tests/common/mac/MacTestMain.cs +++ b/tests/common/mac/MacTestMain.cs @@ -32,22 +32,22 @@ static void RunTests() class NSRunLoopIntegration : NSObject, IMainLoopIntegration { - public void InitializeToolkit () + public void InitializeToolkit() { } - public void RunMainLoop () + public void RunMainLoop() { } - - public void InvokeOnMainLoop (InvokerHelper helper) + + public void InvokeOnMainLoop(InvokerHelper helper) { - NSApplication.SharedApplication.InvokeOnMainThread (helper.Invoke); + NSApplication.SharedApplication.InvokeOnMainThread(helper.Invoke); } - public void Shutdown () + public void Shutdown() { - Environment.Exit (TestRunner.ExitCode); + Environment.Exit(TestRunner.ExitCode); } } } diff --git a/tests/common/mac/MobileBinding.csproj b/tests/common/mac/MobileBinding.csproj new file mode 100644 index 000000000000..b5f8fe145e34 --- /dev/null +++ b/tests/common/mac/MobileBinding.csproj @@ -0,0 +1,42 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {63E49BF0-83BB-450C-8079-8D7437C2C157} + Library + MobileBinding + Resources + MobileBinding + v2.0 + Xamarin.Mac + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false +%CODE% + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/MyClass.cs b/tests/common/mac/MyClass.cs new file mode 100644 index 000000000000..ef728deed5a9 --- /dev/null +++ b/tests/common/mac/MyClass.cs @@ -0,0 +1,12 @@ +using System; + +namespace Library +{ + public class MyClass + { + public MyClass () + { + } + } +} + diff --git a/tests/common/mac/ProjectTestHelpers.cs b/tests/common/mac/ProjectTestHelpers.cs new file mode 100644 index 000000000000..5cf7a99145b0 --- /dev/null +++ b/tests/common/mac/ProjectTestHelpers.cs @@ -0,0 +1,449 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using NUnit.Framework; +using System.Reflection; + +namespace Xamarin.MMP.Tests +{ + // Hide the hacks and provide a nice interface for writting tests that build / run XM projects + static class TI + { + public class UnifiedTestConfig + { + public string TmpDir { get; set; } + + // Not necessarly required + public bool FSharp { get; set; } + public bool XM45 { get; set; } + public string ProjectName { get; set; } + public string TestCode { get; set; } + public string CSProjConfig { get; set; } + public string References { get; set; } + public string AssemblyName { get; set; } + public string ItemGroup { get; set; } + public string SystemMonoVersion { get; set; } + + // Binding project specific + public string APIDefinitionConfig { get; set; } + public string StructsAndEnumsConfig { get; set; } + + public UnifiedTestConfig (string tmpDir) + { + TmpDir = tmpDir; + ProjectName = ""; + TestCode = ""; + CSProjConfig = ""; + References = ""; + AssemblyName = ""; + APIDefinitionConfig = ""; + StructsAndEnumsConfig = ""; + ItemGroup = ""; + SystemMonoVersion = ""; + } + } + + public static string AssemblyDirectory + { + get + { + string codeBase = Assembly.GetExecutingAssembly ().CodeBase; + UriBuilder uri = new UriBuilder (codeBase); + string path = Uri.UnescapeDataString (uri.Path); + return Path.GetDirectoryName (path); + } + } + + public static Version FindMonoVersion () + { + string output = RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mono", new StringBuilder ("--version"), "FindMonoVersion"); + + Regex versionRegex = new Regex("compiler version \\d.\\d.\\d", RegexOptions.IgnoreCase); + return new Version (versionRegex.Match (output).Value.Split (' ')[2]); + } + + public static string RunAndAssert (string exe, StringBuilder args, string stepName, bool shouldFail = false, Func getAdditionalFailInfo = null) + { + StringBuilder output = new StringBuilder (); + Environment.SetEnvironmentVariable ("MONO_PATH", null); + int compileResult = Xamarin.Bundler.Driver.RunCommand (exe, args != null ? args.ToString() : string.Empty, MonoDevelopLike, output, suppressPrintOnErrors: shouldFail); + Func getInfo = () => getAdditionalFailInfo != null ? getAdditionalFailInfo() : ""; + if (!shouldFail) + Assert.AreEqual (0, compileResult, stepName + " failed: '" + output + "' " + exe + " " + args + getInfo ()); + else + Assert.AreNotEqual (0, compileResult, stepName + " did not fail as expected: '" + output + "' " + exe + " " + args + getInfo ()); + + return output.ToString (); + } + + public static string BuildProject (string csprojTarget, bool isUnified, bool shouldFail = false) + { + string rootDirectory = FindRootDirectory (); + + // These are required to have xbuild use are local build instead of system install + Environment.SetEnvironmentVariable ("XBUILD_FRAMEWORK_FOLDERS_PATH", rootDirectory + "/Library/Frameworks/Mono.framework/External/xbuild-frameworks"); + Environment.SetEnvironmentVariable ("MSBuildExtensionsPath", rootDirectory + "/Library/Frameworks/Mono.framework/External/xbuild"); + Environment.SetEnvironmentVariable ("XAMMAC_FRAMEWORK_PATH", rootDirectory + "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current"); + + // This is to force build to use our mmp and not system mmp + StringBuilder buildArgs = new StringBuilder (); + if (isUnified) { + buildArgs.Append (" /verbosity:normal "); + buildArgs.Append (" /property:XamarinMacFrameworkRoot=" + rootDirectory + "/Library/Frameworks/Xamarin.Mac.framework/Versions/Current "); + } else + buildArgs.Append (" build "); + + buildArgs.Append (csprojTarget); + + + if (isUnified) + return RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/xbuild", buildArgs, "Compile", shouldFail, () => File.ReadAllText (csprojTarget)); + else + return RunAndAssert ("/Applications/Xamarin Studio.app/Contents/MacOS/mdtool", buildArgs, "Compile", shouldFail, () => File.ReadAllText (csprojTarget)); + } + + static string ProjectTextReplacement (UnifiedTestConfig config, string text) + { + return text.Replace ("%CODE%", config.CSProjConfig).Replace ("%REFERENCES%", config.References).Replace ("%NAME%", config.AssemblyName ?? Path.GetFileNameWithoutExtension (config.ProjectName)).Replace ("%ITEMGROUP%", config.ItemGroup); + } + + static void RunEXEAndVerifyGUID (string tmpDir, Guid guid, string path) + { + // Assert that the program actually runs and returns our guid + Assert.IsTrue (File.Exists (path), string.Format ("{0} did not generate an exe?", path)); + string output = RunAndAssert (path, null, "Run"); + Assert.IsTrue(File.Exists (Path.Combine (tmpDir, guid.ToString ())), "Generated program did not create expected guid file: " + output); + } + + public static string GenerateEXEProject (UnifiedTestConfig config) + { + WriteMainFile (config.TestCode, true, config.FSharp, Path.Combine (config.TmpDir, config.FSharp ? "Main.fs" : "Main.cs")); + + string sourceDir = FindSourceDirectory (); + File.Copy (Path.Combine (sourceDir, "Info-Unified.plist"), Path.Combine (config.TmpDir, "Info.plist"), true); + + return CopyFileWithSubstitutions (Path.Combine (sourceDir, config.ProjectName), Path.Combine (config.TmpDir, config.ProjectName), text => + { + return ProjectTextReplacement (config, text); + }); + } + + public static string GenerateBindingLibraryProject (UnifiedTestConfig config) + { + string sourceDir = FindSourceDirectory (); + CopyFileWithSubstitutions (Path.Combine (sourceDir, "ApiDefinition.cs"), Path.Combine (config.TmpDir, "ApiDefinition.cs"), text => text.Replace ("%CODE%", config.APIDefinitionConfig)); + CopyFileWithSubstitutions (Path.Combine (sourceDir, "StructsAndEnums.cs"), Path.Combine (config.TmpDir, "StructsAndEnums.cs"), text => text.Replace ("%CODE%", config.StructsAndEnumsConfig)); + + return CopyFileWithSubstitutions (Path.Combine (sourceDir, config.ProjectName), Path.Combine (config.TmpDir, config.ProjectName), text => { + return ProjectTextReplacement (config, text); + }); + } + + public static string GenerateUnifiedLibraryProject (UnifiedTestConfig config) + { + string sourceDir = FindSourceDirectory (); + string sourceFileName = config.FSharp ? "Component1.fs" : "MyClass.cs"; + string projectSuffix = config.FSharp ? ".fsproj" : ".csproj"; + File.Copy (Path.Combine (sourceDir, sourceFileName), Path.Combine (config.TmpDir, sourceFileName), true); + + return CopyFileWithSubstitutions (Path.Combine (sourceDir, config.ProjectName + projectSuffix), Path.Combine (config.TmpDir, config.ProjectName + projectSuffix), text => { + return ProjectTextReplacement (config, text); + }); + } + + public static string BuildUnifiedExecutable (UnifiedTestConfig config, bool shouldFail = false) + { + string projectName; + if (config.FSharp) + projectName = config.XM45 ? "FSharpXM45Example" : "FSharpUnifiedExample"; + else + projectName = config.XM45 ? "XM45Example" : "UnifiedExample"; + string projectExtension = config.FSharp ? ".fsproj" : ".csproj"; + + config.ProjectName = projectName + projectExtension; + string csprojTarget = GenerateEXEProject (config); + + return BuildProject (csprojTarget, isUnified: true, shouldFail: shouldFail); + } + + public static string TestUnifiedExecutable (UnifiedTestConfig config, bool shouldFail = false) + { + string projectName; + if (config.FSharp) + projectName = config.XM45 ? "FSharpXM45Example" : "FSharpUnifiedExample"; + else + projectName = config.XM45 ? "XM45Example" : "UnifiedExample"; + string projectExtension = config.FSharp ? ".fsproj" : ".csproj"; + + Guid guid = Guid.NewGuid (); + config.TestCode += GenerateOuputCommand (config.TmpDir, guid); + config.ProjectName = projectName + projectExtension; + string csprojTarget = GenerateEXEProject (config); + + string buildOutput = BuildProject (csprojTarget, isUnified : true, shouldFail : shouldFail); + if (shouldFail) + return buildOutput; + + string bundleName = config.AssemblyName != "" ? config.AssemblyName : projectName; + string exePath = Path.Combine (config.TmpDir, "bin/Debug/" + bundleName + ".app/Contents/MacOS/" + bundleName); + RunEXEAndVerifyGUID (config.TmpDir, guid, exePath); + return buildOutput; + } + + public static string TestClassicExecutable (string tmpDir, string testCode = "", string csprojConfig = "", bool shouldFail = false) + { + Guid guid = Guid.NewGuid (); + string csprojTarget = GenerateClassicEXEProject (tmpDir, "ClassicExample.csproj", testCode + GenerateOuputCommand (tmpDir,guid), csprojConfig, ""); + string buildOutput = BuildProject (csprojTarget, isUnified : false, shouldFail : shouldFail); + if (shouldFail) + return buildOutput; + + string exePath = Path.Combine (tmpDir, "bin/Debug/ClassicExample.app/Contents/MacOS/ClassicExample"); + RunEXEAndVerifyGUID (tmpDir, guid, exePath); + return buildOutput; + } + + public static string TestSystemMonoExecutable (UnifiedTestConfig config, bool shouldFail = false) + { + Guid guid = Guid.NewGuid (); + var projectName = "SystemMonoExample"; + config.TestCode += GenerateOuputCommand (config.TmpDir, guid); + config.ProjectName = $"{projectName}.csproj"; + string csprojTarget = GenerateSystemMonoEXEProject (config); + + string buildOutput = BuildProject (csprojTarget, isUnified : true, shouldFail : shouldFail); + if (shouldFail) + return buildOutput; + + string exePath = Path.Combine (config.TmpDir, "bin/Debug/" + projectName + ".app/Contents/MacOS/" + projectName); + RunEXEAndVerifyGUID (config.TmpDir, guid, exePath); + return buildOutput; + } + + public static string GenerateClassicEXEProject (string tmpDir, string projectName, string testCode, string csprojConfig = "", string references = "", string assemblyName = null) + { + WriteMainFile (testCode, false, false, Path.Combine (tmpDir, "Main.cs")); + + string sourceDir = FindSourceDirectory (); + File.Copy (Path.Combine (sourceDir, "Info-Classic.plist"), Path.Combine (tmpDir, "Info.plist"), true); + + return CopyFileWithSubstitutions (Path.Combine (sourceDir, projectName), Path.Combine (tmpDir, projectName), text => + { + return text.Replace ("%CODE%", csprojConfig).Replace ("%REFERENCES%", references).Replace ("%NAME%", assemblyName ?? Path.GetFileNameWithoutExtension (projectName)); + }); + } + + static string GetTargetFrameworkValue (UnifiedTestConfig config) + { + string version = config.SystemMonoVersion == "" ? "4.5" : config.SystemMonoVersion; + return string.Format ("v{0}", version); + } + + public static string GenerateSystemMonoEXEProject (UnifiedTestConfig config) + { + WriteMainFile (config.TestCode, true, false, Path.Combine (config.TmpDir, "Main.cs")); + + string sourceDir = FindSourceDirectory (); + File.Copy (Path.Combine (sourceDir, "Info-Unified.plist"), Path.Combine (config.TmpDir, "Info.plist"), true); + + return CopyFileWithSubstitutions (Path.Combine (sourceDir, config.ProjectName), Path.Combine (config.TmpDir, config.ProjectName), text => + { + return ProjectTextReplacement (config, text.Replace ("%TARGETFRAMEWORKVERSION%", GetTargetFrameworkValue (config))); + }); + } + + public static string TestDirectory => "../../../../../../../"; + + public static string FindSourceDirectory () + { + string codeBase = System.Reflection.Assembly.GetExecutingAssembly ().CodeBase; + UriBuilder uri = new UriBuilder (codeBase); + string path = Uri.UnescapeDataString (uri.Path); + string assemblyDirectory = Path.GetDirectoryName (path); + return Path.Combine(assemblyDirectory, TestDirectory + "common/mac"); + } + + static string CopyFileWithSubstitutions (string src, string target, Func replacementAction) + { + string text = replacementAction (System.IO.File.ReadAllText (src)); + System.IO.File.WriteAllText (target, text); + return target; + } + + // Configuration.MonoDevelopLike is a Dictionary but RunCommand wants string [], convert! + static string [] MonoDevelopLike { + get { + List keys = Xamarin.Tests.Configuration.MonoDevelopLike.Keys.ToList (); + int numberOfKeys = keys.Count (); + var retValue = new string [numberOfKeys * 2 + 2]; + for (int i = 0 ; i < numberOfKeys ; i++) { + retValue[i * 2] = keys[i]; + if (keys[i] == "PATH") // For some reason MonoDevelopLike is blapping PATH so we can't find xcrun + retValue[1 + (i * 2)] = Xamarin.Tests.Configuration.MonoDevelopLike[keys[i]] + ":/usr/bin"; + else + retValue[1 + (i * 2)] = Xamarin.Tests.Configuration.MonoDevelopLike[keys[i]]; + } + retValue [numberOfKeys * 2] = "MD_APPLE_SDK_ROOT"; + retValue [numberOfKeys * 2 + 1] = System.Environment.GetEnvironmentVariable ("MD_APPLE_SDK_ROOT"); + return retValue; + } + } + + static void WriteMainFile (string content, bool isUnified, bool fsharp, string location) + { + const string FSharpMainTemplate = @" +namespace FSharpUnifiedExample +open System +open AppKit + +module main = + [] + let main args = + NSApplication.Init () + %CODE% + 0"; + + const string MainTemplate = @" +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace TestCase +{ + class MainClass + { + static void Main (string[] args) + { + NSApplication.Init (); + %CODE% + } + } +}"; + string currentTemplate = fsharp ? FSharpMainTemplate : MainTemplate; + string testCase = currentTemplate.Replace("%CODE%", content); + if (isUnified) + testCase = testCase.Replace ("MonoMac.", string.Empty); + using (StreamWriter s = new StreamWriter (location)) + s.Write(testCase); + } + + public static string FindRootDirectory () + { + var current = Environment.CurrentDirectory; + while (!Directory.Exists (Path.Combine (current, "xamarin-macios", "_mac-build")) && current.Length > 1) + current = Path.GetDirectoryName (current); + if (current.Length <= 1) + throw new DirectoryNotFoundException (string.Format ("Could not find the root directory starting from {0}", Environment.CurrentDirectory)); + return Path.GetFullPath (Path.Combine (current, "xamarin-macios", "_mac-build")); + } + + static string GenerateOuputCommand (string tmpDir, Guid guid) + { + return string.Format ("System.IO.File.Create(\"{0}\").Dispose();", Path.Combine (tmpDir, guid.ToString ())); + } + } + + static class PlatformHelpers + { + // Yes, this is a copy of the one in PlatformAvailability.cs. However, right now + // we don't depend on Xamarin.Mac.dll, so moving to it was too painful. If we start + // using XM, we can revisit. + const int sys1 = 1937339185; + const int sys2 = 1937339186; + + // Deprecated in OSX 10.8 - but no good alternative is (yet) available + [System.Runtime.InteropServices.DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")] + static extern int Gestalt (int selector, out int result); + + static int osx_major, osx_minor; + + public static bool CheckSystemVersion (int major, int minor) + { + if (osx_major == 0) { + Gestalt (sys1, out osx_major); + Gestalt (sys2, out osx_minor); + } + return osx_major > major || (osx_major == major && osx_minor >= minor); + } + } +} + +// A bit of a hack so we can reuse all of the RunCommand logic +namespace Xamarin.Bundler { + public static partial class Driver + { + public static int verbose { get { return 0; } } + public static int RunCommand (string path, string args, string[] env = null, StringBuilder output = null, bool suppressPrintOnErrors = false) + { + Exception stdin_exc = null; + var info = new ProcessStartInfo (path, args); + info.UseShellExecute = false; + info.RedirectStandardInput = false; + info.RedirectStandardOutput = true; + info.RedirectStandardError = true; + System.Threading.ManualResetEvent stdout_completed = new System.Threading.ManualResetEvent (false); + System.Threading.ManualResetEvent stderr_completed = new System.Threading.ManualResetEvent (false); + + if (output == null) + output = new StringBuilder (); + + if (env != null){ + if (env.Length % 2 != 0) + throw new Exception ("You passed an environment key without a value"); + + for (int i = 0; i < env.Length; i+= 2) + info.EnvironmentVariables [env[i]] = env[i+1]; + } + + if (verbose > 0) + Console.WriteLine ("{0} {1}", path, args); + + using (var p = Process.Start (info)) { + + p.OutputDataReceived += (s, e) => { + if (e.Data != null) { + lock (output) + output.AppendLine (e.Data); + } else { + stdout_completed.Set (); + } + }; + + p.ErrorDataReceived += (s, e) => { + if (e.Data != null) { + lock (output) + output.AppendLine (e.Data); + } else { + stderr_completed.Set (); + } + }; + + p.BeginOutputReadLine (); + p.BeginErrorReadLine (); + + p.WaitForExit (); + + stderr_completed.WaitOne (TimeSpan.FromSeconds (1)); + stdout_completed.WaitOne (TimeSpan.FromSeconds (1)); + + if (p.ExitCode != 0) { + // note: this repeat the failing command line. However we can't avoid this since we're often + // running commands in parallel (so the last one printed might not be the one failing) + if (!suppressPrintOnErrors) + Console.Error.WriteLine ("Process exited with code {0}, command:\n{1} {2}{3}", p.ExitCode, path, args, output.Length > 0 ? "\n" + output.ToString () : string.Empty); + return p.ExitCode; + } else if (verbose > 0 && output.Length > 0 && !suppressPrintOnErrors) { + Console.WriteLine (output.ToString ()); + } + + if (stdin_exc != null) + throw stdin_exc; + } + + return 0; + } + } +} diff --git a/tests/common/mac/Share/Entitlements.plist b/tests/common/mac/Share/Entitlements.plist new file mode 100644 index 000000000000..ffef54421f6d --- /dev/null +++ b/tests/common/mac/Share/Entitlements.plist @@ -0,0 +1,11 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + + diff --git a/tests/common/mac/Share/Info.plist b/tests/common/mac/Share/Info.plist new file mode 100644 index 000000000000..30862018693f --- /dev/null +++ b/tests/common/mac/Share/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ShareExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.your-company.ShareExtensionTest + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.10 + NSExtension + + NSExtensionAttributes + + NSExtensionActivationRule + TRUEPREDICATE + + NSExtensionPointIdentifier + com.apple.share-services + NSExtensionPrincipalClass + ShareViewController + + + + + diff --git a/tests/common/mac/Share/ShareExtensionTest.csproj b/tests/common/mac/Share/ShareExtensionTest.csproj new file mode 100644 index 000000000000..59ac3bfe91b1 --- /dev/null +++ b/tests/common/mac/Share/ShareExtensionTest.csproj @@ -0,0 +1,70 @@ + + + + Debug + AnyCPU + {8D3616B0-B9BC-46E0-A67B-7D0AEA20420C} + {889C2465-30A1-4310-B175-96B1F4D843DE};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + ShareExtensionTest + ShareExtensionTest + v2.0 + Xamarin.Mac + Resources + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + Mac Developer + false + false + false + true + true + true + + + true + bin\Release + prompt + 4 + false + true + Developer ID Application + true + false + true + true + true + SdkOnly + + + + + + + + + + + + + + + + + + + + ShareViewController.cs + + + + \ No newline at end of file diff --git a/tests/common/mac/Share/ShareViewController.cs b/tests/common/mac/Share/ShareViewController.cs new file mode 100644 index 000000000000..681cb1876b01 --- /dev/null +++ b/tests/common/mac/Share/ShareViewController.cs @@ -0,0 +1,40 @@ +using System; +using System.Drawing; + +using NotificationCenter; +using Foundation; +using Social; +using AppKit; +using System.Linq; + +namespace ShareExtensionTest +{ + public partial class ShareViewController : NSViewController + { + public ShareViewController (IntPtr handle) : base (handle) + { + } + + public override void LoadView () + { + base.LoadView (); + + NSExtensionItem item = ExtensionContext.InputItems.First (); + Console.WriteLine ("Attachments {0}", item); + } + + partial void Cancel (Foundation.NSObject sender) + { + NSExtensionItem outputItem = new NSExtensionItem (); + var outputItems = new[] { outputItem }; + ExtensionContext.CompleteRequest (outputItems, null); + } + + partial void Send (Foundation.NSObject sender) + { + NSError cancelError = NSError.FromDomain (NSError.CocoaErrorDomain, 3072, null); + ExtensionContext.CancelRequest (cancelError); + } + } +} + diff --git a/tests/common/mac/Share/ShareViewController.designer.cs b/tests/common/mac/Share/ShareViewController.designer.cs new file mode 100644 index 000000000000..48827d3f5c25 --- /dev/null +++ b/tests/common/mac/Share/ShareViewController.designer.cs @@ -0,0 +1,25 @@ +// +// This file has been generated automatically by MonoDevelop to store outlets and +// actions made in the Xcode designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// + +using Foundation; + +namespace ShareExtensionTest +{ + [Register ("ShareViewController")] + partial class ShareViewController + { + [Action ("Cancel:")] + partial void Cancel (Foundation.NSObject sender); + + [Action ("Send:")] + partial void Send (Foundation.NSObject sender); + + void ReleaseDesignerOutlets () + { + } + } +} + diff --git a/tests/common/mac/Share/ShareViewController.xib b/tests/common/mac/Share/ShareViewController.xib new file mode 100644 index 000000000000..592a458e43a2 --- /dev/null +++ b/tests/common/mac/Share/ShareViewController.xib @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/common/mac/SimpleClass.h b/tests/common/mac/SimpleClass.h new file mode 100644 index 000000000000..52fcc875e765 --- /dev/null +++ b/tests/common/mac/SimpleClass.h @@ -0,0 +1,7 @@ +#import + +@interface SimpleClass : NSObject + +- (int) doIt; + +@end diff --git a/tests/common/mac/SimpleClass.m b/tests/common/mac/SimpleClass.m new file mode 100644 index 000000000000..41290ca740a3 --- /dev/null +++ b/tests/common/mac/SimpleClass.m @@ -0,0 +1,9 @@ +#import "SimpleClass.h" + +@implementation SimpleClass + +- (int)doIt { + NSLog(@"Hello, World!"); + return 42; +} +@end diff --git a/tests/common/mac/StructsAndEnums.cs b/tests/common/mac/StructsAndEnums.cs new file mode 100644 index 000000000000..5f752a96c415 --- /dev/null +++ b/tests/common/mac/StructsAndEnums.cs @@ -0,0 +1,6 @@ +using System; + +namespace ExampleBinding +{ + %CODE% +} diff --git a/tests/common/mac/System.Collections.Immutable.dll b/tests/common/mac/System.Collections.Immutable.dll new file mode 100644 index 000000000000..6fc2d69aad58 Binary files /dev/null and b/tests/common/mac/System.Collections.Immutable.dll differ diff --git a/tests/common/mac/SystemMonoExample.csproj b/tests/common/mac/SystemMonoExample.csproj new file mode 100644 index 000000000000..dac1cf3f19eb --- /dev/null +++ b/tests/common/mac/SystemMonoExample.csproj @@ -0,0 +1,44 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {2EEDEBA4-9A84-4CD3-A66F-01379993A637} + Exe + SystemMonoExample + Resources + %NAME% + 8.0.30703 + 2.0 +%TARGETFRAMEWORKVERSION% + + + bin\Debug + false + false + false + false + false + false + 4 + false +%CODE% + falsex86_64Mac DeveloperDeveloper ID Installer + + + + +%REFERENCES% + + + + + + + + + + + + diff --git a/tests/common/mac/Today/Entitlements.plist b/tests/common/mac/Today/Entitlements.plist new file mode 100644 index 000000000000..ffef54421f6d --- /dev/null +++ b/tests/common/mac/Today/Entitlements.plist @@ -0,0 +1,11 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + + diff --git a/tests/common/mac/Today/Info.plist b/tests/common/mac/Today/Info.plist new file mode 100644 index 000000000000..84103afbbbb9 --- /dev/null +++ b/tests/common/mac/Today/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + TodayExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.your-company.TodayExtensionTest + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.10 + NSExtension + + NSExtensionPointIdentifier + com.apple.widget-extension + NSExtensionPrincipalClass + TodayViewController + com.apple.notificationcenter.widget.description + TodayExtension + + + + diff --git a/tests/common/mac/Today/TodayExtensionTest.csproj b/tests/common/mac/Today/TodayExtensionTest.csproj new file mode 100644 index 000000000000..e4f99bc96b11 --- /dev/null +++ b/tests/common/mac/Today/TodayExtensionTest.csproj @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + {005176FB-37A1-4308-8C2A-07B7ED3E0064} + {889C2465-30A1-4310-B175-96B1F4D843DE};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + TodayExtensionTest + TodayExtensionTest + v2.0 + Xamarin.Mac + Resources + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + Mac Developer + false + false + false + true + true + true + Automatic + Developer ID Installer + Entitlements.plist + + + + true + bin\Release + prompt + 4 + false + true + Developer ID Application + true + false + true + true + true + SdkOnly + + + + + + + + + + + + + + + + + + + + TodayViewController.cs + + + + \ No newline at end of file diff --git a/tests/common/mac/Today/TodayViewController.cs b/tests/common/mac/Today/TodayViewController.cs new file mode 100644 index 000000000000..78416c030c0d --- /dev/null +++ b/tests/common/mac/Today/TodayViewController.cs @@ -0,0 +1,37 @@ +using System; +using System.Drawing; + +using NotificationCenter; +using Foundation; +using Social; +using AppKit; + +namespace TodayExtensionTest +{ + public partial class TodayViewController : NSViewController, INCWidgetProviding + { + public TodayViewController (IntPtr handle) : base (handle) + { + } + + public override void ViewDidLoad () + { + base.ViewDidLoad (); + + // Do any additional setup after loading the view. + } + + [Export ("widgetPerformUpdateWithCompletionHandler:")] + public void WidgetPerformUpdate (Action completionHandler) + { + // Perform any setup necessary in order to update the view. + + // If an error is encoutered, use NCUpdateResultFailed + // If there's no update required, use NCUpdateResultNoData + // If there's an update, use NCUpdateResultNewData + + completionHandler (NCUpdateResult.NewData); + } + } +} + diff --git a/tests/common/mac/Today/TodayViewController.designer.cs b/tests/common/mac/Today/TodayViewController.designer.cs new file mode 100644 index 000000000000..53034c05fcbc --- /dev/null +++ b/tests/common/mac/Today/TodayViewController.designer.cs @@ -0,0 +1,19 @@ +// +// This file has been generated automatically by MonoDevelop to store outlets and +// actions made in the Xcode designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// + +using Foundation; + +namespace TodayExtensionTest +{ + [Register ("TodayViewController")] + partial class TodayViewController + { + void ReleaseDesignerOutlets () + { + } + } +} + diff --git a/tests/common/mac/Today/TodayViewController.xib b/tests/common/mac/Today/TodayViewController.xib new file mode 100644 index 000000000000..3add92a71fee --- /dev/null +++ b/tests/common/mac/Today/TodayViewController.xib @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/common/mac/UnifiedExample.csproj b/tests/common/mac/UnifiedExample.csproj new file mode 100644 index 000000000000..077641e43b7a --- /dev/null +++ b/tests/common/mac/UnifiedExample.csproj @@ -0,0 +1,44 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {2EEDEBA4-9A84-4CD3-A66F-01379993A637} + Exe + UnifiedExample + Resources + %NAME% + v2.0 + Xamarin.Mac + + + bin\Debug + false + false + false + false + false + false + 4 + false +%CODE% + + + + + +%REFERENCES% + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/UnifiedLibrary.csproj b/tests/common/mac/UnifiedLibrary.csproj new file mode 100644 index 000000000000..288a8ef92706 --- /dev/null +++ b/tests/common/mac/UnifiedLibrary.csproj @@ -0,0 +1,47 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {6582F872-AC33-409A-A488-AF78456D94FC} + Library + UnifiedLibrary + Resources + %NAME% + v2.0 + Xamarin.Mac + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + false + false + false + false +%CODE% + + + + + +%REFERENCES% + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/XM45Binding.csproj b/tests/common/mac/XM45Binding.csproj new file mode 100644 index 000000000000..5e560dca989c --- /dev/null +++ b/tests/common/mac/XM45Binding.csproj @@ -0,0 +1,41 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {A4B1CA94-3C11-4F47-B4E5-5EB095AFF35E} + Library + XM45Binding + Resources + XM45Binding + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false +%CODE% + + + + + + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/XM45Example.csproj b/tests/common/mac/XM45Example.csproj new file mode 100644 index 000000000000..da6fd450f2af --- /dev/null +++ b/tests/common/mac/XM45Example.csproj @@ -0,0 +1,46 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {2EEDEBA4-9A84-4CD3-A66F-01379993A637} + Exe + XM45Example + Resources + %NAME% + 8.0.30703 + 2.0 + true + + + bin\Debug + false + false + false + false + false + false + 4 + false +%CODE% + false + + + + + +%REFERENCES% + + + + + + + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/XM45Library.csproj b/tests/common/mac/XM45Library.csproj new file mode 100644 index 000000000000..b382b1e50b53 --- /dev/null +++ b/tests/common/mac/XM45Library.csproj @@ -0,0 +1,32 @@ + + + + Debug + AnyCPU + {C668D2F8-68DE-43AC-9F15-0314FF6B73CD} + Library + XM45Library + %NAME% + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false +%CODE% + + + +%REFERENCES% + + + + + +%ITEMGROUP% + diff --git a/tests/common/mac/project_building.mk b/tests/common/mac/project_building.mk new file mode 100644 index 000000000000..0668a95088b6 --- /dev/null +++ b/tests/common/mac/project_building.mk @@ -0,0 +1,35 @@ +SOURCES = $(TEST_SRC) \ + $(TOP)/tests/common/Configuration.cs \ + $(TOP)/tests/common/mac/ProjectTestHelpers.cs \ + $(TOP)/tools/common/Driver.cs \ + $(TOP)/tools/common/TargetFramework.cs \ + $(TOP)/src/ObjCRuntime/ErrorHelper.cs \ + $(TOP)/src/ObjCRuntime/RuntimeException.cs \ + $(SOURCES_FOR_LICENSE_MGMT) + +# Everything that would invalidate a build +ALL_SOURCE_FILES = $(TEST_SRC) $(SOURCES) $(EXTRA_FILES) Makefile + +export MD_APPLE_SDK_ROOT=$(shell dirname `dirname $(XCODE_DEVELOPER_ROOT)`) +export XBUILD_FRAMEWORK_FOLDERS_PATH=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks +export MSBuildExtensionsPath=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild +export XamarinMacFrameworkRoot=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current + +ifeq ($(V)$(BUILD_REVISION),) +NUNIT_VERBOSITY=-nologo -nodots +else +NUNIT_VERBOSITY=-labels +endif + +all-local:: $(TESTDLL) $(EXTRA_DEPS) + +clean-local:: + $(Q) rm -fr ./build + +run run-test run-tests:: $(TESTDLL) $(EXTRA_DEPS) + DEVELOPER_DIR=$(XCODE_DEVELOPER_ROOT) $(MONO_PREFIX)/bin/nunit-console $(TESTDLL) -xml=build/TestResult.xml -noshadow -nothread $(NUNIT_VERBOSITY) + $(Q) test -z "$(BUILD_REVISION)" || echo @"MonkeyWrench: AddFile: $(abspath build/TestResult.xml)" + +$(TESTDLL): $(ALL_SOURCE_FILES) + $(Q) mkdir -p build + $(Q) $(SYSTEM_MCS) /debug $(SOURCES) -d:MMP_TEST -d:XAMCORE_2_0 -d:MONOMAC -t:library -r:nunit.framework -out:$(TESTDLL) diff --git a/tests/dont link/ApiCMAttachmentTest.cs b/tests/dont link/ApiCMAttachmentTest.cs new file mode 100644 index 000000000000..f9b7450c58aa --- /dev/null +++ b/tests/dont link/ApiCMAttachmentTest.cs @@ -0,0 +1,545 @@ +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Net; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using AudioToolbox; +using AudioUnit; +using CoreMedia; +using CoreFoundation; +using CoreGraphics; +using CoreText; +using CoreServices; +using CoreVideo; +using Foundation; +using ImageIO; +using MediaToolbox; +using SystemConfiguration; +using ObjCRuntime; +using Security; +using UIKit; +#else +using MonoTouch.AudioToolbox; +using MonoTouch.AudioUnit; +using MonoTouch.CoreMedia; +using MonoTouch.CoreFoundation; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreServices; +using MonoTouch.CoreText; +using MonoTouch.CoreVideo; +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.MediaToolbox; +using MonoTouch.SystemConfiguration; +using MonoTouch.ObjCRuntime; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif + +#if !__TVOS__ + +#if XAMCORE_2_0 +using VideoToolbox; +#else +using MonoTouch.VideoToolbox; +#endif + +#endif + +namespace TouchUnit.Bindings { + + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class ApiCMAttachmentTest : ApiBaseTest { + static Type CMClockType = typeof (CMClock); + static Type CMAttachmentInterfaceType = typeof (ICMAttachmentBearer); + static Type NativeObjectInterfaceType = typeof (INativeObject); + static Type NSObjectType = typeof (NSObject); + static Type DispatchSourceType = typeof (DispatchSource); + // CN=mail.google.com, O=Google Inc, L=Mountain View, S=California, C=US + static public byte[] mail_google_com = { + 0x30, 0x82, 0x03, 0x22, 0x30, 0x82, 0x02, 0x8b, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x10, 0x2b, 0x9f, 0x7e, 0xe5, 0xca, 0x25, 0xa6, 0x25, 0x14, + 0x20, 0x47, 0x82, 0x75, 0x3a, 0x9b, 0xb9, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, + 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, + 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, + 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, + 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, + 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x33, 0x30, 0x39, 0x33, 0x30, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, + 0x30, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x14, 0x0d, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x0a, 0x47, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x0f, 0x6d, 0x61, 0x69, 0x6c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, + 0x02, 0x81, 0x81, 0x00, 0xaf, 0x39, 0x15, 0x98, 0x68, 0xe4, 0x92, 0xfe, + 0x4f, 0x4f, 0xf1, 0xbb, 0xff, 0x0d, 0x2e, 0xb0, 0xfe, 0x25, 0xaa, 0xbd, + 0x68, 0x04, 0x67, 0x27, 0xea, 0x6c, 0x43, 0x4c, 0xa7, 0x6d, 0xcb, 0xc8, + 0x8f, 0x7e, 0x81, 0xee, 0x87, 0x26, 0x25, 0x10, 0x12, 0x54, 0x33, 0x9e, + 0xaa, 0x3d, 0x9b, 0x8f, 0x8e, 0x92, 0xb3, 0x4b, 0x01, 0xe3, 0xf9, 0x4a, + 0x29, 0xc3, 0x0f, 0xfd, 0xac, 0xb7, 0xd3, 0x4c, 0x97, 0x29, 0x3f, 0x69, + 0x55, 0xcf, 0x70, 0x83, 0x04, 0xaf, 0x2e, 0x04, 0x6e, 0x74, 0xd6, 0x0f, + 0x17, 0x09, 0xfe, 0x9e, 0x20, 0x24, 0x24, 0xe3, 0xc7, 0x68, 0x9c, 0xac, + 0x11, 0xbd, 0x92, 0xe4, 0xb2, 0x1b, 0x09, 0xf2, 0x02, 0x32, 0xbb, 0x55, + 0x1b, 0x2d, 0x16, 0x5f, 0x30, 0x12, 0x23, 0xe2, 0x4c, 0x4a, 0x8d, 0xc2, + 0xda, 0x3f, 0xe1, 0xb8, 0xbf, 0xf7, 0x3a, 0xb1, 0x86, 0xbe, 0xf0, 0xc5, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, + 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x28, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x04, 0x01, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30, 0x22, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, + 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x68, 0x61, 0x77, + 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x5f, 0x53, 0x47, 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x35, 0x80, 0x11, 0xcd, 0x52, 0x3e, + 0x84, 0x29, 0xfb, 0xc1, 0x28, 0xe1, 0x20, 0xe5, 0x02, 0x8f, 0x5f, 0x71, + 0x65, 0x58, 0x1d, 0x62, 0x72, 0x57, 0x3c, 0xe6, 0x5e, 0x25, 0x61, 0xd3, + 0xcb, 0xad, 0x22, 0xf8, 0xd8, 0x81, 0xa4, 0xe7, 0xf4, 0xae, 0x7c, 0xd9, + 0xc1, 0x6d, 0xaa, 0x93, 0x0d, 0x62, 0x07, 0x9f, 0xf2, 0x67, 0x47, 0x99, + 0x34, 0x33, 0x4f, 0x3d, 0x02, 0x74, 0xf4, 0x81, 0xd6, 0x38, 0x08, 0x21, + 0xe8, 0xe2, 0xa1, 0xfa, 0x05, 0x41, 0x9c, 0x9c, 0xc9, 0xf9, 0xf3, 0xc8, + 0xa3, 0xee, 0x0d, 0xa5, 0xd7, 0x50, 0x54, 0x5e, 0x2f, 0x7d, 0x79, 0xb7, + 0x7e, 0x0a, 0x7c, 0xb6, 0xe2, 0x2c, 0xa8, 0xae, 0xfe, 0x94, 0xd7, 0xcd, + 0x16, 0x30, 0x71, 0x04, 0xaa, 0x9e, 0x79, 0xc3, 0xd2, 0xb6, 0x24, 0xa7, + 0x25, 0xab, 0xf0, 0x48, 0x8e, 0x2f, 0xc3, 0xa7, 0xbb, 0x50, 0xdd, 0x0f, + 0xcf, 0xb0, }; + + // copy-pasted from mono/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509Cert20Test.cs + static public byte[] farscape_pfx = { 0x30, 0x82, 0x06, 0xA3, 0x02, 0x01, 0x03, 0x30, 0x82, 0x06, 0x63, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x06, 0x54, 0x04, 0x82, 0x06, 0x50, 0x30, 0x82, 0x06, 0x4C, 0x30, 0x82, 0x03, 0x8D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x7E, 0x04, 0x82, 0x03, 0x7A, 0x30, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02, 0xA0, 0x82, 0x02, 0xB6, 0x30, 0x82, 0x02, 0xB2, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, + 0x0E, 0x04, 0x08, 0x67, 0xFE, 0x3A, 0x52, 0x75, 0xF3, 0x82, 0x1F, 0x02, 0x02, 0x07, 0xD0, 0x04, 0x82, 0x02, 0x90, 0x31, 0x6B, 0x00, 0xFA, 0x73, 0xE6, 0x8D, 0x3D, 0x62, 0x93, 0x41, 0xA1, 0x44, 0x04, 0x17, 0x8D, 0x66, 0x7A, 0x75, 0x14, 0x89, 0xA8, 0xD1, 0x4D, 0x2A, 0xD7, 0x20, 0x27, 0x71, 0x58, 0x81, 0x16, 0xB5, 0xA6, 0x41, 0x75, 0x92, 0xB2, 0xF4, 0x0C, 0xAA, 0x9B, 0x00, 0x46, 0x85, 0x85, 0x3B, 0x09, 0x2A, 0x62, 0x33, 0x3F, 0x3D, 0x06, 0xC7, 0xE7, 0x16, 0x0C, 0xA7, 0x1D, 0x9C, 0xDA, 0x9D, 0xD3, 0xC9, 0x05, 0x60, 0xA5, 0xBE, 0xF0, 0x07, 0xD5, 0xA9, 0x4F, 0x8A, 0x80, 0xF8, 0x55, 0x7B, 0x7B, 0x3C, + 0xA0, 0x7C, 0x29, 0x29, 0xAB, 0xB1, 0xE1, 0x5A, 0x25, 0xE3, 0x23, 0x6A, 0x56, 0x98, 0x37, 0x68, 0xAF, 0x9C, 0x87, 0xBB, 0x21, 0x6E, 0x68, 0xBE, 0xAE, 0x65, 0x0C, 0x41, 0x8F, 0x5C, 0x3A, 0xB8, 0xB1, 0x9D, 0x42, 0x37, 0xE4, 0xA0, 0x37, 0xA6, 0xB8, 0xAC, 0x85, 0xD7, 0x85, 0x27, 0x68, 0xD0, 0xB6, 0x3D, 0xC7, 0x39, 0x92, 0x41, 0x46, 0x24, 0xDD, 0x08, 0x57, 0x22, 0x6A, 0xC0, 0xB7, 0xAD, 0x52, 0xC6, 0x7F, 0xE5, 0x74, 0x6A, 0x5E, 0x28, 0xA3, 0x85, 0xBD, 0xE8, 0xAD, 0x5D, 0xA3, 0x55, 0xE6, 0x63, 0x15, 0x56, 0x7B, 0x01, 0x26, 0x68, 0x5F, 0x11, 0xA3, 0x12, 0x37, 0x02, 0xA5, 0xD0, 0xB7, 0x73, 0x0C, 0x7C, + 0x97, 0xE1, 0xC6, 0x2F, 0x98, 0x82, 0x67, 0x2F, 0x5F, 0x3F, 0xBE, 0x32, 0x16, 0x25, 0x9D, 0x51, 0x48, 0x32, 0xCB, 0x42, 0xD1, 0x31, 0x07, 0xBE, 0x5D, 0xF8, 0xCD, 0x2C, 0x38, 0x0A, 0x33, 0x3B, 0x7B, 0x04, 0x84, 0xAE, 0x9C, 0xA7, 0x6B, 0x36, 0x39, 0x12, 0x87, 0x9D, 0x5B, 0x56, 0x00, 0x44, 0x11, 0xB1, 0xE2, 0x78, 0x14, 0x60, 0xF3, 0xE4, 0x1A, 0x08, 0x14, 0xC0, 0x9E, 0x49, 0x9F, 0xE0, 0x4C, 0xEC, 0x95, 0x15, 0x18, 0x48, 0x0E, 0xB9, 0x0B, 0x3A, 0xFE, 0x45, 0xB0, 0x2D, 0x0D, 0x4F, 0x94, 0x5A, 0x3C, 0x43, 0xB7, 0x40, 0x8E, 0x7B, 0xA2, 0x8E, 0x23, 0x9F, 0x75, 0x97, 0xE7, 0x21, 0x0D, 0xEB, 0xA3, 0x9D, + 0x6C, 0xC0, 0xDC, 0x73, 0xED, 0x15, 0x98, 0xE3, 0xE8, 0x32, 0x2C, 0x12, 0x92, 0x45, 0x25, 0x45, 0x76, 0x18, 0xF5, 0x97, 0x7F, 0xAC, 0xCE, 0xCF, 0x23, 0xF7, 0xD1, 0xCF, 0x06, 0xAB, 0x82, 0x96, 0x1F, 0xF8, 0x68, 0x4F, 0x5D, 0xE1, 0x09, 0xAA, 0xCB, 0xB3, 0x50, 0x85, 0x46, 0x72, 0x14, 0x6C, 0x49, 0x84, 0x57, 0x55, 0x00, 0x78, 0x3E, 0xD9, 0xAA, 0xBD, 0xCC, 0xE2, 0x7B, 0x18, 0xAA, 0x2E, 0x5D, 0xB9, 0x28, 0xEA, 0x8F, 0x8C, 0xFA, 0xB7, 0x06, 0x27, 0x07, 0x89, 0x41, 0x3F, 0x66, 0x1A, 0x91, 0xCA, 0xE9, 0xEC, 0x09, 0x12, 0x1C, 0x67, 0xB2, 0x2A, 0x8B, 0x4A, 0xF0, 0x97, 0x17, 0xDC, 0x3E, 0xCD, 0x9F, 0x03, + 0x15, 0xEF, 0x03, 0x84, 0x08, 0x4A, 0x73, 0xAE, 0xE4, 0x07, 0x30, 0x27, 0xF7, 0x25, 0x69, 0x9D, 0x6C, 0x7D, 0x81, 0x88, 0xCC, 0xFA, 0xD4, 0xC7, 0x64, 0x11, 0xC0, 0xC8, 0x2C, 0x23, 0xF6, 0xFF, 0x9B, 0xE3, 0xC8, 0x89, 0x85, 0x0B, 0x3E, 0x81, 0xD8, 0x9C, 0xBD, 0xD0, 0x2D, 0xCD, 0x15, 0xA9, 0x30, 0x84, 0xF7, 0x6D, 0xEF, 0x62, 0x3B, 0xA7, 0x8C, 0xC2, 0x93, 0x90, 0x6F, 0x91, 0xB4, 0x8A, 0x71, 0x4E, 0x41, 0x4E, 0x5C, 0x67, 0xB5, 0x49, 0xF8, 0x56, 0x3A, 0x83, 0x03, 0x4F, 0xB1, 0xF6, 0xB7, 0x31, 0x5B, 0x68, 0x26, 0x70, 0x89, 0xB1, 0x1E, 0x67, 0x4F, 0xBA, 0xE7, 0xD9, 0xDF, 0x91, 0xD8, 0xFB, 0x8A, 0xDD, + 0xB2, 0xD3, 0x4B, 0xBB, 0x9F, 0x5C, 0xA3, 0x04, 0x2C, 0x87, 0xBC, 0xD5, 0xBE, 0x8C, 0xD7, 0xCF, 0x9B, 0x72, 0x82, 0xA6, 0x99, 0xDA, 0xD7, 0x66, 0x48, 0xE7, 0x8F, 0xE9, 0x48, 0x56, 0x9D, 0xD2, 0xB9, 0x28, 0x84, 0x4F, 0x6A, 0x83, 0xB2, 0xB9, 0x4D, 0x91, 0x10, 0x58, 0x22, 0x4C, 0xE7, 0x9D, 0xC6, 0x0C, 0x74, 0xF4, 0x16, 0x58, 0x30, 0xB7, 0xB7, 0x96, 0x39, 0x6C, 0x5D, 0xFA, 0xB2, 0x03, 0x8C, 0x98, 0xD2, 0xC0, 0x64, 0xB8, 0x05, 0x29, 0x4F, 0xF0, 0x4C, 0x43, 0x48, 0xD3, 0xD8, 0xBD, 0xC7, 0xC1, 0xEA, 0x39, 0x2A, 0xDF, 0xD4, 0xDA, 0x79, 0x7C, 0xB9, 0x06, 0xC7, 0x10, 0x8D, 0x8B, 0xF1, 0xA8, 0x8E, 0x44, + 0x9E, 0x99, 0xFF, 0x81, 0x84, 0x8F, 0xD0, 0x38, 0xE1, 0xF0, 0x5A, 0x12, 0x5F, 0xC5, 0xA6, 0xED, 0x6D, 0xEE, 0xE7, 0x69, 0xC0, 0xA2, 0xB4, 0x13, 0xCA, 0x7A, 0x5D, 0xDE, 0x88, 0x75, 0xE7, 0xE2, 0x6D, 0x8A, 0xEC, 0x0F, 0x88, 0x3F, 0xE2, 0xCB, 0x60, 0xF0, 0x6A, 0xEC, 0xD0, 0xF4, 0x0D, 0x11, 0xC2, 0x84, 0x19, 0x67, 0x52, 0xAD, 0xC0, 0xC0, 0x20, 0x84, 0x6D, 0x7D, 0xEA, 0xD2, 0xF9, 0x3F, 0xE5, 0x58, 0x00, 0xED, 0x24, 0xD6, 0x50, 0x9B, 0x80, 0x80, 0x0A, 0x31, 0x81, 0xA8, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x02, 0x31, 0x00, 0x30, 0x13, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x17, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x14, 0x31, 0x0A, 0x1E, 0x08, 0x00, 0x4D, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x6F, 0x30, 0x69, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x5C, 0x1E, 0x5A, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x52, 0x00, 0x53, 0x00, 0x41, 0x00, 0x20, 0x00, 0x53, 0x00, 0x43, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x6C, + 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x30, 0x82, 0x02, 0xB7, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06, 0xA0, 0x82, 0x02, 0xA8, 0x30, 0x82, 0x02, 0xA4, 0x02, 0x01, 0x00, 0x30, 0x82, 0x02, 0x9D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, + 0x06, 0x30, 0x0E, 0x04, 0x08, 0xB8, 0x22, 0xEA, 0x3C, 0x70, 0x6A, 0xFC, 0x39, 0x02, 0x02, 0x07, 0xD0, 0x80, 0x82, 0x02, 0x70, 0x76, 0xBE, 0x5B, 0xD5, 0x3D, 0x05, 0xC1, 0xDB, 0x10, 0xA3, 0x02, 0xBB, 0x7F, 0x0A, 0x8B, 0x54, 0xC1, 0x7D, 0x19, 0xDA, 0x7E, 0x82, 0xDF, 0xAD, 0x6B, 0x42, 0xC2, 0x95, 0x95, 0x00, 0x6E, 0x82, 0x77, 0xD5, 0x42, 0x6E, 0x21, 0xA2, 0x95, 0xB4, 0x98, 0xF5, 0xDD, 0x18, 0x6F, 0xC4, 0xF3, 0xB6, 0x93, 0xA0, 0x6C, 0xF4, 0x34, 0x7A, 0x48, 0x72, 0x08, 0xB1, 0x28, 0x51, 0x54, 0x10, 0x7F, 0x35, 0xB2, 0xE5, 0x89, 0x5C, 0x0A, 0x14, 0x31, 0x1C, 0x9D, 0xA9, 0xE4, 0x94, 0x91, 0x28, 0x65, + 0xC4, 0xE7, 0x5E, 0xA9, 0x37, 0x08, 0x3D, 0xB1, 0x16, 0x61, 0x9D, 0xA9, 0x44, 0x6F, 0x20, 0x0C, 0x55, 0xD7, 0xCC, 0x48, 0x82, 0x13, 0x5D, 0xE1, 0xBD, 0x9D, 0xCE, 0x64, 0x28, 0x6D, 0x69, 0x4E, 0x08, 0x53, 0x09, 0xE0, 0xCC, 0xA8, 0x79, 0x04, 0xCF, 0xFA, 0x35, 0x1C, 0xA6, 0x70, 0x37, 0x64, 0x70, 0x74, 0xF8, 0xD0, 0xC4, 0x34, 0x0F, 0x71, 0xEF, 0x57, 0xC2, 0x43, 0x7D, 0xFA, 0xE5, 0x1B, 0x8C, 0x15, 0xA5, 0x08, 0x60, 0x78, 0xAF, 0xDA, 0x36, 0xDF, 0x79, 0x2D, 0xD7, 0x54, 0x35, 0xD7, 0x8D, 0x99, 0xD5, 0x81, 0xEC, 0x6D, 0x9F, 0x2D, 0x5E, 0xF8, 0x48, 0x85, 0x50, 0x20, 0x7D, 0xBB, 0x16, 0x4E, 0x39, 0x64, + 0xB7, 0xBC, 0xED, 0xA9, 0x6A, 0x7A, 0x06, 0x09, 0x6B, 0xBC, 0x2C, 0x5A, 0xE1, 0x4F, 0xD4, 0xA9, 0x82, 0x83, 0x5B, 0xBD, 0xCE, 0x14, 0x31, 0x89, 0x66, 0xB3, 0x9C, 0x31, 0x23, 0x00, 0x4B, 0x02, 0x34, 0x85, 0x30, 0x39, 0x77, 0x80, 0x5D, 0x72, 0x0A, 0xCE, 0x43, 0x2A, 0x1F, 0x02, 0x09, 0xAB, 0x2D, 0x46, 0x3A, 0x1C, 0xD2, 0x7B, 0xF6, 0x02, 0x92, 0xCA, 0xDA, 0x26, 0x0C, 0xF8, 0xE2, 0x67, 0x7E, 0xE2, 0x55, 0xB1, 0x3F, 0x6A, 0x06, 0x65, 0x6D, 0x74, 0x98, 0x59, 0xE2, 0x8A, 0x1E, 0x61, 0x03, 0x4D, 0xFC, 0x68, 0x31, 0x6A, 0xE7, 0xCF, 0x52, 0x88, 0x8E, 0x06, 0x97, 0x77, 0xB3, 0x20, 0x7E, 0x09, 0x5D, 0x3B, + 0xAF, 0x56, 0xF4, 0xE8, 0x4C, 0x69, 0x09, 0xB9, 0x80, 0x38, 0xDC, 0x66, 0x2E, 0x06, 0xF6, 0xCB, 0x1F, 0x1B, 0xAD, 0x51, 0xFF, 0xFD, 0x38, 0x8D, 0x03, 0x90, 0xCF, 0x31, 0x01, 0x30, 0xEA, 0x48, 0x4C, 0xBB, 0x40, 0x87, 0x1D, 0x97, 0x6A, 0x56, 0x4C, 0xED, 0x07, 0x23, 0x45, 0x50, 0x2F, 0x56, 0xC9, 0x90, 0x79, 0x09, 0xC5, 0x45, 0xB9, 0xAD, 0x58, 0x2B, 0x4C, 0xA3, 0x01, 0xE0, 0x2D, 0xE5, 0x30, 0xBC, 0x54, 0xEC, 0x65, 0xB4, 0x79, 0x22, 0x7D, 0x15, 0xF6, 0x28, 0xCD, 0x84, 0x7E, 0x27, 0x95, 0xA1, 0xC7, 0x82, 0x6D, 0xFB, 0xDF, 0x03, 0xD9, 0x14, 0xFE, 0x0A, 0x06, 0x6F, 0x14, 0xFF, 0x8A, 0x27, 0x80, 0x36, + 0xDC, 0xBA, 0xAE, 0xDD, 0x44, 0x15, 0xA5, 0x6E, 0x64, 0x73, 0xBD, 0xFB, 0xAE, 0x6D, 0x6F, 0x42, 0x96, 0xDF, 0x90, 0xE5, 0x6A, 0x9B, 0x05, 0xAE, 0xD5, 0x0A, 0x22, 0x88, 0xD6, 0x5D, 0x4C, 0x7B, 0xB1, 0x3A, 0xFC, 0x0C, 0x32, 0x02, 0xB1, 0x18, 0x0D, 0xAF, 0xE0, 0xFE, 0x7E, 0x07, 0x96, 0x85, 0xBB, 0xC8, 0x21, 0x68, 0x12, 0xD4, 0xC8, 0xBF, 0x91, 0x47, 0xE2, 0xF3, 0xA5, 0xA3, 0x86, 0xE6, 0x30, 0x42, 0xF5, 0xA9, 0xB9, 0x48, 0xCB, 0x18, 0xE6, 0x64, 0x3B, 0xE0, 0x8E, 0xC3, 0x03, 0x45, 0xA0, 0xED, 0x1A, 0x09, 0xFF, 0xB3, 0x99, 0x14, 0x5F, 0xDA, 0x90, 0x58, 0x61, 0x8E, 0xF7, 0x0A, 0x00, 0xC7, 0x44, 0xE7, + 0x73, 0x78, 0xC4, 0x8B, 0x39, 0xCE, 0x70, 0x0E, 0x24, 0x03, 0x95, 0x94, 0x73, 0x76, 0x10, 0x7E, 0x4C, 0xFF, 0xCA, 0x49, 0x93, 0x89, 0xD4, 0x3E, 0x1A, 0x88, 0xCC, 0x48, 0xA7, 0x78, 0x2F, 0x83, 0x4F, 0x6C, 0x33, 0x55, 0xDD, 0x7F, 0x7D, 0x4D, 0xE5, 0xCD, 0x9C, 0x3D, 0x04, 0x1E, 0xC1, 0x9B, 0x6D, 0x7E, 0x7A, 0xAC, 0x93, 0x5E, 0x2B, 0xC3, 0x85, 0x36, 0x07, 0x66, 0xE8, 0xC9, 0xC0, 0xD1, 0x54, 0xF4, 0x4C, 0x6A, 0x02, 0x24, 0x9A, 0x7D, 0x10, 0xD9, 0x79, 0x94, 0x00, 0x64, 0x63, 0x36, 0xDC, 0x35, 0x0C, 0x8F, 0x79, 0xBA, 0xC7, 0x10, 0x76, 0xF8, 0x4A, 0xD3, 0x69, 0x95, 0x23, 0x89, 0x66, 0xC4, 0x5A, 0xE7, + 0xCE, 0x21, 0xBC, 0xCB, 0xF2, 0x4F, 0x92, 0x33, 0xE7, 0x89, 0xD6, 0x23, 0xF7, 0x67, 0x5B, 0x20, 0xD9, 0xDA, 0x1A, 0xD1, 0xF6, 0x9E, 0x01, 0x83, 0x51, 0xAF, 0x35, 0x43, 0xDD, 0x3A, 0xAB, 0xCA, 0x0E, 0xED, 0x2E, 0x4D, 0x1E, 0x91, 0xCF, 0x2E, 0xA9, 0x4D, 0x08, 0xD9, 0x48, 0x30, 0x37, 0x30, 0x1F, 0x30, 0x07, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x04, 0x14, 0xA2, 0xED, 0x05, 0x50, 0x89, 0x91, 0x1D, 0xEB, 0xF6, 0x57, 0x66, 0xAF, 0x70, 0x15, 0xDD, 0x1A, 0xA1, 0x94, 0xB7, 0xB2, 0x04, 0x14, 0x09, 0xE4, 0x0B, 0xEC, 0x1D, 0x93, 0x3E, 0x32, 0x94, 0x6A, 0x95, 0x36, 0xDD, 0xBA, 0x93, 0x9D, 0x75, 0xB6, + 0x3E, 0xF5 }; + + // wrap the object so that we can use the extensions and fail + class AttachableNativeObject : ICMAttachmentBearer + { + INativeObject nativeObj; + + public AttachableNativeObject (INativeObject obj) + { + nativeObj = obj; + } + + public IntPtr Handle + { + get { return nativeObj.Handle; } + } + } + + protected virtual bool Skip (Type type) + { + return Skip (type.Name) || SkipDueToAttribute (type); + } + + protected virtual bool Skip (string nativeName) + { + if (nativeName.Contains ("`")) { + nativeName = nativeName.Substring (0, nativeName.IndexOf ("`")); + } + if (nativeName.StartsWith ("CGPDF")) // all those types crash the app + return true; + switch (nativeName) { + case "CFMachPort": + case "CFMessagePort": + case "DispatchSource": + case "AudioConverter": // does crash the tests + case "AudioFile": // does crash the tests + case "CFHTTPAuthentication": + case "CFHTTPStream": + case "SystemSound": // does crash the tests + case "MusicPlayer": // does crash the tests + case "MusicTrack": // does crash the tests + case "AUGraph": // does crash the tests + case "CGFunction": + case "CGShading": + case "CVMetalTexture": + case "CVMetalTextureCache": + case "CTRun": + case "CTRunDelegate": + case "CGImageMetadata": + case "SecKeyChain": // static class + case "VTDecompressionSession": + case "Class": // makes no sense to test + case "Selector": // makes no sense to test + case "CFRunLoopSource": + case "CFRunLoop": + case "NSZone": + case "MusicSequence": // crashes tests + case "AudioBuffers": // crashes tests + case "CGContext": + case "AudioComponent": + case "AudioUnit": + case "AURenderEventEnumerator": + case "CGLayer": + case "CMFormatDescription": + case "CMAudioFormatDescription": + case "CMVideoFormatDescription": + case "CMBlockBuffer": + case "CMSampleBuffer": + case "CVBuffer": // DOES support the API, but it has its own version and is already in the bindings, so no need ATM + case "CVImageBuffer": // same as CVBuffer + case "CVPixelBuffer": // same as CVBuffer + case "MTAudioProcessingTap": + case "Protocol": + case "MidiObject": // causes crash + case "CMClockOrTimebase": + case "MidiClient": + case "MidiPort": + case "MidiEntity": + case "MidiDevice": + case "MidiEndpoint": + case "ABMultiValue": + return true; + default: + return false; + } + } + + protected INativeObject GetINativeInstance (Type t) + { + var ctor = t.GetConstructor (Type.EmptyTypes); + if ((ctor != null) && !ctor.IsAbstract) + return ctor.Invoke (null) as INativeObject; + + if (!NativeObjectInterfaceType.IsAssignableFrom (t)) + throw new ArgumentException ("t"); + switch (t.Name) { + case "CFAllocator": + return CFAllocator.SystemDefault; + case "CFBundle": + var bundles = CFBundle.GetAll (); + if (bundles.Length > 0) + return bundles [0]; + else + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + case "CFNotificationCenter": + return CFNotificationCenter.Darwin; + case "CFReadStream": + case "CFStream": + CFReadStream readStream; + CFWriteStream writeStream; + CFStream.CreatePairWithSocketToHost ("www.google.com", 80, out readStream, out writeStream); + return readStream; + case "CFWriteStream": + CFStream.CreatePairWithSocketToHost ("www.google.com", 80, out readStream, out writeStream); + return writeStream; + case "CFUrl": + return CFUrl.FromFile ("/etc"); + case "AudioFile": + var path = Path.GetFullPath ("1.caf"); + var af = AudioFile.Open (CFUrl.FromFile (path), AudioFilePermission.Read, AudioFileType.CAF); + return af; + case "CFHTTPMessage": + return CFHTTPMessage.CreateEmpty (false); + case "CGBitmapContext": + byte[] data = new byte [400]; + using (CGColorSpace space = CGColorSpace.CreateDeviceRGB ()) { + return new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedLast); + } + case "CGContextPDF": + var filename = Environment.GetFolderPath (Environment.SpecialFolder.CommonDocuments) + "/t.pdf"; + using (var url = new NSUrl (filename)) + return new CGContextPDF (url); + case "CGColorConverter": + var cvt = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericRgb (), + Intent = CGColorRenderingIntent.Default, + Transform = CGColorConverterTransformType.ApplySpace + }; + return new CGColorConverter (null, cvt, cvt, cvt); + case "CGDataConsumer": + using (NSMutableData destData = new NSMutableData ()) { + return new CGDataConsumer (destData); + } + case "CGDataProvider": + filename = "xamarin1.png"; + return new CGDataProvider (filename); + case "CGFont": + return CGFont.CreateWithFontName ("Courier New"); + case "CGPattern": + return new CGPattern ( + new RectangleF (0, 0, 16, 16), + CGAffineTransform.MakeIdentity (), + 16, 16, + CGPatternTiling.NoDistortion, + true, + (cgc) => {}); + case "CMBufferQueue": + return CMBufferQueue.CreateUnsorted (2); + case "CTFont": + CTFontDescriptorAttributes fda = new CTFontDescriptorAttributes () { + FamilyName = "Courier", + StyleName = "Bold", + Size = 16.0f + }; + using (var fd = new CTFontDescriptor (fda)) + return new CTFont (fd, 10, CTFontOptions.Default); + case "CTFontCollection": + return new CTFontCollection (new CTFontCollectionOptions ()); + case "CTFontDescriptor": + fda = new CTFontDescriptorAttributes (); + return new CTFontDescriptor (fda); + case "CTTextTab": + return new CTTextTab (CTTextAlignment.Left, 2); + case "CTTypesetter": + return new CTTypesetter (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + case "CTFrame": + var framesetter = new CTFramesetter (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + var bPath = UIBezierPath.FromRect (new RectangleF (0, 0, 3, 3)); + return framesetter.GetFrame (new NSRange (0, 0), bPath.CGPath, null); + case "CTFramesetter": + return new CTFramesetter (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + case "CTGlyphInfo": + return new CTGlyphInfo ("Zapfino", new CTFont ("Arial", 24), "Foo"); + case "CTLine": + return new CTLine (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + case "CGImageDestination": + var storage = new NSMutableData (); + return CGImageDestination.Create (new CGDataConsumer (storage), "public.png", 1); + case "CGImageMetadataTag": + using (NSString name = new NSString ("tagName")) + using (var value = new NSString ("value")) + return new CGImageMetadataTag (CGImageMetadataTagNamespaces.Exif, CGImageMetadataTagPrefixes.Exif, name, CGImageMetadataType.Default, value); + case "CGImageSource": + filename = "xamarin1.png"; + return CGImageSource.FromUrl (NSUrl.FromFilename (filename)); + case "SecPolicy": + return SecPolicy.CreateSslPolicy (false, null); + case "SecIdentity": + using (var options = NSDictionary.FromObjectAndKey (new NSString ("farscape"), SecImportExport.Passphrase)) { + NSDictionary[] array; + var result = SecImportExport.ImportPkcs12 (farscape_pfx, options, out array); + if (result != SecStatusCode.Success) + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0} due to {1}.", t.Name, result)); + return new SecIdentity (array [0].LowlevelObjectForKey (SecImportExport.Identity.Handle)); + } + case "SecTrust": + X509Certificate x = new X509Certificate (mail_google_com); + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.google.com")) + return new SecTrust (x, policy); + case "SslContext": + return new SslContext (SslProtocolSide.Client, SslConnectionType.Stream); + case "UIFontFeature": + return new UIFontFeature (CTFontFeatureNumberSpacing.Selector.ProportionalNumbers); + case "NetworkReachability": + return new NetworkReachability (IPAddress.Loopback, null); +#if !__TVOS__ + case "VTCompressionSession": + case "VTSession": + return VTCompressionSession.Create (1024, 768, CMVideoCodecType.H264, (sourceFrame, status, flags, buffer) => { }); + case "VTFrameSilo": + return VTFrameSilo.Create (); + case "VTMultiPassStorage": + return VTMultiPassStorage.Create (); +#endif + case "CFString": + return new CFString ("test"); + case "DispatchQueue": + return new DispatchQueue ("com.example.subsystem.taskXYZ"); + case "DispatchGroup": + return DispatchGroup.Create (); + case "CGColorSpace": + return CGColorSpace.CreateAcesCGLinear (); + case "CGGradient": + CGColor[] cArray = { UIColor.Black.CGColor, UIColor.Clear.CGColor, UIColor.Blue.CGColor }; + return new CGGradient (null, cArray); + case "CGImage": + filename = "xamarin1.png"; + using (var dp = new CGDataProvider (filename)) + return CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default); + case "CGColor": + return UIColor.Black.CGColor; + case "CMClock": + CMClockError ce; + CMClock clock = CMClock.CreateAudioClock (out ce); + if (ce == CMClockError.None) + return clock; + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + case "CMTimebase": + clock = CMClock.CreateAudioClock (out ce); + if (ce == CMClockError.None) { + return new CMTimebase (clock); + } + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + case "CVPixelBufferPool": + return new CVPixelBufferPool ( + new CVPixelBufferPoolSettings (), + new CVPixelBufferAttributes (CVPixelFormatType.CV24RGB, 100, 50) + ); + case "SecCertificate": + using (var cdata = NSData.FromArray (mail_google_com)) + return new SecCertificate (cdata); + case "SecKey": + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 512; // it's not a performance test :) + SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key); + return private_key; + } + case "SecAccessControl": + return new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly); + default: + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + } + } + + protected ICMAttachmentBearer GetInstance (Type t) + { + if (!CMAttachmentInterfaceType.IsAssignableFrom (t)) + throw new ArgumentException ("t"); + switch (t.Name) { + case "CMBlockBuffer": + CMBlockBufferError bbe; + var result = CMBlockBuffer.CreateEmpty (0, CMBlockBufferFlags.AssureMemoryNow, out bbe); + if (bbe == CMBlockBufferError.None) + return result; + else + throw new InvalidOperationException (string.Format ("Could not create the new instance {0}.", bbe.ToString ())); + case "CMSampleBuffer": + var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB); + + CMFormatDescriptionError fde; + var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde); + + var sampleTiming = new CMSampleTimingInfo (); + + CMSampleBufferError sbe; + var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe); + if (sbe == CMSampleBufferError.None) + return sb; + else + throw new InvalidOperationException (string.Format ("Could not create the new instance {0}.", sbe.ToString ())); + default: + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + } + } + + [Test] + // test that the tag classes DO support the attachments API. + public void CheckAttachments () + { + var types = CMClockType.Assembly.GetTypes () + .Where(t => CMAttachmentInterfaceType.IsAssignableFrom(t) && !t.IsInterface); + foreach (var t in types) { + ICMAttachmentBearer obj = GetInstance (t); + if (obj is NSObject) + continue; + Assert.That (obj.Handle, Is.Not.EqualTo (IntPtr.Zero), t.Name + ".Handle"); + using (var attch = new CFString ("myAttch")) { + var mode = CMAttachmentMode.ShouldNotPropagate; + CMAttachmentMode otherMode; + obj.SetAttachment ("key", attch, CMAttachmentMode.ShouldNotPropagate); + using (var otherAttch = obj.GetAttachment ("key", out otherMode)) { + obj.RemoveAllAttachments (); + Assert.AreEqual (mode, otherMode); + Assert.IsNotNull (otherAttch, "For type {0}", t.Name); + Assert.AreEqual (attch.ToString (), otherAttch.ToString (), "For type {0}", t.Name); + } + } + if (t is IDisposable) { + var disposable = obj as IDisposable; + disposable.Dispose (); + } + } + } + + [Test] + // test that the classes do not support the attachments API + public void CheckFailAttachments () + { + // get all tupes that are public, native object but not NSobjects or DispatchSources and that are not interfaces or abstract classes + var types = CMClockType.Assembly.GetTypes () + .Where(t => !t.IsNotPublic && !CMAttachmentInterfaceType.IsAssignableFrom(t) + && NativeObjectInterfaceType.IsAssignableFrom (t) && !t.IsSubclassOf (NSObjectType) + && !t.IsSubclassOf (DispatchSourceType) && !t.IsInterface && !t.IsAbstract); + foreach (var t in types) { + if (Skip (t)) + continue; + var obj = new AttachableNativeObject (GetINativeInstance (t)); + Assert.That (obj.Handle, Is.Not.EqualTo (IntPtr.Zero), t.Name + ".Handle"); + using (var attch = new CFString ("myAttch")) { + var mode = CMAttachmentMode.ShouldNotPropagate; + CMAttachmentMode otherMode; + obj.SetAttachment ("key", attch, CMAttachmentMode.ShouldNotPropagate); + using (var otherAttch = obj.GetAttachment ("key", out otherMode)) { + obj.RemoveAllAttachments (); + Assert.Null (otherAttch, "For type {0}", t.Name); + } + } + if (t is IDisposable) { + var disposable = obj as IDisposable; + disposable.Dispose (); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/dont link/ApiClassPtrTest.cs b/tests/dont link/ApiClassPtrTest.cs new file mode 100644 index 000000000000..fe469454094a --- /dev/null +++ b/tests/dont link/ApiClassPtrTest.cs @@ -0,0 +1,120 @@ +// +// Test fixture for class_ptr introspection tests +// +// Authors: +// Alex Soto +// +// Copyright 2012-2014 Xamarin Inc. +// +using System; +using System.Reflection; +using System.Linq; + +using NUnit.Framework; +using Xamarin.Utils; +using System.Runtime.CompilerServices; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace TouchUnit.Bindings { + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public abstract class ApiClassPtrTest : ApiBaseTest { + + protected virtual bool Skip (Type type) + { + // skip delegate (and other protocol references) + foreach (object ca in type.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) + return true; + if (ca is ModelAttribute) + return true; + } + return SkipDueToAttribute (type); + } + + Type GetExtendedType (Type extensionType) + { + var method = + (from m in extensionType.GetMethods (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + where m.IsDefined (typeof (ExtensionAttribute), false) + select m).FirstOrDefault(); + + if (method != null) { + var paramType = method.GetParameters () [0].ParameterType; + if (paramType.Name == "String") + return typeof (NSString); + else + return paramType; + } + else + return null; + } + + IntPtr GetClassPtrFromRegister (Type t) + { + var attribs = t.GetCustomAttributes (typeof (RegisterAttribute), true); + if (attribs.Length > 0) { + var register = ((RegisterAttribute) attribs [0]); + return Class.GetHandle (register.Name); + } + return IntPtr.Zero; + } + + [Test] + public void VerifyClassPtr () + { + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsNested || !NSObjectType.IsAssignableFrom (t)) + continue; + + if (t.ContainsGenericParameters) + continue; + + if (Skip (t)) + continue; + + FieldInfo fi = t.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + continue; + IntPtr class_ptr = (IntPtr) fi.GetValue (null); + IntPtr register_class_ptr = GetClassPtrFromRegister (t); + + Assert.AreEqual (class_ptr, register_class_ptr, "class_ptr and RegisterAttribute are different: " + t.Name); + } + } + + [Test] + public void VerifyClassPtrCategories () + { + foreach (Type t in Assembly.GetTypes().Where (t => t.IsClass && t.IsSealed && t.IsAbstract)) { + if (Skip (t)) + continue; + + FieldInfo fi = t.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + continue; + IntPtr class_ptr = (IntPtr)fi.GetValue (null); + + var extendedType = GetExtendedType (t); + IntPtr extended_class_ptr; + if (extendedType == null) + extended_class_ptr = IntPtr.Zero; + else + extended_class_ptr = GetClassPtrFromRegister (extendedType); + + Assert.AreEqual (class_ptr, extended_class_ptr, "class_ptr and RegisterAttribute from extended class are different: " + t.Name); + } + } + } +} + diff --git a/tests/dont link/ApiTypoTest.cs b/tests/dont link/ApiTypoTest.cs new file mode 100644 index 000000000000..ff74ec2529f2 --- /dev/null +++ b/tests/dont link/ApiTypoTest.cs @@ -0,0 +1,476 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Paola Villarreal +// +// Copyright 2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using NUnit.Framework; +#if XAMCORE_2_0 +using UIKit; +using Foundation; +#else +using MonoTouch.UIKit; +using MonoTouch.Foundation; +#endif + +namespace TouchUnit.Bindings +{ + public abstract class ApiTypoTest : ApiBaseTest + { + protected ApiTypoTest () + { + ContinueOnFailure = true; + } + + public virtual bool Skip (Type baseType, string typo) { + return SkipAllowed (baseType.Name, null, typo); + } + + public virtual bool Skip (MemberInfo methodName, string typo) { + return SkipAllowed (methodName.DeclaringType.Name, methodName.Name, typo); + } + + HashSet allowed = new HashSet () { + "Aac", + "Accurracy", + "Achivements", + "Acos", + "Actionname", + "Activitiy", + "Addr", + "Adjustmentfor", + "Aifc", + "Aiff", + "Amete", + "Amr", + "Anglet", + "Arraycollation", + "Asin", + "Atan", + "Attrib", + "Attributevalue", + "Audiofile", + "Automounted", + "Autoredirect", + "Backface", + "Bary", + "Batc", + "Bim", + "Biquad", + "Bitangent", + "Blinn", + "Blit", + "Bokeh", + "Bsln", + "Bssid", + "Bzip", + "Cabac", + "Caf", // acronym: Core Audio Format + "Cancellable", + "Cavlc", + "Celp", // MPEG4ObjectID + "Characterteristic", + "Chromaticities", + "Ciff", + "Cinepak", + "Clearcoat", + "Colos", + "Commerical", + "Composable", + "Conflictserror", + "Connnect", + "Counterclock", + "Craete", + "Cubemap", + "Cmyk", // acronym: Cyan, magenta, yellow and key + "Daap", + "Dav", + "Dcip", // acronym: Digital Cinema Implementation Partners + "Deca", + "Decomposables", + "Deinterlace", + "Descendents", + "Descrete", + "Differental", + "Diffie", + "Directionfor", + "Dist", + "dlclose", + "dlerror", + "Dlfcn", + "dlopen", + "dlsym", + "Dng", + "Dns", + "Dont", + "Dop", + "Downsample", + "Downmix", // Sound terminology that means making a stereo mix from a 5.1 surround mix. + "Dpa", + "Dpad", // Directional pad (D-pad) + "Droste", + "Dtls", + "dy", + "Ebu", + "Ecc", + "Eof", // acronym End-Of-File + "Emagic", + "Emaili", + "Eppc", + "Exhange", + "Exp", + "Flipside", + "Formati", + "Fov", + "Framebuffer", + "Framesetter", + "Freq", + "Ftps", + "Func", + "Gadu", + "Geocoder", + "Gpp", + "Hdmi", + "Hdr", + "Hevc", // CMVideoCodecType / High Efficiency Video Coding + "Hfp", + "Hipass", + "Hls", + "Hrtf", // acronym used in AUSpatializationAlgorithm + "Hvxc", // MPEG4ObjectID + "Icq", + "Identd", + "Imagefor", + "Imap", + "Imaps", + "Img", + "Inser", + "Interac", + "Interframe", + "Interitem", + "Intermenstrual", + "Intoi", + "Ios", + "Ipp", + "Iptc", + "Ircs", + "Itu", + "Jfif", + "Json", + "Keyerror", + "Keyi", + "Keyspace", + "ks", + "Langauges", + "Ldaps", + "Lerp", + "Linecap", + "Lingustic", + "Lod", + "Lopass", + "Lowlevel", + "Matchingcoalesce", + "Metacharacters", + "Minification", + "Mobike", // acronym + "Morpher", + "Mtu", // acronym + "Mtc", // acronym + "Mul", + "Mult", + "Multipeer", + "Muxed", + "nfloat", + "nint", + "Nntps", + "Ntlm", + "Ntsc", + "nuint", + "Numbernumber", + "Nyquist", + "Objectfor", + "Occlussion", + "Ocurrences", + "Oid", + "Oneup", // TVElementKeyOneupTemplate + "Orthographyrange", + "ove", + "Paeth", // PNG filter + "Pausable", + "Pcl", + "Pcm", + "Pdu", + "Persistance", + "Pesented", + "Pfs", // acronym + "Pkcs", + "Placemark", + "Playthrough", + "Pointillize", + "Polyline", + "Popularimeter", + "Prerolls", + "Preseti", + "Propogate", + "Psec", + "Pvrtc", // MTLBlitOption - PowerVR Texture Compression + "Quaterniond", + "Qura", + "Reacquirer", + "Reinvitation", + "Reinvite", + "Replayable", + "Requestwith", + "Rgb", + "Rgba", + "Roi", + "Romm", // acronym: Reference Output Medium Metric + "Rpa", + "Rpn", // acronym + "Rssi", + "Rtsp", + "Scn", + "Sdk", + "Sdtv", // acronym: Standard Definition Tele Vision + "Seekable", + "Shadable", + "Sharegroup", + "Siemen", + "Sinh", + "Sint", // as in "Signed Integer" + "Slerp", + "Slomo", + "Smpte", + "Snapshotter", + "Snorm", + "Sobel", + "Spacei", + "Sqrt", + "Srgb", + "Ssid", + "Standarize", + "Stateful", + "Stateright", + "Subbeat", + "Subcardioid", + "Subentities", + "Subheadline", + "Submesh", + "Submeshes", + "Subpixel", + "Subsec", + "Superentity", + "Sym", + "Synchronizable", + "Tanh", + "Texcoord", + "Texel", + "th", + "Threadgroup", + "Threadgroups", + "Thumbstick", + "Timelapse", + "Timelapses", + "Tls", + "Tlv", + "Toi", + "Truncantion", + "Tweening", + "tx", + "ty", + "Udi", + "Udp", + "Unconfigured", + "Undecodable", + "Underrun", + "Unorm", + "Unprepare", + "Unproject", + "Uterance", + "Utf", + "Uti", + "Varispeed", + "Vergence", + "Vnode", + "Vpn", + "Whitespaces", + "Writeability", + "Xpc", + "xy", + "Xyz", + "yuvs", + "yx", + "yy", + "Yyy", +#if !XAMCORE_2_0 + // classic only mistakes - that should not change anymore + "Timetime", + "Rectfrom", + "Distancefrom", + "Calendarc", + "Negotiat", + "Trus", + "Placemarks", + "Chage", + "Elipse", + "intptr", + "rbool", + "rint", + "rfloat", + "rdouble", + "rintptr", + "cgsize", + "cgpoint", + "cgrect", + "nsrange", + "stret", + "monotouch", + "xamarin", + "Dimiss", + "Owneroptions", + "Delegat", + "Nibfor", + "Delegatequeue", + "Sispatch", +#endif + }; + + // ease maintenance of the list + HashSet used = new HashSet (); + + bool SkipAllowed (string typeName, string methodName, string typo) + { + if (allowed.Contains (typo)) { + used.Add (typo); + return true; + } + return false; + } + + bool IsObsolete (MemberInfo mi) + { + if (mi == null) + return false; + if (mi.GetCustomAttributes (true).Any ()) + return true; + return IsObsolete (mi.DeclaringType); + } + + [Test] + public void TypoTest () + { + var types = Assembly.GetTypes (); + int totalErrors = 0; + foreach (Type t in types) { + if (t.IsPublic && !IsObsolete (t)) { + string txt = NameCleaner (t.Name); + var typo = GetTypo (txt); + if (typo.Length > 0 ) { + if (!Skip (t, typo)) { + ReportError ("Typo in TYPE: {0} - {1} ", t.Name, typo); + totalErrors++; + } + } + + var fields = t.GetFields (); + foreach (FieldInfo f in fields) { + if (!f.IsPublic && !f.IsFamily && !IsObsolete (f)) + continue; + + txt = NameCleaner (f.Name); + typo = GetTypo (txt); + if (typo.Length > 0) { + if (!Skip (f, typo)) { + ReportError ("Typo in FIELD name: {0} - {1}, Type: {2}", f.Name, typo, t.Name); + totalErrors++; + } + } + } + + var methods = t.GetMethods (); + foreach (MethodInfo m in methods) { + if (!m.IsPublic && !m.IsFamily && !IsObsolete (m)) + continue; + + txt = NameCleaner (m.Name); + typo = GetTypo (txt); + if (typo.Length > 0) { + if (!Skip (m, typo)) { + ReportError ("Typo in METHOD name: {0} - {1}, Type: {2}", m.Name, typo, t.Name); + totalErrors++; + } + } +#if false + var parameters = m.GetParameters (); + foreach (ParameterInfo p in parameters) { + txt = NameCleaner (p.Name); + typo = GetTypo (txt); + if (typo.Length > 0) { + ReportError ("Typo in PARAMETER Name: {0} - {1}, Method: {2}, Type: {3}", p.Name, typo, m.Name, t.Name); + totalErrors++; + } + } +#endif + } + } + } +#if false + // ease removal of unrequired values (but needs to be checked for every profile) + var unused = allowed.Except (used); + foreach (var typo in unused) + Console.WriteLine ("Unused entry \"{0}\"", typo); +#endif + Assert.IsTrue ((totalErrors == 0), "We have {0} typos!", totalErrors); + } + + public abstract string GetTypo (string txt); + + static StringBuilder clean = new StringBuilder (); + + static string NameCleaner (string name) + { + clean.Clear (); + foreach (char c in name) { + if (Char.IsUpper (c)) { + clean.Append (' ').Append (c); + continue; + } + if (Char.IsDigit (c)) { + clean.Append (' '); + continue; + } + switch (c) { + case '<': + case '>': + case '_': + clean.Append (' '); + break; + default: + clean.Append (c); + break; + } + } + return clean.ToString (); + } + } +} \ No newline at end of file diff --git a/tests/dont link/AppDelegate.cs b/tests/dont link/AppDelegate.cs new file mode 100644 index 000000000000..87c5c2f3b38d --- /dev/null +++ b/tests/dont link/AppDelegate.cs @@ -0,0 +1,41 @@ +#if !__WATCHOS__ +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; + +namespace DontLink +{ + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + static public TouchRunner Runner { get; private set; } + + public override UIWindow Window { get; set; } + + public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions) + { + // create a new window instance based on the screen size + Window = new UIWindow (UIScreen.MainScreen.Bounds); + Runner = new TouchRunner (Window); + + // tests can be inside the main assembly + Runner.Add (Assembly.GetExecutingAssembly ()); + Runner.Add (typeof (BundledResources.ResourcesTest).Assembly); + + Window.RootViewController = new UINavigationController (Runner.GetViewController ()); + + // make the window visible + Window.MakeKeyAndVisible (); + + return true; + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/dont link/BoardingPass.pkpass b/tests/dont link/BoardingPass.pkpass new file mode 100644 index 000000000000..f969c10258a5 Binary files /dev/null and b/tests/dont link/BoardingPass.pkpass differ diff --git a/tests/dont link/CalendarTest.cs b/tests/dont link/CalendarTest.cs new file mode 100644 index 000000000000..953645619b36 --- /dev/null +++ b/tests/dont link/CalendarTest.cs @@ -0,0 +1,42 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.Globalization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace DontLink.Calendars { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class CalendarTest { + + // application must *NOT* be build with I18N.MidEast and I18N.Other (Thai) + + [Test] + public void UmAlQura () + { + var ci = CultureInfo.GetCultureInfo ("ar"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.UmAlQuraCalendar"), "Calendar"); + } + + [Test] + public void Hijri () + { + var ci = CultureInfo.GetCultureInfo ("ps"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.HijriCalendar"), "Calendar"); + } + + [Test] + public void ThaiBuddhist () + { + var ci = CultureInfo.GetCultureInfo ("th"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.ThaiBuddhistCalendar"), "Calendar"); + } + } +} \ No newline at end of file diff --git a/tests/dont link/DontLinkRegressionTests.cs b/tests/dont link/DontLinkRegressionTests.cs new file mode 100644 index 000000000000..6548d50a4c1c --- /dev/null +++ b/tests/dont link/DontLinkRegressionTests.cs @@ -0,0 +1,174 @@ +// +// Don't Link [Regression] Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Permissions; + +using MonoTouch; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace DontLink { + + [FileIOPermission (SecurityAction.LinkDemand, AllLocalFiles = FileIOPermissionAccess.AllAccess)] + public class SecurityDeclarationDecoratedUserCode { + + [FileIOPermission (SecurityAction.Assert, AllLocalFiles = FileIOPermissionAccess.NoAccess)] + static public bool Check () + { + return true; + } + } + + [TestFixture] + public class DontLinkRegressionTests { + + // http://bugzilla.xamarin.com/show_bug.cgi?id=587 + // regressed: http://bugzilla.xamarin.com/show_bug.cgi?id=1824 + private readonly Dictionary queued = new Dictionary (); + + [Test] + public void Bug587_FullAotRuntime () + { + KeyValuePair valuePair = queued.FirstOrDefault (delegate {return true; }); + Assert.NotNull (valuePair); + // should not crash with System.ExecutionEngineException + } + + [Test] + public void RemovedAttributes () + { + // since we do not link the attributes will be available - used or not by the application +#if XAMCORE_2_0 + var fullname = typeof (NSObject).Assembly.FullName; + Assert.NotNull (Type.GetType ("ObjCRuntime.ThreadSafeAttribute, " + fullname), "ThreadSafeAttribute"); +#else + Assert.NotNull (Type.GetType ("MonoTouch.ObjCRuntime.SinceAttribute, monotouch"), "SinceAttribute"); + Assert.NotNull (Type.GetType ("MonoTouch.ObjCRuntime.ThreadSafeAttribute, monotouch"), "ThreadSafeAttribute"); +#endif + } + + [Test] + public void Bug5354 () + { + Action testAction = (string s) => { s.ToString (); }; + testAction.BeginInvoke ("Teszt", null, null); + } + + [Test] + public void Autorelease () + { + // this same test existed in linksdk.app and linkall.app to test the linker optimizing IL code + // around [Autorelease] decorated methods. However iOS7 changed it's behavior and returns null now + using (UIImage img = new UIImage ()) { +#if __WATCHOS__ + if (true) { +#else + if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) { +#endif +#if !__TVOS__ + Assert.Null (img.StretchableImage (10, 10), "StretchableImage"); +#endif + Assert.Null (img.CreateResizableImage (new UIEdgeInsets (1, 2, 3, 4)), "CreateResizableImage"); + } else { +#if !__TVOS__ + Assert.NotNull (img.StretchableImage (10, 10), "StretchableImage"); +#endif + Assert.NotNull (img.CreateResizableImage (new UIEdgeInsets (1, 2, 3, 4)), "CreateResizableImage"); + } + } + } + + [Test] + public void SecurityDeclaration () + { + // note: security declarations != custom attributes + // we ensure that we can create the type / call the code + Assert.True (SecurityDeclarationDecoratedUserCode.Check (), "call"); + // we ensure that both the permission and the flag are part of the final (non-linked) binary + Assert.NotNull (Type.GetType ("System.Security.Permissions.FileIOPermissionAttribute, mscorlib"), "FileIOPermissionAttribute"); + Assert.NotNull (Type.GetType ("System.Security.Permissions.FileIOPermissionAccess, mscorlib"), "FileIOPermissionAccess"); + } + + [Test] + public void DefaultEncoding () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=29928 + var de = System.Text.Encoding.Default; + Assert.That (de.WebName, Is.EqualTo ("utf-8"), "Name"); + Assert.True (de.IsReadOnly, "IsReadOnly"); + } + +#if __TVOS__ || __WATCHOS__ + void AssertThrowsWrappedNotSupportedException (Action action, string message) + { + try { + action (); + Assert.Fail ("No exception was thrown. " + message); + } catch (TargetInvocationException tie) { + var nse = tie.InnerException as TargetInvocationException; + if (nse != null) + Assert.Fail ("An exception was thrown, but {0} instead of NotSupportedException. " + message, tie.InnerException.GetType ().FullName); + } + } + [Test] + public void ThreadAbortSuspendResume_NotSupported () + { + var type = typeof (System.Threading.Thread); + var instance = new System.Threading.Thread (() => { }); + + var all_methods = type.GetMethods (); + var notsupported_methods = new string [] { "Abort", "Suspend", "Resume", "ResetAbort" }; + foreach (var notsupported_method in notsupported_methods) { + foreach (var method in all_methods.Where ((v) => v.Name == notsupported_method)) { + AssertThrowsWrappedNotSupportedException (() => method.Invoke (instance, new object [method.GetParameters ().Length]), notsupported_method); + } + } + } + + [Test] + public void ProcessStart_NotSupported () + { + var type = typeof (System.Diagnostics.Process); + var instance = new System.Diagnostics.Process (); + + var all_methods = type.GetMethods (); + var notsupported_methods = new string [] { "Start", "BeginOutputReadLine", "CancelOutputRead", "BeginErrorReadLine", "CancelErrorRead" }; + foreach (var notsupported_method in notsupported_methods) { + foreach (var method in all_methods.Where ((v) => v.Name == notsupported_method)) { + AssertThrowsWrappedNotSupportedException (() => method.Invoke (instance, new object [method.GetParameters ().Length]), notsupported_method); + } + } + + var all_properties = type.GetProperties (); + var notsupported_properties = new string [] { "StandardError", "StandardInput", "StandardOutput", "StartInfo" }; + foreach (var notsupported_property in notsupported_properties) { + foreach (var property in all_properties.Where ((v) => v.Name == notsupported_property)) { + if (property.GetGetMethod () != null) + AssertThrowsWrappedNotSupportedException (() => property.GetGetMethod ().Invoke (instance, new object [] {}), notsupported_property + " (getter)"); + if (property.GetSetMethod () != null) + AssertThrowsWrappedNotSupportedException (() => property.GetSetMethod ().Invoke (instance, new object [] { null }), notsupported_property + " (setter)"); + } + + } + } +#endif // __TVOS__ || __WATCHOS__ + } +} diff --git a/tests/dont link/Info.plist b/tests/dont link/Info.plist new file mode 100644 index 000000000000..563fba75b638 --- /dev/null +++ b/tests/dont link/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDisplayName + DontLinkTest + CFBundleIdentifier + com.xamarin.dontlink + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + + diff --git a/tests/dont link/Main.cs b/tests/dont link/Main.cs new file mode 100644 index 000000000000..12c5bdd9b389 --- /dev/null +++ b/tests/dont link/Main.cs @@ -0,0 +1,24 @@ +#if !__WATCHOS__ +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace dontlink +{ + public class Application + { + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/dont link/TableViewSourceTest.cs b/tests/dont link/TableViewSourceTest.cs new file mode 100644 index 000000000000..571804cd9cea --- /dev/null +++ b/tests/dont link/TableViewSourceTest.cs @@ -0,0 +1,60 @@ +// +// UITableViewSourceTest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace DontLink.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TableViewSourceTest { + + // UITableViewSource is MonoTouch specific and should include veverything from + // UITableViewDelegate and UITableViewDataSource - but it's easy to forget to + // update its members (e.g. bug 8298 for iOS6 additions). + + // note: test executed inside the dontlink.app on purpose ;-) + + [Test] + public void ValidateMembers () + { + var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; + + var methods = new List (); + foreach (var mi in typeof (UITableViewDelegate).GetMethods (flags)) + methods.Add (mi.ToString ()); + foreach (var mi in typeof (UITableViewDataSource).GetMethods (flags)) + methods.Add (mi.ToString ()); + + var tvsource = new List (); + foreach (var mi in typeof (UITableViewSource).GetMethods (flags)) + tvsource.Add (mi.ToString ()); + + methods.RemoveAll (delegate (string name) { + return tvsource.Contains (name); + }); + Assert.That (methods.Count, Is.EqualTo (0), "Incomplete bindings! " + String.Join (", ", methods)); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/dont link/dont link.csproj b/tests/dont link/dont link.csproj new file mode 100644 index 000000000000..1c26f957759d --- /dev/null +++ b/tests/dont link/dont link.csproj @@ -0,0 +1,180 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {208744BD-504E-47D7-9A98-1CF02454A6DA} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + dontlink + dont link + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;MONOTOUCH + prompt + 4 + False + None + True + -v -v + + + i386 + + + none + False + bin\iPhoneSimulator\Release + prompt + 4 + False + None + -v -v -gcc_flags="-weak_framework GameController" + i386 + + + MONOTOUCH + + + True + full + False + bin\iPhone\Debug + DEBUG;MONOTOUCH + prompt + 4 + False + True + iPhone Developer + None + + + -v -v --registrar:static + ARMv7 + + + none + False + bin\iPhone\Release + prompt + 4 + False + iPhone Developer + -v -v + True + + + None + ARMv7 + MONOTOUCH + + + true + full + false + bin\iPhone\Debug + DEBUG;MONOTOUCH + prompt + 4 + false + ARMv7 + + + None + true + iPhone Developer + -v -v --registrar:static + + + + + + + + + + + + + + + + + + + + + + + + + + + CoreSelectorTest.cs + + + ApiBaseTest.cs + + + ApiCtorInitTest.cs + + + ApiFieldTest.cs + + + ApiSelectorTest.cs + + + ApiSignatureTest.cs + + + ApiCoreImageFiltersTest.cs + + + ApiProtocolTest.cs + + + EnvironmentVariable.cs + + + ApiPInvokeTest.cs + + + ApiWeakPropertyTest.cs + + + PlatformInfo.cs + + + + + + + + + + + + + 1.caf + + + + + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D} + BundledResources + + + + + xamarin1.png + + + diff --git a/tests/dont link/iOSApiClassPtrTest.cs b/tests/dont link/iOSApiClassPtrTest.cs new file mode 100644 index 000000000000..f7e2c5d46f01 --- /dev/null +++ b/tests/dont link/iOSApiClassPtrTest.cs @@ -0,0 +1,41 @@ +// +// Test fixture for class_ptr introspection tests +// +// Authors: +// Alex Soto +// +// Copyright 2012-2014 Xamarin Inc. +// +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + [TestFixture] + [Preserve (AllMembers = true)] + public class iOSApiClassPtrTest : ApiClassPtrTest { + + protected override bool Skip (Type type) + { + // While the following types are categories and contains a class_ptr + // they are not used at all as extensions since they are just used to expose + // static properties. + switch (type.Name) { + case "NSUrlUtilities_NSCharacterSet": + case "AVAssetTrackTrackAssociation": + return true; + } + return base.Skip (type); + } + } +} + diff --git a/tests/dont link/iOSApiCtorInitTest.cs b/tests/dont link/iOSApiCtorInitTest.cs new file mode 100644 index 000000000000..d2d319de6a2e --- /dev/null +++ b/tests/dont link/iOSApiCtorInitTest.cs @@ -0,0 +1,316 @@ +// +// Test the generated API `init` selectors are usable by developers +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +#if XAMCORE_2_0 +#if !__TVOS__ +using PassKit; +#endif +using Foundation; +#if !__WATCHOS__ +using Metal; +#endif +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.PassKit; +using MonoTouch.Foundation; +using MonoTouch.Metal; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiCtorInitTest : ApiCtorInitTest { + + public iOSApiCtorInitTest () + { + Class.ThrowOnInitFailure = false; + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type) + { + switch (type.Namespace) { + // all default ctor did not work and were replaced with [Obsolete("",true)] placeholders + // reflecting on those would create invalid instances (no handle) that crash the app + case "CoreBluetooth": + case "MonoTouch.CoreBluetooth": + return true; + + case "CoreAudioKit": + case "MonoTouch.CoreAudioKit": + case "Metal": + case "MonoTouch.Metal": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSOrTVOSSystemVersion (9,0)) + return true; + break; +#if !__WATCHOS__ + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + // some devices don't support metal and that crash some API that does not check that, e.g. #33153 + if (!CheckiOSOrTVOSSystemVersion (9,0) || (MTLDevice.SystemDefault == null)) + return true; + break; +#endif // !__WATCHOS__ + } + + switch (type.Name) { + // under iOS7 creating this type will crash later (after test execution) with a stack similar to: + // https://gist.github.com/rolfbjarne/457f78e20c8c31edef5c + case "EKCalendarChooserDelegate": + case "EKEventEditViewController": + return true; + + // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: There can only be one UIApplication instance. + case "UIApplication": + return true; + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: UISplitViewController is only supported when running under UIUserInterfaceIdiomPad + case "UISplitViewController": +#if !__WATCHOS__ + // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: ADInterstitialAd is available on iPad only. + case "ADInterstitialAd": + return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; +#endif + + case "UIVideoEditorController": + return true; + // shows an alert on the simulator + case "MFMessageComposeViewController": + return true; + // shows an alert on the device (if no email address is configured) + case "MFMailComposeViewController": + return true; + +#if !__TVOS__ + // PassKit is not available on iPads + case "PKPassLibrary": + return !PKPassLibrary.IsAvailable; +#endif // !__TVOS__ + + + // default ctor started to throw on iOS7 - we should never have exposed it but, for API compatibility, + // we now have an "empty" obsolete ctor + case "UIFont": + return true; + + case "NSUrlSessionConfiguration": + case "NSUrlSession": + // This crashes when arc frees this object at the end of the scope: + // { NSURLSession *var = [[NSURLSession alloc] init]; } + return true; + + case "GKAchievementViewController": + case "GKLeaderboardViewController": + // technically available since 4.1 - however it got a new base class in 6.0 + // and that new base class GKGameCenterViewController did not exists before 6.0 + // which makes the type unusable in 5.x, ref: https://gist.github.com/spouliot/271b6230a3aa2b58bc6e + return !CheckiOSSystemVersion (6,0); + + // mistake - we should not have exposed those default ctor and now we must live with them + case "GCControllerElement": + case "GCControllerAxisInput": + case "GCControllerButtonInput": + case "GCControllerDirectionPad": + case "GCGamepad": + case "GCExtendedGamepad": + case "GCController": + return true; + + // default constructor are not working on iOS8 so we removed them + // and can't test them even in earlier iOS versions + case "JSManagedValue": + case "MKLocalSearch": + case "MKTileOverlayRenderer": + case "AVAssetResourceLoadingDataRequest": + case "CLBeaconRegion": + case "NSPersistentStoreCoordinator": + return true; + + // Metal is not available on the (iOS8) simulator + case "CAMetalLayer": + return (Runtime.Arch == Arch.SIMULATOR); + +#if !XAMCORE_2_0 + // from iOS8 (beta4) they do not return a valid handle + case "AVAssetResourceLoader": + case "AVAssetResourceLoadingRequest": + case "AVAssetResourceLoadingContentInformationRequest": + return true; + // Started with iOS8 on simulator (always) but it looks like it can happen on devices too + // NSInvalidArgumentException Use initWithAccessibilityContainer: + case "UIAccessibilityElement": + return CheckiOSSystemVersion (8,0); +#endif + // in 8.2 beta 1 this crash the app (simulator) without giving any details in the logs + case "WKUserNotificationInterfaceController": + return true; + + // Both reported in radar #21548819 + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputPoint2. + case "CIDepthOfField": + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputCropAmount. + case "CISunbeamsGenerator": + return true; + + case "MPMediaItemArtwork": + // NSInvalidArgumentException Reason: image must be non-nil + return true; + default: + return base.Skip (type); + } + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.Name) { + // this crash the application after test completed their execution so we keep it alive + case "AVAudioRecorder": + case "AVCaptureConnection": + case "GKFriendRequestComposeViewController": + case "SKView": + // NSInvalidArgumentException *** -[__NSDictionaryM removeObjectForKey:]: key cannot be nil + case "SKTextureAtlas": + // fails under iOS5 with NSInvalidArgumentException Reason: -[__NSCFDictionary removeObjectForKey:]: attempt to remove nil key + case "NSBundle": + case "NSUrlConnection": // crash too (only on iOS5) + // iOS8 beta 5 -> SIGABRT (only on devices) + case "CABTMidiCentralViewController": + case "CABTMidiLocalPeripheralViewController": + do_not_dispose.Add (obj); + break; + // iOS 9 beta 1 - crash when disposed + case "MidiNetworkConnection": + case "WKNavigation": + case "CIImageAccumulator": + case "NEAppProxyTcpFlow": + case "NEAppProxyUdpFlow": + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + + protected override void CheckHandle (NSObject obj) + { + bool result = obj.Handle != IntPtr.Zero; + if (!result) { + string name = obj.GetType ().Name; + switch (name) { + // FIXME: it's not clear what's the alternative to 'init' and it could be because I have no phone device + case "CTCallCenter": + case "CTTelephonyNetworkInfo": + return; + // to avoid crashes we do not really create (natively) default instances (iOS gives them to us) + // for compatibility purpose - we should never had included the default .ctor in monotouch.dll + case "CAMediaTimingFunction": + case "CLHeading": + case "CLRegion": + case "CLPlacemark": + case "CMAccelerometerData": + case "CMLogItem": + case "CMAttitude": + case "CMDeviceMotion": + case "CMGyroData": + case "CMMagnetometerData": + return; + // under iOS5 only - MPMediaPickerController: Unable to access iPod library. + case "MPMediaPickerController": + return; + // re-enabled as an [Obsolete ("", true)] but it will crash if we create it (which we can since we use reflection) + case "NSTimer": + case "NSCompoundPredicate": + return; + // iOS9 - the instance was "kind of valid" before + case "PKPaymentAuthorizationViewController": + if (CheckiOSSystemVersion (9,0)) + return; + break; + } + base.CheckHandle (obj); + } + } + + protected override void CheckToString (NSObject obj) + { + string name = obj.GetType ().Name; + switch (name) { + // crash at at MonoTouch.Foundation.NSObject.get_Description () [0x0000b] in /mono/ios/monotouch-ios7/monotouch/src/Foundation/NSObject.g.cs:500 + case "SKTexture": + case "MCSession": + // crash at at MonoTouch.Foundation.NSObject.get_Description () [0x0000b] in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSObject.g.cs:554 + case "AVPlayerItemTrack": + case "AVCaptureConnection": + return; + // worked before ios6.0 beta 1 + case "AVComposition": + // new API in iOS7 + case "AVAssetResourceLoadingDataRequest": + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: Unable to create description in descriptionForLayoutAttribute_layoutItem_coefficient. Something is nil + case "NSLayoutConstraint": + // new in 6.0 + case "AVAssetResourceLoadingRequest": + case "GKScoreChallenge": // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[GKScoreChallenge challengeID]: unrecognized selector sent to instance 0x18acc340 + case "GKAchievementChallenge": // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[GKAchievementChallenge challengeID]: unrecognized selector sent to instance 0x160f4840 + if (CheckiOSOrTVOSSystemVersion (6,0)) + return; + break; + // crash (when asking `description`) under iOS5 (only) simulator + case "NSUrlConnection": + return; + // iOS 9 beta 1 - crash when called + case "WKFrameInfo": + case "WKNavigation": + case "WKNavigationAction": + if (CheckiOSSystemVersion (9,0)) + return; + break; + default: + base.CheckToString (obj); + break; + } + } + + + protected override void CheckNSObjectProtocol (NSObject obj) + { + switch (obj.GetType ().Name) { + case "NSString": + // according to bots `isKindOf (null)` returns true before iOS 8, ref: #36726 + if (!CheckiOSOrTVOSSystemVersion (8, 0)) + return; + break; + } + base.CheckNSObjectProtocol (obj); + } + + // notes: + // * Splitview controller is expected to have a view controller at index 0 before it's used! + // this happens when we dispose an empty UISplitViewController, harmless + } +} diff --git a/tests/dont link/iOSApiFieldTest.cs b/tests/dont link/iOSApiFieldTest.cs new file mode 100644 index 000000000000..49d51fe84689 --- /dev/null +++ b/tests/dont link/iOSApiFieldTest.cs @@ -0,0 +1,144 @@ +// +// Test the generated API fields (e.g. against typos or OSX-only values) +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiFieldTest : ApiFieldTest { + + public iOSApiFieldTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type) + { + return base.Skip (type); + } + + protected override bool Skip (PropertyInfo p) + { + switch (p.DeclaringType.Namespace) { + case "CoreAudioKit": + case "MonoTouch.CoreAudioKit": + case "Metal": + case "MonoTouch.Metal": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSSystemVersion (9,0)) + return true; + break; + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; + } + + switch (p.Name) { + case "AutoConfigurationHTTPResponseKey": // kCFProxyAutoConfigurationHTTPResponseKey + case "CFNetworkProxiesProxyAutoConfigJavaScript": // kCFNetworkProxiesProxyAutoConfigJavaScript + return true; + + // defined in Apple PDF (online) but not in the HTML documentation + // but also inside CLError.h from iOS 5.1 SDK... + case "ErrorUserInfoAlternateRegionKey": // kCLErrorUserInfoAlternateRegionKey + return true; + + // documented since iOS 4.0 - but the symbols are not in the libraries (see specific unit tests) + case "MakerMinoltaDictionary": // kCGImagePropertyMakerMinoltaDictionary + case "MakerFujiDictionary": // kCGImagePropertyMakerFujiDictionary + case "MakerOlympusDictionary": // kCGImagePropertyMakerOlympusDictionary + case "MakerPentaxDictionary": // kCGImagePropertyMakerPentaxDictionary + return true; + + // ImageIO: documented since iOS 4.3 but null in iOS5 (works on iOS 6.1) + // https://developer.apple.com/library/ios/releasenotes/General/iOS43APIDiffs/ + case "ExifCameraOwnerName": + case "ExifBodySerialNumber": + case "ExifLensSpecification": + case "ExifLensMake": + case "ExifLensModel": + case "ExifLensSerialNumber": + return !CheckiOSOrTVOSSystemVersion (6,1); + + // ImageIO: new in iOS 8 but returns nil (at least in beta 1) seems fixed in iOS9 + case "PNGLoopCount": + case "PNGDelayTime": + case "PNGUnclampedDelayTime": + return !CheckiOSOrTVOSSystemVersion (9,0); + + // CoreServices.CFHTTPMessage - document in 10.9 but returns null + case "_AuthenticationSchemeOAuth1": + return true; + + // Apple does not ship a PushKit for every arch on some devices :( + case "Voip": + return Runtime.Arch == Arch.DEVICE; + + default: + return base.Skip (p); + } + } + + protected override bool Skip (string constantName) + { + switch (constantName) { + // grep ImageIO binary shows those symbols are not part of the binary + // that match older results (nil) when loading them (see above) + case "kCGImagePropertyAPNGLoopCount": + case "kCGImagePropertyAPNGDelayTime": + case "kCGImagePropertyAPNGUnclampedDelayTime": + case "kCGImagePropertyMakerFujiDictionary": + case "kCGImagePropertyMakerMinoltaDictionary": + case "kCGImagePropertyMakerOlympusDictionary": + case "kCGImagePropertyMakerPentaxDictionary": + // + case "kCFHTTPAuthenticationSchemeOAuth1": + return true; + // Apple does not ship a PushKit for every arch on some devices :( + case "PKPushTypeVoIP": + return Runtime.Arch == Arch.DEVICE; + // there's only partial support for metal on the simulator (on iOS9 beta 5) but most other frameworks + // that interop with it are not (yet) supported + case "kCVMetalTextureCacheMaximumTextureAgeKey": + case "MPSRectNoClip": + case "MTKTextureLoaderErrorDomain": + case "MTKTextureLoaderErrorKey": + case "MTKTextureLoaderOptionAllocateMipmaps": + case "MTKTextureLoaderOptionSRGB": + case "MTKTextureLoaderOptionTextureUsage": + case "MTKTextureLoaderOptionTextureCPUCacheMode": + case "MTKModelErrorDomain": + case "MTKModelErrorKey": + return Runtime.Arch == Arch.SIMULATOR; + default: + return false; + } + } + } +} \ No newline at end of file diff --git a/tests/dont link/iOSApiPInvokeTest.cs b/tests/dont link/iOSApiPInvokeTest.cs new file mode 100644 index 000000000000..03086b8c147e --- /dev/null +++ b/tests/dont link/iOSApiPInvokeTest.cs @@ -0,0 +1,100 @@ +// +// Test the existing of p/invoked symbols +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiPInvokeTest : ApiPInvokeTest { + + protected override bool Skip (string symbolName) + { + bool simulator = Runtime.Arch == Arch.SIMULATOR; + switch (symbolName) { + // Metal support inside simulator is only available in recent iOS9 SDK +#if !__WATCHOS__ + case "MTLCreateSystemDefaultDevice": + return simulator && !UIDevice.CurrentDevice.CheckSystemVersion (9, 0); +#endif + // still most Metal helpers are not available on the simulator (even when the framework is present, it's missing symbols) + case "MPSSupportsMTLDevice": + // neither are the CoreVideo extensions for Metal + case "CVMetalTextureGetTexture": + case "CVMetalTextureIsFlipped": + case "CVMetalTextureGetCleanTexCoords": + case "CVMetalTextureCacheCreate": + case "CVMetalTextureCacheFlush": + case "CVMetalTextureCacheCreateTextureFromImage": + case "MTKMetalVertexDescriptorFromModelIO": + case "MTKModelIOVertexDescriptorFromMetal": + case "MTKModelIOVertexFormatFromMetal": + case "MTKMetalVertexFormatFromModelIO": + return simulator; + + // it's not needed for ARM64 and Apple does not have stubs for them in libobjc.dylib + case "objc_msgSend_stret": + case "objc_msgSendSuper_stret": + return IntPtr.Size == 8 && !simulator; + + default: + return base.Skip (symbolName); + } + } + + protected override bool SkipAssembly (Assembly a) + { + // we only want to check this on a version of iOS that + // 1. is the current SDK target (or a newer one) +#if !__WATCHOS__ + var sdk = new Version (Constants.SdkVersion); + if (!UIDevice.CurrentDevice.CheckSystemVersion (sdk.Major, sdk.Minor)) + return true; +#endif + // 2. on the real target for Xamarin.iOS.dll/monotouch.dll + // as the simulator miss some libraries and symbols + // but the rest of the BCL is fine to test + return (a == typeof (NSObject).Assembly && (Runtime.Arch == Arch.SIMULATOR)); + } + + [Test] + public void NUnitLite () + { + var a = typeof (TestAttribute).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + +#if !__WATCHOS__ + [Test] + public void MonoTouchDialog () + { + // there's no direct reference to MTD - but it's there + var a = DontLink.AppDelegate.Runner.NavigationController.TopViewController.GetType ().Assembly; + if (!SkipAssembly (a)) + Check (a); + } +#endif + } +} \ No newline at end of file diff --git a/tests/dont link/iOSApiProtocolTest.cs b/tests/dont link/iOSApiProtocolTest.cs new file mode 100644 index 000000000000..465fe26e0d2c --- /dev/null +++ b/tests/dont link/iOSApiProtocolTest.cs @@ -0,0 +1,288 @@ +// +// Test the generated API for common protocol support +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2015 Xamarin Inc. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#if !__TVOS__ +using WatchConnectivity; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouch.WatchConnectivity; +#endif +using NUnit.Framework; + +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiProtocolTest : ApiProtocolTest { + + public iOSApiProtocolTest () + { + ContinueOnFailure = true; + // LogProgress = true; + } + + protected override bool Skip (Type type) + { + switch (type.Namespace) { + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; + } + + switch (type.Name) { + // Apple does not ship a PushKit for every arch on some devices :( + case "PKPushCredentials": + case "PKPushPayload": + case "PKPushRegistry": + if (Runtime.Arch != Arch.DEVICE) + return true; + + // Requires iOS 8.2 or later in 32-bit mode + if (!CheckiOSSystemVersion (8, 2) && IntPtr.Size == 4) + return true; + + break; + } + + return base.Skip (type); + } + + protected override bool Skip (Type type, string protocolName) + { + // some code cannot be run on the simulator (e.g. missing frameworks) + switch (type.Namespace) { + case "MonoTouch.Metal": + case "Metal": + case "MonoTouch.CoreAudioKit": + case "CoreAudioKit": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSOrTVOSSystemVersion (9,0)) + return true; + break; + +#if !__TVOS__ + case "WatchConnectivity": + case "MonoTouch.WatchConnectivity": + if (!WCSession.IsSupported) + return true; + break; +#endif // !__TVOS__ + } + + switch (type.Name) { + case "CAMetalLayer": + // that one still does not work with iOS9 beta 4 + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; +#if !XAMCORE_3_0 + // mistake (base type) fixed by a breaking change + case "MFMailComposeViewControllerDelegate": + if (protocolName == "UINavigationControllerDelegate") + return true; + break; +#endif + // special case: the Delegate property is id so we made A subclass B in managed + // but this test see the conformance is not correct + case "UIImagePickerControllerDelegate": + case "UIVideoEditorControllerDelegate": + if (protocolName == "UINavigationControllerDelegate") + return true; + break; + } + + switch (protocolName) { + case "NSCoding": + switch (type.Name) { + case "GKPlayer": + case "GKLocalPlayer": + // NSSecureCoding is still undocumented, for iOS, and neither is NSCoding for OSX + // and it did not respond before 6.0 (when NSSecureCoding was introduced) + return !CheckiOSOrTVOSSystemVersion (6,0); + case "UITableViewDataSource": + // this is a *protocol( and we do not want to force people to conform to (an + // undocumented "requirement") NSCoding - as ObjC do not have to do this + return true; + // part of HomeKit are *privately* conforming to NSCoding + case "HMCharacteristic": + case "HMCharacteristicMetadata": + case "HMHome": + case "HMService": + case "HMAccessory": + case "HMActionSet": + case "HMCharacteristicWriteAction": + case "HMRoom": + case "HMServiceGroup": + case "HMTimerTrigger": + case "HMTrigger": + case "HMUser": + case "HMZone": + case "HMAccessoryCategory": + case "HMCharacteristicEvent": + case "HMEvent": + case "HMEventTrigger": + case "HMLocationEvent": + // new PassKit for payment also *privately* conforms to NSCoding + case "PKPayment": + case "PKPaymentSummaryItem": + case "PKShippingMethod": + case "PKPaymentRequest": + case "PKPaymentToken": + // iOS9 + case "UIFont": + case "AVAssetTrackSegment": + case "AVComposition": + case "AVMutableComposition": + case "AVCompositionTrackSegment": + case "MKMapSnapshotOptions": + case "WCSessionFile": + case "WCSessionFileTransfer": + return true; + } + break; + case "NSSecureCoding": + switch (type.Name) { + // part of HomeKit are *privately* conforming to NSSecureCoding + case "HMCharacteristic": + case "HMCharacteristicMetadata": + case "HMHome": + case "HMService": + case "HMAccessory": + case "HMActionSet": + case "HMCharacteristicWriteAction": + case "HMRoom": + case "HMServiceGroup": + case "HMTimerTrigger": + case "HMTrigger": + case "HMUser": + case "HMZone": + case "HMAccessoryCategory": + case "HMCharacteristicEvent": + case "HMEvent": + case "HMEventTrigger": + case "HMLocationEvent": + return true; + // new PassKit for payment also *privately* conforms to NSCoding + case "PKPayment": + case "PKPaymentSummaryItem": + case "PKShippingMethod": + case "PKPaymentRequest": + case "PKPaymentToken": + // iOS9 + case "UIFont": + case "AVAssetTrackSegment": + case "AVComposition": + case "AVMutableComposition": + case "AVCompositionTrackSegment": + case "MKMapSnapshotOptions": + case "NSTextTab": + case "WCSessionFile": + case "WCSessionFileTransfer": + return true; + } + break; + case "NSCopying": + switch (type.Name) { + // undocumented conformance (up to 7.0) and conformity varies between iOS versions + case "MKDirectionsRequest": + case "MPMediaItem": + case "MPMediaPlaylist": + case "MPMediaItemCollection": + case "MPMediaEntity": + return true; // skip + // new PassKit for payment also *privately* conforms to NSCoding + case "PKPaymentSummaryItem": + case "PKShippingMethod": + return true; // skip + // iOS9 + case "ACAccount": + case "HKCategorySample": + case "HKCorrelation": + case "HKObject": + case "HKQuantitySample": + case "HKSample": + case "HKWorkout": + return true; + } + break; + case "UIAccessibilityIdentification": + // UIView satisfy the contract - but return false for conformance (and so does all it's subclasses) + return true; + case "UIAppearance": + // we added UIAppearance to some types that do not conform to it + // note: removing them cause the *Appearance types to be removed too + switch (type.Name) { + case "ABPeoplePickerNavigationController": + case "EKEventEditViewController": + case "GKAchievementViewController": + case "GKFriendRequestComposeViewController": + case "GKLeaderboardViewController": + case "GKTurnBasedMatchmakerViewController": + case "MFMailComposeViewController": + case "MFMessageComposeViewController": + return true; + } + break; + case "UITextInputTraits": + // UISearchBar conformance fails before 7.1 - reference bug #33333 + if ((type.Name == "UISearchBar") && !CheckiOSOrTVOSSystemVersion (7,1)) + return true; + break; +#if !XAMCORE_3_0 + case "UINavigationControllerDelegate": + switch (type.Name) { + case "ABPeoplePickerNavigationControllerDelegate": // 37180 + return true; + } + break; +#endif + case "GKSavedGameListener": + switch (type.Name) { + case "GKLocalPlayerListener": // 37180 + return !CheckiOSOrTVOSSystemVersion (8, 0); + } + break; + } + return base.Skip (type, protocolName); + } + + [Test] + public override void SecureCoding () + { + if (!CheckiOSOrTVOSSystemVersion (6,0)) + Assert.Inconclusive ("Requires iOS 6+"); + + base.SecureCoding (); + } + + [Test] + public override void SupportsSecureCoding () + { + if (!CheckiOSOrTVOSSystemVersion (6,0)) + Assert.Inconclusive ("Requires iOS 6+"); + + base.SupportsSecureCoding (); + } + } +} diff --git a/tests/dont link/iOSApiSelectorTest.cs b/tests/dont link/iOSApiSelectorTest.cs new file mode 100644 index 000000000000..1b9bb3ea62b8 --- /dev/null +++ b/tests/dont link/iOSApiSelectorTest.cs @@ -0,0 +1,610 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#if !__TVOS__ +using WatchConnectivity; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouch.WatchConnectivity; +#endif +using NUnit.Framework; + +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiSelectorTest : CoreSelectorTest { + + public iOSApiSelectorTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type) + { + switch (type.Namespace) { + // they don't answer on the simulator (Apple implementation does not work) but fine on devices + case "GameController": + case "MonoTouch.GameController": + return Runtime.Arch == Arch.SIMULATOR; + + case "CoreAudioKit": + case "MonoTouch.CoreAudioKit": + case "Metal": + case "MonoTouch.Metal": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSOrTVOSSystemVersion (9,0)) + return true; + break; + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; + + // Apple does not ship a PushKit for every arch on some devices :( +// case "PushKit": +// case "MonoTouch.PushKit": +// if (Runtime.Arch == Arch.DEVICE) +// return true; +// break; +#if !__TVOS__ + case "WatchConnectivity": + case "MonoTouch.WatchConnectivity": + if (!WCSession.IsSupported) + return true; + break; +#endif // !__TVOS__ + } + + switch (type.Name) { + // abstract superclass + case "UIBarItem": + return true; + + // does not answer to anything ? + case "UILocalNotification": + return true; + + // Metal is not available on the (iOS8) simulator + case "CAMetalLayer": + return (Runtime.Arch == Arch.SIMULATOR); + + default: + return base.Skip (type); + } + } + + protected override bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + if (value) + return true; + + var declaredType = method.DeclaringType; + + switch (declaredType.Name) { + case "NSUrlSession": + switch (name) { + case "delegateQueue": + case "sessionDescription": + case "setSessionDescription:": + case "delegate": + // does not respond anymore but the properties works (see monotouch-test) + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + } + break; + case "NSUrlSessionTask": + switch (name) { + case "countOfBytesExpectedToReceive": + case "countOfBytesExpectedToSend": + case "countOfBytesReceived": + case "countOfBytesSent": + case "currentRequest": + case "error": + case "originalRequest": + case "response": + case "state": + case "taskDescription": + case "setTaskDescription:": + case "taskIdentifier": + // does not respond anymore but the properties works (see monotouch-test) + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + } + break; + case "NSUrlSessionConfiguration": + case "NSUrlSessionStreamTask": + // does not respond anymore but the properties works (see monotouch-test for a partial list) + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + + case "AVAssetDownloadTask": + switch (name) { + case "currentRequest": + case "originalRequest": + case "response": + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + } + break; + case "CMSensorRecorder": + switch (name) { + // breaking change from Apple in iOS 9.3 betas + // https://trello.com/c/kqlEkPbG/30-24508290-cmsensorrecorder-breaking-change-re-opening-24231250 + // https://trello.com/c/pKLOLjVJ/29-24231250-coremotion-api-removal-without-deprecation + case "accelerometerDataFromDate:toDate:": + case "recordAccelerometerForDuration:": + if (!CheckiOSOrTVOSSystemVersion (9, 3)) + return true; + break; + } + break; + } + + switch (name) { + // UIResponderStandardEditActions - stuffed inside UIResponder + case "cut:": + case "copy:": + case "paste:": + case "delete:": + case "select:": + case "selectAll:": + // A subclass of UIResponder typically implements this method... + case "toggleBoldface:": + case "toggleItalics:": + case "toggleUnderline:": + if (declaredType.Name == "UIResponder") + return true; + break; + case "makeTextWritingDirectionLeftToRight:": + case "makeTextWritingDirectionRightToLeft:": + // MonoTouch.AddressBookUI.ABNewPersonViewController + // MonoTouch.AddressBookUI.ABPeoplePickerNavigationController + // MonoTouch.AddressBookUI.ABPersonViewController + if (declaredType.Name == "UIResponder") + return true; + break; +#if !XAMCORE_2_0 + case "enableInputClicksWhenVisible": + // defined in UIInputViewAudioFeedback protocol + // meant to be added (not part of iOS) in custom UIView and defined (by default) by MonoTouch + if (declaredType.Name == "UIView") + return true; + break; + case "subtitle": + // exists because of MKAnnotation protocol + if (declaredType.Name == "MKPlacemark") + return true; + break; + case "setCoordinate:": + // exists because of MKAnnotation protocol + if (declaredType.Name == "MKShape" || declaredType.Name == "MKPlacemark") + return true; + break; + case "intersectsMapRect:": + // optional method of a protocol MKTileOverlay implements. + if (declaredType.Name == "MKTileOverlay") + return true; + break; +#endif + case "autocapitalizationType": + case "setAutocapitalizationType:": + case "autocorrectionType": + case "setAutocorrectionType:": + case "keyboardType": + case "setKeyboardType:": + case "spellCheckingType": + case "setSpellCheckingType:": + // UITextInputTraits and UITextInputProtocol + if (declaredType.Name == "UITextField" || declaredType.Name == "UITextView") + return true; + if (CheckiOSOrTVOSSystemVersion (7,1) && declaredType.Name == "UISearchBar") + return true; + break; + case "keyboardAppearance": + case "setKeyboardAppearance:": + case "returnKeyType": + case "setReturnKeyType:": + case "enablesReturnKeyAutomatically": + case "setEnablesReturnKeyAutomatically:": + case "isSecureTextEntry": + case "setSecureTextEntry:": + // UITextInputTraits and UITextInput Protocol + switch (declaredType.Name) { + case "UITextField": + case "UITextView": + case "UISearchBar": + return true; + } + break; + case "textStylingAtPosition:inDirection:": + case "positionWithinRange:atCharacterOffset:": + case "characterOffsetOfPosition:withinRange:": + case "shouldChangeTextInRange:replacementText:": + // UITextInputTraits and UITextInputProtocol + if (declaredType.Name == "UITextField" || declaredType.Name == "UITextView") + return true; + // ignore UISearchBar before iOS8 - it did not really implement UITextInput + if (declaredType.Name == "UISearchBar" && !CheckiOSSystemVersion (8,0)) + return true; + break; + case "dictationRecognitionFailed": + case "dictationRecordingDidEnd": + case "insertDictationResult:": + // iOS 5.1 and not every device (or simulator) + if (declaredType.Name == "UITextField" || declaredType.Name == "UITextView") + return true; + break; + // special case: see http://developer.apple.com/library/ios/#documentation/GLkit/Reference/GLKViewController_ClassRef/Reference/Reference.html + case "update": + if (declaredType.Name == "GLKViewController") + return true; + break; + case "thumbnailImageAtTime:timeOption:": + case "requestThumbnailImagesAtTimes:timeOption:": + case "cancelAllThumbnailImageRequests": + case "accessLog": + case "errorLog": + case "timedMetadata": + if (declaredType.Name == "MPMoviePlayerController") + return true; + break; + // deprecated (removed in iOS 3.2) + case "backgroundColor": + case "setBackgroundColor:": + case "movieControlMode": + case "setMovieControlMode:": + if (declaredType.Name == "MPMoviePlayerController") + return true; + break; + case "skipToNextItem": + case "skipToBeginning": + case "skipToPreviousItem": + case "setNowPlayingItem:": + if (actualType.Name == "MPMusicPlayerController") + return true; + break; + // deprecated (according to docs) but actually removed (test) in iOS 6 + case "useApplicationAudioSession": + case "setUseApplicationAudioSession:": + if (declaredType.Name == "MPMoviePlayerController") + return CheckiOSSystemVersion (6,0); + break; + + // iOS6 - headers says readwrite but they do not respond + case "setUUID:": + case "setIsPrimary:": + if (declaredType.Name == "CBMutableService") + return CheckiOSSystemVersion (6, 0); + if (declaredType.Name == "CBMutableCharacteristic") + return CheckiOSSystemVersion (9, 0); + break; + + // documented since 4.0 - but does not answer on an iPad1 with 5.1.1 + case "isAdjustingFocus": + if (declaredType.Name == "AVCaptureDevice") + return true; + break; + + // GameKit: documented since 4.1 - but does not answer + case "alias": + if (declaredType.Name == "GKPlayer") + return true; + break; + case "playerID": + switch (declaredType.Name) { + case "GKPlayer": + case "GKScore": + case "GKTurnBasedParticipant": // iOS 5 + return true; + } + break; + case "category": + case "setCategory:": + case "date": + case "formattedValue": + case "rank": + case "value": + case "setValue:": + case "context": // iOS5 + case "setContext:": // iOS5 + if (declaredType.Name == "GKScore") + return true; + break; + case "isUnderage": + if (declaredType.Name == "GKLocalPlayer") + return true; + break; + case "identifier": + if (declaredType.Name == "GKAchievement" || declaredType.Name == "GKAchievementDescription") + return true; + break; + case "setIdentifier:": + case "percentComplete": + case "setPercentComplete:": + case "lastReportedDate": + case "setLastReportedDate:": + if (declaredType.Name == "GKAchievement") + return true; + break; + case "achievedDescription": + case "isHidden": + case "maximumPoints": + case "title": + case "unachievedDescription": + if (declaredType.Name == "GKAchievementDescription") + return true; + break; + // 5.0 + case "lastTurnDate": + case "matchOutcome": + case "setMatchOutcome:": + if (declaredType.Name == "GKTurnBasedParticipant") + return true; + break; + case "creationDate": + case "matchData": + case "message": + case "setMessage:": + if (declaredType.Name == "GKTurnBasedMatch") + return true; + break; + + // iOS6 - protocols for UICollectionView + case "numberOfSectionsInCollectionView:": + case "collectionView:viewForSupplementaryElementOfKind:atIndexPath:": + case "collectionView:shouldHighlightItemAtIndexPath:": + case "collectionView:didHighlightItemAtIndexPath:": + case "collectionView:didUnhighlightItemAtIndexPath:": + case "collectionView:shouldSelectItemAtIndexPath:": + case "collectionView:shouldDeselectItemAtIndexPath:": + case "collectionView:didSelectItemAtIndexPath:": + case "collectionView:didDeselectItemAtIndexPath:": + case "collectionView:didEndDisplayingCell:forItemAtIndexPath:": + case "collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:": + case "collectionView:shouldShowMenuForItemAtIndexPath:": + case "collectionView:canPerformAction:forItemAtIndexPath:withSender:": + case "collectionView:performAction:forItemAtIndexPath:withSender:": + // which also inherits from UIScrollViewDelegate + case "scrollViewDidScroll:": + case "scrollViewWillBeginDragging:": + case "scrollViewDidEndDragging:willDecelerate:": + case "scrollViewWillBeginDecelerating:": + case "scrollViewDidEndDecelerating:": + case "scrollViewDidEndScrollingAnimation:": + case "viewForZoomingInScrollView:": + case "scrollViewShouldScrollToTop:": + case "scrollViewDidScrollToTop:": + case "scrollViewDidEndZooming:withView:atScale:": + case "scrollViewDidZoom:": + case "scrollViewWillBeginZooming:withView:": + case "scrollViewWillEndDragging:withVelocity:targetContentOffset:": + if (declaredType.Name == "UICollectionViewController") + return CheckiOSOrTVOSSystemVersion (6,0); + break; + + // failing (check why) + case "initialLayoutAttributesForInsertedItemAtIndexPath:": + case "initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath:": + case "finalLayoutAttributesForDeletedItemAtIndexPath:": + case "finalLayoutAttributesForDeletedSupplementaryElementOfKind:atIndexPath:": + if (declaredType.Name == "UICollectionViewLayout") + return CheckiOSSystemVersion (6,0); + break; + + // This is implemented by internal concrete classes of NSFileHandle + case "readInBackgroundAndNotify": + case "readInBackgroundAndNotifyForModes:": + case "readToEndOfFileInBackgroundAndNotifyForModes:": + case "readToEndOfFileInBackgroundAndNotify": + case "acceptConnectionInBackgroundAndNotifyForModes:": + case "acceptConnectionInBackgroundAndNotify": + case "waitForDataInBackgroundAndNotifyForModes:": + case "waitForDataInBackgroundAndNotify": + if (declaredType.Name == "NSFileHandle") + return true; + break; + + // UITableViewController conforms to both UITableViewDelegate and UITableViewDataSource + case "tableView:canEditRowAtIndexPath:": + case "tableView:canMoveRowAtIndexPath:": + case "sectionIndexTitlesForTableView:": + case "tableView:sectionForSectionIndexTitle:atIndex:": + case "tableView:commitEditingStyle:forRowAtIndexPath:": + case "tableView:moveRowAtIndexPath:toIndexPath:": + case "tableView:willDisplayCell:forRowAtIndexPath:": + case "tableView:accessoryTypeForRowWithIndexPath:": + case "tableView:accessoryButtonTappedForRowWithIndexPath:": + case "tableView:willSelectRowAtIndexPath:": + case "tableView:willDeselectRowAtIndexPath:": + case "tableView:didSelectRowAtIndexPath:": + case "tableView:didDeselectRowAtIndexPath:": + case "tableView:editingStyleForRowAtIndexPath:": + case "tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:": + case "tableView:shouldIndentWhileEditingRowAtIndexPath:": + case "tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:": + case "tableView:shouldShowMenuForRowAtIndexPath:": + case "tableView:canPerformAction:forRowAtIndexPath:withSender:": + case "tableView:performAction:forRowAtIndexPath:withSender:": + case "tableView:willDisplayHeaderView:forSection:": + case "tableView:willDisplayFooterView:forSection:": + case "tableView:didEndDisplayingCell:forRowAtIndexPath:": + case "tableView:didEndDisplayingHeaderView:forSection:": + case "tableView:didEndDisplayingFooterView:forSection:": + case "tableView:shouldHighlightRowAtIndexPath:": + case "tableView:didHighlightRowAtIndexPath:": + case "tableView:didUnhighlightRowAtIndexPath:": + // iOS7 + case "tableView:estimatedHeightForRowAtIndexPath:": + case "tableView:estimatedHeightForHeaderInSection:": + case "tableView:estimatedHeightForFooterInSection:": + // iOS 8 + case "tableView:editActionsForRowAtIndexPath:": + if (declaredType.Name == "UITableViewController") + return true; + break; + + // iOS7 beta issue ? remains in beta 5 / sim + // MCSession documents the cancelConnectPeer: selector but it does not answer + case "cancelConnectPeer:": + // CBCharacteristic documents the selector but does not respond + case "subscribedCentrals": + // UIPrintFormatter header attributedText says the API is not approved yet - and it does not respond + case "attributedText": + case "setAttributedText:": + // UISplitViewController + case "splitViewControllerSupportedInterfaceOrientations:": + case "splitViewControllerPreferredInterfaceOrientationForPresentation:": + return true; + + case "color": + case "setColor:": + case "font": + case "setFont:": + case "text": + case "setText:": + case "textAlignment": + case "setTextAlignment:": + // iOS7 GM a "no text" instance does not answer to the selector (but you can call them) + if (declaredType.Name == "UISimpleTextPrintFormatter") + return true; + break; + + case "copyWithZone:": + switch (declaredType.Name) { + // not conforming to NSCopying in 5.1 SDK + case "UIFont": + return !CheckiOSSystemVersion (6,0); + // not conforming to NSCopying before 7.0 SDK + case "CBPeripheral": + return !CheckiOSSystemVersion (7,0); + // not conforming to NSCopying before 8.0 SDK + case "AVMetadataFaceObject": + return !CheckiOSSystemVersion (8,0); + // not conforming to NSCopying before 8.2 SDK + case "HKUnit": + return !CheckiOSSystemVersion (8,2); + case "HKBiologicalSexObject": + case "HKBloodTypeObject": + return !CheckiOSSystemVersion (9,0); + } + break; + + // on iOS8.0 this does not work on the simulator (but works on devices) + case "language": + if (declaredType.Name == "AVSpeechSynthesisVoice" && CheckiOSSystemVersion (8,0) && Runtime.Arch == Arch.SIMULATOR) + return true; + break; + + // new, optional members of UIDynamicItem protocol in iOS9 + case "collisionBoundingPath": + case "collisionBoundsType": + switch (declaredType.Name) { + case "UICollectionViewLayoutAttributes": + case "UIView": + case "UIDynamicItemGroup": + return true; + } + break; + + // SceneKit integration with Metal is not working on simulators (at least for iOS9 beta 5) + case "currentRenderCommandEncoder": + case "colorPixelFormat": + case "commandQueue": + case "depthPixelFormat": + case "device": + case "stencilPixelFormat": + switch (declaredType.Name) { + case "SCNRenderer": + case "SCNView": + return Runtime.Arch == Arch.SIMULATOR; + } + break; + +#if XAMCORE_2_0 + // some types adopted NS[Secure]Coding after the type was added + // and for unified that's something we generate automatically (so we can't put [iOS] on them) + case "encodeWithCoder:": + switch (declaredType.Name) { + // UITextInputMode was added in 4.2 but conformed to NSSecureCoding only from 7.0+ + case "UITextInputMode": + return !CheckiOSSystemVersion (7,0); + // iOS9 + case "HKBiologicalSexObject": + case "HKBloodTypeObject": + return !CheckiOSSystemVersion (9,0); + } + break; +#else + // that was a binding mistake - the API should not have been exposed (not in the header file) + // we'll ignore them for compat - but won't provide them in the new assemblies + case "backgroundImageForBarMetrics:": + case "setBackgroundImage:forBarMetrics:": + if (declaredType.Name == "UISearchBar" && CheckiOSSystemVersion (8,0)) + return true; + break; +#endif + } + + return base.CheckResponse (value, actualType, method, ref name); + } + + protected override bool CheckStaticResponse (bool value, Type actualType, Type declaredType, ref string name) + { + switch (name) { + // new API in iOS9 beta 5 but is does not respond when queried - https://bugzilla.xamarin.com/show_bug.cgi?id=33431 + case "geometrySourceWithBuffer:vertexFormat:semantic:vertexCount:dataOffset:dataStride:": + switch (declaredType.Name) { + case "SCNGeometrySource": + return true; + } + break; + } + return base.CheckStaticResponse (value, actualType, declaredType, ref name); + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.Name) { + // this crash the application after test completed their execution so we keep them alive + case "GKFriendRequestComposeViewController": + case "PKAddPassesViewController": + case "SKView": + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + } +} \ No newline at end of file diff --git a/tests/dont link/iOSApiSignatureTest.cs b/tests/dont link/iOSApiSignatureTest.cs new file mode 100644 index 000000000000..c1b5a7f7eeb0 --- /dev/null +++ b/tests/dont link/iOSApiSignatureTest.cs @@ -0,0 +1,181 @@ +// +// iOS tests for the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; + +using NUnit.Framework; +using TouchUnit.Bindings; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +using UIKit; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace MonoTouchFixtures{ + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiSignatureTest : ApiSignatureTest { + + public iOSApiSignatureTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override int Size (Type t, bool simd = false) + { + switch (t.Name) { + // rdar 21375616 - Breaking change with EventKit[UI] enum base type + // EventKit.EK* enums are anonymous enums in 10.10 and iOS 8, but an NSInteger in 10.11 and iOS 9. + case "EKCalendarChooserSelectionStyle": + case "EKCalendarChooserDisplayStyle": + if (!IsOSX11OrIOS9) + return 4; + break; + } + return base.Size (t, simd); + } + + protected override bool Skip (Type type, MethodBase method, string selector) + { + switch (type.Name) { + case "UIAlertView": + // variable length parameters ... + if (selector == "initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:") + return true; + break; + case "UIViewController": + switch (selector) { + // offically added in 6.0 - but retroactively supported in iOS5 (including documentation) + // the code works (see monotouch-test.app) but Apple changed their return value in 6.0 + // (they used to return `bool`) + case "beginAppearanceTransition:animated:": + case "endAppearanceTransition": + if (!CheckiOSOrTVOSSystemVersion (6,0)) + return true; + break; + } + break; + case "NKIssue": + // Apple "promoted" this to `NSInteger` in iOS8 but this already existed (as a 32bits value) in iOS 7.x + // sadly, and even with a bug report with a few exchanges, this was not fixed before iOS8 GM :-( + // 64bits application for iOS 7.x will be uncommon so we prefer to be forward compatible + if (selector == "status") + return !CheckiOSSystemVersion (8,0); + break; + case "CMMotionManager": + // iOS 8.3 changed CMMotionManager from 4 to 8 bytes on 64bits CPU and we have to follow that breaking + // change unless Apple revert that before final. [radar 20295259] + if ((IntPtr.Size == 4) || CheckiOSSystemVersion (8,3)) + return false; + // which means iOS 8.2 (and earlier can't match) + switch (selector) { + case "startDeviceMotionUpdatesUsingReferenceFrame:": + case "startDeviceMotionUpdatesUsingReferenceFrame:toQueue:withHandler:": + case "attitudeReferenceFrame": + return true; + default: + return false; + } + } + + return base.Skip (type, method, selector); + } + + protected override bool IsValidStruct (Type type, string structName) + { + switch (structName) { + // CIImage 'static MonoTouch.CoreImage.CIImage FromImageBuffer(MonoTouch.CoreVideo.CVPixelBuffer)' selector: imageWithCVPixelBuffer: == @12@0:4^{__CVBuffer=} + case "__CVBuffer": + return type.Name == "CVPixelBuffer" || type.Name == "CVImageBuffer"; + } + return base.IsValidStruct (type, structName); + } + + // only handle exception here (to return true) otherwise call base to deal with it + // `caller` is provided to make it easier to detect "special" cases + protected override bool Check (char encodedType, Type type) + { + // return an error if null (instead of throwing) so we can continue execution + if (type == null) + return false; + + switch (encodedType) { + case 'c': // char, used for C# bool +#if !XAMCORE_2_0 + switch (type.FullName) { + // looks like it returns a bool even if documented as a void + // UIPrintInteractionController 'instance Void Present(Boolean, MonoTouch.UIKit.UIPrintInteractionCompletionHandler)' selector: presentAnimated:completionHandler: + // update: documentation (and header) mistake that Apple corrected (IIRC I filled that issue) + case "System.Void": + return CurrentType.Name == "UIPrintInteractionController"; + } +#endif + break; + // float (32 bits) + case 'f': + switch (type.FullName) { + // documented (web and header file) as NSInteger + // UIImageView 'instance Void set_AnimationRepeatCount(Int32)' selector: setAnimationRepeatCount: == v12@0:4f8 + case "System.Int32": + return CurrentType.FullName == "MonoTouch.UIKit.UIImageView"; + } + break; + case 'i': + switch (type.FullName) { + case "MonoTouch.EventKitUI.EKCalendarChooserSelectionStyle": + case "MonoTouch.EventKitUI.EKCalendarChooserDisplayStyle": + case "EventKitUI.EKCalendarChooserSelectionStyle": + case "EventKitUI.EKCalendarChooserDisplayStyle": + return (IntPtr.Size == 4) || !IsOSX11OrIOS9; + case "System.UInt32": + // numberOfTouchesRequired was signed before iOS6, unsigned since then + return true; + } + break; + // unsigned 32 bits + case 'I': + switch (type.FullName) { + case "System.Int32": + // sign-ness mis-binding, several of them (not critical) + // CBATTRequest 'instance Int32 get_Offset()' selector: offset == I8@0:4 + return true; + } + break; + // unsigned 32 bits + case 'L': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // CAMediaTimingFunction 'instance Void GetControlPointAtIndex(Int32, IntPtr)' selector: getControlPointAtIndex:values: == v16@0:4L8[2f]12 + case "System.Int32": + return true; + } + break; + // unsigned 64 bits + case 'Q': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // NSIncrementalStoreNode 'instance Int64 get_Version()' selector: version == Q8@0:4 + case "System.Int64": + return true; + } + break; + } + return base.Check (encodedType, type); + } + } +} \ No newline at end of file diff --git a/tests/dont link/iOSApiTypoTest.cs b/tests/dont link/iOSApiTypoTest.cs new file mode 100644 index 000000000000..40ee7cae415b --- /dev/null +++ b/tests/dont link/iOSApiTypoTest.cs @@ -0,0 +1,55 @@ +using System; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +namespace TouchUnit.Bindings +{ + [TestFixture] + public class iOSApiTypoTest : ApiTypoTest + { +#if !__WATCHOS__ + UITextChecker checker = new UITextChecker (); +#endif + + [SetUp] + public void SetUp () + { +#if __WATCHOS__ + Assert.Fail ("Need to find alternative for UITextChecker on WatchOS."); +#else + // that's slow and there's no value to run it on devices as the API names + // being verified won't change from the simulator + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Typos only detected on simulator"); + + // the dictionary used by iOS varies with versions and + // we don't want to maintain special cases for each version + var sdk = new Version (Constants.SdkVersion); + if (!UIDevice.CurrentDevice.CheckSystemVersion (sdk.Major, sdk.Minor)) + Assert.Ignore ("Typos only verified using the latest SDK"); +#endif + } + + public override string GetTypo (string txt) + { +#if __WATCHOS__ + return string.Empty; +#else + var checkRange = new NSRange (0, txt.Length); + var typoRange = checker.RangeOfMisspelledWordInString (txt, checkRange, checkRange.Location, false, "en_US"); + if (typoRange.Length == 0) + return String.Empty; + return txt.Substring ((int) typoRange.Location, (int) typoRange.Length); +#endif + } + } +} diff --git a/tests/dont link/iOSApiWeakPropertyTest.cs b/tests/dont link/iOSApiWeakPropertyTest.cs new file mode 100644 index 000000000000..dc64ea7825f7 --- /dev/null +++ b/tests/dont link/iOSApiWeakPropertyTest.cs @@ -0,0 +1,56 @@ +using System; +using System.Reflection; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiWeakPropertyTest : ApiWeakPropertyTest { + + public iOSApiWeakPropertyTest () + { + ContinueOnFailure = true; + } + + protected override bool Skip (PropertyInfo property) + { + switch (property.DeclaringType.Name) { + // WeakVideoGravity is an NSString that we could/should provide a better binding (e.g. enum) + case "AVPlayerViewController": + return property.Name == "WeakVideoGravity"; + // CATextLayer.WeakFont is done correctly by hand + case "CATextLayer": + return property.Name == "WeakFont"; + // NSAttributedStringDocumentAttributes is a DictionaryContainer that expose some Weak* NSDictionary + case "NSAttributedStringDocumentAttributes": + return property.Name == "WeakDocumentType" || property.Name == "WeakDefaultAttributes"; + // UIFontAttributes is a DictionaryContainer that expose a Weak* NSDictionary + case "UIFontAttributes": + return property.Name == "WeakFeatureSettings"; + // UIStringAttributes is a DictionaryContainer that expose a Weak* NSString + case "UIStringAttributes": + return property.Name == "WeakTextEffect"; +#if !XAMCORE_3_0 + // #37451 - setter does not exists but we have to keep it for binary compatibility + // OTOH we can't give it a selector (private API) even if we suspect Apple is mostly running `strings` on executable + case "IUIViewControllerPreviewing": + return property.Name == "WeakDelegate"; + case "UIViewControllerPreviewingWrapper": + return property.Name == "WeakDelegate"; +#endif + } + return base.Skip (property); + } + } +} \ No newline at end of file diff --git a/tests/dont link/iOSCoreImageFiltersTest.cs b/tests/dont link/iOSCoreImageFiltersTest.cs new file mode 100644 index 000000000000..d0a54d2ace4f --- /dev/null +++ b/tests/dont link/iOSCoreImageFiltersTest.cs @@ -0,0 +1,37 @@ +// +// Test the generated API for all iOS CoreImage filters +// +// Authors: +// Sebastien Pouliot +// Alex Soto +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using CoreImage; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; +using TouchUnit.Bindings; + +namespace MonoTouchFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSCoreImageFiltersTest : ApiCoreImageFiltersTest { + + + } +} +#endif // !__WATCHOS__ diff --git a/tests/dont link/sample_sorenson.mov b/tests/dont link/sample_sorenson.mov new file mode 100644 index 000000000000..92aa0176adeb Binary files /dev/null and b/tests/dont link/sample_sorenson.mov differ diff --git a/tests/dontlink-mac/.gitignore b/tests/dontlink-mac/.gitignore new file mode 100644 index 000000000000..e82b2790c20e --- /dev/null +++ b/tests/dontlink-mac/.gitignore @@ -0,0 +1,4 @@ +TestResult*xml +dontlink.sln +tests.xml +build diff --git a/tests/dontlink-mac/Info.plist b/tests/dontlink-mac/Info.plist new file mode 100644 index 000000000000..7de8f9e319a1 --- /dev/null +++ b/tests/dontlink-mac/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleDisplayName + apitest + CFBundleIdentifier + com.xamarin.apitest + CFBundleName + apitest + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSPrincipalClass + NSApplication + + diff --git a/tests/dontlink-mac/Mac.cs b/tests/dontlink-mac/Mac.cs new file mode 100644 index 000000000000..3c8845b011f6 --- /dev/null +++ b/tests/dontlink-mac/Mac.cs @@ -0,0 +1,40 @@ +// +// Mac-specific Helpers +// +// Authors: +// Sebastien Pouliot +// Aaron Bockover +// +// Copyright 2012-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using ObjCRuntime; +#else +using MonoMac.ObjCRuntime; +#endif + +using TouchUnit.Bindings; + +namespace MonoMacFixtures { + + public static class Mac { + public static readonly Version Version_10_7 = new Version (10, 7); + public static readonly Version Version_10_8 = new Version (10, 8); + public static readonly Version Version_10_9 = new Version (10, 9); + public static readonly Version Version_10_10 = new Version (10, 10); + public static readonly Version Version_10_11 = new Version (10, 11); + + static PlatformInfo host => PlatformInfo.Host; + + public static bool CheckSystemVersion (int major, int minor) => host.Version >= new Version (major, minor); + public static bool Is32BitMavericks => host.IsArch32 && IsAtLeast (Version_10_9); + public static bool IsYosemiteOrHigher => IsAtLeast (Version_10_10); + public static bool IsElCapitanOrHigher => IsAtLeast (Version_10_11); + public static bool IsAtLeast (int major, int minor) => IsAtLeast (new Version (major, minor)); + public static bool IsAtLeast (Version version) => host.IsMac && host.Version >= version; + } +} diff --git a/tests/dontlink-mac/MacApiCtorInitTest.cs b/tests/dontlink-mac/MacApiCtorInitTest.cs new file mode 100644 index 000000000000..9f474d846148 --- /dev/null +++ b/tests/dontlink-mac/MacApiCtorInitTest.cs @@ -0,0 +1,245 @@ +// +// Mac-specific `init*` selectors validations +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013,2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoMac.Foundation; +#endif + +using NUnit.Framework; +using TouchUnit.Bindings; + +namespace MonoMacFixtures { + + [TestFixture] + public class MacApiCtorInitTest : ApiCtorInitTest { + + public MacApiCtorInitTest () + { + //LogProgress = true; + ContinueOnFailure = true; + } + + protected override bool Skip (Attribute attr) + { + return base.Skip (attr); + } + + protected override bool Skip (Type type) + { + switch (type.FullName) { + // These should be DisableDefaultCtor but can't due to backward compat + case "MonoMac.EventKit.EKParticipant": + case "EventKit.EKParticipant": + case "XamCore.CoreImage.CISampler": + case "CoreImage.CISampler": + return true; + // OSX 10.8+ + case "MonoMac.AppKit.NSSharingService": + case "AppKit.NSSharingService": + case "MonoMac.AppKit.NSSharingServicePicker": + case "AppKit.NSSharingServicePicker": + case "MonoMac.Foundation.NSUserNotification": + case "Foundation.NSUserNotification": + case "MonoMac.Foundation.NSUserNotificationCenter": + case "Foundation.NSUserNotificationCenter": + case "MonoMac.AVFoundation.AVPlayerItemVideoOutput": + case "AVFoundation.AVPlayerItemVideoOutput": + case "MonoMac.Foundation.NSUuid": + case "Foundation.NSUuid": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + // Native exception coming from [NSWindow init] which calls + // [NSWindow initWithContentRect:styleMask:backing:defer] + case "MonoMac.AppKit.NSWindow": + case "AppKit.NSWindow": + return true; +#if !XAMCORE_2_0 + case "MonoMac.AppKit.NSToolbar": // mono[10518:626783] *** -[__NSDictionaryM removeObjectForKey:]: key cannot be nil + case "MonoMac.SceneKit.SCNRenderer": // -[SCNRenderer init]: unrecognized selector sent to instance 0x7c6446c0 + case "MonoMac.SceneKit.SCNLookAtConstraint": + return true; +#endif + case "MonoMac.Foundation.NSUrlSession": + case "Foundation.NSUrlSession": + case "MonoMac.Foundation.NSUrlSessionTask": + case "Foundation.NSUrlSessionTask": + case "MonoMac.Foundation.NSUrlSessionDataTask": + case "Foundation.NSUrlSessionDataTask": + case "MonoMac.Foundation.NSUrlSessionUploadTask": + case "Foundation.NSUrlSessionUploadTask": + case "MonoMac.Foundation.NSUrlSessionDownloadTask": + case "Foundation.NSUrlSessionDownloadTask": + case "MonoMac.Foundation.NSUrlSessionConfiguration": + case "Foundation.NSUrlSessionConfiguration": + // These types were introduced as 64-bit only in Mavericks, and 32+64bits in Yosemite. We can't + // express that with our AvailabilityAttribute, we set it as available (for all architectures, since + // we can't distinguish them) starting with Mavericks. + if (Mac.Is32BitMavericks) + return true; + break; + + case "GLKit.GLKSkyboxEffect": + // Crashes inside libGL.dylib, most likely because something hasn't been initialized yet, because + // I can reproduce in an Xcode project if I put [[GLKSkyboxEffect alloc] init]; in main, but it doesn't + // crash in applicationDidFinishLaunching. + // + // frame #0: 0x00007fff8d570db1 libGL.dylib`glGetError + 13 + // frame #1: 0x0000000100025542 GLKit`-[GLKEffect initWithPropertyArray:] + 1142 + // frame #2: 0x0000000100022c2d GLKit`-[GLKSkyboxEffect init] + 493 + // + if (IntPtr.Size == 8) + return true; + break; + +#if !XAMCORE_3_0 + case "SpriteKit.SKView": + // Causes a crash later. Filed as radar://18440271. + // Apple said they won't fix this ('init' isn't a designated initializer) + if (IntPtr.Size == 8) + return true; + break; +#endif + + case "MonoMac.AppKit.NSSpeechRecognizer": + case "AppKit.NSSpeechRecognizer": + // Makes OSX put up "a download is required for speech recognition" dialog. + return true; + + case "MonoMac.Foundation.NSUserActivity": + case "Foundation.NSUserActivity": + // Crashes by default: + // Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Caller did not provide an activityType, and this process does not have a NSUserActivityTypes in its Info.plist. + // but since it looks like the constructor is usable with the proper Info.plist, we can't remove it. + return true; + } + + switch (type.Namespace) { + // OSX 10.8+ + case "MonoMac.Accounts": + case "Accounts": + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.Social": + case "Social": + case "MonoMac.StoreKit": + case "StoreKit": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "SceneKit": + case "MonoMac.SceneKit": + if (!Mac.CheckSystemVersion (10, 8) || IntPtr.Size != 8) + return true; + break; + } + + return base.Skip (type); + } + + protected override void CheckNSObjectProtocol (NSObject obj) + { + switch (obj.GetType ().Name) { + case "NSString": + // according to bots `isKindOf (null)` returns true before Yosemite + break; + case "SBObject": + // *** NSForwarding: warning: object 0x77a49a0 of class '__NSMessageBuilder' does not implement doesNotRecognizeSelector: -- abort + break; + default: + base.CheckNSObjectProtocol (obj); + break; + } + } + + protected override void CheckToString (NSObject obj) + { + switch (obj.GetType ().FullName) { + // native crash calling MonoMac.Foundation.NSObject.get_Description () + case "WebKit.WKNavigationAction": + case "WebKit.WKFrameInfo": // EXC_BAD_ACCESS (code=1, address=0x0) + case "MonoMac.Foundation.NSUrlConnection": + case "Foundation.NSUrlConnection": + case "MonoMac.AppKit.NSLayoutConstraint": // Unable to create description in descriptionForLayoutAttribute_layoutItem_coefficient. Something is nil + case "AppKit.NSLayoutConstraint": + case "MonoMac.AVFoundation.AVPlayerItemTrack": + case "AVFoundation.AVPlayerItemTrack": + // 10.8 + case "MonoMac.AVFoundation.AVComposition": + case "AVFoundation.AVComposition": + case "MonoMac.GameKit.GKPlayer": // Crashing on 10.8.3 from the Apple beta channel for abock (on 2013-01-30) + case "GameKit.GKPlayer": + case "MonoMac.AVFoundation.AVAssetResourceLoadingRequest": // Crashing on 10.9.1 for abock (2014-01-13) + case "AVFoundation.AVAssetResourceLoadingRequest": + case "MonoMac.AVFoundation.AVAssetResourceLoadingDataRequest": // Crashes on 10.9.3 for chamons (constructor found in AVCompat) + case "AVFoundation.AVAssetResourceLoadingDataRequest": + case "MonoMac.AVFoundation.AVCaptureDeviceInputSource": // Crashes on 10.9.5 + case "AVFoundation.AVCaptureDeviceInputSource": + break; + default: + base.CheckToString (obj); + break; + } + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.FullName) { + // FIXME: those crash the application when Dispose is called + case "MonoMac.JavaScriptCore.JSManagedValue": + case "JavaScriptCore.JSManagedValue": + // JSManagedValue crashes in Yosemite (b7), but not Mavericks. + if (!Mac.CheckSystemVersion (10, 10)) + goto default; + goto case "MonoMac.ImageKit.IKScannerDeviceView"; // fallthrough + case "MonoMac.ImageKit.IKScannerDeviceView": // 19835 + case "ImageKit.IKScannerDeviceView": + case "MonoMac.AppKit.NSFontPanel": // *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x11491cc00 of class NSButton was deallocated while key value observers were still registered with it. + case "AppKit.NSFontPanel": + case "MonoMac.AVFoundation.AVAudioRecorder": // same on iOS + case "AVFoundation.AVAudioRecorder": + case "MonoMac.Foundation.NSUrlConnection": + case "Foundation.NSUrlConnection": + // 10.8: + case "MonoMac.Accounts.ACAccount": // maybe the default .ctor is not allowed ? + case "Accounts.ACAccount": + case "MonoMac.Accounts.ACAccountCredential": + case "Accounts.ACAccountCredential": + case "MonoMac.Accounts.ACAccountStore": + case "Accounts.ACAccountStore": + case "MonoMac.Accounts.ACAccountType": + case "Accounts.ACAccountType": + case "MonoMac.CoreData.NSPersistentStoreCoordinator": + case "CoreData.NSPersistentStoreCoordinator": + do_not_dispose.Add (obj); + break; + // 10.11 + case "MonoMac.CoreImage.CIImageAccumulator": + case "CoreImage.CIImageAccumulator": + case "WebKit.WKNavigation": + // crashes on El Capitan (b2) but not before + if (!Mac.CheckSystemVersion (10, 11)) + goto default; + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + } +} diff --git a/tests/dontlink-mac/MacApiFieldTest.cs b/tests/dontlink-mac/MacApiFieldTest.cs new file mode 100644 index 000000000000..da552d7a12cb --- /dev/null +++ b/tests/dontlink-mac/MacApiFieldTest.cs @@ -0,0 +1,233 @@ +// +// Mac specific fields validator +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Linq; +using System.Reflection; + +using NUnit.Framework; +using TouchUnit.Bindings; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +namespace MonoMacFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MacApiFieldTest : ApiFieldTest { + + public MacApiFieldTest () + { + ContinueOnFailure = true; + } + + static bool IsUnified { + get + { + return AppDomain.CurrentDomain.GetAssemblies().Any(x => x.FullName.Contains("Xamarin.Mac")); + } + } + + protected override bool Skip (Type type) + { + switch (type.FullName) { + // OS X 10.8 + + case "MonoMac.AppKit.NSSharingService": + case "AppKit.NSSharingService": + case "MonoMac.Foundation.NSUserNotification": + case "Foundation.NSUserNotification": + return !Mac.CheckSystemVersion (10, 8); + } + + switch (type.Namespace) { + // OSX 10.8+ + case "MonoMac.Accounts": + case "Accounts": + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.Social": + case "Social": + return !Mac.CheckSystemVersion (10, 8); + case "SceneKit": + case "MonoMac.SceneKit": + return !Mac.CheckSystemVersion (10, 8) || IntPtr.Size != 8; + default: + return false; + } + } + + protected override bool Skip (PropertyInfo p) + { + switch (p.DeclaringType.Name) { + case "NSUrlSessionDownloadDelegate": + switch (p.Name) { + case "TaskResumeDataKey": + // This field was introduced as 64-bit only in Mavericks, and 32+64bits in Yosemite. We can't + // express that with our AvailabilityAttribute, we set it as available (for all architectures, since + // we can't distinguish them) starting with Mavericks. + if (Mac.Is32BitMavericks) + return true; + break; + } + break; + } + + switch (p.Name) { + // NSTableView + case "RowViewKey": + return true; + // NSBitmapImageRep + case "CompressionMethod": + case "CompressionFactor": + case "DitherTransparency": + return true; + // CIImage 10.8+ + case "AutoAdjustFeaturesKey": // kCIImageAutoAdjustFeatures - documented in 10.8 + case "AutoAdjustRedEyeKey": + case "AutoAdjustEnhanceKey": + case "CIImagePropertiesKey": + return true; + // CIImage + case "CIImageColorSpaceKey": + return true; // returns null but documented prior to 10.8 + // CLLocation 10.8+ + case "ErrorUserInfoAlternateRegionKey": // kCLErrorUserInfoAlternateRegionKey also returns null on iOS + return true; + // NSUrl 10.8+ + case "PathKey": + return !Mac.CheckSystemVersion (10, 8); + // AVMediaCharacteristic 10.8+ + case "IsMainProgramContent": + case "IsAuxiliaryContent": + case "ContainsOnlyForcedSubtitles": + case "TranscribesSpokenDialogForAccessibility": + case "DescribesMusicAndSoundForAccessibility": + case "DescribesVideoForAccessibility": + return !Mac.CheckSystemVersion (10, 8); + // AVVideo 10.8+ + case "ProfileLevelH264Main32": + return !Mac.CheckSystemVersion (10, 8); + // AVMetadata 10.8+ + case "QuickTimeUserDataKeyTaggedCharacteristic": + return !Mac.CheckSystemVersion (10, 8); + // CIDetector + case "TypeFace": // CIDetectorTypeFace - documented as available in 10.7 + case "Accuracy": // CIDetectorAccuracy 10.7 + case "AccuracyLow": // CIDetectorAccuracyLow 10.7 + case "AccuracyHigh": // CIDetectorAccuracyHigh 10.7 + return true; + // CIDetector + case "ImageOrientation": // documented in 10.8 + case "Tracking": + case "MinFeatureSize": + return true; + // CGImageProperties - all new (10.7) values are missing (from pre-6 iOS too iirc) + case "ExifCameraOwnerName": // kCGImagePropertyExifCameraOwnerName + case "ExifBodySerialNumber": // kCGImagePropertyExifBodySerialNumber + case "ExifLensSpecification": // kCGImagePropertyExifLensSpecification + case "ExifLensMake": // kCGImagePropertyExifLensMake + case "ExifLensModel": // kCGImagePropertyExifLensModel + case "ExifLensSerialNumber": // kCGImagePropertyExifLensSerialNumber + return true; + // ACErrorDomain is _listed_ in the 10.8 Accounts Changes but like iOS it's not documented anywhere else (and does not seems to exists) + case "ErrorDomain": + // ACAccountStoreDidChangeNotification - documented in 10.8 + case "ChangeNotification": + // ACAccountType - documented in 10.8 + case "Twitter": // ACAccountTypeIdentifierTwitter + case "SinaWeibo": + case "Facebook": + case "AppId": // ACFacebookAppIdKey + case "Permissions": // ACFacebookPermissionsKey + case "Audience": // *** NOT documented in 10.8 - but part of our API enhancement + case "Everyone": // ^ MonoMac.Accounts.ACFacebookAudienceValue.Everyone + case "Friends": // ^ MonoMac.Accounts.ACFacebookAudienceValue.Friends + case "OnlyMe": // ^ MonoMac.Accounts.ACFacebookAudienceValue.OnlyMe + return true; + // MonoMac.CoreServices.CFHTTPMessage - document in 10.9 but returns null + case "_AuthenticationSchemeOAuth1": + return true; + default: + return base.Skip (p); + } + } + + protected override bool Skip (string constantName) + { + switch (constantName) { + // Only there for API compat + case "kSecUseNoAuthenticationUI": + case "kSecUseOperationPrompt": + return !IsUnified; + // MonoMac.CoreServices.CFHTTPMessage - document in 10.9 but returns null + case "kCFHTTPAuthenticationSchemeOAuth1": + return true; + // kCLErrorUserInfoAlternateRegionKey also returns null on iOS + case "kCLErrorUserInfoAlternateRegionKey": + return true; + case "NSURLSessionTransferSizeUnknown": + case "NSURLSessionDownloadTaskResumeData": + if (Mac.Is32BitMavericks) + return true; + goto default; + default: + return base.Skip (constantName); + } + } + + protected override string FindLibrary (string libraryName, bool requiresFullPath = false) + { + switch (libraryName) { + case "CFNetwork": + if (Mac.IsAtLeast (10,8)) + break; + return "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/CFNetwork"; + case "CoreText": + case "CoreGraphics": + if (Mac.IsAtLeast (10,8)) + break; + return string.Format ("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/{0}.framework/{0}", libraryName); + case "ImageIO": + if (Mac.IsAtLeast (10,9)) + break; + return "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/ImageIO"; + case "CoreImage": + // generated code uses QuartzCore correctly - even if the [Field] property is wrong + libraryName = "QuartzCore"; + break; + case "QuartzComposer": + case "PdfKit": + case "ImageKit": + // generated code uses Quartz correctly - even if the [Field] property is wrong + libraryName = "Quartz"; + break; + case "CoreBluetooth": + if (Mac.IsYosemiteOrHigher) { + // CoreBluetooth is in /System/Library/Frameworks/CoreBluetooth.framework starting with Yosemite. + break; + } + + // CoreBluetooth is inside IOBluetooth.framework in earlier OSXs + return "/System/Library/Frameworks/IOBluetooth.framework/Versions/A/Frameworks/CoreBluetooth.framework/CoreBluetooth"; + case "SearchKit": + return "/System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/SearchKit"; + } + + return base.FindLibrary (libraryName, requiresFullPath); + } + } +} diff --git a/tests/dontlink-mac/MacApiPInvokeTest.cs b/tests/dontlink-mac/MacApiPInvokeTest.cs new file mode 100644 index 000000000000..df2399fdc59b --- /dev/null +++ b/tests/dontlink-mac/MacApiPInvokeTest.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using System.IO; +using System.Reflection; + +using NUnit.Framework; +using TouchUnit.Bindings; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +namespace MonoMacFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MacApiPInvokeTest : ApiPInvokeTest { + protected override bool SkipLibrary (string libraryName) + { + switch (libraryName){ + case "/System/Library/Frameworks/OpenGL.framework/OpenGL": + return true; + } + return base.SkipLibrary (libraryName); + } + + static bool IsUnified { + get + { + return AppDomain.CurrentDomain.GetAssemblies().Any(x => x.FullName.Contains("Xamarin.Mac")); + } + } + + protected override bool Skip (Type type) + { + string typeName = type.ToString (); + bool is32Bit = IntPtr.Size == 4; + if (is32Bit && typeName.StartsWith ("MapKit")) // MapKit is 64-bit only + return true; + + switch (type.Namespace) { + case "SceneKit": + case "MonoMac.SceneKit": + if (is32Bit) + return true; + break; + } + + switch (typeName) { + case "MonoMac.GameController.GCExtendedGamepadSnapshot": // These next 4 are in the compat API, even if they don't work. + case "MonoMac.GameController.GCGamepadSnapshot": + case "MonoMac.GameController.GCExtendedGamepadSnapShotDataV100": + case "MonoMac.GameController.GCGamepadSnapShotDataV100": + return !IsUnified; + case "GameController.GCGamepadSnapShotDataV100": // These are 64-bit only + case "GameController.GCExtendedGamepadSnapShotDataV100": + return is32Bit; + case "MonoMac.AudioToolbox.AudioSession": // These are iOS APIs that were mistakenly pulled into OSX. Removed in unified but not classic + case "MonoMac.AudioUnit.AudioUnitUtils": + return !IsUnified; // If these are in unified, don't skip, we want to scream + } + + return base.Skip(type); + } + + protected override bool Skip (string symbolName) + { + switch (symbolName) { + case "SKTerminateForInvalidReceipt": // Only there for API compat + return !IsUnified; + } + return false; + } + + protected override bool SkipAssembly (Assembly a) + { + // too many things are missing from XM 32bits bindings + // and the BCL is identical for 64 bits (no need to test it 3 times) +// return IntPtr.Size == 4; + return true; // skip everything until fixed + } + } +} \ No newline at end of file diff --git a/tests/dontlink-mac/MacApiProtocolTest.cs b/tests/dontlink-mac/MacApiProtocolTest.cs new file mode 100644 index 000000000000..a4125d0d1443 --- /dev/null +++ b/tests/dontlink-mac/MacApiProtocolTest.cs @@ -0,0 +1,176 @@ +// +// Test the generated API for common protocol support +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +using System; + +#if XAMCORE_2_0 +using Foundation; +using AppKit; +using CoreImage; +#else +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.CoreImage; +#endif + +using NUnit.Framework; + +using TouchUnit.Bindings; + +namespace MonoMacFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MonoMacFixtures : ApiProtocolTest { + + protected override bool Skip (Type type, string protocolName) + { + switch (protocolName) { + case "NSSecureCoding": + switch (type.Name) { + case "NSCachedImageRep": // Not declared in header file + case "NSCIImageRep": + case "NSCustomImageRep": + case "NSEPSImageRep": + case "NSBitmapImageRep": + case "NSImageRep": + case "NSPdfImageRep": + case "AVAssetTrackSegment": // Not declared in header file + case "AVComposition": // Not declared in header file + case "AVMutableComposition": // Not declared in header file + case "AVCompositionTrackSegment": // Not declared in header file + case "MKMapSnapshotOptions": // Not declared in header file + case "NSTextTab": // Not declared in header file + return true; + default: + // CIFilter started implementing NSSecureCoding in 10.11 + if (!Mac.CheckSystemVersion (10, 11) && (type == typeof(CIFilter) || type.IsSubclassOf (typeof(CIFilter)))) + return true; + break; + } + break; + case "NSCopying": + switch (type.Name) { + case "DomNodeFilter": // Not declared in header file + case "MKDirectionsRequest": // Not declared in header file + case "EKObject": // Not declared in header file + case "EKCalendarItem": // Not declared in header file + case "EKSource": // Not declared in header file + case "EKCalendar": // Not declared in header file + case "EKEvent": // Not declared in header file + case "EKReminder": // Not declared in header file + case "ACAccount": // Not declared in header file + return true; + } + break; + case "NSMutableCopying": + switch (type.Name) { + case "EKObject": // Not declared in header file + case "EKCalendarItem": // Not declared in header file + case "EKSource": // Not declared in header file + case "EKStructuredLocation": // Not declared in header file + case "EKAlarm": // Not declared in header file + case "EKCalendar": // Not declared in header file + case "EKEvent": // Not declared in header file + case "EKParticipant": // Not declared in header file + case "EKRecurrenceRule": // Not declared in header file + case "EKReminder": // Not declared in header file + return true; + } + break; + case "NSCoding": + switch (type.Name) { + case "EKObject": // Not declared in header file + case "EKCalendarItem": // Not declared in header file + case "EKSource": // Not declared in header file + case "EKStructuredLocation": // Not declared in header file + case "EKAlarm": // Not declared in header file + case "EKCalendar": // Not declared in header file + case "EKEvent": // Not declared in header file + case "EKParticipant": // Not declared in header file + case "EKRecurrenceRule": // Not declared in header file + case "EKReminder": // Not declared in header file + case "AVAssetTrackSegment": // Not declared in header file + case "AVComposition": // Not declared in header file + case "AVMutableComposition": // Not declared in header file + case "AVCompositionTrackSegment": // Not declared in header file + case "MKMapSnapshotOptions": // Not declared in header file + return true; + } + break; + case "NSWindowRestoration": + switch (type.Name) { + case "NSDocumentController": + // There's a category that implements the NSWindowRestoration protocol for NSDocumentController, + // but that apparently doesn't make conformsToProtocol: return true. + // '@interface NSDocumentController (NSWindowRestoration) ' + return true; + } + break; + case "NSUserInterfaceItemIdentification": + // NSViewController started implementing NSUserInterfaceItemIdentification in 10.10 + if (!Mac.CheckSystemVersion (10, 10) && (type == typeof(NSViewController) || type.IsSubclassOf (typeof (NSViewController)))) + return true; + + break; + case "NSMenuDelegate": + switch (type.Name) { + case "PdfView": + if (!Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + break; + case "NSTextFinderClient": // Not listed in header, nor conformsToProtocol, but works in sample. But it just repondsToSelectors + if (type.Name == "NSTextView") + return true; + break; +#if !XAMCORE_4_0 + case "NSDraggingInfo": + return true; // We have to keep the type to maintain backwards compatibility. +#endif + } + + switch (type.Name) { +#if !XAMCORE_3_0 + case "NSRemoteSavePanel": + case "NSRemoteOpenPanel": + return true; // These two classes don't show up in any documentation. +#endif + } + + switch (type.Namespace) { + case "MonoMac.SceneKit": + case "SceneKit": + return IntPtr.Size == 4; // 64bits should be fine + } + + return base.Skip (type, protocolName); + } + + [Test] + public override void SecureCoding () + { + if (!Mac.CheckSystemVersion (10, 8)) + return; + + base.SecureCoding (); + } + + [Test] + public override void SupportsSecureCoding () + { + if (!Mac.CheckSystemVersion (10,8)) + return; + + base.SupportsSecureCoding (); + } + } +} diff --git a/tests/dontlink-mac/MacApiSelectorTest.cs b/tests/dontlink-mac/MacApiSelectorTest.cs new file mode 100644 index 000000000000..9d5d361c1e1c --- /dev/null +++ b/tests/dontlink-mac/MacApiSelectorTest.cs @@ -0,0 +1,819 @@ +// +// Mac specific selector validators +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +using NUnit.Framework; +using TouchUnit.Bindings; + +namespace MonoMacFixtures { + + [TestFixture] + public class MacApiSelectorTest : CoreSelectorTest { + + static MacApiSelectorTest () + { + Runtime.RegisterAssembly (typeof (NSObject).Assembly); + } + + public MacApiSelectorTest () + { + //LogProgress = true; Don't uncomment this anymore, export API_TEST_LOG_PROGRESS=1 + ContinueOnFailure = true; + } + + protected override bool Skip (Type type) + { + switch (type.FullName) { + case "MonoMac.CIFilter.CIMaskedVariableBlur": // Appears to be missing from 10.11, not documented + case "CIFilter.CIMaskedVariableBlur": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + case "MonoMac.Foundation.NSUrlSession": + case "Foundation.NSUrlSession": + case "MonoMac.Foundation.NSUrlSessionTask": + case "Foundation.NSUrlSessionTask": + case "MonoMac.Foundation.NSUrlSessionDataTask": + case "Foundation.NSUrlSessionDataTask": + case "MonoMac.Foundation.NSUrlSessionUploadTask": + case "Foundation.NSUrlSessionUploadTask": + case "MonoMac.Foundation.NSUrlSessionDownloadTask": + case "Foundation.NSUrlSessionDownloadTask": + case "MonoMac.Foundation.NSUrlSessionConfiguration": + case "Foundation.NSUrlSessionConfiguration": + // These classes are available in 32-bit Yosemite, or 32+64bit Mavericks. + if (IntPtr.Size == 4 && !Mac.CheckSystemVersion (10, 10)) + return true; + break; + case "MonoMac.AppKit.NSSharingService": + case "AppKit.NSSharingService": + case "MonoMac.AppKit.NSSharingServicePicker": + case "AppKit.NSSharingServicePicker": + case "MonoMac.Foundation.NSByteCountFormatter": + case "Foundation.NSByteCountFormatter": + case "MonoMac.Foundation.NSUserNotification": + case "Foundation.NSUserNotification": + case "MonoMac.Foundation.NSUserNotificationCenter": + case "Foundation.NSUserNotificationCenter": + case "MonoMac.AVFoundation.AVPlayerItemOutput": + case "AVFoundation.AVPlayerItemOutput": + case "MonoMac.AVFoundation.AVPlayerItemVideoOutput": + case "AVFoundation.AVPlayerItemVideoOutput": + case "MonoMac.Foundation.NSUuid": + case "Foundation.NSUuid": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + } + + switch (type.Namespace) { + // OSX 10.8+ + case "MonoMac.Accounts": + case "Accounts": + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.Social": + case "Social": + case "MonoMac.StoreKit": + case "StoreKit": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "SceneKit": + case "MonoMac.SceneKit": + if (!Mac.CheckSystemVersion (10, 8) || IntPtr.Size != 8) + return true; + break; + // not installed by default + case "MonoMac.Growl": + case "Growl": + return true; + } + + return base.Skip (type); + } + + protected override bool Skip (Type type, string selectorName) + { + switch (selectorName) { +#if !XAMCORE_4_0 + case "xamarinselector:removed:": + return true; +#endif +#if !XAMCORE_3_0 + case "initWithPasteboardPropertyList:ofType:": + // This is a broken binding, but it's an abstract protocol + // method, so there's no way to remove it without breaking + // compat. + return true; +#endif + case "waitUntilExit": + // category, NSTask won't respond -> @interface NSTask (NSTaskConveniences) + if (type.Name == "NSTask") + return true; + break; + case "readInBackgroundAndNotifyForModes:": + case "readInBackgroundAndNotify": + case "readToEndOfFileInBackgroundAndNotifyForModes:": + case "readToEndOfFileInBackgroundAndNotify": + case "acceptConnectionInBackgroundAndNotifyForModes:": + case "acceptConnectionInBackgroundAndNotify": + case "waitForDataInBackgroundAndNotifyForModes:": + case "waitForDataInBackgroundAndNotify": + // category, NSFileHandle won't respond -> @interface NSFileHandle (NSFileHandleAsynchronousAccess) + if (type.Name == "NSFileHandle") + return true; + break; + // initWithPlayerIDs: works (valid handle) and is documented - but does not respond when queried + case "initWithPlayerIDs:": + if (type.Name == "GKLeaderboard") + return true; + break; + // some types had NSCopying added after they were first introduced + case "copyWithZone:": + if (type.Name == "CBPeripheral" && !Mac.CheckSystemVersion (10, 9)) + return true; + break; + case "readingOptionsForType:pasteboard:": + case "writingOptionsForType:pasteboard:": + return true; // Optional selectors on NSPasteboardReading/NSPasteboardWriting + } + + switch (type.Namespace) { + // Notifications seems to follow a pattern were selectors are routed to an internal concrete type + case "MonoMac.Foundation": + case "Foundation": + switch (type.Name) { + // looks like it's routed to (private) NSConcreteUserNotificationCenter + case "NSUserNotificationCenter": + switch (selectorName) { + case "delegate": + case "setDelegate:": + case "scheduledNotifications": + case "setScheduledNotifications:": + case "deliveredNotifications": + return true; + } + break; + // looks like it's routed to (private) NSConcreteUserNotification + case "NSUserNotification": + switch (selectorName) { + case "title": + case "setTitle:": + case "subtitle": + case "setSubtitle:": + case "informativeText": + case "setInformativeText:": + case "actionButtonTitle": + case "setActionButtonTitle:": + case "userInfo": + case "setUserInfo:": + case "deliveryDate": + case "setDeliveryDate:": + case "deliveryTimeZone": + case "setDeliveryTimeZone:": + case "deliveryRepeatInterval": + case "setDeliveryRepeatInterval:": + case "actualDeliveryDate": + case "isPresented": + case "isRemote": + case "soundName": + case "setSoundName:": + case "hasActionButton": + case "setHasActionButton:": + case "activationType": + case "otherButtonTitle": + case "setOtherButtonTitle:": + return true; + } + break; + case "NSFileHandle": //Fails on Lion + case "NSUrlAuthenticationChallenge": + case "NSUrlCredential": + case "NSUrlProtectionSpace": + case "NSAppleEventDescriptor": + if (selectorName == "encodeWithCoder:" && !Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "NSValue": + switch (selectorName) { + case "SCNMatrix4Value": + case "SCNVector3Value": + case "SCNVector4Value": + case "valueWithSCNMatrix4:": + if (IntPtr.Size != 8) + return true; + break; + } + break; + case "NSUrlSession": + switch (selectorName) { + case "delegateQueue": + case "sessionDescription": + case "setSessionDescription:": + case "delegate": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionStreamTask": + switch (selectorName) { + case "captureStreams": + case "closeRead": + case "closeWrite": + case "readDataOfMinLength:maxLength:timeout:completionHandler:": + case "startSecureConnection": + case "stopSecureConnection": + case "writeData:timeout:completionHandler:": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionTask": + switch (selectorName) { + case "countOfBytesExpectedToReceive": + case "countOfBytesExpectedToSend": + case "countOfBytesReceived": + case "countOfBytesSent": + case "currentRequest": + case "error": + case "originalRequest": + case "response": + case "state": + case "taskDescription": + case "setTaskDescription:": + case "taskIdentifier": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionConfiguration": + if (Mac.IsAtLeast (10, 11)) + return true; + break; + } + break; + case "MonoMac.AppKit": + case "AppKit": + switch (type.Name) { +#if !XAMCORE_3_0 // These should be not be marked [Abstract] but can't fix w/o breaking change... + case "NSScrollView": + case "NSTextView": + switch (selectorName) { + case "contentViewAtIndex:effectiveCharacterRange:": + case "didReplaceCharacters": + case "drawCharactersInRange:forContentView:": + case "rectsForCharacterRange:": + case "replaceCharactersInRange:withString:": + case "scrollRangeToVisible:": + case "shouldReplaceCharactersInRanges:withStrings:": + case "stringAtIndex:effectiveRange:endsWithSearchBoundary:": + case "stringLength": + case "allowsMultipleSelection": + case "isEditable": + case "firstSelectedRange": + case "isSelectable": + case "selectedRanges": + case "setSelectedRanges:": + case "string": + case "visibleCharacterRanges": + return true; + } + break; +#endif + case "NSMenuDelegate": + switch (selectorName) { +#if !XAMCORE_3_0 + case "menu:willHighlightItem:": + return true; // bound +#endif + } + break; + case "NSResponder": + switch (selectorName) { + case "smartMagnifyWithEvent:": + case "quickLookWithEvent:": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + } + break; + case "NSViewController": + switch (selectorName) { + case "identifier": // + case "setIdentifier:": + // In Yosemite (but not before) NSViewController implements the NSUserInterfaceItemIdentification + // protocol (which brings a r/w Identifier property). We don't have any way of expressing that + // a type started implementing a protocol in a particular version, so just ignore these selectors. + if (!Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + break; + } + break; + // GameKit seems to follow a pattern were selectors are routed to an internal concrete type + case "MonoMac.GameKit": + case "GameKit": + switch (type.Name) { + case "GKTurnBasedExchange": + switch (selectorName) { + case "completionDate": + case "data": + case "exchangeID": + case "sendDate": + case "timeoutDate": + return true; + } + break; + case "GKTurnBasedExchangeReply": + switch (selectorName) { + case "data": + case "replyDate": + return true; + } + break; + // looks like it's routed to (private) GKDialogController_Concrete + case "GKDialogController": + switch (selectorName) { + case "parentWindow": + case "setParentWindow:": + return true; + } + break; + // looks like it's routed to (private) GKVoiceChat_Concrete + case "GKVoiceChat": + switch (selectorName) { + case "start": + case "stop": + case "setMute:forPlayer:": + case "name": + case "isActive": + case "setActive:": + case "volume": + case "setVolume:": + case "playerStateUpdateHandler": + case "setPlayerStateUpdateHandler:": + case "playerIDs": + return true; + } + break; + // looks like it's routed to (private) GKLeaderboard_Concrete + case "GKLeaderboard": + switch (selectorName) { + case "loadScoresWithCompletionHandler:": + case "timeScope": + case "setTimeScope:": + case "playerScope": + case "setPlayerScope:": + case "maxRange": + case "category": + case "setCategory:": + case "title": + case "range": + case "setRange:": + case "scores": + case "localPlayerScore": + case "groupIdentifier": + case "setGroupIdentifier:": + return true; + } + break; + // looks like it's routed to (private) GKLeaderboard_Concrete + case "GKLocalPlayer": + switch (selectorName) { + case "authenticateWithCompletionHandler:": + case "loadDefaultLeaderboardCategoryIDWithCompletionHandler:": + case "setDefaultLeaderboardCategoryID:completionHandler:": + case "authenticateHandler": + case "setAuthenticateHandler:": + case "loadFriendsWithCompletionHandler:": + case "isAuthenticated": + return true; + } + break; + // looks like it's routed to (private) GKMatch_Concrete + case "GKMatch": + switch (selectorName) { + case "sendData:toPlayers:withDataMode:error:": + case "sendDataToAllPlayers:withDataMode:error:": + case "disconnect": + case "voiceChatWithName:": + case "playerIDs": + case "delegate": + case "setDelegate:": + case "expectedPlayerCount": + return true; + } + break; + // looks like it's routed to (private) GKMatchmater_Concrete + case "GKMatchmaker": + switch (selectorName) { + case "inviteHandler": + case "setInviteHandler:": + case "findMatchForRequest:withCompletionHandler:": + case "findPlayersForHostedMatchRequest:withCompletionHandler:": + case "addPlayersToMatch:matchRequest:completionHandler:": + case "cancel": + case "queryPlayerGroupActivity:withCompletionHandler:": + case "queryActivityWithCompletionHandler:": + return true; + } + break; + } + break; + // Gone in Mavericks + case "MonoMac.StoreKit": + case "StoreKit": + switch (type.Name) { + case "SKPayment": + case "SKMutablePayment": + switch (selectorName) { + case "paymentWithProductIdentifier:": + if (Mac.CheckSystemVersion (10, 9)) + return true; + break; + } + break; + } + break; + case "MonoMac.PdfKit": // Bug 20232 + case "PdfKit": + switch (type.Name) { + case "PdfBorder": // Fails on Lion + case "PdfAnnotation": + if (selectorName == "encodeWithCoder:" && !Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "PdfView": + switch (selectorName) { +#if !XAMCORE_3_0 + case "menu:willHighlightItem:": + return true; +#endif + } + break; + } + break; + case "MonoMac.SceneKit": + case "SceneKit": + switch (type.Name) { + case "SCNGeometryElement": + // Ignore on 10.8 where SCNGeometryPrimitiveType is int (32), but + // on 10.9+ is NSInteger/nint (32/64). SceneKit is next to useless + // on 10.8 anyway. -abock + if (selectorName == "primitiveType" && Mac.CheckSystemVersion (10, 8)) + return true; + // fall through + goto case "SCNCamera"; + case "SCNCamera": + case "SCNGeometry": + case "SCNGeometrySource": + case "SCNLight": + case "SCNMaterial": + case "SCNMaterialProperty": + case "SCNNode": + case "SCNProgram": + case "SCNScene": + case "SCNMorpher": + case "SCNSkinner": + case "SCNConstraint": + case "SCNLevelOfDetail": + // The NSSecureCoding protocol was added to these types in Yosemite, + // and we can't (yet?) describe "type added protocol P in version X.Y" + // with our AvailabilityAttribute, so do this check manually. + if (selectorName == "encodeWithCoder:" && !Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + + switch (type.Name) { + case "SCNGeometry": + // SCNGeometry added the SCNShadable protocol in 10.9, which brings in the 'program' selector. + switch (selectorName) { + case "program": + case "setProgram:": + if (!Mac.CheckSystemVersion (10, 9)) + return true; + break; + } + break; + } + break; + } + return base.Skip (type, selectorName); + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.FullName) { + // FIXME: those crash the application when Dispose is called + case "MonoMac.AVFoundation.AVAudioRecorder": + case "AVFoundation.AVAudioRecorder": + case "MonoMac.Foundation.NSUrlConnection": + case "Foundation.NSUrlConnection": + + // 10.8: + case "MonoMac.Accounts.ACAccount": // maybe the default .ctor is not allowed ? + case "Accounts.ACAccount": + case "MonoMac.Accounts.ACAccountCredential": + case "Accounts.ACAccountCredential": + case "MonoMac.Accounts.ACAccountStore": + case "Accounts.ACAccountStore": + case "MonoMac.Accounts.ACAccountType": + case "Accounts.ACAccountType": + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + + protected override bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + var declaredType = method.DeclaringType; + + switch (name) { + // NSDraggingDestination protocol + case "concludeDragOperation:": // e.g. NSTokenField + case "draggingEnded:": // e.g. NSMatrix + case "draggingExited:": // e.g. NSTokenField + case "draggingUpdated:": // e.g. NSTokenField + case "performDragOperation:": // e.g. NSTokenField + case "prepareForDragOperation:": // e.g. NSTokenField + case "wantsPeriodicDraggingUpdates": // e.g. NSBrowser - optional, [DefaultValue(true)] if it does not exists + return true; + // NSDraggingSource + case "draggedImage:beganAt:": // e.g. NSTextView + case "draggedImage:endedAt:deposited:": // e.g. NSTableView + case "draggedImage:movedTo:": // e.g. NSCollectionView + case "ignoreModifierKeysWhileDragging": // e.g. NSTextView + case "namesOfPromisedFilesDroppedAtDestination:": // e.g. NSTextView + return true; + // NSAnimatablePropertyContainer + case "animationForKey:": // e.g. NSViewAnimation + case "animator": + case "animations": + case "setAnimations:": + return true; + // NSTypeSetter - Layout Phase Interface (needs to be overridden, not really part of the provided types) + case "willSetLineFragmentRect:forGlyphRange:usedRect:baselineOffset:": + case "shouldBreakLineByWordBeforeCharacterAtIndex:": + case "shouldBreakLineByHyphenatingBeforeCharacterAtIndex:": + case "hyphenationFactorForGlyphAtIndex:": + case "hyphenCharacterForGlyphAtIndex:": + case "boundingBoxForControlGlyphAtIndex:forTextContainer:proposedLineFragment:glyphPosition:characterIndex:": + return true; + // in NSView documentation but defined in NSClipView - no answers to call + case "scrollClipView:toPoint:": + return true; + // IKFilterBrowserPanel ??? not clear why + case "finish:": + return true; + // IKFilterUIView + case "viewForUIConfiguration:excludedKeys:": // [Target] on CIFilter + return true; + // NSDictionaryEnumerator + case "fileModificationDate": + case "fileType": + case "filePosixPermissions": + case "fileOwnerAccountName": + case "fileGroupOwnerAccountName": + case "fileSystemNumber": + case "fileSystemFileNumber": + case "fileExtensionHidden": + case "fileHFSCreatorCode": + case "fileHFSTypeCode": + case "fileIsImmutable": + case "fileIsAppendOnly": + case "fileCreationDate": + case "fileOwnerAccountID": + case "fileGroupOwnerAccountID": + return true; // all [Target] on NSDictionary + // SBObject + case "get": + return true; + + // NSCoder - documented as available in 10.8 + case "allowedClasses": + case "requiresSecureCoding": + return true; + + // NSFileManager + case "ubiquityIdentityToken": // documented in 10.8 + return true; + // NS[Mutable]UrlRequest + case "allowsCellularAccess": // documented in 10.8 + case "setAllowsCellularAccess:": // documented in 10.8 + return true; + // NSString + case "capitalizedStringWithLocale:": // documented in 10.8 + case "lowercaseStringWithLocale:": // documented in 10.8 + case "uppercaseStringWithLocale:": // documented in 10.8 + return true; + // AVVideoComposition + case "isValidForAsset:timeRange:validationDelegate:": // documented in 10.8 + return true; + // AVPlayer + case "setRate:time:atHostTime:": // 10.8+ + case "prerollAtRate:completionHandler:": // 10.8+ + case "cancelPendingPrerolls": // 10.8+ + case "masterClock": // 10.8+ + case "setMasterClock:": // 10.8+ + // NSDateComponents + case "isLeapMonth": // 10.8+ + case "setLeapMonth:": // 10.8+ + // NSFileCoordinator + case "itemAtURL:willMoveToURL:": // 10.8+ + return true; // documented (but does not respond) + + // MonoMac.CoreImage.CIDetector (10.8+) + case "featuresInImage:options:": + // MonoMac.CoreImage.CIFaceFeature (10.8+) + case "hasTrackingID": + case "trackingID": + case "hasTrackingFrameCount": + case "trackingFrameCount": + // MonoMac.CoreImage.CIImage : only in 10.8+ + case "properties": // only documented in header files + case "autoAdjustmentFilters": + case "autoAdjustmentFiltersWithOptions:": + // MonoMac.AVFoundation.AVAssetExportSession (10.8+) + case "asset": + // MonoMac.AVFoundation.AVAssetReaderOutput + case "alwaysCopiesSampleData": + case "setAlwaysCopiesSampleData:": + // MonoMac.AVFoundation.AVAssetTrack + case "isPlayable": + // MonoMac.AVFoundation.AVAudioPlayer (10.8+) + case "enableRate": + case "setEnableRate:": + case "rate": + case "setRate:": + // MonoMac.AVFoundation.AVMutableCompositionTrack + case "insertTimeRanges:ofTracks:atTime:error:": + // MonoMac.AVFoundation.AVPlayerItem + case "addOutput:": + case "removeOutput:": + case "canPlayFastReverse": + case "canPlayFastForward": + case "canPlaySlowForward": + case "canPlayReverse": + case "canPlaySlowReverse": + case "canStepForward": + case "canStepBackward": + case "outputs": + case "timebase": + // MonoMac.CoreAnimation.CAAnimation : only on OSX, added for SceneKit + case "usesSceneTimeBase": + case "setUsesSceneTimeBase:": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "initWithString:": + if (declaredType.Name == "NSTextStorage") + return true; + break; + } + + switch (declaredType.Name) { + case "NSUrlSession": + case "Foundation.NSUrlSession": + switch (name) { + case "delegateQueue": + case "sessionDescription": + case "setSessionDescription:": + case "delegate": + if (!Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionTask": + case "Foundation.NSUrlSessionTask": + switch (name) { + case "countOfBytesExpectedToReceive": + case "countOfBytesExpectedToSend": + case "countOfBytesReceived": + case "countOfBytesSent": + case "currentRequest": + case "error": + case "originalRequest": + case "response": + case "state": + case "taskDescription": + case "setTaskDescription:": + case "taskIdentifier": + case "priority": + case "setPriority:": + if (!Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "Foundation.NSUrlSessionStreamTask": + case "NSUrlSessionStreamTask": + switch (name) { + case "captureStreams": + case "closeRead": + case "closeWrite": + case "readDataOfMinLength:maxLength:timeout:completionHandler:": + case "startSecureConnection": + case "stopSecureConnection": + case "writeData:timeout:completionHandler:": + if (!Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + } + +// Console.WriteLine ("{0} {1}", declaredType, name); + return base.CheckResponse (value, actualType, method, ref name); + } + + protected override bool CheckStaticResponse (bool value, Type actualType, Type declaredType, ref string name) + { + switch (name) { + // 10.7 exceptions + + // NSAnimatablePropertyContainer protocol (10.7) -> NSViewAnimation + case "defaultAnimationForKey:": + return true; + + // 10.8 exceptions + + // GKPlayer - documented as available in 10.8 + case "loadPlayersForIdentifiers:withCompletionHandler:": + // SLRequest - documented as available in 10.8 + case "requestForServiceType:requestMethod:URL:parameters:": + // NSDictionary - documented as available in 10.8 + case "dictionaryWithSharedKeySet:": + case "sharedKeySetForKeys:": + // AVMetadataItem - documented as available in 10.8 + case "metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:": + return true; + } + return base.CheckStaticResponse (value, actualType, declaredType, ref name); + } + + protected override bool SkipInit (string selector, MethodBase m) + { + switch (selector) { +#if !XAMCORE_3_0 + // DomEvent + case "initEvent:canBubbleArg:cancelableArg:": + // DomOverflowEvent + case "initOverflowEvent:horizontalOverflow:verticalOverflow:": + // DomUIEvent + case "initUIEvent:canBubble:cancelable:view:detail:": + // DomKeyboardEvent + case "initKeyboardEvent:canBubble:cancelable:view:keyIdentifier:keyLocation:ctrlKey:altKey:shiftKey:metaKey:altGraphKey:": + case "initKeyboardEvent:canBubble:cancelable:view:keyIdentifier:keyLocation:ctrlKey:altKey:shiftKey:metaKey:": + // DomMouseEvent + case "initMouseEvent:canBubble:cancelable:view:detail:screenX:screenY:clientX:clientY:ctrlKey:altKey:shiftKey:metaKey:button:relatedTarget:": + // DomWheelEvent + case "initWheelEvent:wheelDeltaY:view:screenX:screenY:clientX:clientY:ctrlKey:altKey:shiftKey:metaKey:": + // QTMovie + case "movieWithTimeRange:error:": + case "initWithQuickTimeMedia:error:": + // NSAppleEventDescriptor + case "initListDescriptor": + case "initRecordDescriptor": + // NSAnimation + case "initWithDuration:animationCurve:": + return true; +#endif + // NSImage + case "initWithDataIgnoringOrientation:": + var mi = m as MethodInfo; + return mi != null && !mi.IsPublic && mi.ReturnType.Name == "IntPtr"; + default: + return base.SkipInit (selector, m); + } + } + } +} diff --git a/tests/dontlink-mac/MacApiSignatureTest.cs b/tests/dontlink-mac/MacApiSignatureTest.cs new file mode 100644 index 000000000000..ec400e542580 --- /dev/null +++ b/tests/dontlink-mac/MacApiSignatureTest.cs @@ -0,0 +1,235 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; + +using NUnit.Framework; +using TouchUnit.Bindings; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +namespace MonoMacFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MacSignatureTest : ApiSignatureTest { + + static MacSignatureTest () + { + Runtime.RegisterAssembly (typeof (NSObject).Assembly); + } + + public MacSignatureTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type, MethodBase method, string selector) + { + switch (type.Namespace) { + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.StoreKit": + case "StoreKit": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "MonoMac.SceneKit": + case "SceneKit": + // SceneKit is half-baked at best, and they broke compatibility significantly + // from Mountain Lion to Mavericks, so just ignore all problems there. + if (!Mac.CheckSystemVersion (10, 9)) + return true; + break; + } + + // Bug 20232 - This is a hack. + if (selector == "geometryElementWithData:primitiveType:primitiveCount:bytesPerIndex:") + return true; + + switch (type.Name) { + case "AVPlayerItemOutput": + case "AVPlayerItemVideoOutput": + case "NSSharingService": + case "NSSharingServicePicker": + case "NSUserNotification": + case "NSUserNotificationCenter": + case "NSUuid": + return !Mac.CheckSystemVersion (10, 8); + + case "CALayer": + case "CAEmitterLayer": + case "CAGradientLayer": + case "CAOpenGLLayer": + case "CAReplicatorLayer": + case "CAScrollLayer": + case "CAShapeLayer": + case "CATextLayer": + case "CATiledLayer": + case "CATransformLayer": + case "QTCaptureLayer": + case "QTMovieLayer": + case "QCCompositionLayer": + case "AVCaptureVideoPreviewLayer": + case "AVPlayerLayer": + case "SCNLayer": + switch (selector) { + // CAGradientLayer 'instance MonoMac.CoreAnimation.CAConstraint[] get_Constraints()' selector: constraints == @?@: + case "constraints": + // CAGradientLayer 'instance Void set_Constraints(MonoMac.CoreAnimation.CAConstraint[])' selector: setConstraints: == v@:@? + case "setConstraints:": + return true; + } + break; + case "SCNSkinner": + return !Mac.CheckSystemVersion (10, 9); + case "NSGradient": + switch (selector) { + case "initWithColorsAndLocations:": // variable length parameters ... + case "initWithColors:atLocations:colorSpace:": // void * -> nfloat [] (internal) + return true; + } + break; + case "AVAudioIONode": + case "AVAudioUnit": + switch (selector) { + case "audioUnit": // ^{ComponentInstanceRecord=[1l], tested to work in an apitest + return true; + } + break; + } + return base.Skip (type, method, selector); + } + + protected override int Size (Type t, bool simd = false) + { + switch (t.FullName) { + case "GameKit.GKGameCenterViewControllerState": + case "AppKit.NSOpenGLContextParameter": + // NSOpenGLContextParameter and GKGameCenterViewControllerState are anonymous enums in 10.9, but an NSInteger in 10.10. + if (IntPtr.Size == 8 && !Mac.CheckSystemVersion (10, 10)) + return 4; + break; + } + + return base.Size (t, simd); + } + + protected override bool IsValidStruct (Type type, string structName) + { + switch (structName) { + case "_NSPoint": +#if XAMCORE_2_0 + return type.FullName == "CoreGraphics.CGPoint"; +#else + return type.FullName == "System.Drawing.PointF"; +#endif + case "_NSRect": +#if XAMCORE_2_0 + return type.FullName == "CoreGraphics.CGRect"; +#else + return type.FullName == "System.Drawing.RectangleF"; +#endif + case "_NSSize": +#if XAMCORE_2_0 + return type.FullName == "CoreGraphics.CGSize"; +#else + return type.FullName == "System.Drawing.SizeF"; +#endif + case "_SCNVector3": + return type.Name == "SCNVector3"; + case "_SCNVector4": + return type.Name == "SCNVector4"; + // CIImage 'static MonoMac.CoreImage.CIImage FromImageBuffer(MonoMac.CoreVideo.CVImageBuffer)' selector: imageWithCVImageBuffer: == @12@0:4^{__CVBuffer=}8 + // AVAssetWriterInputPixelBufferAdaptor 'instance Boolean AppendPixelBufferWithPresentationTime(MonoMac.CoreVideo.CVPixelBuffer, CMTime)' selector: appendPixelBuffer:withPresentationTime: == c36@0:4^{__CVBuffer=}8{?=qiIq}12 + case "__CVBuffer": + return type.Name == "CVImageBuffer" || type.Name == "CVPixelBuffer";; + case "CATransform3D": + return type.Name == "CATransform3D" || type.Name == "SCNMatrix4"; + case "SCNVector4": + return type.Name == "SCNVector4" || type.Name == "SCNQuaternion"; // "SCNQuaternion is a SCNVector 3, then a nfloat, so same structure + } + return base.IsValidStruct (type, structName); + } + + // only handle exception here (to return true) otherwise call base to deal with it + protected override bool Check (string encodedType, Type type) + { + switch (encodedType) { + case "^{OpaqueSecTrustRef=}": + // On 10.7 and 10.8: + // [FAIL] Signature failure in MonoMac.Foundation.NSUrlCredential initWithTrust: Parameter 'trust' (#1) is encoded as '^{OpaqueSecTrustRef=}' and bound as 'MonoMac.Security.SecTrust' + return type.Name == "SecTrust" || type.FullName == "System.IntPtr"; + } + return base.Check (encodedType, type); + } + + // only handle exception here (to return true) otherwise call base to deal with it + // `caller` is provided to make it easier to detect "special" cases + protected override bool Check (char encodedType, Type type) + { + switch (encodedType) { + case 'i': + switch (type.FullName) { + case "System.nuint": + case "System.UInt32": + // sign-ness mis-binding, not critical + // Signature failure in MonoMac.AppKit.NSViewController presentViewController:asPopoverRelativeToRect:ofView:preferredEdge:behavior: Parameter 'preferredEdge' (#4) is encoded as 'i' and bound as 'System.UInt32' + return true; + case "GameKit.GKGameCenterViewControllerState": + case "AppKit.NSOpenGLContextParameter": + // NSOpenGLContextParameter and GKGameCenterViewControllerState are anonymous enums in 10.9, but an NSInteger in 10.10. + if (IntPtr.Size == 8 && !Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + break; + // unsigned 32 bits + case 'I': + switch (type.FullName) { + case "System.Int32": + // sign-ness mis-binding, several of them (not critical) + // NSActionCell 'instance Int32 get_MnemonicLocation()' selector: mnemonicLocation == I8@0:4 + // NSPathCell 'instance Int32 get_MnemonicLocation()' selector: mnemonicLocation == I8@0:4 + // SCNText 'instance Void InsertMaterial(MonoMac.SceneKit.SCNMaterial, Int32)' selector: insertMaterial:atIndex: == v16@0:4@8I12 + return true; + } + break; + // unsigned 32 bits + case 'L': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // CAMediaTimingFunction 'instance Void GetControlPointAtIndex(Int32, IntPtr)' selector: getControlPointAtIndex:values: == v16@0:4L8[2f]12 + case "System.Int32": + return true; + } + break; + // unsigned 64 bits + case 'Q': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // NSEvent 'instance Int64 get_UniqueID()' selector: uniqueID == Q8@0:4 + case "System.Int64": + return true; + } + break; + } + return base.Check (encodedType, type); + } + } +} diff --git a/tests/dontlink-mac/MacApiWeakPropertyTest.cs b/tests/dontlink-mac/MacApiWeakPropertyTest.cs new file mode 100644 index 000000000000..fc1bc5510b4c --- /dev/null +++ b/tests/dontlink-mac/MacApiWeakPropertyTest.cs @@ -0,0 +1,30 @@ +using System; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoMac.Foundation; +#endif + +using NUnit.Framework; + +using TouchUnit.Bindings; + +namespace MonoMacFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MacApiWeakPropertyTest : ApiWeakPropertyTest { + protected override bool Skip (Type type) + { + switch (type.Name) { + case "CATextLayer": // CATextLayer.WeakFont is done correctly by hand + return true; + case "NSAttributedStringDocumentAttributes": // NSAttributedStringDocumentAttributes.WeakDocumentType is done by hand, not a binding + return true; + } + return base.Skip (type); + } + } +} diff --git a/tests/dontlink-mac/MacCoreImageFiltersTest.cs b/tests/dontlink-mac/MacCoreImageFiltersTest.cs new file mode 100644 index 000000000000..6a74472c936f --- /dev/null +++ b/tests/dontlink-mac/MacCoreImageFiltersTest.cs @@ -0,0 +1,62 @@ +// +// Test the generated API for all Mac CoreImage filters +// +// Authors: +// Sebastien Pouliot +// Alex Soto +// +// Copyright 2013, 2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Reflection; + +using NUnit.Framework; +using TouchUnit.Bindings; + +#if XAMCORE_2_0 +using CoreImage; +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.CoreImage; +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +namespace MonoMacFixtures { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MacCoreImageFiltersTest : ApiCoreImageFiltersTest + { + protected override bool Skip (string nativeName) + { + switch (nativeName) { + case "CIMaskedVariableBlur": // Appears removed in 10.11 but not documented + if (Mac.CheckSystemVersion (10, 11)) + return true; + return false; + case "CICMYKHalftone": // Renamed as CICmykHalftone + return true; + default: + return base.Skip (nativeName); + } + } + } +} + diff --git a/tests/dontlink-mac/dontlink-mac.csproj b/tests/dontlink-mac/dontlink-mac.csproj new file mode 100644 index 000000000000..586104563d72 --- /dev/null +++ b/tests/dontlink-mac/dontlink-mac.csproj @@ -0,0 +1,118 @@ + + + + Debug + x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + dontlink + dontlink-mac + Resources + v4.5 + + + true + full + false + bin\x86\Debug + DEBUG;MONOMAC + prompt + 4 + false + false + Mac Developer + false + false + false + false + x86 + + + true + bin\x86\Release + MONOMAC + prompt + 4 + false + true + Developer ID Application + true + false + true + false + SdkOnly + x86 + + + + + + + + + + ..\..\..\xamarin-macios\external\guiunit\bin\net_4_5\GuiUnit.exe + + + + + + + + + + + + + + CoreSelectorTest.cs + + + ApiBaseTest.cs + + + ApiCtorInitTest.cs + + + ApiFieldTest.cs + + + ApiSelectorTest.cs + + + EnvironmentVariable.cs + + + ApiCoreImageFiltersTest.cs + + + ApiPInvokeTest.cs + + + ApiProtocolTest.cs + + + ApiSignatureTest.cs + + + ApiStructTest.cs + + + PlatformInfo.cs + + + + ApiWeakPropertyTest.cs + + + + + MacTestMain.cs + + + + + + + diff --git a/tests/framework-test/AppDelegate.cs b/tests/framework-test/AppDelegate.cs new file mode 100644 index 000000000000..652920d9e297 --- /dev/null +++ b/tests/framework-test/AppDelegate.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; + +namespace frameworktest +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + UIWindow window; + TouchRunner runner; + + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + // create a new window instance based on the screen size + window = new UIWindow (UIScreen.MainScreen.Bounds); + runner = new TouchRunner (window); + + // register every tests included in the main application/assembly + runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); + + window.RootViewController = new UINavigationController (runner.GetViewController ()); + + // make the window visible + window.MakeKeyAndVisible (); + + return true; + } + } +} + diff --git a/tests/framework-test/Entitlements.plist b/tests/framework-test/Entitlements.plist new file mode 100644 index 000000000000..9ae599370b42 --- /dev/null +++ b/tests/framework-test/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/framework-test/FrameworkTests.cs b/tests/framework-test/FrameworkTests.cs new file mode 100644 index 000000000000..c30bb9f073a8 --- /dev/null +++ b/tests/framework-test/FrameworkTests.cs @@ -0,0 +1,47 @@ +// +// Framework tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 + +using MonoTouch; +using Foundation; +using ObjCRuntime; +using UIKit; + +using NUnit.Framework; + +using Bindings.Test; + +namespace MonoTouchFixtures { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FrameworkTests { + [Test] + public void CFunction () + { + Assert.AreEqual (42, CFunctions.theUltimateAnswer (), "a"); + Assert.AreEqual (42, CFunctions.object_theUltimateAnswer (), "object"); + Assert.AreEqual (42, CFunctions.ar_theUltimateAnswer (), "ar"); + } + + [Test] + public void ObjCClass () + { + using (var obj = new FrameworkTest ()) { + Assert.AreEqual (42, obj.Func (), "a"); + } + } + } +} + +#endif diff --git a/tests/framework-test/Info.plist b/tests/framework-test/Info.plist new file mode 100644 index 000000000000..63055db162d1 --- /dev/null +++ b/tests/framework-test/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleName + framework-test + CFBundleIdentifier + com.xamarin.framework-test + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 8.0 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/tests/framework-test/Main.cs b/tests/framework-test/Main.cs new file mode 100644 index 000000000000..b45a64c2cbf2 --- /dev/null +++ b/tests/framework-test/Main.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace frameworktest +{ + public class Application + { + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } + } +} diff --git a/tests/framework-test/Resources/Default-568h@2x.png b/tests/framework-test/Resources/Default-568h@2x.png new file mode 100644 index 000000000000..29973dcbed50 Binary files /dev/null and b/tests/framework-test/Resources/Default-568h@2x.png differ diff --git a/tests/framework-test/framework-test.csproj b/tests/framework-test/framework-test.csproj new file mode 100644 index 000000000000..bd23088c4f35 --- /dev/null +++ b/tests/framework-test/framework-test.csproj @@ -0,0 +1,107 @@ + + + + Debug + iPhoneSimulator + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 8.0.30703 + 2.0 + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C} + Exe + frameworktest + Resources + frameworktest + MonoTouch + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG; + prompt + 4 + false + i386 + None + true + true + true + true + iPhone Developer + true + + + full + true + bin\iPhone\Release + prompt + 4 + false + ARMv7 + Entitlements.plist + true + true + iPhone Developer + true + + + full + true + bin\iPhoneSimulator\Release + prompt + 4 + false + i386 + None + true + iPhone Developer + true + + + true + full + false + bin\iPhone\Debug + DEBUG; + prompt + 4 + false + ARMv7 + Entitlements.plist + true + iPhone Developer + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + {E40B0B77-3467-4891-9117-7AF8F248E306} + bindings-framework-test + + + \ No newline at end of file diff --git a/tests/fsharp/AppDelegate.fs b/tests/fsharp/AppDelegate.fs new file mode 100644 index 000000000000..6332cac3e3bf --- /dev/null +++ b/tests/fsharp/AppDelegate.fs @@ -0,0 +1,35 @@ +namespace fsharp + +#if !__WATCHOS__ +open System +open System.Reflection + +#if __UNIFIED__ +open UIKit +open Foundation +#else +open MonoTouch.UIKit +open MonoTouch.Foundation +#endif + +open MonoTouch.NUnit.UI + +[] +type AppDelegate () = + inherit UIApplicationDelegate () + + let mutable window = Unchecked.defaultof + let mutable runner = Unchecked.defaultof + + // This method is invoked when the application is ready to run. + override this.FinishedLaunching (app, options) = + window <- new UIWindow (UIScreen.MainScreen.Bounds) + runner <- new TouchRunner (window) + + runner.Add (Assembly.GetExecutingAssembly ()) + + window.RootViewController <- new UINavigationController (runner.GetViewController ()) + window.MakeKeyAndVisible () + + true +#endif // !__WATCHOS__ diff --git a/tests/fsharp/Entitlements.plist b/tests/fsharp/Entitlements.plist new file mode 100644 index 000000000000..9ae599370b42 --- /dev/null +++ b/tests/fsharp/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/fsharp/FSharpTests.fs b/tests/fsharp/FSharpTests.fs new file mode 100644 index 000000000000..5b52270e5a7d --- /dev/null +++ b/tests/fsharp/FSharpTests.fs @@ -0,0 +1,21 @@ +namespace fsharp + +open System +open System.Reflection + +#if __UNIFIED__ +open UIKit +open Foundation +#else +open MonoTouch.UIKit +open MonoTouch.Foundation +#endif + +open NUnit.Framework + +[] +[] +type FSharpTest () = + [] + member x.Func () = + () diff --git a/tests/fsharp/Info.plist b/tests/fsharp/Info.plist new file mode 100644 index 000000000000..99e019b9a1d0 --- /dev/null +++ b/tests/fsharp/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleName + fsharptest + CFBundleIdentifier + com.xamarin.fsharptest + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + MinimumOSVersion + 5.1.1 + + diff --git a/tests/fsharp/Main.fs b/tests/fsharp/Main.fs new file mode 100644 index 000000000000..c726fe69a8af --- /dev/null +++ b/tests/fsharp/Main.fs @@ -0,0 +1,17 @@ +namespace Test + +#if __UNIFIED__ +open UIKit +#else +open MonoTouch.UIKit +#endif + +#if !__WATCHOS__ + +module Main = + [] + let main args = + UIApplication.Main(args, null, "AppDelegate") + 0 + +#endif diff --git a/tests/fsharp/fsharp.fsproj b/tests/fsharp/fsharp.fsproj new file mode 100644 index 000000000000..37e7353b7757 --- /dev/null +++ b/tests/fsharp/fsharp.fsproj @@ -0,0 +1,104 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {7862FE5A-530A-4651-825F-C80836B0A3A1} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{F2A71F9B-5D33-465A-A702-920D77279786} + Exe + fsharp + fsharp + Resources + MonoTouch + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG + prompt + false + iPhone Developer + true + false + true + HttpClientHandler + true + true + None + i386 + + + true + bin\iPhone\Release + + prompt + false + iPhone Developer + HttpClientHandler + true + true + true + Entitlements.plist + ARMv7 + true + None + + + true + bin\iPhoneSimulator\Release + + prompt + false + iPhone Developer + HttpClientHandler + true + true + None + i386 + true + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + false + iPhone Developer + true + true + false + true + HttpClientHandler + true + true + true + Entitlements.plist + None + ARMv7 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/fsharplibrary/AssemblyInfo.fs b/tests/fsharplibrary/AssemblyInfo.fs new file mode 100644 index 000000000000..8d3e9f33b0af --- /dev/null +++ b/tests/fsharplibrary/AssemblyInfo.fs @@ -0,0 +1,20 @@ +namespace fsharplibrary +open System.Reflection +open System.Runtime.CompilerServices + +[] +[] +[] +[] +[] +[] +[] + +// The assembly version has the format {Major}.{Minor}.{Build}.{Revision} + +[] + +//[] +//[] + +() diff --git a/tests/fsharplibrary/ObjCRuntime/RegistrarTest.fs b/tests/fsharplibrary/ObjCRuntime/RegistrarTest.fs new file mode 100644 index 000000000000..28831acb158f --- /dev/null +++ b/tests/fsharplibrary/ObjCRuntime/RegistrarTest.fs @@ -0,0 +1,33 @@ +namespace MonoTouchFixtures + +open System +#if __UNIFIED__ +open Foundation +#else +open MonoTouch.Foundation +#endif + +type Registrar_OutExportClass() = + inherit NSObject() + + abstract member Func: NSObject byref -> IntPtr + + [] + default this.Func ([] value: NSObject byref) = + let tmp = if Object.ReferenceEquals (value, null) then IntPtr.Zero else value.Handle + let value = new NSObject () + tmp + +type Registrar_OutExportDerivedClass() = + inherit Registrar_OutExportClass() + + override this.Func (value: NSObject byref) = + let tmp = if Object.ReferenceEquals (value, null) then IntPtr.Zero else value.Handle + let value = new NSDate () + tmp + +type ClassWithAnonymousFSharpClass() = + let anonymous = { + new NSObject () with + member x.ToString() = "ToString" + } diff --git a/tests/fsharplibrary/fsharplibrary.fsproj b/tests/fsharplibrary/fsharplibrary.fsproj new file mode 100644 index 000000000000..833a1a7cde1b --- /dev/null +++ b/tests/fsharplibrary/fsharplibrary.fsproj @@ -0,0 +1,60 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {C7212169-BA46-413B-91CD-A32C52AD5E0D} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{F2A71F9B-5D33-465A-A702-920D77279786} + Library + fsharplibrary + fsharplibrary + Resources + true + ..\..\..\xamarin-macios\product.snk + MonoTouch + + + true + full + false + bin\Debug + DEBUG + prompt + false + HttpClientHandler + true + true + + + + true + bin\Release + + prompt + false + HttpClientHandler + true + true + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/generator/.gitignore b/tests/generator/.gitignore new file mode 100644 index 000000000000..9ec1f99dd294 --- /dev/null +++ b/tests/generator/.gitignore @@ -0,0 +1,2 @@ +*.source +*.tmpdir diff --git a/tests/generator/Makefile b/tests/generator/Makefile new file mode 100644 index 000000000000..766ed209ad30 --- /dev/null +++ b/tests/generator/Makefile @@ -0,0 +1,129 @@ +TOP=../../../xamarin-macios + +include $(TOP)/Make.config + +# +# * Use [IOS|MAC]_TESTS for simple tests that just verify the code can compile / generate. +# To add such a test, just add the file, and add the name of the file (without extension) to [IOS|MAC]_TESTS. +# +# * Use [IOS|MAC]_CUSTOM_TESTS for more advanced tests that needs more validation. +# In this case you additionally need to add a target for the name of the test, with the +# your test logic. +# + +IOS_CURRENT_DIR=$(IOS_DESTDIR)/Library/Frameworks/Xamarin.iOS.framework/Versions/Current +IOS_GENERATOR = $(IOS_CURRENT_DIR)/bin/btouch /baselib:$(IOS_CURRENT_DIR)/lib/mono/2.1/monotouch.dll /unsafe /compiler:$(IOS_CURRENT_DIR)/bin/smcs +IOS_TESTS = bug15283 bug15307 bug15799 bug16036 sof20696157 bug23041 bug27430 bug27428 bug34042 btouch-with-hyphen-in-name property-redefination-ios arrayfromhandlebug bug36457 bug39614 bug40282 bug17232 bug24078-ignore-methods-events +IOS_CUSTOM_TESTS = forum54078 desk63279 desk79124 multiple-api-definitions1 multiple-api-definitions2 bug29493 classNameCollision bi1036 bug37527 bug27986 bug35176 + +MAC_CURRENT_DIR=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current +MAC_GENERATOR = $(MAC_CURRENT_DIR)/bin/bmac +MAC_TESTS = bmac_smoke bmac-with-hyphen-in-name property-redefination-mac NSApplicationPublicEnsureMethods protocol-duplicate-abstract +MAC_CUSTOM_TESTS = bug31788 protocol-duplicate-abstract-error protocol-duplicate-method-diff-length protocol-duplicate-method-diff-out protocol-duplicate-method-diff-type protocol-duplicate-method-diff-return + +ALL_TESTS = +ifdef INCLUDE_IOS +ALL_TESTS += $(IOS_TESTS) $(IOS_CUSTOM_TESTS) +endif +ifdef INCLUDE_MAC +ALL_TESTS += $(MAC_TESTS) $(MAC_CUSTOM_TESTS) +endif + +all-local:: $(ALL_TESTS) + +$(MAC_TESTS): + $(if $(V),,@echo "$@";) $(MAC_GENERATOR) -d=MONOMAC $@.cs + $(if $(V),,@echo "$@";) $(MAC_GENERATOR) -d=MONOMAC -d=XAMCORE_2_0 --unified-full-profile $@.cs + $(if $(V),,@echo "$@";) $(MAC_GENERATOR) -d=MONOMAC -d=XAMCORE_2_0 --unified-mobile-profile $@.cs + +$(IOS_TESTS): + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) $@.cs + +define ProtocolTestTemplate +$(1): + $(if $(V),,@echo "$$@";) $(MAC_GENERATOR) -d=MONOMAC $(1).cs 2>&1 | grep BI$(2) > /dev/null + $(if $(V),,@echo "$$@";) $(MAC_GENERATOR) -d=MONOMAC -d=XAMCORE_2_0 --unified-full-profile $(1).cs 2>&1 | grep BI$(2) > /dev/null + $(if $(V),,@echo "$$@";) $(MAC_GENERATOR) -d=MONOMAC -d=XAMCORE_2_0 --unified-mobile-profile $(1).cs 2>&1 | grep BI$(2) > /dev/null +endef + +$(eval $(call ProtocolTestTemplate,protocol-duplicate-abstract-error,1037)) +$(eval $(call ProtocolTestTemplate,protocol-duplicate-method-diff-length,1039)) +$(eval $(call ProtocolTestTemplate,protocol-duplicate-method-diff-out,1040)) +$(eval $(call ProtocolTestTemplate,protocol-duplicate-method-diff-type,1041)) +$(eval $(call ProtocolTestTemplate,protocol-duplicate-method-diff-return,1038)) + +classNameCollision: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) $@.cs -s:classNameCollision-enum.cs -tmpdir=$@.tmpdir + +bug31788: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(MAC_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir $@.cs + @grep -q xamarin_IntPtr_objc_msgSend bug31788.tmpdir/Test/MarshalOnProperty.g.cs + @grep -q xamarin_IntPtr_objc_msgSend bug31788.tmpdir/Test/MarshalInProperty.g.cs + +desk63279: + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) desk63279A.cs desk63279B.cs + +desk79124: + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) $@.cs >/dev/null 2>&1 + @if ! monodis $@.dll --typedef | grep WYPopoverBackgroundViewAppearance > /dev/null; then \ + echo "error: Could not find WYPopoverBackgroundViewAppearance in generated code."; \ + fi + +forum54078: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir $@.cs + @! grep "Type does not conform to NSCoding" forum54078.tmpdir/Test/CustomController.g.cs + +multiple-api-definitions1: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir $@.cs + +multiple-api-definitions2: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir --api=$@-a.cs --api=$@-b.cs + +bug29493: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir $@.cs + @! grep -r "static readonly IntPtr class_ptr = Class.GetHandle (\"global::" bug29493.tmpdir/Bug29493 + +bug37527: + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) $@-missing-property.cs | grep "BaseType.Delegates were set but no properties could be found. Do ensure that the WrapAttribute is used on the right properties." >/dev/null 2>&1 + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) $@-wrong-property.cs | grep "should be renamed to 'Delegate' for BaseType.Events and BaseType.Delegates to work." >/dev/null 2>&1 + +bug27986: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir $@.cs + @if ! grep -r Preserve bug27986.tmpdir/bug27986 > /dev/null; then \ + echo "error: Could not find Preserve attribute in generated code."; exit 1; \ + fi + @if [ `grep -r Preserve bug27986.tmpdir/bug27986 | wc -l` -ne 28 ]; then \ + echo "Error: Expected 28 Preserve attributes in generated code. If you modified code that generates PreserveAttributes please update the preserve count."; exit 1; \ + fi + +bug35176: + @rm -Rf $@.tmpdir + @mkdir -p $@.tmpdir + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) --sourceonly:$@.source -tmpdir=$@.tmpdir $@.cs + @if ! grep -r Introduced bug35176.tmpdir/bug35176 > /dev/null; then \ + echo "error: Could not find Introduced attribute in generated code."; exit 1; \ + fi + @if [ `grep -r Introduced bug35176.tmpdir/bug35176 | wc -l` -ne 8 ]; then \ + echo "Error: Expected 4 Introduced attributes in generated code."; exit 1; \ + fi + +bi1036: + $(if $(V),,@echo "$@";) $(IOS_GENERATOR) $@.cs | grep BI1036 >/dev/null 2>&1 + +clean-local:: + rm -f *.dll *.source + rm -Rf *.tmpdir diff --git a/tests/generator/NSApplicationPublicEnsureMethods.cs b/tests/generator/NSApplicationPublicEnsureMethods.cs new file mode 100644 index 000000000000..9b0f3e9fc5c8 --- /dev/null +++ b/tests/generator/NSApplicationPublicEnsureMethods.cs @@ -0,0 +1,36 @@ +/* + * Errors when doing non-internal (Xamarin.Mac.dll) bindings with a weak delegate: + * + * /var/folders/d5/0m2657ws4b339b0ryh0brkhw0000gn/T/etr9ustz.vgc/Test/TestClass.g.cs(105,19): error CS0122: `AppKit.NSApplication.EnsureDelegateAssignIsNotOverwritingInternalDelegate(object, object, System.Type)' is inaccessible due to its protection level + * /var/folders/d5/0m2657ws4b339b0ryh0brkhw0000gn/T/etr9ustz.vgc/Test/TestClass.g.cs(133,19): error CS0122: `AppKit.NSApplication.EnsureEventAndDelegateAreNotMismatched(object, System.Type)' is inaccessible due to its protection level + * + * EnsureDelegateAssignIsNotOverwritingInternalDelegate should be marked as public, not internal + * EnsureEventAndDelegateAreNotMismatched should be marked as public, not internal + * + */ +using System; +#if !XAMCORE_2_0 +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test { + [BaseType (typeof (NSObject), Delegates=new string [] {"WeakDelegate"}, Events=new Type [] {typeof (SharedDelegate)})] + public interface TestClass { + [Export ("delegate", ArgumentSemantic.Assign), NullAllowed] + NSObject WeakDelegate { get; set; } + + [Wrap ("WeakDelegate")] + [Protocolize] + SharedDelegate Delegate { get; set; } + } + + [BaseType (typeof (NSObject))] + [Model] + [Protocol] + public interface SharedDelegate { + } +} \ No newline at end of file diff --git a/tests/generator/README.md b/tests/generator/README.md new file mode 100644 index 000000000000..62a6bea58182 --- /dev/null +++ b/tests/generator/README.md @@ -0,0 +1,9 @@ +Tests for the binding generator +=============================== + +New test +-------- + +* Create a C# file with the api definition. +* Add the C# file to the Makefile, like all the other tests. + Remember to add it to the 'all' target. \ No newline at end of file diff --git a/tests/generator/arrayfromhandlebug.cs b/tests/generator/arrayfromhandlebug.cs new file mode 100644 index 000000000000..c6aaf11c7c72 --- /dev/null +++ b/tests/generator/arrayfromhandlebug.cs @@ -0,0 +1,40 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +#else +using MonoTouch.Foundation; +#endif +#else +using Foundation; +#endif + +namespace AudioUnit { + // @interface AUParameterNode : NSObject + [BaseType (typeof(NSObject))] + interface AUParameterNode + { + } + + // @interface AUParameterGroup : AUParameterNode + [BaseType (typeof(AUParameterNode))] + interface AUParameterGroup : INSSecureCoding + { + [Export ("allParameters")] + AUParameter[] AllParameters { get; } + } + + // @interface AUParameter : AUParameterNode + [BaseType (typeof(AUParameterNode))] + interface AUParameter : INSSecureCoding + { + } + + // Commenting this out "fixes" the problem + [BaseType (typeof(NSObject))] + interface AudioUnit + { + } +} diff --git a/tests/generator/bi1036.cs b/tests/generator/bi1036.cs new file mode 100644 index 000000000000..5170a7e84832 --- /dev/null +++ b/tests/generator/bi1036.cs @@ -0,0 +1,10 @@ +using MonoTouch.Foundation; + +namespace NS { + [BaseType (typeof (NSObject))] + interface Foo { + [Export ("foo:")] + [Async (ResultTypeName="Result")] + void Method (string arg); + } +} diff --git a/tests/generator/bmac-with-hyphen-in-name.cs b/tests/generator/bmac-with-hyphen-in-name.cs new file mode 100644 index 000000000000..31af3b611dd5 --- /dev/null +++ b/tests/generator/bmac-with-hyphen-in-name.cs @@ -0,0 +1,15 @@ +#if !XAMCORE_2_0 +using MonoMac.Foundation; +#else +using Foundation; +#endif + +namespace Test +{ + [BaseType (typeof (NSObject))] + interface TestBMACLib + { + [Export ("addTwoRows:withSecond:")] + int Add (int first, int second); + } +} \ No newline at end of file diff --git a/tests/generator/bmac_smoke.cs b/tests/generator/bmac_smoke.cs new file mode 100644 index 000000000000..5c73f7a114a9 --- /dev/null +++ b/tests/generator/bmac_smoke.cs @@ -0,0 +1,15 @@ +#if !XAMCORE_2_0 +using MonoMac.Foundation; +#else +using Foundation; +#endif + +namespace Test +{ + [BaseType (typeof (NSObject))] + interface TestBMACLib + { + [Export ("addTwoRows:withSecond:")] + int Add (int first, int second); + } +} \ No newline at end of file diff --git a/tests/generator/btouch-with-hyphen-in-name.cs b/tests/generator/btouch-with-hyphen-in-name.cs new file mode 100644 index 000000000000..e22fc9043547 --- /dev/null +++ b/tests/generator/btouch-with-hyphen-in-name.cs @@ -0,0 +1,15 @@ +using System.Drawing; +using System; + +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; + +namespace Desk79124 { + [BaseType (typeof (UIView))] + public interface WYPopoverBackgroundView : IUIAppearance { + [Export ("glossShadowOffset", ArgumentSemantic.Assign)] + [Appearance] + SizeF GlossShadowOffset { get; set; } + } +} \ No newline at end of file diff --git a/tests/generator/bug15283.cs b/tests/generator/bug15283.cs new file mode 100644 index 000000000000..d3e03a65fabd --- /dev/null +++ b/tests/generator/bug15283.cs @@ -0,0 +1,18 @@ +using System; +using System.Drawing; +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using System.Runtime.InteropServices; + +namespace BindingTests +{ + delegate NSObject MyBlockToBind (NSObject[] keys); + + [BaseType (typeof (NSObject))] + interface TestInterface { + [Export ("testMethod:")] + void TestMethod (MyBlockToBind myBlockToBind); + } +} + diff --git a/tests/generator/bug15307.cs b/tests/generator/bug15307.cs new file mode 100644 index 000000000000..af7365a53fc6 --- /dev/null +++ b/tests/generator/bug15307.cs @@ -0,0 +1,14 @@ +// https://bugzilla.xamarin.com/show_bug.cgi?id=15307#c3 + +using System; +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; + +namespace BindingTests { + + // error BI1018: btouch: No [Export] attribute on property MonoTouch.ObjCRuntime.INativeObject.Handle + [BaseType (typeof (UIPageViewController))] + interface MyPageViewController : IUIPageViewControllerDelegate, IUIPageViewControllerDataSource { + } +} \ No newline at end of file diff --git a/tests/generator/bug15799.cs b/tests/generator/bug15799.cs new file mode 100644 index 000000000000..2b0d28e7966a --- /dev/null +++ b/tests/generator/bug15799.cs @@ -0,0 +1,14 @@ +using System; +using System.Drawing; +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.CoreBluetooth; + +namespace Bug15799 { + + // Device Manager + [BaseType (typeof (NSObject))] + public partial interface Foo : ICBCentralManagerDelegate, ICBPeripheralDelegate { + } +} \ No newline at end of file diff --git a/tests/generator/bug16036.cs b/tests/generator/bug16036.cs new file mode 100644 index 000000000000..a31bcabd34a5 --- /dev/null +++ b/tests/generator/bug16036.cs @@ -0,0 +1,13 @@ +using MonoTouch.Foundation; + +namespace TestCase { + + delegate void TestHandler (int result, NSError err); + + [BaseType (typeof (NSObject))] + interface Foo { + + [Async, Static, Export ("someMethod:")] + bool SomeMethod (TestHandler callback); + } +} \ No newline at end of file diff --git a/tests/generator/bug17232.cs b/tests/generator/bug17232.cs new file mode 100644 index 000000000000..4d976c0fd2b2 --- /dev/null +++ b/tests/generator/bug17232.cs @@ -0,0 +1,34 @@ +using System; +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; + +namespace xam.bug17232 { + [BaseType (typeof (NSObject))] + interface FieldsTest { + + [Field ("MyFooFieldA", "libFoo.a")] + NSString FooFieldA { get; } + + [Field ("MyFooFieldB", "libFoo.a")] + NSString FooFieldB { get; set; } + + [Field ("MyBarFieldA", "Frameworks/Bar.framework/Bar")] + NSString BarFieldA { get; } + + [Field ("MyBarFieldB", "Frameworks/Bar.framework/Bar")] + NSString BarFieldB { get; set; } + + [Field ("MyBarFieldA", "Xyz")] + NSString XyzFieldA { get; } + + [Field ("XyzFieldB", "Xyz")] + NSString XyzFieldB { get; set; } + + [Field ("MyUnboundField", Constants.CoreGraphicsLibrary)] + NSString UnboundField { get; set; } + + [Field ("MyUnboundUIKitField", "UIKit")] + NSString UnboundUIKitField { get; set; } + } +} \ No newline at end of file diff --git a/tests/generator/bug23041.cs b/tests/generator/bug23041.cs new file mode 100644 index 000000000000..0ad1200eb032 --- /dev/null +++ b/tests/generator/bug23041.cs @@ -0,0 +1,10 @@ +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.UIKit; + +namespace Test { +[Model, BaseType (typeof (UIPopoverControllerDelegate))] +[Protocol] +public partial interface BindingMainTabBarControllerScreensHandler { +} +} diff --git a/tests/generator/bug24078-ignore-methods-events.cs b/tests/generator/bug24078-ignore-methods-events.cs new file mode 100644 index 000000000000..13c29c3ddb66 --- /dev/null +++ b/tests/generator/bug24078-ignore-methods-events.cs @@ -0,0 +1,42 @@ +/* + * Allow to ignore certain methods from the generation of events. + * + */ +using System; +#if !XAMCORE_2_0 +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#else +using Foundation; +using ObjCRuntime; +using UIKit; +#endif + +namespace Test { + + [BaseType (typeof (NSObject), + Delegates=new string [] {"WeakDelegate"}, + Events=new Type [] { typeof (UIPopoverPresentationControllerDelegate) })] + public partial interface TestController { + [Export ("delegate", ArgumentSemantic.UnsafeUnretained)] + NSObject WeakDelegate { get; set; } + + [Wrap ("WeakDelegate")] + [Protocolize] + UIPopoverPresentationControllerDelegate Delegate { get; set; } + } + + [Protocol, Model] + [BaseType (typeof (NSObject))] + public partial interface UIPopoverPresentationControllerDelegate { + [IgnoredInDelegate] // ignore this method in the c# events + [Export ("adaptivePresentationStyleForPresentationController:")] + UIModalPresentationStyle GetAdaptivePresentationStyle (UIPresentationController forPresentationController); + + [Export ("adaptivePresentationStyleForPresentationController:traitCollection:"), + DelegateName ("AdaptivePresentationStyleWithTraitsRequested"), DefaultValue (UIModalPresentationStyle.None)] + UIModalPresentationStyle GetAdaptivePresentationStyle (UIPresentationController controller, UITraitCollection traitCollection); + + } +} diff --git a/tests/generator/bug27428.cs b/tests/generator/bug27428.cs new file mode 100644 index 000000000000..2859d9f3a517 --- /dev/null +++ b/tests/generator/bug27428.cs @@ -0,0 +1,16 @@ +using System; +using System.Drawing; + +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; + +namespace Foo.BindingBugs +{ + [BaseType (typeof (NSObject))] + interface Widget { + [Export ("doSomething:atIndex:")] + void DoSomething (NSObject @object, int index); + } +} + diff --git a/tests/generator/bug27430.cs b/tests/generator/bug27430.cs new file mode 100644 index 000000000000..baf52f6c2be4 --- /dev/null +++ b/tests/generator/bug27430.cs @@ -0,0 +1,91 @@ +using System; +using System.Drawing; + +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; + +namespace Bug27430 +{ + delegate void SomeHandler (int @int, string @string, NSError @namespace); + delegate void SomeHandler2 (NSDictionary[] @switch, string[] @case, NSError @namespace); + + [BaseType (typeof (NSObject))] + interface Widget { + + [Export ("initWithTest:")] + IntPtr Constructor (IFooTestDelegate @delegate); + + [Async (ResultTypeName = "FooResultTask")] + [Export ("doSomething:atIndex::::")] + void DoSomething (NSObject obj, string str, int i, uint @uint, SomeHandler handler); + + [Async] + [Export ("doSomething1:atIndex::::")] + void DoSomething1 (NSObject @object, string @string, int @int, uint @uint, Action @delegate); + + [Export ("outTest:atIndex::::")] + void OutTest (out NSObject @object, out string @string, out int @int, out uint @uint, Action @delegate); + + [Export ("refTest:atIndex::::")] + void RefTest (ref NSObject @object, ref string @string, ref int @int, ref uint @uint, Action @delegate); + + [Export ("RefHandlderTest:atIndex::::")] + void RefHandlderTest (ref NSObject @object, ref string @string, ref int @int, ref uint @uint, SomeHandler @delegate); + + [Export ("PlainStringTest:atIndex::::")] + void PlainStringTest (NSObject @object, [PlainString] string @string, NSString @for, NSNumber @foreach, NSNumber @override); + + [Export ("NullAllowedTest:atIndex::::")] + void NullAllowedTest ([NullAllowed] NSObject @object, [NullAllowed] string @string, [NullAllowed] NSString @for, [NullAllowed] NSNumber @foreach, [NullAllowed] NSNumber @override); + + [Async] + [Export ("arrayTest:atIndex::::")] + void ArrayTest (NSObject [] @object, string [] @string, int @int, uint @uint, Action @delegate); + + [Async (ResultTypeName = "ArrayResultTask")] + [Export ("arrayTest2:atIndex::::")] + void ArrayTest2 (NSObject [] @object, string [] @string, int @int, uint @uint, SomeHandler2 @delegate); + + [Async] + [Export ("doSomethingErr:atIndex::::")] + void DoSomethingErrTest (NSObject @object, string @string, int @int, uint @uint, Action @delegate); + + [Async (ResultTypeName = "FooResultTask2")] + [Export ("doSomethingErr2:atIndex::::")] + void DoSomethingErr2Test (NSObject @object, string @string, int @int, uint @uint, Action @delegate); + + [Export ("putDelegatesSomewhere:::")] + void PutDelegatesTest (IFooTestDelegate @delegate, IUIPageViewControllerDelegate @namespace, int @int); + + [Export ("delegate", ArgumentSemantic.Weak), NullAllowed] + IFooTestDelegate @delegate { get; set; } + + [Export ("dont")] + string @string { get; set; } + + [Export ("dont2")] + int @int { [Bind ("isDont2")] get; set; } + + [Export ("dont3")] + UIView [] @foreach { get; [Bind ("foo3:")] set; } + + [Export ("dont4")] + UIView [] @case {[Bind ("bar4")] get; [Bind ("foo4:")] set; } + + [Export ("dont")] + NSArray @void { get; } + } + + interface IFooTestDelegate { } + + [Protocol, Model] + [BaseType (typeof (NSObject))] + interface FooTestDelegate { + + [Export ("someFakeDelegateMethod:withDelegate:")] + void SomeFakeDelegateMethod (UIViewController @switch, IFooTestDelegate @delegate); + } +} + + diff --git a/tests/generator/bug27986.cs b/tests/generator/bug27986.cs new file mode 100644 index 000000000000..389405374228 --- /dev/null +++ b/tests/generator/bug27986.cs @@ -0,0 +1,70 @@ +using System; + +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using System.Drawing; + +namespace bug27986 +{ + interface IFooProtocol { } + + [Model, Protocol, Preserve (AllMembers = true)] + [BaseType (typeof (NSObject))] + interface FooProtocol { + + [Preserve] + [Export ("doSomething:atIndex:")] + void DoSomething (NSObject @object, int index); + + [Abstract] + [Preserve (Conditional = true)] + [Export ("doSomething:atIndex2:")] + void DoSomething2 (NSObject @object, int index); + + [Abstract] + [Preserve (Conditional = true)] + [Export ("center")] + NSObject Center { get; set; } + + [Preserve] + [Export ("center2")] + NSObject Center2 { get; set; } + } + + + [BaseType (typeof (NSObject))] + [Preserve (AllMembers = true)] + interface Widget { + + [Preserve (Conditional = true)] + [Export ("initWithElmo:")] + IntPtr Constructor (uint elmo); + + [Preserve] + [Export ("doSomething:atIndex:")] + void DoSomething (NSObject @object, int index); + + [Preserve (Conditional = true)] + [Export ("center")] + NSObject Center { get; set; } + + [Export("noCenter")] + PointF NoCenter { [Preserve (Conditional = true)] get; [Preserve] set; } + + [Preserve] + [Field ("FooField", "__Internal")] + NSString FooField { get; } + + [Field ("IntField", "__Internal")] + int IntField { [Preserve (Conditional = true)] get; [Preserve] set; } + + [Wrap ("Center")] + [Preserve] + NSString CenterWrap { get; set; } + + [Preserve (Conditional = true)] + [Export ("delegate")] + IFooProtocol Delegate { get; set; } + } +} + diff --git a/tests/generator/bug29493.cs b/tests/generator/bug29493.cs new file mode 100644 index 000000000000..58321e6fb6dc --- /dev/null +++ b/tests/generator/bug29493.cs @@ -0,0 +1,111 @@ +using System; + +using MonoTouch.UIKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreGraphics; + +namespace Bug29493 +{ + [Category] + [BaseType (typeof(UIColor))] + interface UIColorExtensions + { + // +(UIColor *)jbill_messageBubbleGreenColor; + [Static] + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor (); + + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor2 (); + } + + [Category] + [BaseType (typeof(NSUrlSession))] + interface NSUrlExtensions + { + // +(UIColor *)jbill_messageBubbleGreenColor; + [Static] + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor (); + + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor2 (); + } + + [BaseType (typeof(NSObject))] + interface HelloKitty + { + + } + + [Category] + [BaseType (typeof(HelloKitty))] + interface HelloKittyExtensions + { + // +(UIColor *)jbill_messageBubbleGreenColor; + [Static] + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor (); + + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor2 (); + } + + [BaseType (typeof(NSObject), Name = "NSBatman")] + interface BecauseImBatman + { + + } + + [Category] + [BaseType (typeof(BecauseImBatman))] + interface BecauseImBatmanExtensions + { + // +(UIColor *)jbill_messageBubbleGreenColor; + [Static] + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor (); + + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor2 (); + } + + [BaseType (typeof(BecauseImBatman), Name = "NSBatman2")] + interface BecauseImBatman2 + { + + } + + [Category] + [BaseType (typeof(BecauseImBatman2))] + interface BecauseImBatman2Extensions + { + // +(UIColor *)jbill_messageBubbleGreenColor; + [Static] + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor (); + + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor2 (); + } + + [BaseType (typeof(BecauseImBatman))] + interface Superman + { + + } + + [Category] + [BaseType (typeof(Superman))] + interface SupermanExtensions + { + // +(UIColor *)jbill_messageBubbleGreenColor; + [Static] + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor (); + + [Export ("jbill_messageBubbleGreenColor")] + UIColor MessageBubbleGreenColor2 (); + } +} \ No newline at end of file diff --git a/tests/generator/bug31788.cs b/tests/generator/bug31788.cs new file mode 100644 index 000000000000..049ec0132286 --- /dev/null +++ b/tests/generator/bug31788.cs @@ -0,0 +1,30 @@ +#if !XAMCORE_2_0 +using MonoMac.Foundation; +#else +using Foundation; +#endif + +namespace Test +{ + [BaseType (typeof (NSObject))] + interface SimServiceConnectionManager {} + + // Both these should produce the same output, + // both calling xamarin_IntPtr_objc_msgSend + [BaseType (typeof (NSObject))] + interface MarshalOnProperty + { + [Static] + [Export ("sharedConnectionManager")] + [MarshalNativeExceptions] + SimServiceConnectionManager Shared { get; } + } + + [BaseType (typeof (NSObject))] + interface MarshalInProperty + { + [Static] + [Export ("sharedConnectionManager")] + SimServiceConnectionManager Shared { [MarshalNativeExceptions]get; } + } +} \ No newline at end of file diff --git a/tests/generator/bug34042.cs b/tests/generator/bug34042.cs new file mode 100644 index 000000000000..e1dcbfad96e0 --- /dev/null +++ b/tests/generator/bug34042.cs @@ -0,0 +1,21 @@ +using System; + +using MonoTouch.UIKit; + +namespace Bug34042.Foo +{ + [BaseType (typeof(UIButton))] + interface FooButton + { + + } +} + +namespace Bug34042.Bar +{ + [BaseType (typeof(Bug34042.Foo.FooButton))] + interface BarButton + { + + } +} \ No newline at end of file diff --git a/tests/generator/bug35176.cs b/tests/generator/bug35176.cs new file mode 100644 index 000000000000..e98284ff37c1 --- /dev/null +++ b/tests/generator/bug35176.cs @@ -0,0 +1,29 @@ +using System; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; + +namespace Bug35176 { + + [Introduced (PlatformName.iOS, 8,0)] + [Introduced (PlatformName.MacOSX, 10,10)] + [Protocol] + interface FooInterface { + + [Abstract] + [Export ("fooView")] + UIView FooView { get; set; } + + [Export ("BarView")] + UIView BarView { [Introduced (PlatformName.iOS, 9,0)] get; } + + [Export ("barMember:")] + UIView GetBarMember (int x); + } + + [BaseType (typeof (NSObject))] + interface BarObject : FooInterface + { + + } +} \ No newline at end of file diff --git a/tests/generator/bug36457.cs b/tests/generator/bug36457.cs new file mode 100644 index 000000000000..cea8a77dbca2 --- /dev/null +++ b/tests/generator/bug36457.cs @@ -0,0 +1,12 @@ +using MonoTouch.Foundation; + +namespace Bug { + delegate string ReturnsString (); + + [BaseType (typeof(NSObject))] + interface Type + { + [Export ("returnString")] + ReturnsString ReturnString { get; set; } + } +} \ No newline at end of file diff --git a/tests/generator/bug37527-missing-property.cs b/tests/generator/bug37527-missing-property.cs new file mode 100644 index 000000000000..4a9408b67fb6 --- /dev/null +++ b/tests/generator/bug37527-missing-property.cs @@ -0,0 +1,26 @@ +/* + * Errors when doing users perform a binding but the Delegate property is missing. + * + */ +using System; +#if !XAMCORE_2_0 +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test { + [BaseType (typeof (NSObject))] + [Model] + [Protocol] + public interface SharedDelegate { + } + + [BaseType (typeof (NSObject), Delegates=new string [] {"WeakDelegate"}, Events=new Type [] {typeof (SharedDelegate)})] + public interface TestMissingPropertyName{ + [Export ("delegate", ArgumentSemantic.Assign), NullAllowed] + NSObject WeakDelegate { get; set; } + } +} diff --git a/tests/generator/bug37527-wrong-property.cs b/tests/generator/bug37527-wrong-property.cs new file mode 100644 index 000000000000..e7b8105e30e8 --- /dev/null +++ b/tests/generator/bug37527-wrong-property.cs @@ -0,0 +1,30 @@ +/* + * Errors when doing users perform a binding but the Delegate property does not use the correct name. + * + */ +using System; +#if !XAMCORE_2_0 +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test { + [BaseType (typeof (NSObject))] + [Model] + [Protocol] + public interface SharedDelegate { + } + + [BaseType (typeof (NSObject), Delegates=new string [] {"WeakDelegate"}, Events=new Type [] {typeof (SharedDelegate)})] + public interface TestWrongPropertyName{ + [Export ("delegate", ArgumentSemantic.Assign), NullAllowed] + NSObject WeakDelegate { get; set; } + + [Wrap ("WeakDelegate")] + [Protocolize] + SharedDelegate TestProperty { get; set; } + } +} diff --git a/tests/generator/bug39614.cs b/tests/generator/bug39614.cs new file mode 100644 index 000000000000..74507c89109f --- /dev/null +++ b/tests/generator/bug39614.cs @@ -0,0 +1,21 @@ +using System; +using MonoTouch.Foundation; + +[BaseType (typeof (NSObject))] +public interface FooType + where GenType : NSObject { + + [Export ("bar")] + GenType bar { get; set; } + + [Static] + [Export ("fooType:value:")] + GenType FromFoo (string fooType, GenType value); + + [Export ("initWithFoo:value:")] + IntPtr Constructor (string foo, GenType value); + + [Export ("getBar:")] + GenType GetBar (string bar); +} + diff --git a/tests/generator/bug40282.cs b/tests/generator/bug40282.cs new file mode 100644 index 000000000000..7528029c9c22 --- /dev/null +++ b/tests/generator/bug40282.cs @@ -0,0 +1,19 @@ +using System; +using MonoTouch.Foundation; + +namespace bug40282 { + [Internal] + [Protocol, Model] + [BaseType (typeof (NSObject))] + interface FooDelegateInternal { + [Export ("fooService:hasUInt32s:numberOfItems:forFooSession:")] + bool FooServiceUInt32 (int service, IntPtr data, ushort numberOfItems, int session); + + [Export ("fooService:hasSInt16s:numberOfItems:forFooSession:")] + bool FooServiceSInt16 (int service, IntPtr data, ushort numberOfItems, int session); + + [Export ("fooService:sessionDidFinish:")] + void FooService (int service, int session); + } +} + diff --git a/tests/generator/classNameCollision-enum.cs b/tests/generator/classNameCollision-enum.cs new file mode 100644 index 000000000000..29e98a92e68b --- /dev/null +++ b/tests/generator/classNameCollision-enum.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +#else +using MonoTouch.Foundation; +#endif +#else +using Foundation; +#endif + +namespace AudioUnit { + [StructLayout (LayoutKind.Sequential)] + public struct AURecordedParameterEvent + { + public ulong hostTime; + public ulong address; + public float value; + } +} diff --git a/tests/generator/classNameCollision.cs b/tests/generator/classNameCollision.cs new file mode 100644 index 000000000000..369c8b1155f5 --- /dev/null +++ b/tests/generator/classNameCollision.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +#else +using MonoTouch.Foundation; +#endif +#else +using Foundation; +#endif + +namespace AudioUnit { + [BaseType (typeof(NSObject))] + interface AUParameterNode + { + [Export ("tokenByAddingParameterRecordingObserver:")] + IntPtr TokenByAddingParameterRecordingObserver (AUParameterRecordingObserver observer); + } + + public unsafe delegate void AUParameterRecordingObserver (int arg0, AURecordedParameterEvent arg1); + + // Commenting this out "fixes" the problem + [BaseType (typeof(NSObject))] + interface AudioUnit + { + } +} diff --git a/tests/generator/desk63279A.cs b/tests/generator/desk63279A.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/generator/desk63279B.cs b/tests/generator/desk63279B.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/generator/desk79124.cs b/tests/generator/desk79124.cs new file mode 100644 index 000000000000..e22fc9043547 --- /dev/null +++ b/tests/generator/desk79124.cs @@ -0,0 +1,15 @@ +using System.Drawing; +using System; + +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; + +namespace Desk79124 { + [BaseType (typeof (UIView))] + public interface WYPopoverBackgroundView : IUIAppearance { + [Export ("glossShadowOffset", ArgumentSemantic.Assign)] + [Appearance] + SizeF GlossShadowOffset { get; set; } + } +} \ No newline at end of file diff --git a/tests/generator/forum54078.cs b/tests/generator/forum54078.cs new file mode 100644 index 000000000000..4ad0b8d4e83f --- /dev/null +++ b/tests/generator/forum54078.cs @@ -0,0 +1,10 @@ +// We test that a third-party binding inheriting from UIViewController +// gets a proper NSCoding constructor. +using MonoTouch.UIKit; + +namespace Test { + [BaseType (typeof (UIViewController))] + public interface CustomController { + + } +} \ No newline at end of file diff --git a/tests/generator/multiple-api-definitions1.cs b/tests/generator/multiple-api-definitions1.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/generator/multiple-api-definitions2-a.cs b/tests/generator/multiple-api-definitions2-a.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/generator/multiple-api-definitions2-b.cs b/tests/generator/multiple-api-definitions2-b.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/generator/property-redefination-ios.cs b/tests/generator/property-redefination-ios.cs new file mode 100644 index 000000000000..57a975f7372a --- /dev/null +++ b/tests/generator/property-redefination-ios.cs @@ -0,0 +1,28 @@ +#if !XAMCORE_2_0 +using MonoTouch.Foundation; +#else +using Foundation; +#endif + +namespace Test +{ + [BaseType (typeof (NSObject))] + [Protocol, Model] + public interface NSTextInputClient + { + [Export ("selectedRange")] + NSRange SelectedRange { get; } + } + + [BaseType (typeof (NSObject))] + interface NSText + { + [Export ("selectedRange")] + NSRange SelectedRange { get; set; } + } + + [BaseType (typeof (NSText))] + interface NSTextView : NSTextInputClient + { + } +} \ No newline at end of file diff --git a/tests/generator/property-redefination-mac.cs b/tests/generator/property-redefination-mac.cs new file mode 100644 index 000000000000..1ef716bd1862 --- /dev/null +++ b/tests/generator/property-redefination-mac.cs @@ -0,0 +1,28 @@ +#if !XAMCORE_2_0 +using MonoMac.Foundation; +#else +using Foundation; +#endif + +namespace Test +{ + [BaseType (typeof (NSObject))] + [Protocol, Model] + public interface NSTextInputClient + { + [Export ("selectedRange")] + NSRange SelectedRange { get; } + } + + [BaseType (typeof (NSObject))] + public interface NSText + { + [Export ("selectedRange")] + NSRange SelectedRange { get; set; } + } + + [BaseType (typeof (NSText))] + public interface NSTextView : NSTextInputClient + { + } +} \ No newline at end of file diff --git a/tests/generator/protocol-duplicate-abstract-error.cs b/tests/generator/protocol-duplicate-abstract-error.cs new file mode 100644 index 000000000000..9f635f3f5fdb --- /dev/null +++ b/tests/generator/protocol-duplicate-abstract-error.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test +{ + [Protocol] + public interface First + { + [Abstract] + [NullAllowed, Export ("identifier")] + string Identifier { set; } + } + + [Protocol] + public interface Second { + [Abstract] + [NullAllowed, Export ("identifier")] + string Identifier { get; } + } + + [BaseType (typeof (NSObject))] + public partial interface Derived : First, Second { + } +} + diff --git a/tests/generator/protocol-duplicate-abstract.cs b/tests/generator/protocol-duplicate-abstract.cs new file mode 100644 index 000000000000..891f84328fac --- /dev/null +++ b/tests/generator/protocol-duplicate-abstract.cs @@ -0,0 +1,54 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test +{ + [Protocol] + public interface First + { + [Abstract] + [NullAllowed, Export ("identifier")] + string Identifier { get; set; } + + [Abstract] + [Export ("doit")] + void DoIt (); + + [Abstract] + [Export ("doit:with:more")] + void DoIt (int a, int b); + } + + [Protocol] + public interface Second { + [Abstract] + [NullAllowed, Export ("identifier")] + string Identifier { get; } + + [Abstract] + [Export ("doit")] + void DoIt (); + + [Abstract] + [Export ("doit:with:more")] + void DoIt (int a, int b); + } + + [BaseType (typeof (NSObject))] + public partial interface Derived : First, Second { + } +} + diff --git a/tests/generator/protocol-duplicate-method-diff-length.cs b/tests/generator/protocol-duplicate-method-diff-length.cs new file mode 100644 index 000000000000..271a64c6a976 --- /dev/null +++ b/tests/generator/protocol-duplicate-method-diff-length.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test +{ + [Protocol] + public interface First + { + [Abstract] + [Export ("doit:itwith:more:")] + void DoIt (int a, int b, int c); + } + + [Protocol] + public interface Second { + [Abstract] + [Export ("doit:itwith:more:")] + void DoIt (int a, int b, int c, int d); + } + + [BaseType (typeof (NSObject))] + public partial interface Derived : First, Second { + } +} + diff --git a/tests/generator/protocol-duplicate-method-diff-out.cs b/tests/generator/protocol-duplicate-method-diff-out.cs new file mode 100644 index 000000000000..d8fdee2af2c3 --- /dev/null +++ b/tests/generator/protocol-duplicate-method-diff-out.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test +{ + [Protocol] + public interface First + { + [Abstract] + [Export ("doit:withmore")] + void DoIt (int a, out int b); + } + + [Protocol] + public interface Second { + [Abstract] + [Export ("doit:withmore")] + void DoIt (int a, int b); + } + + [BaseType (typeof (NSObject))] + public partial interface Derived : First, Second { + } +} + diff --git a/tests/generator/protocol-duplicate-method-diff-return.cs b/tests/generator/protocol-duplicate-method-diff-return.cs new file mode 100644 index 000000000000..d62d3ea6e132 --- /dev/null +++ b/tests/generator/protocol-duplicate-method-diff-return.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test +{ + [Protocol] + public interface First + { + [Abstract] + [Export ("doit:with:more:stuff")] + void DoIt (int a, int b, int c); + } + + [Protocol] + public interface Second { + [Abstract] + [Export ("doit:with:more:stuff")] + bool DoIt (int a, int b, int c); + } + + [BaseType (typeof (NSObject))] + public partial interface Derived : First, Second { + } +} + diff --git a/tests/generator/protocol-duplicate-method-diff-type.cs b/tests/generator/protocol-duplicate-method-diff-type.cs new file mode 100644 index 000000000000..97e3ed43ff35 --- /dev/null +++ b/tests/generator/protocol-duplicate-method-diff-type.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +#if !XAMCORE_2_0 +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +#else +using Foundation; +using ObjCRuntime; +#endif + +namespace Test +{ + [Protocol] + public interface First + { + [Abstract] + [Export ("doit:with:more:")] + void DoIt (int a, int b, int c); + } + + [Protocol] + public interface Second { + [Abstract] + [Export ("doit:with:more:")] + void DoIt (int a, int b, NSObject c); + } + + [BaseType (typeof (NSObject))] + public partial interface Derived : First, Second { + } +} + diff --git a/tests/generator/sof20696157.cs b/tests/generator/sof20696157.cs new file mode 100644 index 000000000000..5bbf91ec52a1 --- /dev/null +++ b/tests/generator/sof20696157.cs @@ -0,0 +1,405 @@ +using MonoMac.AVFoundation; +using MonoMac.AddressBook; +using MonoMac.AppKit; +using MonoMac.AudioToolbox; +using MonoMac.AudioUnit; +using MonoMac.AudioUnitWrapper; +using MonoMac.Constants; +using MonoMac.CoreAnimation; +using MonoMac.CoreBluetooth; +using MonoMac.CoreData; +using MonoMac.CoreFoundation; +using MonoMac.CoreGraphics; +using MonoMac.CoreImage; +using MonoMac.CoreLocation; +using MonoMac.CoreMedia; +using MonoMac.CoreMidi; +using MonoMac.CoreServices; +using MonoMac.CoreText; +using MonoMac.CoreVideo; +using MonoMac.CoreWlan; +using MonoMac.Darwin; +using MonoMac.Foundation; +using MonoMac.GameKit; +using MonoMac.Growl; +using MonoMac.ImageIO; +using MonoMac.ImageKit; +using MonoMac.ObjCRuntime; +using MonoMac.OpenAL; +using MonoMac.OpenGL; +using MonoMac.PdfKit; +using MonoMac.QTKit; +using MonoMac.QuartzComposer; +using MonoMac.QuickLook; +using MonoMac.SceneKit; +using MonoMac.ScriptingBridge; +using MonoMac.Security; +using MonoMac.StoreKit; +using MonoMac.WebKit; +using MonoTouch; +using MonoTouch.AVFoundation; +using MonoTouch.Accelerate; +using MonoTouch.Accounts; +using MonoTouch.AdSupport; +using MonoTouch.AddressBook; +using MonoTouch.AddressBookUI; +using MonoTouch.AssetsLibrary; +using MonoTouch.AudioToolbox; +using MonoTouch.AudioUnit; +using MonoTouch.AudioUnitWrapper; +using MonoTouch.CoreAnimation; +using MonoTouch.CoreBluetooth; +using MonoTouch.CoreData; +using MonoTouch.CoreFoundation; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreImage; +using MonoTouch.CoreLocation; +using MonoTouch.CoreMedia; +using MonoTouch.CoreMidi; +using MonoTouch.CoreMotion; +using MonoTouch.CoreServices; +using MonoTouch.CoreTelephony; +using MonoTouch.CoreText; +using MonoTouch.CoreVideo; +using MonoTouch.EventKit; +using MonoTouch.EventKitUI; +using MonoTouch.ExternalAccessory; +using MonoTouch.Foundation; +using MonoTouch.GLKit; +using MonoTouch.GameController; +using MonoTouch.GameKit; +using MonoTouch.ImageIO; +using MonoTouch.JavaScriptCore; +using MonoTouch.MapKit; +using MonoTouch.MediaAccessibility; +using MonoTouch.MediaPlayer; +using MonoTouch.MediaToolbox; +using MonoTouch.MessageUI; +using MonoTouch.MobileCoreServices; +using MonoTouch.MultipeerConnectivity; +using MonoTouch.NewsstandKit; +using MonoTouch.ObjCRuntime; +using MonoTouch.OpenGLES; +using MonoTouch.PassKit; +using MonoTouch.QuickLook; +using MonoTouch.Registrar; +using MonoTouch.SafariServices; +using MonoTouch.Security; +using MonoTouch.Social; +using MonoTouch.SpriteKit; +using MonoTouch.StoreKit; +using MonoTouch.SystemConfiguration; +using MonoTouch.Twitter; +using MonoTouch.UIKit; +using MonoTouch.iAd; +using OpenTK; +using System.Drawing; +using System.Reflection.Emit; +namespace Test { + [Protocol] interface C1 : ICFType {} + [Protocol] interface C2 : INativeObject {} + [Protocol] interface C3 : IUITextInputTraits {} + [Protocol] interface C4 : IUIGuidedAccessRestrictionDelegate {} + [Protocol] interface C5 : IGLKNamedEffect {} + [Protocol] interface C6 : IGLKViewDelegate {} + [Protocol] interface C7 : IGLKViewControllerDelegate {} + [Protocol] interface C8 : IMPMediaPickerControllerDelegate {} + [Protocol] interface C9 : IMFMailComposeViewControllerDelegate {} + [Protocol] interface C10 : IMFMessageComposeViewControllerDelegate {} + [Protocol] interface C11 : INSTextAttachmentContainer {} + [Protocol] interface C12 : INSTextStorageDelegate {} + [Protocol] interface C13 : INSLayoutManagerDelegate {} + [Protocol] interface C14 : IUIAccelerometerDelegate {} + [Protocol] interface C15 : IUIActionSheetDelegate {} + [Protocol] interface C16 : IUIActivityItemSource {} + [Protocol] interface C17 : IUIAlertViewDelegate {} + [Protocol] interface C18 : IUIAppearance {} + [Protocol] interface C19 : IUIStateRestoring {} + [Protocol] interface C20 : IUIApplicationDelegate {} + [Protocol] interface C21 : IUICollectionViewSource {} + [Protocol] interface C22 : IUICollectionViewDataSource {} + [Protocol] interface C23 : IUICollectionViewDelegate {} + [Protocol] interface C24 : IUICollectionViewDelegateFlowLayout {} + [Protocol] interface C25 : IUICollisionBehaviorDelegate {} + [Protocol] interface C26 : IUIDynamicAnimatorDelegate {} + [Protocol] interface C27 : IUIDynamicItem {} + [Protocol] interface C28 : IUIGestureRecognizerDelegate {} + [Protocol] interface C29 : IUITextInputTokenizer {} + [Protocol] interface C30 : IUITextInputDelegate {} + [Protocol] interface C31 : IUIBarPositioning {} + [Protocol] interface C32 : IUIBarPositioningDelegate {} + [Protocol] interface C33 : IUIDocumentInteractionControllerDelegate {} + [Protocol] interface C34 : IUIImagePickerControllerDelegate {} + [Protocol] interface C35 : IUINavigationBarDelegate {} + [Protocol] interface C36 : IUINavigationControllerDelegate {} + [Protocol] interface C37 : IUIPageViewControllerDelegate {} + [Protocol] interface C38 : IUIPageViewControllerDataSource {} + [Protocol] interface C39 : IUIPickerViewDelegate {} + [Protocol] interface C40 : IUIPickerViewDataSource {} + [Protocol] interface C41 : IUIScrollViewDelegate {} + [Protocol] interface C42 : IUISearchBarDelegate {} + [Protocol] interface C43 : IUISearchDisplayDelegate {} + [Protocol] interface C44 : IUITabBarDelegate {} + [Protocol] interface C45 : IUITabBarControllerDelegate {} + [Protocol] interface C46 : IUITableViewDataSource {} + [Protocol] interface C47 : IUITableViewDelegate {} + [Protocol] interface C48 : IUITextFieldDelegate {} + [Protocol] interface C49 : IUITextViewDelegate {} + [Protocol] interface C50 : IUIToolbarDelegate {} + [Protocol] interface C51 : IUIVideoEditorControllerDelegate {} + [Protocol] interface C52 : IUIViewControllerContextTransitioning {} + [Protocol] interface C53 : IUIViewControllerAnimatedTransitioning {} + [Protocol] interface C54 : IUIViewControllerInteractiveTransitioning {} + [Protocol] interface C55 : IUIViewControllerTransitioningDelegate {} + [Protocol] interface C57 : IUIViewControllerTransitionCoordinatorContext {} + [Protocol] interface C58 : IUIViewControllerTransitionCoordinator {} + [Protocol] interface C59 : IUIWebViewDelegate {} + [Protocol] interface C60 : IUISplitViewControllerDelegate {} + [Protocol] interface C61 : IUIPopoverControllerDelegate {} + [Protocol] interface C62 : IUIPrintInteractionControllerDelegate {} + [Protocol] interface C63 : IUILayoutSupport {} + [Protocol] interface C64 : IMKAnnotation {} + [Protocol] interface C65 : IMKOverlay {} + [Protocol] interface C66 : IMKMapViewDelegate {} + [Protocol] interface C67 : IMKReverseGeocoderDelegate {} + [Protocol] interface C68 : IMKLocalSearch {} + [Protocol] interface C69 : IMKLocalSearchRequest {} + [Protocol] interface C70 : IMKLocalSearchResponse {} + [Protocol] interface C71 : IABNewPersonViewControllerDelegate {} + [Protocol] interface C72 : IABPeoplePickerNavigationControllerDelegate {} + [Protocol] interface C73 : IABPersonViewControllerDelegate {} + [Protocol] interface C74 : IABUnknownPersonViewControllerDelegate {} + [Protocol] interface C75 : IEAAccessoryDelegate {} + [Protocol] interface C76 : IADBannerViewDelegate {} + [Protocol] interface C77 : IADInterstitialAdDelegate {} + [Protocol] interface C78 : IEKEventViewDelegate {} + [Protocol] interface C79 : IEKEventEditViewDelegate {} + [Protocol] interface C80 : IEKCalendarChooserDelegate {} + [Protocol] interface C81 : IPKAddPassesViewControllerDelegate {} + [Protocol] interface C82 : ISKPhysicsContactDelegate {} + [Protocol] interface C83 : IMCSessionDelegate {} + [Protocol] interface C84 : IMCNearbyServiceAdvertiserDelegate {} + [Protocol] interface C85 : IMCNearbyServiceBrowserDelegate {} + [Protocol] interface C86 : IMCBrowserViewControllerDelegate {} + [Protocol] interface C87 : IMCAdvertiserAssistantDelegate {} + [Protocol] interface C88 : IAVAudioPlayerDelegate {} + [Protocol] interface C89 : IAVAudioRecorderDelegate {} + [Protocol] interface C90 : IAVAudioSessionDelegate {} + [Protocol] interface C91 : IAVAssetResourceLoaderDelegate {} + [Protocol] interface C92 : IAVVideoCompositing {} + [Protocol] interface C93 : IAVVideoCompositionValidationHandling {} + [Protocol] interface C94 : IAVCaptureVideoDataOutputSampleBufferDelegate {} + [Protocol] interface C95 : IAVCaptureAudioDataOutputSampleBufferDelegate {} + [Protocol] interface C96 : IAVCaptureFileOutputRecordingDelegate {} + [Protocol] interface C97 : IAVCaptureMetadataOutputObjectsDelegate {} + [Protocol] interface C98 : IAVPlayerItemOutputPullDelegate {} + [Protocol] interface C99 : IAVPlayerItemOutputPushDelegate {} + [Protocol] interface C100 : IAVPlayerItemLegibleOutputPushDelegate {} + [Protocol] interface C101 : IAVAsynchronousKeyValueLoading {} + [Protocol] interface C102 : IAVSpeechSynthesizerDelegate {} + [Protocol] interface C103 : ICAMediaTiming {} + [Protocol] interface C104 : ICALayerDelegate {} + [Protocol] interface C105 : ICAAction {} + [Protocol] interface C106 : ICBCentralManagerDelegate {} + [Protocol] interface C107 : ICBPeripheralDelegate {} + [Protocol] interface C108 : ICBPeripheralManagerDelegate {} + [Protocol] interface C109 : INSFetchedResultsControllerDelegate {} + [Protocol] interface C110 : INSFetchedResultsSectionInfo {} + [Protocol] interface C111 : INSCacheDelegate {} + [Protocol] interface C112 : INSCoding {} + [Protocol] interface C113 : INSSecureCoding {} + [Protocol] interface C114 : INSCopying {} + [Protocol] interface C115 : INSMutableCopying {} + [Protocol] interface C116 : INSKeyedArchiverDelegate {} + [Protocol] interface C117 : INSKeyedUnarchiverDelegate {} + [Protocol] interface C118 : INSMetadataQueryDelegate {} + [Protocol] interface C119 : INSUrlConnectionDelegate {} + [Protocol] interface C120 : INSUrlConnectionDownloadDelegate {} + [Protocol] interface C121 : INSUrlSessionDelegate {} + [Protocol] interface C122 : INSUrlSessionTaskDelegate {} + [Protocol] interface C123 : INSUrlSessionDataDelegate {} + [Protocol] interface C124 : INSUrlSessionDownloadDelegate {} + [Protocol] interface C125 : INSStreamDelegate {} + [Protocol] interface C126 : INSNetServiceDelegate {} + [Protocol] interface C127 : INSNetServiceBrowserDelegate {} + [Protocol] interface C128 : INSPortDelegate {} + [Protocol] interface C129 : INSMachPortDelegate {} + [Protocol] interface C130 : INSFileManagerDelegate {} + [Protocol] interface C131 : INSFilePresenter {} + [Protocol] interface C132 : IGKPeerPickerControllerDelegate {} + [Protocol] interface C133 : IGKVoiceChatClient {} + [Protocol] interface C134 : IGKSessionDelegate {} + [Protocol] interface C135 : IGKLeaderboardViewControllerDelegate {} + [Protocol] interface C136 : IGKMatchDelegate {} + [Protocol] interface C137 : IGKMatchmakerViewControllerDelegate {} + [Protocol] interface C138 : IGKAchievementViewControllerDelegate {} + [Protocol] interface C139 : IGKFriendRequestComposeViewControllerDelegate {} + [Protocol] interface C140 : IGKTurnBasedEventHandlerDelegate {} + [Protocol] interface C141 : IGKTurnBasedMatchmakerViewControllerDelegate {} + [Protocol] interface C142 : IGKGameCenterControllerDelegate {} + [Protocol] interface C143 : IGKChallengeEventHandlerDelegate {} + [Protocol] interface C144 : IGKLocalPlayerListener {} + [Protocol] interface C145 : IGKChallengeListener {} + [Protocol] interface C146 : IGKInviteEventListener {} + [Protocol] interface C147 : IGKTurnBasedEventListener {} + [Protocol] interface C148 : IQLPreviewControllerDataSource {} + [Protocol] interface C149 : IQLPreviewControllerDelegate {} + [Protocol] interface C150 : IQLPreviewItem {} + [Protocol] interface C151 : ISKPaymentTransactionObserver {} + [Protocol] interface C152 : ISKRequestDelegate {} + [Protocol] interface C153 : ISKProductsRequestDelegate {} + [Protocol] interface C154 : ISKStoreProductViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M1 : ICFType {} + [Protocol] [BaseType (typeof (NSObject))] interface M2 : INativeObject {} + [Protocol] [BaseType (typeof (NSObject))] interface M3 : IUITextInputTraits {} + [Protocol] [BaseType (typeof (NSObject))] interface M4 : IUIGuidedAccessRestrictionDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M5 : IGLKNamedEffect {} + [Protocol] [BaseType (typeof (NSObject))] interface M6 : IGLKViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M7 : IGLKViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M8 : IMPMediaPickerControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M9 : IMFMailComposeViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M10 : IMFMessageComposeViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M11 : INSTextAttachmentContainer {} + [Protocol] [BaseType (typeof (NSObject))] interface M12 : INSTextStorageDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M13 : INSLayoutManagerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M14 : IUIAccelerometerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M15 : IUIActionSheetDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M16 : IUIActivityItemSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M17 : IUIAlertViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M18 : IUIAppearance {} + [Protocol] [BaseType (typeof (NSObject))] interface M19 : IUIStateRestoring {} + [Protocol] [BaseType (typeof (NSObject))] interface M20 : IUIApplicationDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M21 : IUICollectionViewSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M22 : IUICollectionViewDataSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M23 : IUICollectionViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M24 : IUICollectionViewDelegateFlowLayout {} + [Protocol] [BaseType (typeof (NSObject))] interface M25 : IUICollisionBehaviorDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M26 : IUIDynamicAnimatorDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M27 : IUIDynamicItem {} + [Protocol] [BaseType (typeof (NSObject))] interface M28 : IUIGestureRecognizerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M29 : IUITextInputTokenizer {} + [Protocol] [BaseType (typeof (NSObject))] interface M30 : IUITextInputDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M31 : IUIBarPositioning {} + [Protocol] [BaseType (typeof (NSObject))] interface M32 : IUIBarPositioningDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M33 : IUIDocumentInteractionControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M34 : IUIImagePickerControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M35 : IUINavigationBarDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M36 : IUINavigationControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M37 : IUIPageViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M38 : IUIPageViewControllerDataSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M39 : IUIPickerViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M40 : IUIPickerViewDataSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M41 : IUIScrollViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M42 : IUISearchBarDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M43 : IUISearchDisplayDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M44 : IUITabBarDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M45 : IUITabBarControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M46 : IUITableViewDataSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M47 : IUITableViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M48 : IUITextFieldDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M49 : IUITextViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M50 : IUIToolbarDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M51 : IUIVideoEditorControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M52 : IUIViewControllerContextTransitioning {} + [Protocol] [BaseType (typeof (NSObject))] interface M53 : IUIViewControllerAnimatedTransitioning {} + [Protocol] [BaseType (typeof (NSObject))] interface M54 : IUIViewControllerInteractiveTransitioning {} + [Protocol] [BaseType (typeof (NSObject))] interface M55 : IUIViewControllerTransitioningDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M57 : IUIViewControllerTransitionCoordinatorContext {} + [Protocol] [BaseType (typeof (NSObject))] interface M58 : IUIViewControllerTransitionCoordinator {} + [Protocol] [BaseType (typeof (NSObject))] interface M59 : IUIWebViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M60 : IUISplitViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M61 : IUIPopoverControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M62 : IUIPrintInteractionControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M63 : IUILayoutSupport {} + [Protocol] [BaseType (typeof (NSObject))] interface M64 : IMKAnnotation {} + [Protocol] [BaseType (typeof (NSObject))] interface M65 : IMKOverlay {} + [Protocol] [BaseType (typeof (NSObject))] interface M66 : IMKMapViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M67 : IMKReverseGeocoderDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M68 : IMKLocalSearch {} + [Protocol] [BaseType (typeof (NSObject))] interface M69 : IMKLocalSearchRequest {} + [Protocol] [BaseType (typeof (NSObject))] interface M70 : IMKLocalSearchResponse {} + [Protocol] [BaseType (typeof (NSObject))] interface M71 : IABNewPersonViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M72 : IABPeoplePickerNavigationControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M73 : IABPersonViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M74 : IABUnknownPersonViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M75 : IEAAccessoryDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M76 : IADBannerViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M77 : IADInterstitialAdDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M78 : IEKEventViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M79 : IEKEventEditViewDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M80 : IEKCalendarChooserDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M81 : IPKAddPassesViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M82 : ISKPhysicsContactDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M83 : IMCSessionDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M84 : IMCNearbyServiceAdvertiserDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M85 : IMCNearbyServiceBrowserDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M86 : IMCBrowserViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M87 : IMCAdvertiserAssistantDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M88 : IAVAudioPlayerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M89 : IAVAudioRecorderDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M90 : IAVAudioSessionDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M91 : IAVAssetResourceLoaderDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M92 : IAVVideoCompositing {} + [Protocol] [BaseType (typeof (NSObject))] interface M93 : IAVVideoCompositionValidationHandling {} + [Protocol] [BaseType (typeof (NSObject))] interface M94 : IAVCaptureVideoDataOutputSampleBufferDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M95 : IAVCaptureAudioDataOutputSampleBufferDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M96 : IAVCaptureFileOutputRecordingDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M97 : IAVCaptureMetadataOutputObjectsDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M98 : IAVPlayerItemOutputPullDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M99 : IAVPlayerItemOutputPushDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M100 : IAVPlayerItemLegibleOutputPushDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M101 : IAVAsynchronousKeyValueLoading {} + [Protocol] [BaseType (typeof (NSObject))] interface M102 : IAVSpeechSynthesizerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M103 : ICAMediaTiming {} + [Protocol] [BaseType (typeof (NSObject))] interface M104 : ICALayerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M105 : ICAAction {} + [Protocol] [BaseType (typeof (NSObject))] interface M106 : ICBCentralManagerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M107 : ICBPeripheralDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M108 : ICBPeripheralManagerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M109 : INSFetchedResultsControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M110 : INSFetchedResultsSectionInfo {} + [Protocol] [BaseType (typeof (NSObject))] interface M111 : INSCacheDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M112 : INSCoding {} + [Protocol] [BaseType (typeof (NSObject))] interface M113 : INSSecureCoding {} + [Protocol] [BaseType (typeof (NSObject))] interface M114 : INSCopying {} + [Protocol] [BaseType (typeof (NSObject))] interface M115 : INSMutableCopying {} + [Protocol] [BaseType (typeof (NSObject))] interface M116 : INSKeyedArchiverDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M117 : INSKeyedUnarchiverDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M118 : INSMetadataQueryDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M119 : INSUrlConnectionDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M120 : INSUrlConnectionDownloadDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M121 : INSUrlSessionDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M122 : INSUrlSessionTaskDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M123 : INSUrlSessionDataDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M124 : INSUrlSessionDownloadDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M125 : INSStreamDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M126 : INSNetServiceDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M127 : INSNetServiceBrowserDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M128 : INSPortDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M129 : INSMachPortDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M130 : INSFileManagerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M131 : INSFilePresenter {} + [Protocol] [BaseType (typeof (NSObject))] interface M132 : IGKPeerPickerControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M133 : IGKVoiceChatClient {} + [Protocol] [BaseType (typeof (NSObject))] interface M134 : IGKSessionDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M135 : IGKLeaderboardViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M136 : IGKMatchDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M137 : IGKMatchmakerViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M138 : IGKAchievementViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M139 : IGKFriendRequestComposeViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M140 : IGKTurnBasedEventHandlerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M141 : IGKTurnBasedMatchmakerViewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M142 : IGKGameCenterControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M143 : IGKChallengeEventHandlerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M144 : IGKLocalPlayerListener {} + [Protocol] [BaseType (typeof (NSObject))] interface M145 : IGKChallengeListener {} + [Protocol] [BaseType (typeof (NSObject))] interface M146 : IGKInviteEventListener {} + [Protocol] [BaseType (typeof (NSObject))] interface M147 : IGKTurnBasedEventListener {} + [Protocol] [BaseType (typeof (NSObject))] interface M148 : IQLPreviewControllerDataSource {} + [Protocol] [BaseType (typeof (NSObject))] interface M149 : IQLPreviewControllerDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M150 : IQLPreviewItem {} + [Protocol] [BaseType (typeof (NSObject))] interface M151 : ISKPaymentTransactionObserver {} + [Protocol] [BaseType (typeof (NSObject))] interface M152 : ISKRequestDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M153 : ISKProductsRequestDelegate {} + [Protocol] [BaseType (typeof (NSObject))] interface M154 : ISKStoreProductViewControllerDelegate {} +} diff --git a/tests/generator/sof20696157.sh b/tests/generator/sof20696157.sh new file mode 100644 index 000000000000..e7cad05194f2 --- /dev/null +++ b/tests/generator/sof20696157.sh @@ -0,0 +1,6 @@ +MONO_PATH=/Developer/MonoTouch/usr/lib/mono/2.1/ monodis /Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll > monotouch.il +for n in `grep [.]namespace *.il | sort | uniq | sed 's/.namespace //'`; do echo "using $n;"; done > sof20696157.cs +echo "namespace Test {" >> sof20696157.cs +C=1; for i in `grep "[.]class interface public" *.il | sed 's/.* //'`; do echo -e "\t[Protocol] interface C$C : $i {}"; let C=$C+1; done >> sof20696157.cs +C=1; for i in `grep "[.]class interface public" *.il | sed 's/.* //'`; do echo -e "\t[Protocol] [BaseType (typeof (NSObject))] interface M$C : $i {}"; let C=$C+1; done >> sof20696157.cs +echo "}" >> sof20696157.cs \ No newline at end of file diff --git a/tests/link all/AppDelegate.cs b/tests/link all/AppDelegate.cs new file mode 100644 index 000000000000..06a94bca4831 --- /dev/null +++ b/tests/link all/AppDelegate.cs @@ -0,0 +1,53 @@ +#if !__WATCHOS__ +using System; +using System.Collections.Generic; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; + +namespace LinkAll +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + UIWindow window; + TouchRunner runner; + + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + // create a new window instance based on the screen size + window = new UIWindow (UIScreen.MainScreen.Bounds); + runner = new TouchRunner (window); + + // register every tests included in the main application/assembly + runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); + runner.Add (typeof (BundledResources.ResourcesTest).Assembly); + + window.RootViewController = new UINavigationController (runner.GetViewController ()); + + // make the window visible + window.MakeKeyAndVisible (); + + return true; + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/link all/AttributeTest.cs b/tests/link all/AttributeTest.cs new file mode 100644 index 000000000000..c72cd763d4c5 --- /dev/null +++ b/tests/link all/AttributeTest.cs @@ -0,0 +1,187 @@ +// +// Link All attribute-related Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Permissions; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +[assembly: Debuggable (DebuggableAttribute.DebuggingModes.Default)] + +[assembly: LinkAll.Attributes.CustomAttributeArray (typeof (LinkAll.Attributes.CustomTypeA))] +[assembly: LinkAll.Attributes.CustomAttribute (typeof (LinkAll.Attributes.CustomType))] + +namespace LinkAll.Attributes { + + // the linker removes those attributes on release builds but must keep them in debug builds + [DebuggerDisplay ("value")] + [DebuggerNonUserCode] + [DebuggerStepThrough] + [DebuggerTypeProxy ("")] + [DebuggerVisualizer ("")] + class FullyDecorated { + + [DebuggerHidden] + [DebuggerStepperBoundary] + public FullyDecorated () + { + } + + [DebuggerBrowsable (DebuggerBrowsableState.Collapsed)] + public int Property { get; set; } + } + + public class CustomAttributeArray : Attribute { + readonly Type[] _types; + + public CustomAttributeArray (params Type[] types) + { + _types = types; + } + } + + public class CustomTypeA { + } + + public class CustomAttribute : Attribute { + readonly Type _type; + + public CustomAttribute (Type type) + { + _type = type; + } + } + + public class CustomType { + } + + [FileIOPermission (SecurityAction.LinkDemand, AllLocalFiles = FileIOPermissionAccess.AllAccess)] + public class SecurityDeclarationDecoratedUserCode { + + [FileIOPermission (SecurityAction.Assert, AllLocalFiles = FileIOPermissionAccess.NoAccess)] + static public bool Check () + { + return true; + } + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class AttributeTest { + + [Test] + public void DebugAssemblyAttributes () + { + bool result = false; + foreach (object ca in typeof(FullyDecorated).Assembly.GetCustomAttributes (false)) { + if (ca is DebuggableAttribute) + result = true; + } +#if DEBUG + Assert.True (result, "DebuggableAttribute"); +#else + Assert.False (result, "DebuggableAttribute"); +#endif + } + + [Test] + public void DebugTypeAttributes () + { + var ca = typeof(FullyDecorated).GetCustomAttributes (false); +#if DEBUG + Assert.That (ca.Length, Is.EqualTo (5), "Debug attributes in debug mode"); +#else + Assert.That (ca.Length, Is.EqualTo (0), "no debug attribute in release mode"); +#endif + } + + [Test] + public void DebugConstructorAttributes () + { + var ca = typeof(FullyDecorated).GetConstructor (Type.EmptyTypes).GetCustomAttributes (false); +#if DEBUG + Assert.That (ca.Length, Is.EqualTo (2), "Debug attributes in debug mode"); +#else + Assert.That (ca.Length, Is.EqualTo (0), "No debug attribute in release mode"); +#endif + } + + [Test] + public void DebugPropertyAttributes () + { + // Ensure the linker won't remove them. Note: we do not want to use [Preserve] + // since it wculd change how the linker process them (and the attributes) + var c = new FullyDecorated (); + c.Property = 1; + + bool result = false; + foreach (object ca in typeof (FullyDecorated).GetProperty ("Property").GetCustomAttributes (false)) { + if (ca is DebuggerBrowsableAttribute) + result = true; + } +#if DEBUG + Assert.True (result, "DebuggerBrowsable"); +#else + Assert.False (result, "DebuggerBrowsable"); +#endif + } + + [Test] + public void DebuggerTypeProxy_24203 () + { + var d = new Dictionary () { { "key", 0 } }; + Assert.NotNull (d); // just to be 100% sure it won't be linked away (with the attribute we'll be looking for) + var proxy = Type.GetType ("System.Collections.Generic.Mscorlib_DictionaryDebugView`2, mscorlib"); +#if DEBUG + Assert.NotNull (proxy, "proxy"); + // having the type is nice, but it must not be empty to be useful + Assert.That (proxy.GetConstructors ().Length, Is.GreaterThan (0), "constructors"); + Assert.That (proxy.GetProperties ().Length, Is.GreaterThan (0), "properties"); +#else + Assert.Null (proxy, "proxy"); +#endif + } + + [Test] + public void CustomAttributesWithTypes () + { + var assembly = GetType ().Assembly; + var ta = assembly.GetCustomAttributes (); + Assert.That (ta.Count (), Is.EqualTo (1), "Type[]"); + Assert.NotNull (Type.GetType ("LinkAll.Attributes.CustomTypeA"), "CustomTypeA"); + + var t = assembly.GetCustomAttributes(); + Assert.That (t.Count (), Is.EqualTo (1), "Type"); + Assert.NotNull (Type.GetType ("LinkAll.Attributes.CustomType"), "CustomType"); + } + + [Test] + public void SecurityDeclaration () + { + // note: security declarations != custom attributes + // we ensure that we can create the type / call the code + Assert.True (SecurityDeclarationDecoratedUserCode.Check (), "call"); + // we ensure that both the permission and the flag are NOT part of the final/linked binary (link all removes security declarations) + Assert.Null (Type.GetType ("System.Security.Permissions.FileIOPermissionAttribute, mscorlib"), "FileIOPermissionAttribute"); + Assert.Null (Type.GetType ("System.Security.Permissions.FileIOPermissionAccess, mscorlib"), "FileIOPermissionAccess"); + } + } +} \ No newline at end of file diff --git a/tests/link all/CalendarTest.cs b/tests/link all/CalendarTest.cs new file mode 100644 index 000000000000..e0621e8fa21e --- /dev/null +++ b/tests/link all/CalendarTest.cs @@ -0,0 +1,42 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.Globalization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Calendars { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class CalendarTest { + + // application *MUST* be build with I18N.MidEast and I18N.Other (Thai) + + [Test] + public void UmAlQura () + { + var ci = CultureInfo.GetCultureInfo ("ar"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.UmAlQuraCalendar"), "Calendar"); + } + + [Test] + public void Hijri () + { + var ci = CultureInfo.GetCultureInfo ("ps"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.HijriCalendar"), "Calendar"); + } + + [Test] + public void ThaiBuddhist () + { + var ci = CultureInfo.GetCultureInfo ("th"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.ThaiBuddhistCalendar"), "Calendar"); + } + } +} \ No newline at end of file diff --git a/tests/link all/ClassLayoutTest.cs b/tests/link all/ClassLayoutTest.cs new file mode 100644 index 000000000000..61f60900c00b --- /dev/null +++ b/tests/link all/ClassLayoutTest.cs @@ -0,0 +1,115 @@ +// +// Link All [Regression] Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Layout { + + class DefaultClass { + public int never_used; // the linker will remove this + public int used; + } + + [StructLayout (LayoutKind.Auto)] + class AutoClass { + public int never_used; // the linker will remove this + public int used; + } + + [StructLayout (LayoutKind.Sequential)] + class SequentialClass { + public int never_used; // the linker MUST NOT remove this + public int used; + } + + [StructLayout (LayoutKind.Explicit)] + class ExplicitClass { + [FieldOffset (0)] + public int never_used; // the linker could remove this + [FieldOffset (4)] + public int used; + [FieldOffset (8)] + public int never_ever_used; // the linker MUST NOT remove this + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class ClassLayoutTest { + + [Test] + public void DefaultLayoutClass () // auto + { + DefaultClass c = new DefaultClass (); + c.used = 1; + // can't ask SizeOf on Auto + var t = typeof (DefaultClass); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (1), "Length"); + Assert.That (fields [0].Name, Is.EqualTo ("used"), "Name"); + + Assert.True (t.IsAutoLayout, "IsAutoLayout"); + Assert.False (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.False (t.IsLayoutSequential, "IsLayoutSequential"); + } + + [Test] + public void AutoLayoutClass () + { + AutoClass c = new AutoClass (); + c.used = 1; + // can't ask SizeOf on Auto + var t = typeof (AutoClass); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (1), "Length"); + Assert.That (fields [0].Name, Is.EqualTo ("used"), "Name"); + + Assert.True (t.IsAutoLayout, "IsAutoLayout"); + Assert.False (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.False (t.IsLayoutSequential, "IsLayoutSequential"); + } + + [Test] + public void LayoutSequential () + { + SequentialClass c = new SequentialClass (); + c.used = 1; + Assert.That (Marshal.SizeOf (c), Is.EqualTo (8), "2 fields"); + var t = typeof (SequentialClass); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (2), "Length"); + + Assert.False (t.IsAutoLayout, "IsAutoLayout"); + Assert.False (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.True (t.IsLayoutSequential, "IsLayoutSequential"); + } + + [Test] + public void ExplicitLayout () + { + ExplicitClass c = new ExplicitClass (); + c.used = 1; + Assert.That (Marshal.SizeOf (c), Is.GreaterThanOrEqualTo (12), "3 fields"); + var t = typeof (ExplicitClass); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (3), "Length"); + + Assert.False (t.IsAutoLayout, "IsAutoLayout"); + Assert.True (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.False (t.IsLayoutSequential, "IsLayoutSequential"); + } + } +} \ No newline at end of file diff --git a/tests/link all/DataContractTest.cs b/tests/link all/DataContractTest.cs new file mode 100644 index 000000000000..753ba3c4f2f9 --- /dev/null +++ b/tests/link all/DataContractTest.cs @@ -0,0 +1,82 @@ +// +// Link All Data Contract Serialization Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Xml; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +namespace LinkAll.Serialization.DataContract { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class DataContractTest { + + // test case from: https://bugzilla.xamarin.com/show_bug.cgi?id=11135 (public bug) + + // You also need to add custom types as '[KnownType(typeof(CustomType))]' attributes + public static string ToXml (T obj) + { + var sb = new StringBuilder(); + using (var x = XmlWriter.Create (sb, new XmlWriterSettings ())) { + var s = new DataContractSerializer (typeof (T)); + s.WriteObject(x, obj); + } + return sb.ToString(); + } + + public static T FromXml (string xml) + { + using (var r = XmlReader.Create (new StringReader (xml))) { + var s = new DataContractSerializer (typeof (T)); + return (T) s.ReadObject (r); + } + } + + [DataContract (Namespace = "mb")] + public class TestClass + { + public TestClass (SomeTypes types) + { + Types = types; + } + + [DataMember] + public SomeTypes Types { get; set; } + } + + [DataContract (Namespace = "mb")][Flags] + public enum SomeTypes { + [Preserve (AllMembers = true)][EnumMember] None = 0, + [Preserve (AllMembers = true)][EnumMember] Image = 1, + [Preserve (AllMembers = true)][EnumMember] Audio = 2, + [Preserve (AllMembers = true)][EnumMember] Video = 4, + [Preserve (AllMembers = true)][EnumMember] Document = 8 + } + + [Test] + public void Flags () + { + var t1 = new TestClass (SomeTypes.Audio | SomeTypes.Image); + var st = ToXml (t1); + var t2 = FromXml (st); + Assert.AreEqual (t2.Types, t1.Types); + } + } +} \ No newline at end of file diff --git a/tests/link all/Info.plist b/tests/link all/Info.plist new file mode 100644 index 000000000000..9dafe4f5bbf2 --- /dev/null +++ b/tests/link all/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDisplayName + LinkAll + CFBundleIdentifier + com.xamarin.linkall + MinimumOSVersion + 5.1.1 + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CFBundleName + LinkAll + + diff --git a/tests/link all/InterfacesTest.cs b/tests/link all/InterfacesTest.cs new file mode 100644 index 000000000000..cb62d254711b --- /dev/null +++ b/tests/link all/InterfacesTest.cs @@ -0,0 +1,111 @@ +// +// Linker interfaces-related Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Interfaces { + + interface I { + void Foo (); + void Bar (); + } + + class A : I { + public void Foo () {} + public void Bar () {} + } + + class B : I { + public void Foo () {} + public void Bar () {} + } + + class UTF8Marshaler : ICustomMarshaler { + + public object MarshalNativeToManaged (IntPtr pNativeData) + { + return null; + } + + public IntPtr MarshalManagedToNative (object managedObject) + { + return IntPtr.Zero; + } + + public int GetNativeDataSize () + { + return 0; + } + + public void CleanUpManagedData (object managedObject) + { + } + + public void CleanUpNativeData (IntPtr pNativeData) + { + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class InterfaceTest { + + static void F (I i) + { + i.Bar (); + } + + [Test] + public void Bug10866 () + { + var a = new A (); + a.Foo (); + a.Bar (); + F (new A ()); + + // Foo and Bar methods are both used on A and must be present + Assert.NotNull (typeof(A).GetMethod ("Foo", BindingFlags.Instance | BindingFlags.Public), "A::Foo"); + Assert.NotNull (typeof(A).GetMethod ("Bar", BindingFlags.Instance | BindingFlags.Public), "A::Bar"); + + // I::Foo is never used and can be removed + Assert.Null (typeof(I).GetMethod ("Foo", BindingFlags.Instance | BindingFlags.Public), "I::Foo"); + // I::Bar is used in F so everyone implementing I needs Bar + Assert.NotNull (typeof(I).GetMethod ("Bar", BindingFlags.Instance | BindingFlags.Public), "I::Bar"); + + // Foo and Bar are never used on B - so Foo can be removed + Assert.Null (typeof(B).GetMethod ("Foo", BindingFlags.Instance | BindingFlags.Public), "B::Foo"); + // but Bar cannot since B implements I + Assert.NotNull (typeof(B).GetMethod ("Bar", BindingFlags.Instance | BindingFlags.Public), "B::Bar"); + } + + [DllImport ("/usr/lib/system/libsystem_dnssd.dylib")] + public static extern int DNSServiceGetProperty ( + [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (UTF8Marshaler))] string name, + IntPtr result, ref uint size); + + uint size; + + [Test] + public void Bug16485 () + { + if (size == 1) + DNSServiceGetProperty ("Xamarin", IntPtr.Zero, ref size); + // we don't want to call the function - we only want the AOT compiler to build the CustomMarshaler + Assert.That (size, Is.EqualTo (0), "size"); + } + } +} \ No newline at end of file diff --git a/tests/link all/InternalsTest.cs b/tests/link all/InternalsTest.cs new file mode 100644 index 000000000000..daad43baf3ec --- /dev/null +++ b/tests/link all/InternalsTest.cs @@ -0,0 +1,93 @@ +// +// Link All Unit Tests for __Internal native functions +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; + +using MonoTouch; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace LinkAll.InernalCalls { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class InternalsTest { + + [DllImport ("__Internal")] + extern static string xamarin_get_locale_country_code (); + + [Test] + public void RegionInfo_CountryCode () + { + Assert.IsNotNull (xamarin_get_locale_country_code (), "xamarin_get_locale_country_code"); + } + + [DllImport ("__Internal", CharSet=CharSet.Unicode)] + extern static void xamarin_log (string s); + + [Test] + public void Console_Log () + { + xamarin_log ("ascii"); + xamarin_log ("ЉЩщӃ"); + } + +#if !XAMCORE_2_0 + [Test] + public void MessagingApi () + { + Messaging.monotouch_IntPtr_objc_msgSend_IntPtr (IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + } +#endif + + [DllImport ("__Internal")] + extern static IntPtr xamarin_timezone_get_names (ref int count); + + [Test] + public void TimeZone_Names () + { + int count = 0; + IntPtr array = xamarin_timezone_get_names (ref count); + Assert.That (count, Is.GreaterThan (400), "count"); + for (int i = 0, offset = 0; i < count; i++, offset += IntPtr.Size) { + IntPtr p = Marshal.ReadIntPtr (array, offset); + string s = Marshal.PtrToStringAnsi (p); + Assert.NotNull (s, i.ToString ()); + Marshal.FreeHGlobal (p); + } + Marshal.FreeHGlobal (array); + } + + [DllImport ("__Internal")] + extern static IntPtr xamarin_timezone_get_data (string name, ref int size); + + [Test] + public void TimeZone_Data () + { + int size = 0; + IntPtr data = xamarin_timezone_get_data (null, ref size); + Assert.That (data, Is.Not.EqualTo (IntPtr.Zero), "default"); + Assert.That (size, Is.GreaterThan (0), "default size"); + Marshal.FreeHGlobal (data); + + data = xamarin_timezone_get_data ("America/Montreal", ref size); + Assert.That (data, Is.Not.EqualTo (IntPtr.Zero), "Montreal"); + Assert.That (size, Is.GreaterThan (0), "Montreal size"); + Marshal.FreeHGlobal (data); + } + } +} \ No newline at end of file diff --git a/tests/link all/LinkAllTest.cs b/tests/link all/LinkAllTest.cs new file mode 100644 index 000000000000..4e74e8ee8bc3 --- /dev/null +++ b/tests/link all/LinkAllTest.cs @@ -0,0 +1,539 @@ +// +// Link All [Regression] Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Reflection; +using System.Security.Cryptography.X509Certificates; + +using MonoTouch; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +using ObjCRuntime; +#if !__WATCHOS__ +using StoreKit; +#endif +using UIKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.StoreKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace LinkAll { + + // we DO NOT want the code to be "fully" available + public partial class NotPreserved { + + public byte One { + get; set; + } + + [DefaultValue (2)] + public int Two { + get; set; + } + } + + // nothing directly uses Parent + public class Parent { + // but the nested type is a subclass of NSObject and gets preserved (as it's not part of monotouch.dll) + public class Derived : NSObject { + [Export ("foo")] + public void Foo () {} + } + + public void UnusedMethod () {} + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class LinkAllRegressionTest { +#if __IOS__ +#if XAMCORE_2_0 + public const string NamespacePrefix = ""; + public const string AssemblyName = "Xamarin.iOS"; +#else + public const string NamespacePrefix = "MonoTouch."; + public const string AssemblyName = "monotouch"; +#endif +#elif __TVOS__ + public const string NamespacePrefix = ""; + public const string AssemblyName = "Xamarin.TVOS"; +#elif __WATCHOS__ + public const string NamespacePrefix = ""; + public const string AssemblyName = "Xamarin.WatchOS"; +#else + #error Unknown platform +#endif + + class TypeAttribute : Attribute { + public TypeAttribute (Type type) {} + } + + [Type (null)] + public void NullTypeInAttribute () + { + // there's no need to execute this test. + // desk #68380. + } + + [Test] + public void GetterOnly () + { + // that ensure the getter is not linked away, + // which means the property will be available for MEF_3862 + NotPreserved np = new NotPreserved (); + Assert.That (np.Two, Is.EqualTo (0), "Two==0"); + PropertyInfo pi = typeof (NotPreserved).GetProperty ("Two"); + // check the *unused* setter absence from the application + Assert.NotNull (pi.GetGetMethod (), "getter"); + Assert.Null (pi.GetSetMethod (), "setter"); + } + + [Test] + public void SetterOnly () + { + // that ensure the setter is not linked away, + NotPreserved np = new NotPreserved (); + np.One = 1; + PropertyInfo pi = typeof (NotPreserved).GetProperty ("One"); + // check the *unused* setter absence from the application + Assert.Null (pi.GetGetMethod (), "getter"); + Assert.NotNull (pi.GetSetMethod (), "setter"); + } + + [Test] + public void MEF_3862 () + { + // note: avoiding using "typeof(DefaultValueAttribute)" in the code + // so the linker does not keep it just because of it + PropertyInfo pi = typeof (NotPreserved).GetProperty ("Two"); + object [] attrs = pi.GetCustomAttributes (false); + bool default_value = false; + foreach (var ca in attrs) { + if (ca.GetType ().Name == "DefaultValueAttribute") { + default_value = true; + break; + } + } + Assert.True (default_value, "DefaultValue"); + } + + class TestPolicy : ICertificatePolicy { + + const int RecoverableTrustFailure = 5; // SecTrustResult + + public TestPolicy () + { + CheckCount = 0; + } + + public int CheckCount { get; private set; } + + public bool CheckValidationResult (ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) + { + Assert.That (certificateProblem, Is.EqualTo (0), "certificateProblem"); + CheckCount++; + return true; + } + } + + static TestPolicy test_policy = new TestPolicy (); + + [Test] + public void TrustUsingOldPolicy () + { + // Three similar tests exists in dontlink, linkall and linksdk to test 3 different cases + // untrusted, custom ICertificatePolicy and ServerCertificateValidationCallback without + // having caching issues (in S.Net or the SSL handshake cache) + ICertificatePolicy old = ServicePointManager.CertificatePolicy; + try { + ServicePointManager.CertificatePolicy = test_policy; + WebClient wc = new WebClient (); + Assert.IsNotNull (wc.DownloadString ("https://wrench.internalx.com/Wrench/Login.aspx")); + // caching means it will be called at least for the first run, but it might not + // be called again in subsequent requests (unless it expires) + Assert.That (test_policy.CheckCount, Is.GreaterThan (0), "policy checked"); + } + finally { + ServicePointManager.CertificatePolicy = old; + } + } + + [Test] + public void DetectPlatform () + { +#if !__WATCHOS__ + // for (future) nunit[lite] platform detection - if this test fails then platform detection won't work + Assert.NotNull (Type.GetType (NamespacePrefix + "UIKit.UIApplicationDelegate, " + AssemblyName), "UIApplicationDelegate"); +#endif + // and you can trust the old trick with the linker + Assert.NotNull (Type.GetType ("Mono.Runtime"), "Mono.Runtime"); + } + + [Test] +#if !XAMCORE_2_0 + // internal (to be removed) in unified + [Since (9,9)] +#endif +#if !XAMCORE_3_0 + [Availability ()] + [iOS (9,9)] + [Mac (10, 99)] +#endif + [Introduced (PlatformName.None)] + [Deprecated (PlatformName.None)] + [Obsoleted (PlatformName.None)] + [Unavailable (PlatformName.None)] + [ThreadSafe] + public void RemovedAttributes () + { + const string prefix = NamespacePrefix; + const string suffix = ", " + AssemblyName; + + // since we're linking the attributes will NOT be available - even if they are used +#if !XAMCORE_3_0 + Assert.Null (Type.GetType (prefix + "ObjCRuntime.AvailabilityAttribute, " + suffix), "AvailabilityAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.iOSAttribute, " + suffix), "AvailabilityAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.AvailabilityAttribute, " + suffix), "AvailabilityAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.SinceAttribute, " + suffix), "SinceAttribute"); +#endif + Assert.Null (Type.GetType (prefix + "ObjCRuntime.IntroducedAttribute, " + suffix), "IntroducedAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.DeprecatedAttribute, " + suffix), "DeprecatedAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.ObsoletedAttribute, " + suffix), "ObsoletedAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.UnavailableAttribute, " + suffix), "UnavailableAttribute"); + Assert.Null (Type.GetType (prefix + "ObjCRuntime.ThreadSafeAttribute, " + suffix), "ThreadSafeAttribute"); + } + + [Test] + public void Assembly_Load () + { + Assembly mscorlib = Assembly.Load ("mscorlib.dll"); + Assert.NotNull (mscorlib, "mscorlib"); + + Assembly system = Assembly.Load ("System.dll"); + Assert.NotNull (system, "System"); + } + + [Test] + public void Assembly_LoadFile () + { + string filename = Path.GetFileName (GetType ().Assembly.Location); + try { + Assert.NotNull (Assembly.LoadFile (filename), "1"); + } + catch (FileNotFoundException) { + // 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too) + filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename); + Assert.NotNull (Assembly.LoadFile (filename), "2"); + } + } + + [Test] + public void Assembly_LoadFrom () + { + string filename = Path.GetFileName (GetType ().Assembly.Location); + try { + Assert.NotNull (Assembly.LoadFrom (filename), "1"); + } + catch (FileNotFoundException) { + // 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too) + filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename); + Assert.NotNull (Assembly.LoadFrom (filename), "2"); + } + } + + [Test] + public void Assembly_ReflectionOnlyLoadFrom () + { + string filename = Path.GetFileName (GetType ().Assembly.Location); + try { + Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "1"); + } + catch (FileNotFoundException) { + // 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too) + filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename); + Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "2"); + } + } + + [Test] + public void SystemDataSqlClient () + { + // notes: + // * this test is mean to fail when building the application using a Community or Indie licenses + // * linksdk.app references System.Data (assembly) but not types in SqlClient namespace + using (var sc = new System.Data.SqlClient.SqlConnection ()) { + Assert.NotNull (sc); + } + } + +#if !__TVOS__ && !__WATCHOS__ + [Test] + public void Pasteboard_ImagesTest () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var dp = new CGDataProvider (file)) { + using (var cgimg = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) { + using (var img = new UIImage (cgimg)) { + UIPasteboard.General.Images = new UIImage[] { img }; + Assert.AreEqual (1, UIPasteboard.General.Images.Length, "a - length"); + + UIPasteboard.General.Images = new UIImage[] { img, img }; + Assert.AreEqual (2, UIPasteboard.General.Images.Length, "b - length"); + Assert.IsNotNull (UIPasteboard.General.Images [0], "b - nonnull[0]"); + Assert.IsNotNull (UIPasteboard.General.Images [1], "b - nonnull[0]"); + } + } + } + } +#endif // !__TVOS__ + + [Test] + public void UltimateBindings () + { + Assert.IsNotNull (Bindings.Test.UltimateMachine.SharedInstance, "SharedInstance"); + } + + #region bug 14456 + + [TypeConverter (typeof (TestEnumTypeConverter))] + public enum TestEnum { + One,Two + } + + [Preserve (AllMembers = true)] + public class TestEnumTypeConverter : System.ComponentModel.TypeConverter { + + public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + return "hello"; + } + } + + [Test] + public void Bug14456 () + { + var tc = TypeDescriptor.GetConverter (typeof (TestEnum)); + // not using Is.TypeOf since it would give additional clue to the linker + Assert.That (tc.GetType ().Name, Is.EqualTo ("TestEnumTypeConverter"), "TestEnumTypeConverter"); + // notes: + // * without [Preserve (AllMembers = true)] -> MissingMethodException : Default constructor + // * without [TypeConverter (typeof (TestEnumTypeConverter))] -> EnumConverter + } + + #endregion + + [Test] + public void SingleEpsilon_Compare () + { + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Known to fail on devices, see bug #15802"); + // works on some ARM CPU (e.g. iPhone5S) but not others (iPad4 or iPodTouch5) + Assert.That (Single.Epsilon, Is.Not.EqualTo (0f), "Epsilon"); + Assert.That (-Single.Epsilon, Is.Not.EqualTo (0f), "-Epsilon"); + } + + [Test] + public void SingleEpsilon_ToString () + { + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Known to fail on devices, see bug #15802"); + var ci = CultureInfo.InvariantCulture; + Assert.That (Single.Epsilon.ToString (ci), Is.EqualTo ("1.401298E-45"), "Epsilon.ToString()"); + Assert.That ((-Single.Epsilon).ToString (ci), Is.EqualTo ("-1.401298E-45"), "-Epsilon.ToString()"); + } + + [Test] + public void DoubleEpsilon_Compare () + { + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Known to fail on devices, see bug #15802"); + // works on some ARM CPU (e.g. iPhone5S) but not others (iPad4 or iPodTouch5) + Assert.That (Double.Epsilon, Is.Not.EqualTo (0f), "Epsilon"); + Assert.That (-Double.Epsilon, Is.Not.EqualTo (0f), "-Epsilon"); + } + + [Test] + public void DoubleEpsilon_ToString () + { + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Known to fail on devices, see bug #15802"); + var ci = CultureInfo.InvariantCulture; + // note: unlike Single this works on both my iPhone5S and iPodTouch5 + Assert.That (Double.Epsilon.ToString (ci), Is.EqualTo ("4.94065645841247E-324"), "Epsilon.ToString()"); + Assert.That ((-Double.Epsilon).ToString (ci), Is.EqualTo ("-4.94065645841247E-324"), "-Epsilon.ToString()"); + } + + [Test] + public void AssemblyReferences_16213 () + { + foreach (var assembly in typeof (System.Data.AcceptRejectRule).Assembly.GetReferencedAssemblies ()) { + // Unlike the original bug report the unit tests uses Mono.Data.Tds so it will be part of the .app + // so we check for System.Transactions which is not used (but referenced by the original System.Data) + if (assembly.Name == "System.Transactions") + Assert.Fail ("System.Transactions reference should have removed by the linker"); + } + } + +#if !__WATCHOS__ + [Test] + public void OpenTk10_Preserved () + { + // that will bring OpenTK-1.0 into the .app + OpenTK.WindowState state = OpenTK.WindowState.Normal; + + var gl = Type.GetType ("OpenTK.Graphics.ES11.GL, OpenTK-1.0", false); + Assert.NotNull (gl, "ES11/GL"); + var core = Type.GetType ("OpenTK.Graphics.ES11.GL/Core, OpenTK-1.0", false); + Assert.NotNull (core, "ES11/Core"); + + gl = Type.GetType ("OpenTK.Graphics.ES20.GL, OpenTK-1.0", false); + Assert.NotNull (gl, "ES20/GL"); + core = Type.GetType ("OpenTK.Graphics.ES20.GL/Core, OpenTK-1.0", false); + Assert.NotNull (core, "ES20/Core"); + } +#endif // !__WATCHOS__ + + [Test] + public void NestedNSObject () + { + // Parent type is not used - but it's not linked out + var p = Type.GetType ("LinkAll.Parent"); + Assert.NotNull (p, "Parent"); + // because a nested type is a subclass of NSObject (and not part of monotouch.dll) + var n = p.GetNestedType ("Derived"); + Assert.NotNull (n, "Derived"); + // however other stuff in Parent, like unused methods, will be removed + Assert.Null (p.GetMethod ("UnusedMethod"), "unused method"); + // while exported stuff will be present + Assert.NotNull (n.GetMethod ("Foo"), "unused Export method"); + } + + [Test] + public void Bug20363 () + { + // testing compile time error + CancelEventArgs cea = new CancelEventArgs (); + Assert.NotNull (cea, "CancelEventArgs"); + } + + string GetField (object o, string s) + { + var f = o.GetType ().GetField (s, BindingFlags.Instance | BindingFlags.NonPublic); + if (f == null) + return s; + //Console.WriteLine (f.GetValue (o)); + return null; + } + + string FromPattern (string pattern, object o) + { + var s = GetField (o, ""); + if (s != null) + return s; + s = GetField (o, ""); + if (s != null) + return s; + return GetField (o, ""); + } + + [Test] + public void AnonymousType () + { + var result = FromPattern ("/{action}/{id}.{contentType}", new { + action = "foo", + id = 1234, + contentType = "xml" + }); + Assert.Null (result, result); + } + +#if !__WATCHOS__ + [Test] + public void Events () + { + using (var pr = new SKProductsRequest ()) { + Assert.Null (pr.WeakDelegate, "none"); + // event on SKProductsRequest itself + pr.ReceivedResponse += (object sender, SKProductsRequestResponseEventArgs e) => {}; + + var t = pr.WeakDelegate.GetType (); + Assert.That (t.Name, Is.EqualTo ("_SKProductsRequestDelegate"), "delegate"); + + var fi = t.GetField ("receivedResponse", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull (fi, "receivedResponse"); + var value = fi.GetValue (pr.WeakDelegate); + Assert.NotNull (value, "value"); + +#if XAMCORE_2_0 + // and on the SKRequest defined one + pr.RequestFailed += (object sender, SKRequestErrorEventArgs e) => {}; + // and the existing (initial field) is still set + fi = t.GetField ("receivedResponse", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull (fi, "receivedResponse/SKRequest"); +#else + // In Classic SKRequest also defines a RequestFailed event, so make sure we get the SKRequest one + // that's because event are re-defined (new) in classic + ((SKRequest) pr).RequestFailed += (object sender, SKRequestErrorEventArgs e) => {}; + + t = pr.WeakDelegate.GetType (); + Assert.That (t.Name, Is.EqualTo ("_SKRequestDelegate"), "delegate-2"); + + fi = t.GetField ("receivedResponse", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.Null (fi, "receivedResponse/SKRequest"); +#endif + } + } +#endif // !__WATCHOS__ + + [Test] + public void Aot_27116 () + { + var nix = (from nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces () + where nic.Id.StartsWith ("en") || nic.Id.StartsWith ("pdp_ip") select nic); + Assert.NotNull (nix); + } + + [Test] + public void TlsProvider_Legacy () + { + var provider = Mono.Security.Interface.MonoTlsProviderFactory.GetProvider (); + Assert.NotNull (provider, "provider"); + Assert.That (provider.ID, Is.EqualTo (new Guid ("97d31751-d0b3-4707-99f7-a6456b972a19")), "correct provider"); + } + + [Test] + public void OldTlsProvider_Selected () + { + // make test work for classic (monotouch) and unified (iOS, tvOS and watchOS) + var fqn = typeof (NSObject).AssemblyQualifiedName.Replace ("Foundation.NSObject", "Security.Tls.OldTlsProvider"); + Assert.NotNull (Type.GetType (fqn), "Should be included"); + } + + [Test] + public void AppleTls_OptOut () + { + // make test work for classic (monotouch) and unified (iOS, tvOS and watchOS) + var fqn = typeof (NSObject).AssemblyQualifiedName.Replace ("Foundation.NSObject", "Security.Tls.AppleTlsProvider"); + Assert.Null (Type.GetType (fqn), "Should not be included"); + } + } +} diff --git a/tests/link all/LinqExpressionTest.cs b/tests/link all/LinqExpressionTest.cs new file mode 100644 index 000000000000..f0862601993a --- /dev/null +++ b/tests/link all/LinqExpressionTest.cs @@ -0,0 +1,33 @@ +using System; +using System.Linq.Expressions; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Linq { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class LinqExpressionTest { + + // Normally this test would have been included in linksdk.app - but there's already + // some code that (indirectly) includes the code we want to test (so it can't fail) + + delegate object Bug14863Delegate (); + + [Test] + public void Expression_T_Ctor () + { + var ctor = typeof (LinqExpressionTest).GetConstructor (Type.EmptyTypes); + var expr = Expression.New (ctor, new Expression [0]); + Assert.NotNull (Expression.Lambda (typeof(Bug14863Delegate), expr, null), "Lambda"); + // note: reflection is used to create an instance of Expression using an internal ctor + // it can be indirectly "preserved" by other code (in Expression) but it can fail in other cases + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=14863 + } + } +} \ No newline at end of file diff --git a/tests/link all/MEFTests.cs b/tests/link all/MEFTests.cs new file mode 100644 index 000000000000..190b093eaca7 --- /dev/null +++ b/tests/link all/MEFTests.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.ComponentModel.Composition.Hosting; +using System.Linq; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Mef { + + // From Desk Case 70807 + public interface IStorageType + { + } + + [System.ComponentModel.Composition.Export(typeof (IStorageType))] + [Preserve (AllMembers = true)] + public class Storage : IStorageType + { + } + + [Preserve (AllMembers = true)] + [TestFixture] + public class MEFTests + { + CompositionContainer _container; + + [ImportMany] + public IEnumerable> StorageTypes { get; set; } + + [Test] + public void MEF_Basic_Import_Test () + { + var catalog = new AggregateCatalog (); + //Adds all the parts found in the same assembly as the Program class + catalog.Catalogs.Add (new AssemblyCatalog (typeof (Application).Assembly)); + + //Create the CompositionContainer with the parts in the catalog + _container = new CompositionContainer (catalog); + + this._container.SatisfyImportsOnce (this); + + Assert.IsTrue (StorageTypes.Count () > 0, "No MEF imports found?"); + } + + [Test] + public void ExportFactoryCreator () + { + // the above code makes sure that ExportFactoryCreator is present + var efc = Type.GetType ("System.ComponentModel.Composition.ReflectionModel.ExportFactoryCreator, System.ComponentModel.Composition"); + Assert.NotNull (efc, "ExportFactoryCreator"); + + // and there's nothing else that refers to them - hence bug: https://bugzilla.xamarin.com/show_bug.cgi?id=29063 + // as it's used thru reflection in CreateStronglyTypedExportFactoryFactory + var t = efc.GetMethod ("CreateStronglyTypedExportFactoryOfT", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); // same binding flags as MS code + Assert.NotNull (t, "CreateStronglyTypedExportFactoryOfT"); + var tm = efc.GetMethod ("CreateStronglyTypedExportFactoryOfTM", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); // same binding flags as MS code + Assert.NotNull (tm, "CreateStronglyTypedExportFactoryOfTM"); + } + + [Test] + public void ExportServices () + { + var es = Type.GetType ("System.ComponentModel.Composition.ExportServices, System.ComponentModel.Composition"); + Assert.NotNull (es, "ExportServices"); + // unlike the test code for ExportFactoryCreator the method can be marked by other call site, so this test is not 100% conclusive + + // used, thru reflection, from CreateStronglyTypedLazyFactory method + var t = es.GetMethod ("CreateStronglyTypedLazyOfT", BindingFlags.NonPublic | BindingFlags.Static); // same binding flags as MS code + Assert.NotNull (t, "CreateStronglyTypedLazyOfT"); + var tm = es.GetMethod ("CreateStronglyTypedLazyOfTM", BindingFlags.NonPublic | BindingFlags.Static); // same binding flags as MS code + Assert.NotNull (tm, "CreateStronglyTypedLazyOfTM"); + + // used, thru reflection, from CreateSemiStronglyTypedLazyFactory method + var l = es.GetMethod ("CreateSemiStronglyTypedLazy", BindingFlags.NonPublic | BindingFlags.Static); // same binding flags as MS code + Assert.NotNull (l, "CreateSemiStronglyTypedLazy"); + } + } +} diff --git a/tests/link all/Main.cs b/tests/link all/Main.cs new file mode 100644 index 000000000000..c9b0815dd93e --- /dev/null +++ b/tests/link all/Main.cs @@ -0,0 +1,23 @@ +using System; + +#if XAMCORE_2_0 +using UIKit; +#else +using MonoTouch.UIKit; +#endif + +namespace LinkAll +{ + public class Application + { +#if !__WATCHOS__ + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } +#endif // !__WATCHOS__ + } +} diff --git a/tests/link all/PreserveTest.cs b/tests/link all/PreserveTest.cs new file mode 100644 index 000000000000..f83addf0961f --- /dev/null +++ b/tests/link all/PreserveTest.cs @@ -0,0 +1,168 @@ +// +// Preserve tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +// this will preserve the specified type (only) +[assembly: Preserve (typeof (LinkAll.Attributes.TypeWithoutMembers))] + +// this will preserve the specified type with all it's members +[assembly: Preserve (typeof (LinkAll.Attributes.TypeWithMembers), AllMembers = true)] + +// as the preserved field is an attribute this means that [Obfuscation] becomes like [Preserve] +// IOW preserving the attribute does not do much good if what it decorates gets removed +[assembly: Preserve (typeof (ObfuscationAttribute))] + +namespace LinkAll.Attributes { + + // type and members preserved by assembly-level attribute above + class TypeWithMembers { + + public string Present { get; set; } + } + + // type (only, not members) preserved by assembly-level attribute above + class TypeWithoutMembers { + + public string Absent { get; set; } + } + + class MemberWithCustomAttribute { + + // since [Obfuscation] was manually preserved then we'll preserve everything that's decorated with the attribute + [Obfuscation] + public string Custom { get; set; } + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class PreserveTest { + +#if DEBUG + const bool Debug = true; +#else + const bool Debug = false; +#endif +#if XAMCORE_2_0 + const string NamespacePrefix = ""; + string AssemblyName = typeof (NSObject).Assembly.ToString (); +#else + const string NamespacePrefix = "MonoTouch."; + const string AssemblyName = "monotouch"; +#endif + + [Test] + public void PreserveTypeWithMembers () + { + var t = Type.GetType ("LinkAll.Attributes.TypeWithMembers"); + // both type and members are preserved + Assert.NotNull (t, "type"); + Assert.NotNull (t.GetProperty ("Present"), "members"); + } + + [Test] + public void PreserveTypeWithoutMembers () + { + var t = Type.GetType ("LinkAll.Attributes.TypeWithoutMembers"); + // type is preserved + Assert.NotNull (t, "type"); + // but we did not ask the linker to preserve it's members + Assert.Null (t.GetProperty ("Absent"), "members"); + } + + [Test] + public void PreserveTypeWithCustomAttribute () + { + var t = Type.GetType ("LinkAll.Attributes.MemberWithCustomAttribute"); + // both type and members are preserved - in this case the type is preserved because it's member was + Assert.NotNull (t, "type"); + // and that member was preserved because it's decorated with a preserved attribute + Assert.NotNull (t.GetProperty ("Custom"), "members"); + } + + [Test] + public void Class_LookupFullName () + { + var klass = Type.GetType (NamespacePrefix + "ObjCRuntime.Class, " + AssemblyName); + Assert.NotNull (klass, "Class"); + // only required (and preserved) for debug builds + var method = klass.GetMethod ("LookupFullName", BindingFlags.NonPublic | BindingFlags.Static); + // note: since iOS/runtime unification this is being called by ObjCRuntime.Runtime.LookupManagedTypeName + // and will never be removed (even on Release builds) + Assert.NotNull (method, "LookupFullName"); + } + + [Test] + public void Runtime_RegisterEntryAssembly () + { + var klass = Type.GetType (NamespacePrefix + "ObjCRuntime.Runtime, " + AssemblyName); + Assert.NotNull (klass, "Runtime"); + // RegisterEntryAssembly is only needed for the simulator (not on devices) so it's only preserved for sim builds + var method = klass.GetMethod ("RegisterEntryAssembly", BindingFlags.NonPublic | BindingFlags.Static, null, new [] { typeof (Assembly) }, null); + Assert.That (method == null, Is.EqualTo (Runtime.Arch == Arch.DEVICE), "RegisterEntryAssembly"); + } + + [Test] + public void MonoTouchException_Unconditional () + { + var klass = Type.GetType (NamespacePrefix + "Foundation.MonoTouchException, " + AssemblyName); + Assert.NotNull (klass, "MonoTouchException"); + } + + [Test] + public void Class_Unconditional () + { + var klass = Type.GetType (NamespacePrefix + "ObjCRuntime.Class, " + AssemblyName); + Assert.NotNull (klass, "Class"); + // handle is unconditionally preserved + var field = klass.GetField ("handle", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull (field, "handle"); + } + + [Test] + public void Runtime_Unconditional () + { + var klass = Type.GetType (NamespacePrefix + "ObjCRuntime.Runtime, " + AssemblyName); + Assert.NotNull (klass, "Runtime"); + // Initialize, RegisterAssembly... are unconditionally preserved + var method = klass.GetMethod ("Initialize", BindingFlags.NonPublic | BindingFlags.Static); + Assert.NotNull (method, "Initialize"); + method = klass.GetMethod ("RegisterAssembly", BindingFlags.Public | BindingFlags.Static); + Assert.NotNull (method, "RegisterAssembly"); + method = klass.GetMethod ("RegisterNSObject", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof (NSObject), typeof (IntPtr) }, null); + Assert.NotNull (method, "RegisterNSObject"); + method = klass.GetMethod ("GetBlockWrapperCreator", BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof (MethodInfo), typeof (int) }, null); + Assert.NotNull (method, "GetBlockWrapperCreator"); + method = klass.GetMethod ("CreateBlockProxy", BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof (MethodInfo), typeof (IntPtr) }, null); + Assert.NotNull (method, "CreateBlockProxy"); + } + + [Test] + public void Selector_Unconditional () + { + var klass = Type.GetType (NamespacePrefix + "ObjCRuntime.Selector, " + AssemblyName); + Assert.NotNull (klass, "Selector"); + // handle and is unconditionally preserved + var field = klass.GetField ("handle", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull (field, "handle"); + var method = klass.GetMethod ("GetHandle", BindingFlags.Public | BindingFlags.Static); + Assert.NotNull (method, "GetHandle"); + } + } +} \ No newline at end of file diff --git a/tests/link all/SealerTest.cs b/tests/link all/SealerTest.cs new file mode 100644 index 000000000000..d6dab5737d3d --- /dev/null +++ b/tests/link all/SealerTest.cs @@ -0,0 +1,71 @@ +// Copyright 2016 Xamarin Inc. All rights reserved. + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace Linker.Sealer { + + [Preserve (AllMembers = true)] + public class Unsealable { + + public virtual bool A () { return true; } + public virtual bool B () { return false; } + } + + [Preserve (AllMembers = true)] + public class Sealable : Unsealable { + public override bool B () { return true; } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class SealerTest { + + [Test] + public void Sealed () + { + // this can not be optimized into a sealed type + Assert.False (typeof (Unsealable).IsSealed, "Unsealed"); +#if DEBUG + // this is not a sealed type (in the source) + Assert.False (typeof (Sealable).IsSealed, "Sealed"); +#else + // but it can be optimized / sealed as nothing else is (or can) subclass it + Assert.True (typeof (Sealable).IsSealed, "Sealed"); +#endif + } + + [Test] + public void Final () + { + var t = typeof (Sealable); +#if DEBUG + // this is not a sealed method (in the source) + Assert.False (t.GetMethod ("B").IsFinal, "Not Final"); +#else + // but it can be optimized / sealed as nothing else is (or can) overrides it + Assert.True (t.GetMethod ("B").IsFinal, "Final"); +#endif + } + + [Test] + public void Virtual () + { + var t = typeof (Sealable); +#if DEBUG + // both methods are virtual (iin the source) + Assert.True (t.GetMethod ("A").IsVirtual, "A"); + Assert.True (t.GetMethod ("B").IsVirtual, "B"); +#else + // but A can be de-virtualized as it overrides nothing and is not overridden + Assert.False (t.GetMethod ("A").IsVirtual, "A"); + Assert.True (t.GetMethod ("B").IsVirtual, "B"); +#endif + } + } +} diff --git a/tests/link all/SerializationTest.cs b/tests/link all/SerializationTest.cs new file mode 100644 index 000000000000..5f2315367103 --- /dev/null +++ b/tests/link all/SerializationTest.cs @@ -0,0 +1,96 @@ +// +// Link All [Regression] Tests for Serialization +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.Serialization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Serialization { + + [Serializable] + public class Unused { + + [OnDeserializing] + void Deserializing () + { + } + + [OnDeserialized] + void Deserialized () + { + } + + [OnSerializing] + void Serializing () + { + } + + [OnSerialized] + void Serialized () + { + } + } + + [Serializable] + public class Used { + + [OnDeserializing] + void Deserializing () + { + } + + [OnDeserialized] + void Deserialized () + { + } + + [OnSerializing] + void Serializing () + { + } + + [OnSerialized] + void Serialized () + { + } + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class SerializationAttributeTests { + + [Test] + public void UnusedType () + { + // the serialization attributes only keeps the method(s) if the type was used + var t = Type.GetType ("LinkAll.Serialization.Unused"); + // since it's not used in the app then it's removed by the linker + Assert.Null (t, "type"); + } + + [Test] + public void UsedType () + { + // the serialization attributes only keeps the method(s) if the type was used + var t = Type.GetType ("LinkAll.Serialization.Used"); + // since it's used here... + Assert.NotNull (new Used (), "reference"); + // it's not removed by the linker + Assert.NotNull (t, "type"); + // and since it's not the 4 decorated methods are also kept (even if uncalled) + Assert.That (t.GetMethods ().Length, Is.EqualTo (4), "4"); + } + } +} diff --git a/tests/link all/StructLayoutTest.cs b/tests/link all/StructLayoutTest.cs new file mode 100644 index 000000000000..2ef9634b7149 --- /dev/null +++ b/tests/link all/StructLayoutTest.cs @@ -0,0 +1,113 @@ +// +// Link All [Regression] Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkAll.Layout { + + struct DefaultStruct { + public int never_used; + public int used; + } + + [StructLayout (LayoutKind.Auto)] + struct AutoStruct { + public int never_used; + public int used; + } + + [StructLayout (LayoutKind.Sequential)] + struct SequentialStruct { + public int never_used; + public int used; + } + + [StructLayout (LayoutKind.Explicit)] + struct ExplicitStruct { + [FieldOffset (0)] + public int never_used; + [FieldOffset (4)] + public int used; + [FieldOffset (8)] + public int never_ever_used; + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class StructLayoutTest { + + [Test] + public void DefaultLayoutStruct () // sequential + { + DefaultStruct c = new DefaultStruct (); + c.used = 1; + Assert.That (Marshal.SizeOf (c), Is.EqualTo (8), "2 fields"); + var t = typeof (DefaultStruct); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (2), "Length"); + + Assert.False (t.IsAutoLayout, "IsAutoLayout"); + Assert.False (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.True (t.IsLayoutSequential, "IsLayoutSequential"); + } + + [Test] + public void AutoLayoutStruct () + { + AutoStruct c = new AutoStruct (); + c.used = 1; + // can't ask SizeOf on Auto + var t = typeof (AutoStruct); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (2), "Length"); + + Assert.True (t.IsAutoLayout, "IsAutoLayout"); + Assert.False (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.False (t.IsLayoutSequential, "IsLayoutSequential"); + } + + [Test] + public void LayoutSequential () + { + SequentialStruct c = new SequentialStruct (); + c.used = 1; + Assert.That (Marshal.SizeOf (c), Is.EqualTo (8), "2 fields"); + var t = typeof (SequentialStruct); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (2), "Length"); + + Assert.False (t.IsAutoLayout, "IsAutoLayout"); + Assert.False (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.True (t.IsLayoutSequential, "IsLayoutSequential"); + } + + [Test] + public void ExplicitLayout () + { + ExplicitStruct c = new ExplicitStruct (); + c.used = 1; + Assert.That (Marshal.SizeOf (c), Is.GreaterThanOrEqualTo (12), "3 fields"); + var t = typeof (ExplicitStruct); + var fields = t.GetFields (); + Assert.That (fields.Length, Is.EqualTo (3), "Length"); + + Assert.False (t.IsAutoLayout, "IsAutoLayout"); + Assert.True (t.IsExplicitLayout, "IsExplicitLayout"); + Assert.False (t.IsLayoutSequential, "IsLayoutSequential"); + } + } +} \ No newline at end of file diff --git a/tests/link all/XmlSerializationTest.cs b/tests/link all/XmlSerializationTest.cs new file mode 100644 index 000000000000..34da3861a1d4 --- /dev/null +++ b/tests/link all/XmlSerializationTest.cs @@ -0,0 +1,79 @@ +// +// Link All Xml Serialization Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Xml; +using System.Xml.Serialization; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +namespace LinkAll.Serialization.Xml { + + [Serializable] + [XmlRoot ("rsp", IsNullable = false)] + public class XmlResult { + [XmlAttribute ("stat")] + public int StatusCode { get; set; } + + [XmlElement ("photos")] + [XmlElement ("photosets")] + public T Result { get; set; } + } + + [Serializable] + [XmlRoot ("rsp")] + public class XmlField { + [XmlElement ("photos")] + [XmlElement ("photosets")] + public T Result; + } + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class XmlSerializationTest { + + [Test] + public void GenericProperty_Bug5543 () + { + XmlResult r = new XmlResult (); + r.Result = "5543"; + r.StatusCode = 10; + + var serializer = new XmlSerializer (typeof (XmlResult)); + using (var ms = new MemoryStream ()) { + serializer.Serialize (ms, r); + r.Result = String.Empty; + r.StatusCode = -1; + + ms.Position = 0; + XmlResult back = (XmlResult) serializer.Deserialize (ms); + + Assert.That (back.Result, Is.EqualTo ("5543"), "Result"); + Assert.That (back.StatusCode, Is.EqualTo (10), "StatusCode"); + } + } + + [Test] + public void GenericField () + { + XmlField f = new XmlField (); + f.Result = "5543"; + // not valid for serialization but the linker should not have issue with that + } + } +} + diff --git a/tests/link all/basn3p08.png b/tests/link all/basn3p08.png new file mode 100644 index 000000000000..0ddad07e5f5d Binary files /dev/null and b/tests/link all/basn3p08.png differ diff --git a/tests/link all/link all.csproj b/tests/link all/link all.csproj new file mode 100644 index 000000000000..cc2f01d2e519 --- /dev/null +++ b/tests/link all/link all.csproj @@ -0,0 +1,126 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkall + link all + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;LINKALL; + prompt + 4 + False + True + Full + mideast,other + --registrar=static --tls-provider=legacy + i386 + + + none + False + bin\iPhoneSimulator\Release + prompt + 4 + False + Full + mideast,other + i386 + LINKALL; + --tls-provider=legacy + + + True + full + False + bin\iPhone\Debug + DEBUG;LINKALL; + prompt + 4 + False + iPhone Developer + True + Full + mideast,other + ARMv7 + --tls-provider=legacy + + + none + False + bin\iPhone\Release + prompt + 4 + False + iPhone Developer + Full + mideast,other + True + ARMv7 + -v -v -v -v --tls-provider=legacy + LINKALL; + + + + + + + + + + + + + + + + + + + + + + + + + + + OptimizeGeneratedCodeTest.cs + + + + + + + + + ReflectionTest.cs + + + + + + + + + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D} + BundledResources + + + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA} + bindings-test + + + + \ No newline at end of file diff --git a/tests/link sdk/AotBugs.cs b/tests/link sdk/AotBugs.cs new file mode 100644 index 000000000000..b6324bef4518 --- /dev/null +++ b/tests/link sdk/AotBugs.cs @@ -0,0 +1,620 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +#if !__WATCHOS__ +using System.Drawing; +#endif +using System.Linq; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +using NUnit.Framework; + +namespace LinkSdk.Aot { + + static class AotExtension { + + // https://bugzilla.xamarin.com/show_bug.cgi?id=3285 + public static IEnumerable GetInterfaces(this Type type, Type interfaceType) + { + Type[] interfaces = type.GetInterfaces(); + foreach (Type t in interfaces) { + Type typeToCheck = t; + if (t.IsGenericType) + typeToCheck = t.GetGenericTypeDefinition(); + if (typeToCheck == interfaceType) + yield return t; + } + yield break; + } + } + + interface IAotTest { + } + + [TestFixture] + // already done in Bug2096Test.cs -> [Preserve (AllMembers = true)] + public partial class AotBugsTest : IAotTest { + + // https://bugzilla.xamarin.com/show_bug.cgi?id=3285 + [Test] + public void Aot_3285 () + { + // called as an extension method (always worked) + Assert.False (GetType ().GetInterfaces (typeof (IExpectException)).Select (interf => interf != null).FirstOrDefault (), "false"); + + // workaround for #3285 - similar to previous fix for monotouch/aot + // called as a static method (does not change the result - but it was closer to the original test case) + Assert.True (AotExtension.GetInterfaces (GetType (), typeof (IAotTest)).Select (interf => interf != null).FirstOrDefault (delegate { return true; }), "delegate"); + + // actual, failing, test case (fixed by inlining code) + Assert.True (GetType ().GetInterfaces (typeof (IAotTest)).Select (interf => interf != null).FirstOrDefault (), "FirstOrDefault/true"); + + // other similar cases (returning bool with optional predicate delegate) + var enumerable = GetType ().GetInterfaces (typeof (IAotTest)).Select (interf => interf != null); + Assert.True (enumerable.Any (), "Any"); + Assert.True (enumerable.ElementAt (0), "ElementAt"); + Assert.True (enumerable.ElementAtOrDefault (0), "ElementAtOrDefault"); + Assert.True (enumerable.First (), "First"); + Assert.True (enumerable.Last (), "Last"); // failed before fix + Assert.True (enumerable.LastOrDefault (), "LastOrDefault"); // failed before fix + Assert.True (enumerable.Max (), "Max"); + Assert.True (enumerable.Min (), "Min"); + Assert.True (enumerable.Single (), "Single"); // failed before fix + Assert.True (enumerable.SingleOrDefault (), "SingleOrDefault"); // failed before fix + } + + [Test] + // https://bugzilla.xamarin.com/show_bug.cgi?id=3444 + public void ConcurrentDictionary_3444 () + { + // note: similar, but simpler, than the original bug report (same exception) + var cd = new ConcurrentDictionary (); + } + + class SomeObject { + public event EventHandler Event; + + public void RaiseEvent () + { + var fn = this.Event; + if (fn != null) + fn (this, EventArgs.Empty); + } + } + + void OnEvent (object sender, EventArgs e) + { + } + + [Test] + public void EventInfo_3682 () + { + var so = new SomeObject (); + + var e = so.GetType ().GetEvent ("Event"); + if (e != null) + e.AddEventHandler (so, new EventHandler (OnEvent)); + } + + [Test] + public void Workaround_3682 () + { + var so = new SomeObject (); + var e = so.GetType ().GetEvent ("Event"); + if (e != null) { + var add = e.GetAddMethod (); + add.Invoke (so, new object[] { new EventHandler(OnEvent) }); + } + } + + class Counseling { + public int FK_PERSON; + + public Counseling (int i) + { + FK_PERSON = i; + } + } + + class PersonDetail { + public int Id; + + public PersonDetail (int i) + { + Id = i; + } + } + + class CounselingWithPerson { + public Counseling Counseling { get; private set; } + public PersonDetail PersonDetail { get; private set; } + + public CounselingWithPerson (Counseling c, PersonDetail p) + { + Counseling = c; + PersonDetail = p; + } + } + + [Test] + public void Linq_Join_3627 () + { + List c = new List () { + new Counseling (1) + }; + List p = new List () { + new PersonDetail (1) + }; + var query = (from wqual in c + join personTable in p on wqual.FK_PERSON equals personTable.Id + select new CounselingWithPerson (wqual, personTable)); + Assert.NotNull (query.ToList ()); + // above throws ExecutionEngineException + } + + public void Workaround_3627 () + { + List c = new List () { + new Counseling (1) + }; + List p = new List () { + new PersonDetail (1) + }; + var query = (from wqual in c + join personTable in p on wqual.FK_PERSON.ToString () equals personTable.Id.ToString () + select new CounselingWithPerson (wqual, personTable)); + Assert.NotNull (query.ToList ()); + } + + public class Foo { + public int Id { get; set; } + public string Name { get; set; } + } + + [Test] + public void Linq () + { + var list = new List(); + list.Add (new Foo { Id = 3, Name="def"}); + list.Add (new Foo { Id = 2, Name="def"}); + list.Add (new Foo { Id = 1, Name="ggg"}); + var x = from l in list orderby l.Name, l.Id select l; + Assert.That (x.Count (), Is.EqualTo (3), "Count"); + // above throws ExecutionEngineException + } + + [Test] + public void Linq_Workaround () + { + var list = new List(); + list.Add (new Foo { Id = 3, Name="def"}); + list.Add (new Foo { Id = 2, Name="def"}); + list.Add (new Foo { Id = 1, Name="ggg"}); + var x = from l in list orderby l.Name, l.Id.ToString () descending select l; + } + + [Test] + public void SortDescending_3114 () + { + List list = new List () { + DateTime.Now, + DateTime.UtcNow + }; + var result = from datetime in list orderby datetime.Date, datetime.TimeOfDay descending select datetime; + // above throws ExecutionEngineException + // Attempting to JIT compile method 'System.Linq.OrderedEnumerable`1:CreateOrderedEnumerable (System.Func`2,System.Collections.Generic.IComparer`1,bool)' while running with --aot-only. + // .ToString hack does not help in this case :( so it looks even worse + } + + [Test] + public void Workaround_3114 () + { + List list = new List () { + DateTime.Now, + DateTime.UtcNow + }; + var result = from datetime in list orderby ((DateTime) datetime).Date.ToString (), ((DateTime) datetime).TimeOfDay.ToString () descending select (DateTime) datetime; + // Attempting to JIT compile method 'System.Linq.OrderedEnumerable`1:CreateOrderedEnumerable (System.Func`2,System.Collections.Generic.IComparer`1,bool)' while running with --aot-only. + Assert.That (result.Count (), Is.EqualTo (2), "Count"); + } + + [Test] + public void Any_3735 () + { + var array = new Environment.SpecialFolder [] { + Environment.SpecialFolder.ApplicationData, + Environment.SpecialFolder.CommonApplicationData + }; + Assert.True (array.Any (folder => folder == Environment.SpecialFolder.ApplicationData)); + // above throws ExecutionEngineException + // Attempting to JIT compile method '(wrapper managed-to-managed) System.Environment/SpecialFolder[]:System.Collections.Generic.IEnumerable`1.GetEnumerator ()' while running with --aot-only. + } + + [Test] + public void Workaround_3735 () + { + // note: we cannot use the same `enum` type in the workaround since it would make the + // AOT compiler add the code (and make the previous test case works) + List list = new List () { + MidpointRounding.AwayFromZero + }; + Assert.True (list.Any (rounding => rounding == MidpointRounding.AwayFromZero)); + } + + Task InnerTestB () + { + return Task.Factory.StartNew (() => default (T)).ContinueWith (t => true); + } + + [Test] + public void Continuation_2337 () + { + InnerTestB (); + if (Runtime.Arch == Arch.SIMULATOR) + Assert.Inconclusive ("only fails on devices"); + } + + // https://bugzilla.xamarin.com/show_bug.cgi?id=3902 + + class Question { + public bool Deleted { get; set; } + public bool IsAnswered { get; set; } + public int Position { get; set; } + public int SectionId { get; set; } + } + + class Section { + public int BoardId { get; set; } + public int Id { get; set; } + public int BulletinBoardId { get; set; } + public int Position { get; set; } + } + + List Table () where T : new () + { + List list = new List (); + for (int i=0; i < 5; i++) + list.Add (new T ()); + return list; + } + + [Test] + public void Linq_3902_c1 () + { + int boardId = 0; + var result = from q in Table () where q.Deleted == false + join s in Table
() on q.SectionId equals s.Id + where s.BoardId == boardId + orderby q.IsAnswered, s.Position, q.Position + select q; + // note: orderby causing: + // Attempting to JIT compile method 'System.Linq.OrderedEnumerable`1<<>__AnonType0`2>:CreateOrderedEnumerable (System.Func`2<<>__AnonType0`2, int>,System.Collections.Generic.IComparer`1,bool)' while running with --aot-only. + Assert.NotNull (result); + } + + [Test] + public void Workaround_3902_c1 () + { + int boardId = 0; + var result = from q in Table () where q.Deleted == false + join s in Table
() on q.SectionId equals s.Id + where s.BoardId == boardId + orderby q.IsAnswered.ToString (), s.Position.ToString (), q.Position.ToString () + select q; + Assert.NotNull (result); + } + + [Test] + public void Linq_3902_c4 () + { + int boardId = 0; + var results = from q in Table () where q.Deleted == false + join s in Table
() on q.SectionId equals s.Id + where s.BoardId == boardId + select q; + // query is ok + foreach (var result in results) + Assert.NotNull (result); + // accessing elements throws with: + // Attempting to JIT compile method 'System.Linq.Enumerable:m__5A (MonoTouchFixtures.AotBugsTest/Section)' while running with --aot-only. + if (Runtime.Arch == Arch.SIMULATOR) + Assert.Inconclusive ("only fails on devices"); + } + + [Test] + public void Workaround_3902_c4 () + { + int boardId = 0; + var results = from q in Table () where q.Deleted == false + join s in Table
() on q.SectionId.ToString () equals s.Id.ToString () + where s.BoardId == boardId + select q; + foreach (var result in results) + Assert.NotNull (result); + } + + public class VirtualGeneric { + public virtual ICollection MakeCollectionOfInputs (T input1, T input2, T input3) + { + Collection alist = new Collection (); + alist.Add (input1); + alist.Add (input2); + alist.Add (input3); + return alist; + } + } + + [Test] + public void Virtual_4114 () + { + VirtualGeneric g = new VirtualGeneric (); + Assert.NotNull (g.MakeCollectionOfInputs (1.0, 2.0, 3.0)); + } + + public class OverrideGeneric : VirtualGeneric { + public override ICollection MakeCollectionOfInputs (T input1, T input2, T input3) + { + Collection alist = new Collection (); + alist.Add (input1); + alist.Add (input2); + alist.Add (input3); + return alist; + } + } + + [Test] + public void Override_4114 () + { + OverrideGeneric g = new OverrideGeneric (); + // Attempting to JIT compile method 'MonoTouchFixtures.AotBugsTest/OverrideGeneric:MakeCollectionOfInputs (double,double,double)' while running with --aot-only. + g.MakeCollectionOfInputs (1.0, 2.0, 3.0); + if (Runtime.Arch == Arch.SIMULATOR) + Assert.Inconclusive ("only fails on devices"); + } + + public sealed class NewDictionary { + Dictionary _dictionary = new Dictionary (); + + public NewDictionary (IEnumerable> items) + { + ForEach (items, (item) => _dictionary.Add (item.Key, item.Value)); + } + + static void ForEach (IEnumerable collection, Action action) + { + if (collection != null) + foreach (T item in collection) + action (item); + } + } + + [Test] + public void ForEachKVP_4114 () + { + // Attempting to JIT compile method 'MonoTouchFixtures.AotBugsTest/NewDictionary`2:ForEach> (System.Collections.Generic.IEnumerable`1>,System.Action`1>)' while running with --aot-only. + new NewDictionary (null); + if (Runtime.Arch == Arch.SIMULATOR) + Assert.Inconclusive ("only fails on devices"); + } + + public class Enumbers { + public IEnumerable> Enumerate (List> alist) + { + return MakeEnumerable (alist.ToArray ()); + } + + IEnumerable> MakeEnumerable (KeyValuePair[] data) + { + return data.AsEnumerable (); + } + } + + [Test] + [ExpectedException (typeof (NullReferenceException))] + public void AsEnumerable_4114 () + { + Enumbers e = new Enumbers (); + // Attempting to JIT compile method 'System.Collections.Generic.List`1>:ToArray ()' while running with --aot-only. + e.Enumerate (null); + } + + static object mInstance = null; + + [MethodImpl(MethodImplOptions.Synchronized)] + public static object getInstance() { + if (mInstance == null) + mInstance = new object(); + return mInstance; + } + + // #9805 + [Test] + public void Synchronized () { + getInstance (); + } + + // https://bugzilla.xamarin.com/show_bug.cgi?id=8379 + + public class Base { + + public static List

CreateList

() + { + return new List

(); + } + + public static List StringList = CreateList (); + public static List IntList = CreateList (); + } + + public class Class1 : Base { + } + + [Test] + public void Bug8379_a () + { + new Base (); + } + + [Test] + public void Bug8379_b () + { + new Class1 (); + } + + [Test] + public void Bug5354 () + { + Action testAction = (string s) => { s.ToString (); }; + testAction.BeginInvoke ("Teszt", null, null); + } + + public static IEnumerable GetStringList() where T : struct, IConvertible + { + return Enum.GetValues(typeof(T)).Cast().Select(x=>x.ToString()); + } + + [Test] + public void Bug12811a () + { + int n = 1; + foreach (var e in GetStringList ()) { + Assert.NotNull (e, n.ToString ()); + n++; + } + } + + [Test] + public void Bug12811b () + { + int n = 1; + foreach (var e in Enum.GetValues (typeof (NSFileManagerItemReplacementOptions)).Cast ().Select (x=>x.ToString ())) { + Assert.NotNull (e, n.ToString ()); + n++; + } + } + + public enum MyEnum8ElementsInInt32 : int + { + Zero = 0 + , One = 1 + , Two = 2 + , Three = 3 + , Four = 4 + , Five = 5 + , Six = 6 + , Seven = 7 + } + + public enum MyEnum8ElementsInUInt32 : uint + { + Zero = 0 + , One = 1 + , Two = 2 + , Three = 3 + , Four = 4 + , Five = 5 + , Six = 6 + , Seven = 7 + } + + public enum MyEnum7ElementsInUInt16 : ushort + { + Zero = 0 + , One = 1 + , Two = 2 + , Three = 3 + , Four = 4 + , Five = 5 + , Six = 6 + } + + public enum MyEnum8ElementsInUInt16 : ushort + { + Zero = 0 + , One = 1 + , Two = 2 + , Three = 3 + , Four = 4 + , Five = 5 + , Six = 6 + , Seven = 7 + } + + [Test] + public void Bug12605 () + { + Assert.AreEqual ("One", Convert.ToString ((MyEnum8ElementsInInt32) 1), "1"); + Assert.AreEqual ("One", Convert.ToString ((MyEnum8ElementsInUInt32) 1), "2"); + Assert.AreEqual ("One", Convert.ToString ((MyEnum7ElementsInUInt16) 1), "3"); + Assert.AreEqual ("One", Convert.ToString ((MyEnum8ElementsInUInt16) 1), "4"); + } + + [Test] + public void Bug12895 () + { + var r = new System.Text.RegularExpressions.Regex (@"(?\G[ ]+)|(?\G? +)|(?\G[][{}:,])|(?\G[A-Za-z]+)|(?\G + \"" # Opening quote + (?: + \\u[0-9a-fA-F]{4} | # Unicode escape + \\b | \\f | \ | \ | \ | # Backspace, form-feed, newline, carriage-return, tab + \\\\ | \\/ | # Escaped backslash, slash + \\"" | # Escaped quotes + [^\p{Cc}\\""] # Any unicode character except a control code, a backslash or a double quote + )* # Zero of more of any of the previous classes + \"" # Closing quote + )|(?\G + -? # Optional minus + (?: + 0 | # Leading zero only allowed on its own (e.g. 0, 0.1, 0e1) + [1-9][0-9]* # Otherwise leading digit must be non-zero (so no 0123, 0001) + ) + (?:[.][0-9]*)? # Optional fraction + (?:[Ee][+-]?[0-9]+)? # Optional exponent + (?![A-Za-z0-9_]) # Must not be followed by an alphanumeric character + )", System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace); + Assert.NotNull (r); // looking got EEE while executing, on devices, the above code + } + + [Test] + public void Bug26245 () + { + var c = new Collection (); + c.Add (new PointF (50, 50)); // crashed under ARM64 + Assert.That (c.Count, Is.EqualTo (1)); + } + + [Test] + public void Bug39443 () + { + // un-reproducible test case (added to have large pool of QA devices run iton different CPU) + var nfe = nfloat.Epsilon.ToString (); + if (IntPtr.Size == 4) { + Assert.That (float.Epsilon.ToString (), Is.EqualTo (nfe), "Epsilon"); + } else { + Assert.That (double.Epsilon.ToString (), Is.EqualTo (nfe), "Epsilon"); + } + } + } +} diff --git a/tests/link sdk/AppDelegate.cs b/tests/link sdk/AppDelegate.cs new file mode 100644 index 000000000000..6b6315b6c400 --- /dev/null +++ b/tests/link sdk/AppDelegate.cs @@ -0,0 +1,53 @@ + +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; + +namespace LinkSdk +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + UIWindow window; + TouchRunner runner; + + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + // create a new window instance based on the screen size + window = new UIWindow (UIScreen.MainScreen.Bounds); + runner = new TouchRunner (window); + + // tests can be inside the main assembly + runner.Add (Assembly.GetExecutingAssembly ()); + runner.Add (typeof (BundledResources.ResourcesTest).Assembly); + + window.RootViewController = new UINavigationController (runner.GetViewController ()); + // make the window visible + window.MakeKeyAndVisible (); + + return true; + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/link sdk/AsyncTest.cs b/tests/link sdk/AsyncTest.cs new file mode 100644 index 000000000000..9776afb5d8eb --- /dev/null +++ b/tests/link sdk/AsyncTest.cs @@ -0,0 +1,28 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AsyncTests { + + public Task LoadCategories () + { + return Task.Run (async () => await (new HttpClient ()).GetStringAsync ("http://google.com")); + } + + [Test] + public void Bug12221 () + { + LoadCategories ().Wait (); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/Bug1820Test.cs b/tests/link sdk/Bug1820Test.cs new file mode 100644 index 000000000000..64062f527ef3 --- /dev/null +++ b/tests/link sdk/Bug1820Test.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk.Serialization { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public partial class XmlSerializationTest { + + [Serializable] + [XmlType (AnonymousType = true)] + [XmlRoot (Namespace = "", IsNullable = false)] + public class Response { + private DataUpdates dataUpdatesField; + private static XmlSerializer serializer; + + public Response () + { + this.dataUpdatesField = new DataUpdates (); + } + + [XmlElement (Order = 0)] + public DataUpdates DataUpdates { + get { return this.dataUpdatesField; } + set { this.dataUpdatesField = value; } + } + + private static XmlSerializer Serializer { + get { + if ((serializer == null)) + serializer = new XmlSerializer (typeof (Response)); + return serializer; + } + } + + public static Response Deserialize (string xml) + { + StringReader stringReader = null; + try { + stringReader = new StringReader (xml); + return ((Response)(Serializer.Deserialize (XmlReader.Create (stringReader)))); + } finally { + if ((stringReader != null)) { + stringReader.Dispose (); + } + } + } + } + + [Serializable] + [XmlType (AnonymousType = true)] + [XmlRoot (Namespace = "", IsNullable = false)] + public class DataUpdates { + private List dataUpdateInfoField; + private static XmlSerializer serializer; + + public DataUpdates () + { + this.dataUpdateInfoField = new List (); + } + + // BUG1820 is here! remove Order = 0 and it works + [XmlElement ("DataUpdateInfo", Form = XmlSchemaForm.Unqualified, Order = 0)] + public List DataUpdateInfo { + get { return this.dataUpdateInfoField; } + set { this.dataUpdateInfoField = value; } + } + + private static XmlSerializer Serializer { + get { + if ((serializer == null)) + serializer = new XmlSerializer (typeof (DataUpdates)); + return serializer; + } + } + + public static DataUpdates Deserialize (string xml) + { + StringReader stringReader = null; + try { + stringReader = new StringReader (xml); + return ((DataUpdates)(Serializer.Deserialize (XmlReader.Create (stringReader)))); + } finally { + if ((stringReader != null)) { + stringReader.Dispose (); + } + } + } + } + + [Serializable] + [XmlType (AnonymousType = true)] + public class DataUpdatesDataUpdateInfo { + + private DateTime dataDateField; + private string dataTypeField; + private DateTime lastUpdatedDateField; + private static XmlSerializer serializer; + + public DataUpdatesDataUpdateInfo () + { + } + + [XmlAttribute] + public DateTime DataDate { + get { return this.dataDateField; } + set { this.dataDateField = value; } + } + + [XmlAttribute] + public string DataType { + get { return this.dataTypeField; } + set { this.dataTypeField = value; } + } + + [XmlAttribute] + public DateTime LastUpdatedDate { + get { return this.lastUpdatedDateField; } + set { this.lastUpdatedDateField = value; } + } + + private static XmlSerializer Serializer { + get { + if ((serializer == null)) + serializer = new XmlSerializer (typeof(DataUpdatesDataUpdateInfo)); + return serializer; + } + } + + public static DataUpdatesDataUpdateInfo Deserialize (string xml) + { + StringReader stringReader = null; + try { + stringReader = new StringReader (xml); + return ((DataUpdatesDataUpdateInfo)(Serializer.Deserialize (XmlReader.Create (stringReader)))); + } finally { + if ((stringReader != null)) { + stringReader.Dispose (); + } + } + } + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1820 + // note: this also test the linker (5.1+) ability not to remove 'unused' XML setters and .ctors used for serialization + public void Bug1820_GenericList () + { + string input = @" + + + + + + + + + ".Trim (); + Response r = Response.Deserialize (input); + Assert.That (r.DataUpdates.DataUpdateInfo.Count, Is.EqualTo (3), "Count"); + Assert.That (r.DataUpdates.DataUpdateInfo [0].DataDate.Day, Is.EqualTo (13), "0"); + Assert.That (r.DataUpdates.DataUpdateInfo [1].DataDate.Day, Is.EqualTo (14), "1"); + Assert.That (r.DataUpdates.DataUpdateInfo [2].DataDate.Day, Is.EqualTo (15), "2"); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/Bug2096Test.cs b/tests/link sdk/Bug2096Test.cs new file mode 100644 index 000000000000..eecd05b4833b --- /dev/null +++ b/tests/link sdk/Bug2096Test.cs @@ -0,0 +1,58 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace LinkSdk.Aot { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public partial class AotBugsTest { + + public struct VT { + public Action a; + } + + public class D { + } + + public class A { + public void OuterMethod (TArg1 value) + { + this.InnerMethod (value, 0); + } + + private void InnerMethod (TArg1 v1, TArg2 v2) + { + Console.WriteLine ("{0} {1}", v1, v2); + } + } + + [Test] + public void Bug2096_Aot () + { + var a = new A (); + + a.OuterMethod (1); + a.OuterMethod (DateTime.Now); + // works with 5.0.2 (5.1) + + var v = new VT (); + a.OuterMethod (v); + // works with 5.0.2 (5.1) + + var x = new D (); + a.OuterMethod (x); + // fails with 5.0.2 (5.1) when running on devices with + // Attempting to JIT compile method 'A:InnerMethod (D,long)' while running with --aot-only. + if (Runtime.Arch == Arch.SIMULATOR) + Assert.Inconclusive ("only fails on devices"); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/CalendarTest.cs b/tests/link sdk/CalendarTest.cs new file mode 100644 index 000000000000..004bedc38662 --- /dev/null +++ b/tests/link sdk/CalendarTest.cs @@ -0,0 +1,42 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.Globalization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk.Calendars { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class CalendarTest { + + // application must *NOT* be build with I18N.MidEast and I18N.Other (Thai) + + [Test] + public void UmAlQura () + { + var ci = CultureInfo.GetCultureInfo ("ar"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.GregorianCalendar"), "Calendar"); + } + + [Test] + public void Hijri () + { + var ci = CultureInfo.GetCultureInfo ("ps"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.GregorianCalendar"), "Calendar"); + } + + [Test] + public void ThaiBuddhist () + { + var ci = CultureInfo.GetCultureInfo ("th"); + Assert.That (ci.Calendar.ToString (), Is.EqualTo ("System.Globalization.GregorianCalendar"), "Calendar"); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/CryptoTest.cs b/tests/link sdk/CryptoTest.cs new file mode 100644 index 000000000000..dcdd431ed3e4 --- /dev/null +++ b/tests/link sdk/CryptoTest.cs @@ -0,0 +1,218 @@ +// +// Cryptographic Unit Tests - for about everything that can go wrong wrt linking +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. +// + +using System; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class CryptoTest { + + [Test] + public void AesCreate () + { + // Aes resides in mscorlib.dll but needs to create instance of types that are + // located inside System.Core.dll - IOW the linker needs to be aware of this + Aes aes = Aes.Create (); + Assert.NotNull (aes, "Aes"); + Assert.True (aes.GetType ().Assembly.FullName.StartsWith ("System.Core, ", StringComparison.Ordinal), "System.Core"); + } + + static int trust_validation_callback; + + [Test] + public void TrustUsingNewCallback () + { + // Three similar tests exists in dontlink, linkall and linksdk to test 3 different cases + // untrusted, custom ICertificatePolicy and ServerCertificateValidationCallback without + // having caching issues (in S.Net or the SSL handshake cache) + try { + ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) { + Assert.That (errors, Is.EqualTo (SslPolicyErrors.None), "certificateProblem"); + X509Certificate2 c2 = new X509Certificate2 (cert.GetRawCertData ()); + Assert.False (chain.Build (c2), "Build"); + Assert.AreSame (c2, chain.ChainElements [0].Certificate, "ChainElements"); + trust_validation_callback++; + return true; + }; + WebClient wc = new WebClient (); + Assert.IsNotNull (wc.DownloadString ("https://wrench.internalx.com/Wrench/Login.aspx")); + // caching means it will be called at least for the first run, but it might not + // be called again in subsequent requests (unless it expires) + Assert.That (trust_validation_callback, Is.GreaterThan (0), "validation done"); + } + finally { + ServicePointManager.ServerCertificateValidationCallback = null; + } + } + + [Test] + public void SSL_IP_5706 () + { + WebClient wc = new WebClient (); + // the certificate contains (several rules) the host name + Assert.NotNull (wc.DownloadString ("https://www.google.com")); + + // IP are (generally) not allowed + foreach (var ip in Dns.GetHostAddresses ("www.google.com")) { + if (ip.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) + continue; + + Assert.Throws (delegate { + wc.DownloadString ("https://" + ip.ToString ()); + }, ip.ToString ()); + return; // checking a single IP is enough to prove the point + } + } + + static int sne_validation_callback; + + [Test] + public void TLS1_ServerNameExtension () + { + // without support for the "server_name" TLS extension (RFC3546) we receive the "general" + // certificate of a server, which might not be the right one if a single server instance + // is used for many hosts (without a common name) + + // note: SSLv3 won't work, test is inside linkall.app (due to result caching) + + var actual = ServicePointManager.SecurityProtocol; + try { + ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) { + Assert.That (errors, Is.EqualTo (SslPolicyErrors.None), "certificateProblem"); + X509Certificate2 c2 = new X509Certificate2 (cert.GetRawCertData ()); + Assert.False (chain.Build (c2), "Build"); + Assert.AreSame (c2, chain.ChainElements [0].Certificate, "ChainElements"); + sne_validation_callback++; + return true; + }; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; + WebClient wc = new WebClient (); + Assert.IsNotNull (wc.DownloadString ("https://api.imgur.com/2/stats")); + } + catch (WebException we) { + // failing to get data does not mean the SSL/TLS session was not established + if (sne_validation_callback == 0) { + // The remote server returned an error: (502) Bad Gateway. + // The remote server returned an error: (503) Service Unavailable. + if (we.Message.Contains ("(502)") || we.Message.Contains ("(503)")) + Assert.Inconclusive (we.Message); + throw; + } + } + finally { + ServicePointManager.ServerCertificateValidationCallback = null; + ServicePointManager.SecurityProtocol = actual; + // caching means it will be called at least for the first run, but it might not + // be called again in subsequent requests (unless it expires) + Assert.That (sne_validation_callback, Is.GreaterThan (0), "validation done"); + } + } + + [Test] + public void Chain () + { + X509Store store = new X509Store ("Trust"); + store.Open (OpenFlags.ReadWrite); + + string certString = "MIIDGjCCAgKgAwIBAgICApowDQYJKoZIhvcNAQEFBQAwLjELMAkGA1UEBhMCQ1oxDjAMBgNVBAoTBVJlYmV4MQ8wDQYDVQQDEwZUZXN0Q0EwHhcNMDAwMTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjAuMQswCQYDVQQGEwJDWjEOMAwGA1UEChMFUmViZXgxDzANBgNVBAMTBlRlc3RDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgeRAcaNLTFaaBhFx8RDJ8b9K655dNUXmO11mbImDbPq4qVeZXDgAjnzPov8iBscwfqBvBpF38LsxBIPA2i1d0RMsQruOhJHttA9I0enElUXXj63sOEVNMSQeg1IMyvNeEotag+Gcx6SF+HYnariublETaZGzwAOD2SM49mfqUyfkgeTjdO6qp8xnoEr7dS5pEBHDg70byj/JEeZd3gFea9TiOXhbCrI89dKeWYBeoHFYhhkaSB7q9EOaUEzKo/BQ6PBHFu6odfGkOjXuwfPkY/wUy9U4uj75LmdhzvJf6ifsJS9BQZF4//JcUYSxiyzpxDYqSbTF3g9w5Ds2LOAscCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgB/MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFD1v20tPgvHTEK/0eLO09j0rL2qXMA0GCSqGSIb3DQEBBQUAA4IBAQAZIjcdR3EZiFJ67gfCnPBrxVgFNvaRAMCYEYYIGDCAUeB4bLTu9dvun9KFhgVNqjgx+xTTpx9d/5mAZx5W3YAG6faQPCaHccLefB1M1hVPmo8md2uw1a44RHU9LlM0V5Lw8xTKRkQiZz3Ysu0sY27RvLrTptbbfkE4Rp9qAMguZT9cFrgPAzh+0zuo8NNj9Jz7/SSa83yIFmflCsHYSuNyKIy2iaX9TCVbTrwJmRIB65gqtTb6AKtFGIPzsb6nayHvgGHFchrFovcNrvRpE71F38oVG+eCjT23JfiIZim+yJLppSf56167u8etDcQ39j2b9kzWlHIVkVM0REpsKF7S"; + X509Certificate2 rootCert = new X509Certificate2 (Convert.FromBase64String (certString)); + if (!store.Certificates.Contains (rootCert)) + store.Add (rootCert); + + store.Close(); + + byte[] certData = new byte[] {0x30,0x82,0x02,0xFA,0x30,0x82,0x01,0xE2,0xA0,0x03,0x02,0x01,0x02,0x02,0x03,0x01,0x4F,0x55,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x5A,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A,0x13,0x05,0x52,0x65,0x62,0x65,0x78,0x31,0x0F,0x30,0x0D,0x06,0x03,0x55,0x04,0x03,0x13,0x06,0x54,0x65,0x73,0x74,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x34,0x32,0x32,0x31,0x38,0x33,0x31,0x35,0x33,0x5A,0x17,0x0D,0x34,0x39,0x31,0x32,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x37,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x5A,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A,0x13,0x05,0x52,0x65,0x62,0x65,0x78,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x03,0x13,0x0F,0x77,0x69,0x6E,0x30,0x31,0x2E,0x64,0x30,0x35,0x2E,0x6C,0x6F,0x63,0x61,0x6C,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xF1,0x4F,0xAC,0x71,0x70,0x8F,0x8A,0xFE,0x38,0x67,0xA7,0x21,0x56,0x8B,0x34,0xBC,0xF5,0xCD,0x48,0x1C,0x69,0xEB,0x83,0x98,0x69,0x3D,0x33,0x2A,0x7B,0x04,0xB1,0x0A,0xA9,0x2C,0x17,0xDD,0x41,0xEC,0x21,0x91,0xB8,0x12,0x95,0xB0,0x4C,0x2A,0x53,0xBF,0x06,0x47,0x72,0xBB,0x68,0xCA,0x49,0x34,0x15,0x7B,0x78,0x4F,0x42,0x03,0xD9,0x58,0xEE,0x9D,0x72,0x61,0xAD,0xAD,0x0C,0x28,0x65,0x61,0x48,0xF8,0x68,0xB5,0x16,0x19,0xD0,0xDD,0x47,0x44,0x86,0xE3,0xA6,0x93,0x81,0xD5,0xA1,0x70,0x23,0x05,0x74,0x33,0xD1,0xD2,0x21,0x17,0x68,0xAF,0x5F,0x25,0xD5,0x8C,0x72,0xF6,0x28,0xF4,0x1F,0x42,0x24,0xCF,0x18,0x7B,0x5D,0xCE,0x29,0x43,0xF2,0x10,0xB6,0x73,0x65,0x4C,0x0A,0x17,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x9B,0x30,0x81,0x98,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x14,0x00,0x58,0x48,0x55,0x6C,0x45,0xC6,0xCC,0x06,0x25,0x2D,0xD3,0xBA,0x0C,0x08,0x81,0x00,0x58,0xDF,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x3D,0x6F,0xDB,0x4B,0x4F,0x82,0xF1,0xD3,0x10,0xAF,0xF4,0x78,0xB3,0xB4,0xF6,0x3D,0x2B,0x2F,0x6A,0x97,0x30,0x31,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2A,0x30,0x28,0x30,0x26,0xA0,0x24,0xA0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x74,0x65,0x73,0x74,0x2D,0x63,0x61,0x2E,0x6C,0x6F,0x63,0x61,0x6C,0x2F,0x74,0x65,0x73,0x74,0x2D,0x63,0x61,0x2E,0x63,0x72,0x6C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x22,0x48,0xC3,0x95,0x3A,0x51,0x72,0x15,0x41,0x5B,0x47,0xC4,0xC5,0x4E,0x2E,0x97,0xAC,0x1D,0x0B,0xD1,0xA4,0x38,0xF2,0xFB,0x6E,0x33,0x9D,0xC8,0x93,0x4C,0x88,0x34,0xA3,0x68,0xC7,0xC6,0x42,0x51,0x54,0x31,0x72,0x72,0xEB,0xEE,0x5C,0xF0,0x7D,0xC9,0xC8,0xAE,0x24,0x9F,0xA0,0x1D,0x2E,0xEE,0x84,0x55,0xC3,0x3A,0xC4,0xCE,0xE1,0xB3,0xA2,0xD2,0x1F,0x44,0xC8,0x81,0x0F,0x9C,0xED,0x5B,0x17,0xBB,0x2C,0xDA,0x4A,0x9D,0xF7,0x7D,0x5A,0x08,0x6C,0xA3,0xF4,0xCB,0x55,0xE6,0x1A,0xAA,0xC7,0x14,0x16,0x7D,0x46,0xD0,0x7C,0x71,0xA8,0xA7,0xEA,0xBF,0xA6,0x92,0xD4,0xC5,0x7A,0xB8,0x45,0x3A,0x00,0xB3,0xDC,0x76,0x2E,0xEB,0xB9,0xF4,0x6B,0xDC,0xF2,0xC4,0x7C,0x0C,0xD5,0x1C,0x73,0xE8,0xE1,0xBB,0xC1,0x5C,0xCC,0xD9,0xBE,0xDE,0x61,0x4D,0xEF,0x2B,0x23,0xFA,0xA6,0xF6,0xED,0x4F,0x5F,0x2C,0xCA,0x68,0x29,0x59,0x27,0x82,0x41,0x5E,0xAD,0xC8,0x93,0xBF,0x83,0x01,0x8F,0x32,0xCB,0x79,0xEE,0x93,0x4C,0xCB,0x87,0x48,0x62,0x0D,0x44,0xD7,0x80,0x31,0x87,0x41,0x72,0x2D,0x12,0xA0,0x2C,0x99,0x89,0x08,0x5F,0xE9,0xFE,0x5E,0xB4,0xEC,0xCB,0x6C,0x23,0xC1,0xB8,0xE4,0xD6,0x1E,0x4B,0x9C,0x88,0x0A,0x63,0x65,0x78,0xC0,0x37,0xAC,0x54,0xCB,0xDE,0xA9,0x0F,0x59,0x43,0x1E,0x41,0xF5,0x32,0xAC,0x85,0x69,0xE9,0xBA,0xA6,0x78,0x87,0x88,0x8B,0x71,0xFB,0xE4,0x51,0xC0,0xF5,0xB7,0x4C,0x1F,0xCF,0x6A,0x1C,0xF6,0x1B,0x27,0x50,0xE9,0xAC,0xBF,0xB7,0x4E}; + + X509Certificate2 cert = new X509Certificate2 (certData); + X509Chain chain = new X509Chain (false); + Assert.False (chain.Build (cert), "Online"); + + chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; + Assert.False (chain.Build (cert), "Offline"); + + chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; + Assert.True (chain.Build (cert), "NoCheck"); + } + + byte[] sha256_data = { + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, + 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0A, 0x4D, 0x49, 0x49, 0x43, 0x78, 0x44, 0x43, 0x43, 0x41, 0x61, 0x79, + 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x44, 0x41, 0x4B, 0x37, 0x6C, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, + 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x4D, 0x43, 0x34, 0x78, 0x43, 0x7A, 0x41, + 0x4A, 0x42, 0x67, 0x4E, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6B, 0x4E, 0x61, 0x0D, 0x0A, 0x4D, 0x51, 0x34, 0x77, 0x44, + 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4B, 0x45, 0x77, 0x56, 0x53, 0x5A, 0x57, 0x4A, 0x6C, 0x65, 0x44, 0x45, 0x50, 0x4D, + 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, 0x47, 0x56, 0x47, 0x56, 0x7A, 0x64, 0x45, 0x4E, 0x42, 0x4D, + 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x7A, 0x4D, 0x44, 0x55, 0x78, 0x4F, 0x54, 0x45, 0x79, 0x4E, 0x44, 0x63, 0x31, 0x0D, + 0x0A, 0x4E, 0x31, 0x6F, 0x58, 0x44, 0x54, 0x51, 0x35, 0x4D, 0x54, 0x49, 0x7A, 0x4D, 0x54, 0x41, 0x77, 0x4D, 0x44, 0x41, + 0x77, 0x4D, 0x46, 0x6F, 0x77, 0x4F, 0x6A, 0x45, 0x57, 0x4D, 0x42, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x4D, + 0x4E, 0x55, 0x6D, 0x56, 0x69, 0x5A, 0x58, 0x67, 0x67, 0x55, 0x33, 0x56, 0x77, 0x63, 0x47, 0x39, 0x79, 0x64, 0x44, 0x45, + 0x67, 0x4D, 0x42, 0x34, 0x47, 0x0D, 0x0A, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x4A, 0x41, + 0x52, 0x59, 0x52, 0x63, 0x33, 0x56, 0x77, 0x63, 0x47, 0x39, 0x79, 0x64, 0x45, 0x42, 0x79, 0x5A, 0x57, 0x4A, 0x6C, 0x65, + 0x43, 0x35, 0x75, 0x5A, 0x58, 0x51, 0x77, 0x67, 0x5A, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, + 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x0D, 0x0A, 0x67, 0x59, 0x30, 0x41, 0x4D, 0x49, 0x47, + 0x4A, 0x41, 0x6F, 0x47, 0x42, 0x41, 0x4B, 0x7A, 0x36, 0x49, 0x37, 0x49, 0x59, 0x4E, 0x4A, 0x4C, 0x44, 0x43, 0x36, 0x42, + 0x79, 0x44, 0x32, 0x75, 0x59, 0x36, 0x69, 0x55, 0x61, 0x34, 0x30, 0x54, 0x34, 0x37, 0x34, 0x44, 0x41, 0x65, 0x59, 0x55, + 0x49, 0x31, 0x37, 0x43, 0x79, 0x39, 0x55, 0x6B, 0x77, 0x62, 0x4E, 0x4D, 0x2B, 0x6B, 0x39, 0x62, 0x57, 0x0D, 0x0A, 0x68, + 0x75, 0x46, 0x62, 0x65, 0x63, 0x56, 0x42, 0x6D, 0x43, 0x37, 0x42, 0x79, 0x31, 0x6C, 0x48, 0x65, 0x2B, 0x79, 0x41, 0x59, + 0x59, 0x78, 0x78, 0x74, 0x47, 0x50, 0x7A, 0x41, 0x48, 0x58, 0x50, 0x76, 0x68, 0x4A, 0x4D, 0x56, 0x50, 0x41, 0x2F, 0x37, + 0x4C, 0x36, 0x41, 0x4B, 0x58, 0x6D, 0x6A, 0x71, 0x69, 0x77, 0x78, 0x7A, 0x47, 0x51, 0x79, 0x30, 0x73, 0x59, 0x67, 0x2F, + 0x6A, 0x36, 0x79, 0x0D, 0x0A, 0x6F, 0x58, 0x39, 0x36, 0x39, 0x52, 0x53, 0x30, 0x49, 0x58, 0x33, 0x75, 0x33, 0x64, 0x31, + 0x72, 0x35, 0x61, 0x6F, 0x44, 0x76, 0x36, 0x4A, 0x58, 0x53, 0x69, 0x53, 0x73, 0x75, 0x67, 0x78, 0x56, 0x47, 0x69, 0x65, + 0x54, 0x53, 0x2F, 0x50, 0x71, 0x55, 0x6E, 0x6E, 0x76, 0x72, 0x49, 0x74, 0x59, 0x78, 0x6F, 0x64, 0x4F, 0x31, 0x58, 0x79, + 0x76, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A, 0x0D, 0x0A, 0x59, 0x7A, 0x42, 0x68, 0x4D, 0x41, 0x34, 0x47, 0x41, + 0x31, 0x55, 0x64, 0x44, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x45, 0x38, 0x44, 0x41, 0x64, 0x42, + 0x67, 0x4E, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x66, 0x75, 0x52, 0x51, 0x78, 0x4E, 0x75, 0x59, 0x71, + 0x77, 0x73, 0x38, 0x56, 0x48, 0x7A, 0x4A, 0x6D, 0x4A, 0x50, 0x6F, 0x39, 0x41, 0x45, 0x6F, 0x0D, 0x0A, 0x6F, 0x50, 0x77, + 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6C, 0x42, 0x41, 0x67, 0x77, 0x42, 0x67, 0x59, 0x45, 0x56, 0x52, 0x30, + 0x6C, 0x41, 0x44, 0x41, 0x66, 0x42, 0x67, 0x4E, 0x56, 0x48, 0x53, 0x4D, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x51, + 0x39, 0x62, 0x39, 0x74, 0x4C, 0x54, 0x34, 0x4C, 0x78, 0x30, 0x78, 0x43, 0x76, 0x39, 0x48, 0x69, 0x7A, 0x74, 0x50, 0x59, + 0x39, 0x0D, 0x0A, 0x4B, 0x79, 0x39, 0x71, 0x6C, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, + 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x41, 0x59, 0x62, 0x69, 0x46, + 0x41, 0x6D, 0x33, 0x6E, 0x71, 0x61, 0x6F, 0x4A, 0x51, 0x45, 0x41, 0x6D, 0x37, 0x7A, 0x34, 0x33, 0x71, 0x6E, 0x71, 0x41, + 0x6B, 0x41, 0x6E, 0x35, 0x30, 0x76, 0x6F, 0x0D, 0x0A, 0x75, 0x4F, 0x39, 0x4E, 0x57, 0x61, 0x33, 0x53, 0x43, 0x45, 0x38, + 0x78, 0x6B, 0x4C, 0x55, 0x2B, 0x31, 0x50, 0x62, 0x67, 0x76, 0x6F, 0x48, 0x4E, 0x50, 0x54, 0x6A, 0x36, 0x4D, 0x51, 0x30, + 0x59, 0x37, 0x6F, 0x63, 0x2B, 0x6D, 0x42, 0x75, 0x55, 0x6B, 0x5A, 0x52, 0x63, 0x4B, 0x33, 0x51, 0x4C, 0x69, 0x58, 0x6C, + 0x62, 0x34, 0x66, 0x6E, 0x7A, 0x39, 0x59, 0x55, 0x36, 0x66, 0x69, 0x7A, 0x4A, 0x0D, 0x0A, 0x79, 0x6A, 0x33, 0x76, 0x33, + 0x42, 0x34, 0x6B, 0x4A, 0x33, 0x5A, 0x62, 0x42, 0x6D, 0x38, 0x48, 0x4E, 0x34, 0x78, 0x79, 0x44, 0x62, 0x66, 0x6E, 0x77, + 0x6C, 0x67, 0x42, 0x55, 0x65, 0x6F, 0x68, 0x78, 0x61, 0x36, 0x2B, 0x50, 0x78, 0x67, 0x2F, 0x37, 0x72, 0x39, 0x34, 0x78, + 0x54, 0x4A, 0x72, 0x35, 0x46, 0x30, 0x43, 0x68, 0x2F, 0x41, 0x68, 0x2F, 0x6D, 0x59, 0x37, 0x66, 0x4B, 0x6C, 0x50, 0x0D, + 0x0A, 0x46, 0x46, 0x35, 0x47, 0x68, 0x4A, 0x2B, 0x62, 0x34, 0x76, 0x55, 0x6F, 0x36, 0x47, 0x74, 0x6E, 0x79, 0x6F, 0x4F, + 0x33, 0x58, 0x57, 0x4C, 0x45, 0x34, 0x4D, 0x38, 0x4B, 0x67, 0x68, 0x6C, 0x39, 0x78, 0x48, 0x4E, 0x32, 0x52, 0x76, 0x57, + 0x47, 0x45, 0x39, 0x4B, 0x6F, 0x31, 0x4B, 0x31, 0x55, 0x62, 0x42, 0x62, 0x53, 0x4A, 0x51, 0x4D, 0x76, 0x66, 0x65, 0x49, + 0x65, 0x52, 0x38, 0x32, 0x71, 0x0D, 0x0A, 0x69, 0x66, 0x37, 0x49, 0x30, 0x56, 0x2B, 0x77, 0x59, 0x70, 0x57, 0x61, 0x4B, + 0x79, 0x5A, 0x68, 0x33, 0x6C, 0x50, 0x4C, 0x34, 0x33, 0x67, 0x35, 0x4C, 0x4F, 0x42, 0x34, 0x75, 0x51, 0x6C, 0x68, 0x76, + 0x76, 0x50, 0x4D, 0x5A, 0x63, 0x43, 0x48, 0x36, 0x4F, 0x37, 0x37, 0x37, 0x6E, 0x2F, 0x33, 0x4C, 0x2B, 0x54, 0x6C, 0x32, + 0x2F, 0x41, 0x56, 0x31, 0x73, 0x7A, 0x73, 0x67, 0x53, 0x6B, 0x54, 0x0D, 0x0A, 0x47, 0x79, 0x74, 0x54, 0x75, 0x4B, 0x6A, + 0x51, 0x35, 0x6E, 0x50, 0x53, 0x58, 0x76, 0x65, 0x44, 0x39, 0x76, 0x4B, 0x42, 0x50, 0x2F, 0x58, 0x4C, 0x73, 0x54, 0x4D, + 0x75, 0x69, 0x6A, 0x48, 0x4C, 0x43, 0x68, 0x57, 0x55, 0x69, 0x33, 0x74, 0x4B, 0x7A, 0x49, 0x48, 0x6F, 0x66, 0x4B, 0x6F, + 0x58, 0x62, 0x42, 0x43, 0x35, 0x37, 0x77, 0x3D, 0x3D, 0x0D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, + 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0A, }; + + [Test] + public void Sha256 () + { + X509Certificate2 c = new X509Certificate2 (sha256_data); + // can't build is fine - as long as we do not throw + Assert.False (new X509Chain (false).Build (c), "Build"); + } + } +} diff --git a/tests/link sdk/DataContractTest.cs b/tests/link sdk/DataContractTest.cs new file mode 100644 index 000000000000..e76945d78fd7 --- /dev/null +++ b/tests/link sdk/DataContractTest.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [DataContract(Namespace="XamarinBugExample")] + public enum MyEnum : short + { + [EnumMember] + Foo = 0, + [EnumMember] + Bar = 1, + [EnumMember] + Baz = 2 + } + + [DataContract(Namespace="XamarinBugExample")] + public class MyClass + { + public MyClass() { } + + [DataMember] + List MyList { get; set; } + } + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class CrashExample { + + [Test] + // http://forums.xamarin.com/discussion/7380/type-cast-error-in-xamarin-6-4-3-on-device-only#latest + // could not be reproduced with 6.4.4 + public void DoCrash() + { + System.Collections.IList lst = new List(); + object value = Enum.Parse (typeof(MyEnum), "1"); + lst.Add (value); // Exception here. List.cs throws ArgumentException. + } + } +} \ No newline at end of file diff --git a/tests/link sdk/DllImportTest.cs b/tests/link sdk/DllImportTest.cs new file mode 100644 index 000000000000..7569f209b9d7 --- /dev/null +++ b/tests/link sdk/DllImportTest.cs @@ -0,0 +1,77 @@ +// +// Unit tests for [DllImport] +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net.NetworkInformation; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DllImportTest { + + class NestedFirstLevel { + + public class NestedSecondLevel { + + [DllImport ("__Internal")] + public extern static string xamarin_get_locale_country_code (); + } + } + + [Test] + public void ScanForStrip_17327 () + { + // note: must be tested on a release (strip'ed) build + Assert.NotNull (NestedFirstLevel.NestedSecondLevel.xamarin_get_locale_country_code ()); + } + + [Test] + public void Sqlite3 () + { + var lib = Dlfcn.dlopen ("/usr/lib/libsqlite3.dylib", 0); + Assert.That (lib, Is.Not.EqualTo (IntPtr.Zero), "/usr/lib/libsqlite3.dylib"); + try { + Assert.That (Dlfcn.dlsym (lib, "sqlite3_bind_int"), Is.Not.EqualTo (IntPtr.Zero), "sqlite3_bind_int"); + // iOS does not have some symbols defined - if that change/fail in the future we'll need to update Mono.Data.Sqlite + Assert.That (Dlfcn.dlsym (lib, "sqlite3_key"), Is.EqualTo (IntPtr.Zero), "sqlite3_key"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_rekey"), Is.EqualTo (IntPtr.Zero), "sqlite3_rekey"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_column_database_name"), Is.EqualTo (IntPtr.Zero), "sqlite3_column_database_name"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_column_database_name16"), Is.EqualTo (IntPtr.Zero), "sqlite3_column_database_name16"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_column_origin_name"), Is.EqualTo (IntPtr.Zero), "sqlite3_column_origin_name"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_column_origin_name16"), Is.EqualTo (IntPtr.Zero), "sqlite3_column_origin_name16"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_column_table_name"), Is.EqualTo (IntPtr.Zero), "sqlite3_column_table_name"); + Assert.That (Dlfcn.dlsym (lib, "sqlite3_column_table_name16"), Is.EqualTo (IntPtr.Zero), "sqlite3_column_table_name16"); + } + finally { + Dlfcn.dlclose (lib); + } + } + + [Test] + public void LackOfCapget () + { + // OSX/iOS libc (libSystem.dylib) does not have a capget - which breaks dlsym=false (required for tvOS) + // iOS (tvOS/watchOS) does not support Process to run ping either so it ends up with a InvalidOperationException + // which is now "optimized" to reduce code size (and remove DllImport) until we implement ping (see: #964) + var p = new Ping (); + Assert.Throws (delegate { p.Send ("localhost"); }); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/Info.plist b/tests/link sdk/Info.plist new file mode 100644 index 000000000000..63e5f235fd48 --- /dev/null +++ b/tests/link sdk/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDisplayName + LinkSdkTest + CFBundleIdentifier + com.xamarin.linksdk + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + + diff --git a/tests/link sdk/LinkExtraDefsTest.cs b/tests/link sdk/LinkExtraDefsTest.cs new file mode 100644 index 000000000000..fb00eb7d05da --- /dev/null +++ b/tests/link sdk/LinkExtraDefsTest.cs @@ -0,0 +1,65 @@ +// +// Unit tests for the mtouch's --xml linker option +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LinkExtraDefsTest { + + // ensure the types in extra-linker-defs.xml are included + // even if they are: + // * part of SDK / product assemblies, where adding [Preserve] is not possible; + // * not used anywhere in this application + + // note: reflection is used so we're testing the XML-based preservation + // not the normal linking process + + [Test] + public void Corlib () + { + Type t = Type.GetType ("System.Security.HostSecurityManager, mscorlib"); + Assert.NotNull (t, "System.Security.HostSecurityManager"); + } + + [Test] + public void System () + { + Type t = Type.GetType ("System.Net.Mime.ContentType, System"); + Assert.NotNull (t, "System.Net.Mime.ContentType"); + // we asked for ParseValue to be preserved + Assert.NotNull (t.GetMethod ("ParseValue", BindingFlags.Instance | BindingFlags.NonPublic), "Parse"); + } + +#if !__WATCHOS__ + [Test] + public void MonoTouch () + { +#if XAMCORE_2_0 + Type t = Type.GetType ("CoreBluetooth.CBUUID, " + typeof(NSObject).Assembly.ToString ()); +#else + Type t = Type.GetType ("MonoTouch.CoreBluetooth.CBUUID, monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); +#endif + Assert.NotNull (t, "[MonoTouch.]CoreBluetooth.CBUUID"); + // check (generated) fields since we instructed the linker to keep them + var f = t.GetFields (BindingFlags.NonPublic | BindingFlags.Static); + Assert.That (f.Length, Is.Not.EqualTo (0), "fields were preserved"); + } +#endif + } +} \ No newline at end of file diff --git a/tests/link sdk/LinkSdkRegressionTest.cs b/tests/link sdk/LinkSdkRegressionTest.cs new file mode 100644 index 000000000000..a8a13763efdd --- /dev/null +++ b/tests/link sdk/LinkSdkRegressionTest.cs @@ -0,0 +1,1047 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Json; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Security.Permissions; +using System.Threading; +using System.Xml; +using Mono.Data.Sqlite; +using MonoTouch; +#if XAMCORE_2_0 +#if !__TVOS__ && !__WATCHOS__ +using AddressBook; +using AddressBookUI; +#endif +#if !__WATCHOS__ +using CoreAnimation; +#endif +using CoreData; +using CoreFoundation; +using Foundation; +using ObjCRuntime; +#if !__TVOS__ +using MapKit; +#endif +using UIKit; +#if !__WATCHOS__ +using OpenGLES; +#endif +#else +using MonoTouch; +using MonoTouch.AddressBook; +using MonoTouch.AddressBookUI; +using MonoTouch.CoreAnimation; +using MonoTouch.CoreData; +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +using MonoTouch.OpenGLES; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [FileIOPermission (SecurityAction.LinkDemand, AllLocalFiles = FileIOPermissionAccess.AllAccess)] + public class SecurityDeclarationDecoratedUserCode { + + [FileIOPermission (SecurityAction.Assert, AllLocalFiles = FileIOPermissionAccess.NoAccess)] + static public bool Check () + { + return true; + } + } + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class LinkSdkRegressionTest { + + [Test] + // https://github.com/xamarin/monotouch/commit/cbefbeaea2eda820dfc7214e976edc83a55df38e + public void MonoAssembly_LinkedOut () + { + Assembly a = Assembly.GetExecutingAssembly (); + Assert.That (a.GetType ().Name, Is.EqualTo ("MonoAssembly"), "MonoAssembly"); + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=205 + // https://bugzilla.novell.com/show_bug.cgi?id=688414 + public void Bug205_ExposingIEnumerable () + { + var ds = new DataContractSerializer (typeof (IEnumerable)); + using (var xw = XmlWriter.Create (System.IO.Stream.Null)) + ds.WriteObject (xw, new int [] { 1, 2, 3 }); + // the above should not throw System.Runtime.Serialization.SerializationException + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=233 + public void Bug233_MonoPInvokeCallback () + { + var c = new SqliteConnection ("Data Source=:memory:"); + c.Open (); + c.Update += (sender, e) => {}; + // the above should not crash + c.Close (); + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=234 + public void Bug234_Interlocked () + { + string str = null; + Assert.Null (Interlocked.Exchange (ref str, "one"), "Exchange"); + // the above should not crash with System.ExecutionEngineException + Assert.That (str, Is.EqualTo ("one"), "one"); + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=300 + // http://stackoverflow.com/questions/6517736/monotouch-crash-dictionary-firstordefault-type-initializer-predicateof + public void Bug300_Linker_PredicateOf () + { + Dictionary queued = new Dictionary (); + KeyValuePair valuePair = queued.FirstOrDefault (); + // above should not crash with System.ExecutionEngineException + Assert.NotNull (valuePair); + } + +#if !__WATCHOS__ + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=328 + public void Bug328_CompletionBlock () + { + CATransaction.Begin (); + CATransaction.CompletionBlock = delegate {}; + // the above should not crash with a MonoTouchException + CATransaction.Commit (); + } +#endif // !__WATCHOS__ + +#if !__TVOS__ && !__WATCHOS__ + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=769 + public void Bug769_UnregistredDelegate () + { + var tmp = Class.ThrowOnInitFailure; + Class.ThrowOnInitFailure = false; + try { + Assert.NotNull (new MKMapViewDelegate ()); + // the above should not throw an Exception + } finally { + Class.ThrowOnInitFailure = tmp; + } + } +#endif // !__TVOS__ && !__WATCHOS__ + +#if !__WATCHOS__ + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=865 + public void Bug865_CanOpenUrl () + { + Assert.False (UIApplication.SharedApplication.CanOpenUrl (null), "null"); + // the above should not throw an ArgumentNullException + // and that's important because NSUrl.FromString and NSUrl.ctor(string) differs + const string bad_tel = "tel://1800 023 009"; + Assert.Null (NSUrl.FromString (bad_tel), "bad url"); + // we now throw if `init*` fails + Assert.Throws (() => new NSUrl (bad_tel), "ctor, bad url"); + } +#endif // !__WATCHOS__ + + [Test] + // issue indirectly found when trying: http://bugzilla.xamarin.com/show_bug.cgi?id=928 + // similar to MonoAssembly_LinkedOut + // https://github.com/xamarin/monotouch/commit/409316f87f23723a384cb072163abd03ae7e6045 + public void Bug928_MonoModule_LinkedOut () + { + Module m = Assembly.GetExecutingAssembly ().ManifestModule; + Assert.That (m.GetType ().Name, Is.EqualTo ("MonoModule"), "MonoModule"); + } + +#if !__TVOS__ && !__WATCHOS__ + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=980 + public void Bug980_AddressBook_NRE () + { + using (ABPeoplePickerNavigationController picker = new ABPeoplePickerNavigationController ()) { + // no NRE should occur + if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) + Assert.Null (picker.AddressBook); + else + Assert.NotNull (picker.AddressBook); + } + } + + [Test] + public void AddressBook_Constants () + { + // we want to ensure we can get the constants without authorization (on iOS 6.0+) so this application + // needs to be unauthorized (in settings.app). Note: authorization checks only occurs on devices + if ((Runtime.Arch == Arch.DEVICE) && UIDevice.CurrentDevice.CheckSystemVersion (6,0)) { + Assert.That (ABAddressBook.GetAuthorizationStatus (), Is.Not.EqualTo (ABAuthorizationStatus.Authorized), + "Please deny access to contacts for this this application (it's important for this test)"); + } + Assert.IsNotNull (ABPersonAddressKey.City, "ABPersonAddressKey"); + } +#endif // !__TVOS__ && !__WATCHOS__ + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1387 + public void Bug1387_UIEdgeInsets_ToString () + { + var insets = new UIEdgeInsets (1, 2, 3, 4); + Assert.False (insets.ToString ().Contains ("UIEdgeInsets")); + } + + void CheckExceptionDetailProperty (PropertyInfo pi) + { + bool data_member = true; + foreach (var ca in pi.GetCustomAttributes (false)) { + if (ca is DataMemberAttribute) { + data_member = true; + break; + } + } + // to be valid both getter and setter must be present if [DataMember] + if (data_member) { + Assert.NotNull (pi.GetGetMethod (true), "get_" + pi.Name); + Assert.NotNull (pi.GetSetMethod (true), "set_" + pi.Name); + } else { + // check well-known [DataMember] + switch (pi.Name) { + case "HelpLink": + case "InnerException": + case "Message": + case "StackTrace": + case "Type": + Assert.Fail ("{0} is missing it's [DataMember] attribute", pi.Name); + break; + } + } + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1415 + public void Bug1415_Linker_DataMember () + { + // the typeof ensure we're can't (totally) link away System.ServiceModel.dll + Type ed = typeof (System.ServiceModel.AuditLevel).Assembly.GetType ("System.ServiceModel.ExceptionDetail", false); + // which means it's [DataContract] / [DataMember] should not be linked out + // even if we're not specifically using them (and without [Preserve] being added) + // which is important since System.ServiceModel.dll is an SDK assembly + Assert.NotNull (ed, "ExceptionDetail"); + bool help_link = false; + bool inner_exception = false; + bool message = false; + bool stack_trace = false; + bool type = false; + foreach (var pi in ed.GetProperties ()) { + CheckExceptionDetailProperty (pi); + switch (pi.Name) { + case "HelpLink": + help_link = true; + break; + case "InnerException": + inner_exception = true; + break; + case "Message": + message = true; + break; + case "StackTrace": + stack_trace = true; + break; + case "Type": + type = true; + break; + } + } + // ensure all properties are still present + Assert.True (help_link, "HelpLink"); + Assert.True (inner_exception, "InnerException"); + Assert.True (message, "Message"); + Assert.True (stack_trace, "StackTrace"); + Assert.True (type, "Type"); + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1415 + // not really part of the bug - but part of the same fix + public void Bug1415_Linker_XmlAttribute () + { + // the typeof ensure we're can't (totally) link away System.ServiceModel.dll + Type ed = typeof (System.ServiceModel.AuditLevel).Assembly.GetType ("System.ServiceModel.EndpointAddress10", false); + // type is decorated with both [XmlSchemaProvider] and [XmlRoot] + Assert.NotNull (ed, "EndpointAddress10"); + +#if !__WATCHOS__ // FIXME: this needs to use a different type than OpenTK.Quaternion, so that the test can run on WatchOS as wells + var q = new OpenTK.Quaternion (); + Assert.Null (q.GetType ().GetProperty ("XYZ"), "XmlIgnore"); + // should be null if application is linked (won't be if "Don't link" is used) +#endif // !__WATCHOS__ + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1443 + public void Bug1443_Linq_Aot () + { + List list = new List (); + Dictionary dict = new Dictionary (); + list.AddRange (from kv in dict orderby kv.Key select kv.Value.ToString ()); + // should not throw an ExecutionEngineException on devices + } + +#if !__TVOS__ && !__WATCHOS__ + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1516 + public void Bug1516_Appearance_Linker () + { + // iOS7, since DP3, validates ?some? appearance properties, e.g. + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -setTintColor: is not allowed for use with the appearance proxy. Perhaps you want to use the barTintColor property. + // UINavigationBar.Appearance.TintColor = UIColor.FromRGB (238,234,222); + UINavigationBar.Appearance.SetTitleTextAttributes (new UITextAttributes () { + TextColor = UIColor.FromRGB (85, 108, 17), + TextShadowColor = UIColor.Clear + }); + // should not throw if the application is linked + } +#endif + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1790 + public void Bug1790_TimeZoneInfo_Local () + { + // the simulator has complete file access but the device won't have - i.e. we can't depend on it + Assert.That (File.Exists ("/etc/localtime"), Is.EqualTo (Runtime.Arch == Arch.SIMULATOR), "/etc/localtime"); + Assert.NotNull (TimeZoneInfo.Local, "Local"); + // should not throw a TimeZoneNotFoundException on devices + } + + [Test] + // http://bugzilla.xamarin.com/show_bug.cgi?id=1922 + public void Bug1922_PLinq_Aot () + { + const int size = 100; + Random random = new Random (); + int[] values = new int [size]; + int currentNumber = 0; + List numbers = new List (); + while (currentNumber < 100) { + values [currentNumber] = random.Next (1, 10); + numbers.Add (currentNumber); + currentNumber ++; + } + numbers.AsParallel ().ForAll (number => { + Thread.Sleep (values [number]); + //Console.WriteLine (number); + }); + if (Runtime.Arch == Arch.SIMULATOR) + Assert.Inconclusive ("only fails on devices"); + } + + [Test] + public void Bug2000_NSPersistentStoreCoordinator () + { + // from http://www.sgmunn.com/?p=1#comments + NSAttributeDescription description = new NSAttributeDescription (); + Assert.That (description.Handle, Is.Not.EqualTo (IntPtr.Zero), "NSAttributeDescription"); + description.AttributeType = NSAttributeType.Integer32; + description.Name = "SomeId"; + description.Optional = false; + + NSEntityDescription entity = new NSEntityDescription (); + Assert.That (entity.Handle, Is.Not.EqualTo (IntPtr.Zero), "NSEntityDescription"); + entity.Name = "TestEntity"; + entity.Properties = new NSPropertyDescription[1] { description }; + + NSManagedObjectModel model = new NSManagedObjectModel (); + Assert.That (model.Handle, Is.Not.EqualTo (IntPtr.Zero), "NSManagedObjectModel"); + model.Entities = new NSEntityDescription[1] { entity }; + model.SetEntities (model.Entities, String.Empty); + + NSUrl url = new NSUrl ("test.sqlite", false); + + // from http://bugzilla.xamarin.com/show_bug.cgi?id=2000 + NSError error; + var c = new NSPersistentStoreCoordinator (model); + c.AddPersistentStoreWithType (NSPersistentStoreCoordinator.SQLiteStoreType, null, url, null, out error); + Assert.True (Runtime.Arch == Arch.SIMULATOR ? error == null : error.Code == 512, "error"); + } + + [Test] + // http://lists.ximian.com/pipermail/monotouch/2011-December/006976.html + public void Linker_RuntimeWrappedException () + { + try { + // can't throw anything else but Exception-derived types from C# + support.throw_object (); + } + catch (Exception e) { + Assert.That (e.GetType ().Name, Is.EqualTo ("RuntimeWrappedException"), "RuntimeWrappedException"); + } + } + + [Test] + // http://stackoverflow.com/questions/8602726/cant-open-sqlite-database-in-read-only-mode + public void Sqlite_ReadOnly () + { + var c = new SqliteConnection ("Data Source=:memory:;Read Only=true"); + c.Open (); + // the above should not throw a 'misuse' exception + c.Close (); + } + + [Test] + public void AsQueryable_3028 () + { + string [] foos = new string [] { "hi", "bye" }; + string f = foos.AsQueryable ().First (); + Assert.That (f, Is.EqualTo ("hi"), "f"); + } + +#if !__WATCHOS__ + [Test] + public void OpenTk_3049 () + { + using (var gc1 = OpenTK.Platform.Utilities.CreateGraphicsContext (EAGLRenderingAPI.OpenGLES1)) { + Assert.NotNull (gc1); + } + using (var gc2 = OpenTK.Platform.Utilities.CreateGraphicsContext (EAGLRenderingAPI.OpenGLES2)) { + Assert.NotNull (gc2); + } + } + + [Test] + public void OpenTk_Preserved () + { +#if XAMCORE_2_0 + const string OpenTKAssembly = "OpenTK-1.0"; +#else + const string OpenTKAssembly = "OpenTK"; +#endif + var gl = Type.GetType ("OpenTK.Graphics.ES11.GL, " + OpenTKAssembly, false); + Assert.NotNull (gl, "ES11/GL"); + var core = Type.GetType ("OpenTK.Graphics.ES11.GL/Core, " + OpenTKAssembly, false); + Assert.NotNull (core, "ES11/Core"); + + gl = Type.GetType ("OpenTK.Graphics.ES20.GL, " + OpenTKAssembly, false); + Assert.NotNull (gl, "ES20/GL"); + core = Type.GetType ("OpenTK.Graphics.ES20.GL/Core, " + OpenTKAssembly, false); + Assert.NotNull (core, "ES20/Core"); + } +#endif // !__WATCHOS__ + + [Test] + public void XElement_3137 () + { + CultureInfo current = Thread.CurrentThread.CurrentCulture; + try { + Thread.CurrentThread.CurrentCulture = new CultureInfo ("en-US"); + var element1 = new System.Xml.Linq.XElement ("Property1", new System.Xml.Linq.XAttribute ("type", "number"), 1.2343445); + Assert.That (element1.ToString (), Is.EqualTo ("1.2343445"), "en-US"); + + Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo ("de-DE"); + // this was already working because the element was created with en-US + Assert.That (element1.ToString (), Is.EqualTo ("1.2343445"), "de-DE/1"); + // however creating a new, identical, element under de-DE return*ed* a different string + var element2 = new System.Xml.Linq.XElement ("Property1", new System.Xml.Linq.XAttribute ("type", "number"), 1.2343445); + Assert.That (element2.ToString (), Is.EqualTo ("1.2343445"), "de-DE/2"); + } + finally { + Thread.CurrentThread.CurrentCulture = current; + } + } + +#if !__TVOS__ && !__WATCHOS__ + [Test] + public void Modal_3489 () + { + using (UIViewController a = new UIViewController ()) + using (UIViewController b = new UIViewController ()) + using (UIViewController c = new UIViewController ()) { + a.PresentModalViewController (b, true); + b.PresentModalViewController (c, true); + +#if XAMCORE_2_0 + b.DismissModalViewController (true); + a.DismissModalViewController (true); //error +#else + b.DismissModalViewControllerAnimated (true); + a.DismissModalViewControllerAnimated (true); //error +#endif + } + } +#endif // !__TVOS__ && !__WATCHOS__ + + [Test] + public void TypeDescriptor_A7793 () + { + Assert.NotNull (TypeDescriptor.GetConverter (typeof (bool))); + } + + [Test] + public void Parse_3677 () + { + Assert.That (sbyte.Parse ("E3", NumberStyles.HexNumber), Is.EqualTo (-29), "SByte"); + Assert.That (short.Parse ("E3E3", NumberStyles.HexNumber), Is.EqualTo (-7197), "Int16"); + } + + public class DeviceHardware { + public const string HardwareProperty = "hw.machine"; + + public enum HardwareVersion { + iPhone, + iPhone3G, + iPhone3GS, + iPhone4, + iPod1G, + iPod2G, + iPod3G, + iPod4G, + iPad, + iPhoneSimulator, + iPhone4Simulator, + iPadSimulator, + Unknown + } + + // Changing the constant to "/usr/bin/libSystem.dylib" allows this P/Invoke to work on Mac OS X + // Using "hw.model" as property gives Macintosh model, "hw.machine" kernel arch (ppc, ppc64, i386, x86_64) + [DllImport (Constants.libSystemLibrary)] + internal static extern int sysctlbyname ([MarshalAs(UnmanagedType.LPStr)] string property, // name of the property + IntPtr output, // output + IntPtr oldLen, // IntPtr.Zero + IntPtr newp, // IntPtr.Zero + uint newlen // 0 + ); + + public static HardwareVersion Version { + get { + // get the length of the string that will be returned + var pLen = Marshal.AllocHGlobal(sizeof(int)); + sysctlbyname(DeviceHardware.HardwareProperty, IntPtr.Zero, pLen, IntPtr.Zero, 0); + + var length = Marshal.ReadInt32(pLen); + + // check to see if we got a length + if (length == 0) + { + Marshal.FreeHGlobal(pLen); + return HardwareVersion.Unknown; + } + + // get the hardware string + var pStr = Marshal.AllocHGlobal(length); + sysctlbyname(DeviceHardware.HardwareProperty, pStr, pLen, IntPtr.Zero, 0); + + // convert the native string into a C# string + var hardwareStr = Marshal.PtrToStringAnsi(pStr); + var ret = HardwareVersion.Unknown; + + // determine which hardware we are running + if (hardwareStr == "iPhone1,1") + ret = HardwareVersion.iPhone; + else if (hardwareStr == "iPhone1,2") + ret = HardwareVersion.iPhone3G; + else if (hardwareStr == "iPhone2,1") + ret = HardwareVersion.iPhone3GS; + else if (hardwareStr == "iPhone3,1") + ret = HardwareVersion.iPhone4; + else if (hardwareStr == "iPad1,1") + ret = HardwareVersion.iPad; + else if (hardwareStr == "iPod1,1") + ret = HardwareVersion.iPod1G; + else if (hardwareStr == "iPod2,1") + ret = HardwareVersion.iPod2G; + else if (hardwareStr == "iPod3,1") + ret = HardwareVersion.iPod3G; + else if (hardwareStr == "iPod4,1") + ret = HardwareVersion.iPod3G; + else if (hardwareStr == "i386" || hardwareStr == "x86_64") { +#if __WATCHOS__ + ret = HardwareVersion.Unknown; +#else + if (UIDevice.CurrentDevice.Model.Contains("iPhone")) + ret = UIScreen.MainScreen.Bounds.Height * UIScreen.MainScreen.Scale == 960 || UIScreen.MainScreen.Bounds.Width * UIScreen.MainScreen.Scale == 960 ? HardwareVersion.iPhone4Simulator : HardwareVersion.iPhoneSimulator; + else + ret = HardwareVersion.iPadSimulator; +#endif + } + else ret = HardwareVersion.Unknown; + + // cleanup + Marshal.FreeHGlobal(pLen); + Marshal.FreeHGlobal(pStr); + + return ret; + } + } + } + + [Test] + // http://stackoverflow.com/questions/9685134/monotouch-fatal-crash-once-deployed + // could not be duplicated on iPad2 (rolf), iPad1 (spouliot), iPodTouch4 (spouliot) + public void Hardware_SO () + { + Assert.NotNull (DeviceHardware.Version, "Hardware"); + } + + public class Location {} + + private static Location mInstance = null; + + [MethodImpl (MethodImplOptions.Synchronized)] + public static Location getInstance () + { + if (mInstance == null) + mInstance = new Location (); + return mInstance; + } + + [Test] + public void Synchronized_3904 () + { + // crash with LLVM + Assert.NotNull (getInstance (), "Location"); + } + + [Test] + [Culture ("en")] + public void Json_Parse_4415 () + { + var f = 4.25987E-06f; + // note: always use '.' see http://www.json.org/fatfree.html + var s = f.ToString (); + var v = JsonValue.Parse (s); + Assert.AreEqual (f, (float) v, "Parse Negative Exponent"); + f *= 10; + Assert.AreNotEqual (f, (float) v, "non-equal"); + } + + [Test] + [Culture ("en")] + public void ConvertToDouble_4620 () + { + // can't duplicate bug when using invarient culture + Assert.That (Convert.ToDouble ("0.0"), Is.EqualTo (0.0d)); + } + + [Test] + public void NetworkInterface_4631 () + { + Assert.NotNull (NetworkInterface.GetAllNetworkInterfaces ()); + } + + [Test] + public void WebClient_SSL_Leak () + { + WebClient wc = new WebClient (); + // note: needs to be executed under Instrument to verify it does not leak + string s = wc.DownloadString ("https://developers.google.com"); + Assert.NotNull (s); + } + +#if !__TVOS__ && !__WATCHOS__ + [Test] + public void WebProxy_Leak () + { + // note: needs to be executed under Instrument to verify it does not leak + Assert.NotNull (CFNetwork.GetSystemProxySettings (), "should not leak"); + } +#endif // !__TVOS__ && !__WATCHOS__ + + [Test] + // https://bugzilla.novell.com/show_bug.cgi?id=650402 + public void ForeignKey_650402 () + { + DataSet data = new DataSet (); + DataTable parent = new DataTable ("parent"); + DataColumn pk = parent.Columns.Add ("PK"); + DataTable child = new DataTable ("child"); + DataColumn fk = child.Columns.Add ("FK"); + + data.Tables.Add (parent); + data.Tables.Add (child); + data.Relations.Add (pk, fk); + + parent.Rows.Add ("value"); + child.Rows.Add ("value"); + data.AcceptChanges (); + child.Rows[0].Delete (); + parent.Rows[0][0] = "value2"; + + data.EnforceConstraints = false; + data.EnforceConstraints = true; + } + + [Test] + public void Pointer_5200 () + { + // ensure the linker did not remove the type, which is used by the runtime + Assert.NotNull (Type.GetType ("System.Reflection.Pointer, mscorlib")); + } + + [Test] + public void LockRecursionException_5311 () + { + Assert.Throws (delegate { throw new LockRecursionException (); }); + } + + class AddedInSilverlight5 : INotifyPropertyChanging { + public event PropertyChangingEventHandler PropertyChanging; + } + + [Test] + public void INotifyPropertyChanging_5337 () + { + new AddedInSilverlight5 ().PropertyChanging += delegate { }; + } + + [Test] + public void MonoIOStat_6118 () + { + string file = NSBundle.MainBundle.ExecutablePath; + DateTime c1 = File.GetCreationTime (file).ToUniversalTime (); + DateTime c2 = (DateTime) NSFileManager.DefaultManager.GetAttributes (file).CreationDate; + Assert.That ((c1 - c2).Seconds, Is.LessThan (30), "MonoIOStat"); + } + + [Test] + public void ObjectHandleCtor () + { + Type o = typeof (Object); + // this returns a new System.Runtime.Remoting.ObjectHandle which (was) linked away previously + Assert.NotNull (Activator.CreateInstance (o.Assembly.GetName ().Name, o.FullName), "ObjectHandle"); + } + + [Test] + public void AttributeUsageAttribute_Persistance () + { + Assert.IsFalse (Attribute.IsDefined (GetType (), typeof(SerializableAttribute))); + } + + [Test] + [ExpectedException (typeof (NotSupportedException))] + public void LinkedAway () + { + new System.Runtime.Remoting.RemotingException (); + } + + [Test] + public void ArrayClear_11184 () + { + byte[] key = new byte [16]; + for (int i = 0; i < key.Length; i++) + key [i] = (byte) (255 - i); + Array.Clear (key, 5, 11); + for (int i = 5; i < key.Length; i++) + Assert.That (key [i], Is.EqualTo (0), i.ToString ()); + } + + public class Demo_14493 { + public void Update (object o) + { + } + } + + [Test] + public void Action_14493 () + { + var Demo = new Demo_14493 (); + Action a = null; + a += Demo.Update; + a -= Demo.Update; // Crash here + } + + enum AnEnum { + First = 1, + Second = 2 + }; + + [Test] + public void AotGcMemmove_Crash_17284 () + { + var arr = new AnEnum [16]; + var c = new ReadOnlyCollection (arr); + Assert.False (c.Contains (AnEnum.First)); + } + + enum MyEnum { + AValue, + AnotherValue + } + + [Test] + public void Aot_Gsharedvt_21893 () + { + IList _myValues = new List { MyEnum.AValue }; + bool pleaseDontCrash = _myValues.Contains (MyEnum.AnotherValue); + Assert.False (pleaseDontCrash); + } + + [Test] + public void PrivateMemorySize64 () + { + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=21882 + var mem = System.Diagnostics.Process.GetCurrentProcess ().PrivateMemorySize64; + // the above used a mach call that iOS samdbox did *not* allow (sandbox) on device + // but has been fixed (different call) for the same PID + Assert.That (mem, Is.Not.EqualTo (0), "PrivateMemorySize64"); + } + + string TestFolder (Environment.SpecialFolder folder, bool supported = true, bool exists = true, bool readOnly = false) + { + var path = Environment.GetFolderPath (folder); + Assert.That (path.Length > 0, Is.EqualTo (supported), folder.ToString ()); + if (!supported) + return path; + + Assert.That (Directory.Exists (path), Is.EqualTo (exists), path); + if (!exists) + return path; + + string file = Path.Combine (path, "temp.txt"); + try { + File.WriteAllText (file, "mine"); + Assert.False (readOnly, "!readOnly " + folder); + } + catch { + Assert.True (readOnly, "readOnly " + folder); + } + finally { + File.Delete (file); + } + return path; + } + + [Test] + public void SpecialFolder () + { + // iOS8 changes the rules of the game + var fm = NSFileManager.DefaultManager; + var docs = fm.GetUrls (NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User) [0].Path; + var libs = fm.GetUrls (NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomain.User) [0].Path; + + // note: this test is more interesting on devices because of the sandbox they have + bool device = Runtime.Arch == Arch.DEVICE; + + // some stuff we do not support (return String.Empty for the path) + TestFolder (Environment.SpecialFolder.Programs, supported: false); + TestFolder (Environment.SpecialFolder.Startup, supported: false); + TestFolder (Environment.SpecialFolder.Recent, supported: false); + TestFolder (Environment.SpecialFolder.SendTo, supported: false); + TestFolder (Environment.SpecialFolder.StartMenu, supported: false); + TestFolder (Environment.SpecialFolder.MyComputer, supported: false); + TestFolder (Environment.SpecialFolder.NetworkShortcuts, supported: false); + TestFolder (Environment.SpecialFolder.CommonStartMenu, supported: false); + TestFolder (Environment.SpecialFolder.CommonPrograms, supported: false); + TestFolder (Environment.SpecialFolder.CommonStartup, supported: false); + TestFolder (Environment.SpecialFolder.CommonDesktopDirectory, supported: false); + TestFolder (Environment.SpecialFolder.PrinterShortcuts, supported: false); + TestFolder (Environment.SpecialFolder.Cookies, supported: false); + TestFolder (Environment.SpecialFolder.History, supported: false); + TestFolder (Environment.SpecialFolder.Windows, supported: false); + TestFolder (Environment.SpecialFolder.System, supported: false); + TestFolder (Environment.SpecialFolder.SystemX86, supported: false); + TestFolder (Environment.SpecialFolder.ProgramFilesX86, supported: false); + TestFolder (Environment.SpecialFolder.CommonProgramFiles, supported: false); + TestFolder (Environment.SpecialFolder.CommonProgramFilesX86, supported: false); + TestFolder (Environment.SpecialFolder.CommonDocuments, supported: false); + TestFolder (Environment.SpecialFolder.CommonAdminTools, supported: false); + TestFolder (Environment.SpecialFolder.AdminTools, supported: false); + TestFolder (Environment.SpecialFolder.CommonMusic, supported: false); + TestFolder (Environment.SpecialFolder.CommonPictures, supported: false); + TestFolder (Environment.SpecialFolder.CommonVideos, supported: false); + TestFolder (Environment.SpecialFolder.LocalizedResources, supported: false); + TestFolder (Environment.SpecialFolder.CommonOemLinks, supported: false); + TestFolder (Environment.SpecialFolder.CDBurning, supported: false); + + // some stuff we return a value - but the directory does not exists + + var path = TestFolder (Environment.SpecialFolder.Desktop, exists: false); + + path = TestFolder (Environment.SpecialFolder.Favorites, exists: false); + + path = TestFolder (Environment.SpecialFolder.MyMusic, exists: false); + + path = TestFolder (Environment.SpecialFolder.MyVideos, exists: false); + + path = TestFolder (Environment.SpecialFolder.DesktopDirectory, exists: false); + + path = TestFolder (Environment.SpecialFolder.Fonts, exists: false); + + path = TestFolder (Environment.SpecialFolder.Templates, exists: false); + + path = TestFolder (Environment.SpecialFolder.MyPictures, exists: false); + + path = TestFolder (Environment.SpecialFolder.CommonTemplates, exists: false); + + // some stuff we return and are usable either as read-only + path = TestFolder (Environment.SpecialFolder.CommonApplicationData, readOnly: true); + Assert.That (path, Is.EqualTo ("/usr/share"), "path - CommonApplicationData"); + + // and the simulator is more lax + path = TestFolder (Environment.SpecialFolder.ProgramFiles, readOnly: device); + Assert.That (path, Is.EqualTo ("/Applications"), "path - ProgramFiles"); + + path = TestFolder (Environment.SpecialFolder.UserProfile, readOnly: device); + if (Runtime.Arch == Arch.DEVICE) { +#if __WATCHOS__ + Assert.True (path.StartsWith ("/private/var/mobile/Containers/Data/Application/", StringComparison.Ordinal), "Containers-ios8"); +#else + if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) + Assert.True (path.StartsWith ("/private/var/mobile/Containers/Data/Application/", StringComparison.Ordinal), "Containers-ios8"); + else + Assert.True (path.StartsWith ("/private/var/mobile/Applications/", StringComparison.Ordinal), "pre-Containers"); +#endif + } + +#if !__WATCHOS__ + // tvOS (device sandbox) is more restricive than iOS as it limit access to more + // directories, mostly because they are not guaranteed to be preserved between executions + bool tvos = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.TV; + if (tvos) + docs = Path.Combine (libs, "Caches", "Documents"); +#else + bool tvos = false; +#endif + + // and some stuff is read/write + path = TestFolder (Environment.SpecialFolder.MyDocuments); + Assert.That (path, Is.EqualTo (docs), "path - MyDocuments"); + + path = TestFolder (Environment.SpecialFolder.ApplicationData); + Assert.That (path, Is.EqualTo (docs + "/.config"), "path - ApplicationData"); + + path = TestFolder (Environment.SpecialFolder.LocalApplicationData); + Assert.That (path, Is.EqualTo (docs), "path - LocalApplicationData"); + + path = TestFolder (Environment.SpecialFolder.InternetCache); + Assert.That (path, Is.EqualTo (libs + "/Caches"), "path - InternetCache"); + + // new: expose NSLibraryDirectory from Environment.GetFolder + path = TestFolder (Environment.SpecialFolder.Resources, readOnly: tvos && device); + Assert.True (path.EndsWith ("/Library", StringComparison.Ordinal), "Resources"); + } + +#if !__WATCHOS__ + [Test] + public void Events () + { + using (var tv = new UITextView ()) { + Assert.Null (tv.WeakDelegate, "none"); + // event on UITextView itself + tv.Ended += (object sender, EventArgs e) => {}; + + var t = tv.WeakDelegate.GetType (); + Assert.That (t.Name, Is.EqualTo ("_UITextViewDelegate"), "textview"); + + var fi = t.GetField ("editingEnded", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull (fi, "editingEnded"); + var value = fi.GetValue (tv.WeakDelegate); + Assert.NotNull (value, "value"); + +#if XAMCORE_2_0 + // and on the UIScrollView defined one + tv.Scrolled += (object sender, EventArgs e) => {}; + // and the existing (initial field) is still set + fi = t.GetField ("editingEnded", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull (fi, "editingEnded/scrollview"); +#else + // In Classic UITextView also defines a Scrolled event, so make sure we get the UIScrollView one. + ((UIScrollView) tv).Scrolled += (object sender, EventArgs e) => {}; + + t = tv.WeakDelegate.GetType (); + Assert.That (t.Name, Is.EqualTo ("_UIScrollViewDelegate"), "scrollview"); + + fi = t.GetField ("editingEnded", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.Null (fi, "editingEnded/scrollview"); +#endif + } + } +#endif // !__WATCHOS__ + + [Test] + public void SecurityDeclaration () + { + // note: security declarations != custom attributes + // we ensure that we can create the type / call the code + Assert.True (SecurityDeclarationDecoratedUserCode.Check (), "call"); + // we ensure that both the permission and the flag are NOT part of the final/linked binary (link removes security declarations) + Assert.Null (Type.GetType ("System.Security.Permissions.FileIOPermissionAttribute, mscorlib"), "FileIOPermissionAttribute"); + Assert.Null (Type.GetType ("System.Security.Permissions.FileIOPermissionAccess, mscorlib"), "FileIOPermissionAccess"); + } + +#if !__WATCHOS__ + [Test] + public void UIButtonSubclass () + { + // ensure the linker keeps the .ctor(UIButtonType) around + using (var b = new UIButton (UIButtonType.Custom)) { + // https://trello.com/c/Nf2B8mIM/484-remove-debug-code-in-the-linker + var m = typeof (UIButton).GetMethod ("VerifyIsUIButton", BindingFlags.Instance | BindingFlags.NonPublic); +#if DEBUG + // kept in debug builds + Assert.NotNull (m, "VerifyIsUIButton"); +#else + // removed from release builds + Assert.Null (m, "VerifyIsUIButton"); +#endif + } + } + +#endif // !__WATCHOS__ + + [Test] + public void MonoRuntime34671 () + { + Assert.NotNull (Type.GetType ("Mono.Runtime"), "Mono.Runtime"); + } + + [Test] + public void TraceListeners36255 () + { + Trace.Close (); // here too + Assert.NotNull (Trace.Listeners, "C6 had a SecurityPermission call"); + } + + [Test] + public void TlsProvider_Apple () + { + var provider = Mono.Security.Interface.MonoTlsProviderFactory.GetProvider (); + Assert.NotNull (provider, "provider"); + Assert.That (provider.ID, Is.EqualTo (new Guid ("981af8af-a3a3-419a-9f01-a518e3a17c1c")), "correct provider"); + } + + [Test] + public void OldTlsProvider_LinkedOut () + { + // make test work for classic (monotouch) and unified (iOS, tvOS and watchOS) + var fqn = typeof (NSObject).AssemblyQualifiedName.Replace ("Foundation.NSObject", "Security.Tls.OldTlsProvider"); + Assert.Null (Type.GetType (fqn), "Should not be included"); + } + + [Test] + public void AppleTls_Default () + { + // make test work for classic (monotouch) and unified (iOS, tvOS and watchOS) + var fqn = typeof (NSObject).AssemblyQualifiedName.Replace ("Foundation.NSObject", "Security.Tls.AppleTlsProvider"); + Assert.NotNull (Type.GetType (fqn), "Should be included"); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/LocaleTest.cs b/tests/link sdk/LocaleTest.cs new file mode 100644 index 000000000000..6ab488df758a --- /dev/null +++ b/tests/link sdk/LocaleTest.cs @@ -0,0 +1,54 @@ +// Copyright 2016 Xamarin Inc. All rights reserved. + +using System; +using System.Collections.Generic; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class LocaleTest { + + [Test] + [SetCulture ("cs-CZ")] + public void CzechDictComparer () + { + DictComparer (); + } + + [Test] + [SetCulture ("en-US")] + public void EnglishDictComparer () + { + DictComparer (); + } + + [Test] + // runs with whatever the device / simulator is configured + public void DefaultDictComparer () + { + DictComparer (); + } + + void DictComparer () + { + var n1 = "SEARCHFIELDS"; + var n2 = "Searchfields"; + + Assert.True (string.Equals (n1, n2, StringComparison.OrdinalIgnoreCase), "string equality"); + + var dict = new Dictionary (StringComparer.OrdinalIgnoreCase); + dict [n1] = "test"; + + string result; + Assert.True (dict.TryGetValue (n2, out result), "dictionary value"); + } + } +} diff --git a/tests/link sdk/Main.cs b/tests/link sdk/Main.cs new file mode 100644 index 000000000000..c43621acb4e1 --- /dev/null +++ b/tests/link sdk/Main.cs @@ -0,0 +1,26 @@ +#if !__WATCHOS__ +using System; +using System.Collections.Generic; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace LinkSdk +{ + public class Application + { + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/link sdk/Makefile b/tests/link sdk/Makefile new file mode 100644 index 000000000000..99c2df58e22a --- /dev/null +++ b/tests/link sdk/Makefile @@ -0,0 +1,19 @@ + +PLATFORM=ios +PROFILE=devunified + +all: + make -C ../ build-$(PLATFORM)-$(PROFILE)-link\ sdk + +clean: + rm -rf obj bin + +install: + make -C ../ install-$(PLATFORM)-$(PROFILE)-link\ sdk + +exec: + make -C ../ exec-$(PLATFORM)-$(PROFILE)-link\ sdk + +debug-dev: + fruitstrap debug --bundle bin/iPhone/Debug/linksdk.app --args "-app-arg:-autostart" + diff --git a/tests/link sdk/OptimizeGeneratedCodeTest.cs b/tests/link sdk/OptimizeGeneratedCodeTest.cs new file mode 100644 index 000000000000..d0015cb884a6 --- /dev/null +++ b/tests/link sdk/OptimizeGeneratedCodeTest.cs @@ -0,0 +1,223 @@ +// +// Unit tests for the linker's OptimizeGeneratedCodeSubStep +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013, 2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +#if !__WATCHOS__ +using System.Drawing; +#endif +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using SizeF=CoreGraphics.CGSize; +using RectangleF=CoreGraphics.CGRect; +#endif + +namespace Linker.Shared { + + partial class NotPreserved { + +#if !__WATCHOS__ + public void Bug11452 () + { + var button = new UIButton (); + button.TouchCancel += delegate { + if (Runtime.Arch == Arch.SIMULATOR) { + // kaboom + } + }; + } +#endif // !__WATCHOS__ + } + + class NSNotPreserved : NSObject { +#if !__WATCHOS__ + public void Bug11452 () + { + var button = new UIButton (); + button.TouchCancel += delegate { + if (Runtime.Arch == Arch.SIMULATOR) { + // kaboom + } + }; + } +#endif // !__WATCHOS__ + } + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class OptimizeGeneratedCodeTest { + + // tests related to IL re-writting inside OptimizeGeneratedCodeSubStep + + // note: the following tests don't really ensure the IL code is ok - + // the best way to be sure if decompiling and reviewing the IL. OTOH + // it's pretty likely to crash if the IL was badly rewritten so running + // them makes me feel better ;-) + +#if !__TVOS__ && !__WATCHOS__ + [Test] + public void IsNewRefcountEnabled () + { + using (UIWebView wv = new UIWebView ()) { + Assert.Null (wv.Request, "IsNewRefcountEnabled"); + } + } + + class MyUIWebViewDelegate : UIWebViewDelegate { + } + + [Test] + public void MarkDirty () + { + using (UIWebView wv = new UIWebView ()) + using (MyUIWebViewDelegate del = new MyUIWebViewDelegate ()) { + wv.WeakDelegate = del; + Assert.That (wv.WeakDelegate, Is.EqualTo (del), "MarkDirty"); + } + } + + // this has a (single) "if (Runtime.Arch == Arch.DEVICE)" condition + + [Test] + public void SingleRuntimeArchDevice () + { + SizeF empty = SizeF.Empty; + using (UIView v = new UIView ()) + using (UIFont font = UIFont.SystemFontOfSize (12f)) { + SizeF size = "MonoTouch".StringSize (font); + Assert.False (size.IsEmpty, "!Empty"); + } + } +#endif // !__TVOS__ + + // this has 2 "if (Runtime.Arch == Arch.DEVICE)" conditions separated + // by "if (IsDirectBinding)" so modifying IL is a bit more tricky - so + // testing this, linked on both the simulator and on device is important + +#if !__WATCHOS__ + [Test] + public void DoubleRuntimeArchDevice () + { + SizeF empty = SizeF.Empty; + using (UIView v = new UIView ()) { + Assert.True (v.SizeThatFits (empty).IsEmpty, "Empty"); + } + } +#endif // !__WATCHOS__ + + // some UIImage bindings are now decorated with [Autorelease] and that + // MUST be considered since it adds a try/finally for the C# using + + [Test] + public void Autorelease () + { + using (UIImage img = new UIImage ()) { + // those are the two UIImage instance methods decorated with [Autorelease] +#if !__TVOS__ + img.StretchableImage (10, 10); +#endif + img.CreateResizableImage (new UIEdgeInsets (1, 2, 3, 4)); + // note: return value is null for iOS7 (and was non-null before it) + // anyway we care about not crashing due to the linker optimizing the IL, not the return values + } + } + +#if !__WATCHOS__ + [Test] + public void AnonymousDelegate () + { + // anonymous delegates are decorated with [CompilerGenerated] attributes but must + // not be processed since the IL inside them is not compiler generated + new NotPreserved ().Bug11452 (); + + using (var ns = new NSNotPreserved ()) { + ns.Bug11452 (); + } + } +#endif // !__WATCHOS__ + +#if LINKALL + [Test] + // the two attributes below are required for the optimizing code to kick in. + [CompilerGenerated] + [Export ("dummy")] + public void IntPtrSizeOptimization () + { + // bug #21541. + Marshal.FreeHGlobal (Marshal.AllocHGlobal (IntPtr.Size)); + + if (IntPtr.Size == 8) { + Console.WriteLine (0x11111111); + } else { + Console.WriteLine (0x22222222); + } + + var arr = MethodInfo.GetCurrentMethod ().GetMethodBody ().GetILAsByteArray (); + if (arr.Length < 2) // single `ret` instruction is added by the stripper + Assert.Inconclusive ("IL was stripped from the assembly (release mode)"); + + bool contains11 = false; + bool contains22 = false; + for (int i = 0; i < arr.Length - 4; i++) { + contains11 |= arr [i] == 0x11 && arr [i + 1] == 0x11 && arr [i + 2] == 0x11 && arr [i + 3] == 0x11; + contains22 |= arr [i] == 0x22 && arr [i + 1] == 0x22 && arr [i + 2] == 0x22 && arr [i + 3] == 0x22; + + } + // the optimization is turned off in case of fat apps (32/64 bits) + bool b32 = Directory.Exists (Path.Combine (NSBundle.MainBundle.BundlePath, ".monotouch-32")); + bool b64 = Directory.Exists (Path.Combine (NSBundle.MainBundle.BundlePath, ".monotouch-64")); + // classic does not use the subdirectories, neither do we for single arch simulator + bool classic_or_sim = !b32 && !b64; + bool single_arch = !(b32 && b64); + if (classic_or_sim || single_arch) + Assert.IsFalse (contains11 && contains22, "neither instructions removed"); + // even if disabled this condition remains + Assert.IsFalse (!contains11 && !contains22, "both instructions removed"); + } + + [Test] + public void FinallyTest () + { + // bug #26415 + FinallyTestMethod (); + Assert.IsTrue (finally_invoked); + } + + bool finally_invoked; + [Export ("finallyTestMethod")] + [CompilerGenerated] + public IntPtr FinallyTestMethod () + { + try { + if (IntPtr.Size == 8) { + return IntPtr.Zero; + } else { + return IntPtr.Zero; + } + } finally { + finally_invoked = true; + } + } +#endif + } +} \ No newline at end of file diff --git a/tests/link sdk/PclTest.cs b/tests/link sdk/PclTest.cs new file mode 100644 index 000000000000..afbc354dd092 --- /dev/null +++ b/tests/link sdk/PclTest.cs @@ -0,0 +1,122 @@ +using System; +using System.IO; +using System.Net; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.Windows.Input; +using System.Xml; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PclTest { + + [Test] + public void Corlib () + { + BinaryWriter bw = new BinaryWriter (Stream.Null); + bw.Dispose (); + } + + [Test] + public void System () + { + const string url = "http://www.google.com"; + Uri uri = new Uri (url); + + Assert.False (this is ICommand, "ICommand"); + + HttpWebRequest hwr = new HttpWebRequest (uri); + try { + Assert.True (hwr.SupportsCookieContainer, "SupportsCookieContainer"); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + + WebResponse wr = hwr.GetResponse (); + try { + Assert.True (wr.SupportsHeaders, "SupportsHeaders"); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + wr.Dispose (); + + try { + Assert.NotNull (WebRequest.CreateHttp (url)); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + + try { + Assert.NotNull (WebRequest.CreateHttp (uri)); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + } + + [Test] + public void ServiceModel () + { + AddressHeaderCollection ahc = new AddressHeaderCollection (); + try { + ahc.FindAll (null, null); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + + try { + FaultException.CreateFault (null, String.Empty, null); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + } + + [Test] + public void Xml () + { + try { + XmlConvert.VerifyPublicId (String.Empty); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + + try { + XmlConvert.VerifyWhitespace (String.Empty); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + + try { + XmlConvert.VerifyXmlChars (String.Empty); + } + catch (NotImplementedException) { + // feature is not available, but the symbol itself is needed + } + + var xr = XmlReader.Create (Stream.Null); + xr.Dispose (); + + var xw = XmlWriter.Create (Stream.Null); + xw.Dispose (); + + XmlReaderSettings xrs = new XmlReaderSettings (); + xrs.DtdProcessing = DtdProcessing.Ignore; + } + } +} \ No newline at end of file diff --git a/tests/link sdk/ReflectionTest.cs b/tests/link sdk/ReflectionTest.cs new file mode 100644 index 000000000000..fcd12a29921f --- /dev/null +++ b/tests/link sdk/ReflectionTest.cs @@ -0,0 +1,43 @@ +// Copyright 2016 Xamarin Inc. All rights reserved. + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace Linker.Shared.Reflection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class ReflectionTest { + + public void MethodWithParameters (string firstParameter, int secondParameter) + { + } + + [Test] + public void ParameterInfoName () + { + // linker will disable the metadata removal optimization if that property is used by user code + // however it's used inside mscorlib.dll (and SDK) so it cannot be checked while testing + //Assert.Null (typeof (ParameterInfo).GetProperty ("Name"), "Name"); + + var mi = this.GetType ().GetMethod ("MethodWithParameters"); + var p = mi.GetParameters (); +#if DEBUG || !LINKALL + // this optimization is only applied for release builds (not debug ones) + // link sdk won't touch this assembly (user code) so the parameters will be available + Assert.That (p [0].ToString (), Is.EqualTo ("System.String firstParameter"), "1"); + Assert.That (p [1].ToString (), Is.EqualTo ("Int32 secondParameter"), "2"); +#else + Assert.That (p [0].ToString (), Is.EqualTo ("System.String "), "1"); + Assert.That (p [1].ToString (), Is.EqualTo ("Int32 "), "2"); +#endif + } + } +} diff --git a/tests/link sdk/TaskTest.cs b/tests/link sdk/TaskTest.cs new file mode 100644 index 000000000000..8c6ef7ca7c75 --- /dev/null +++ b/tests/link sdk/TaskTest.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Threading; +using System.Threading.Tasks; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace LinkSdk { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TaskBugsTest { + + [Test] + public void ContinueWithDifferentOptionsAreCanceledTest () + { + TaskScheduler.UnobservedTaskException += (obj, evt) => evt.SetObserved (); + var mre = new ManualResetEventSlim (); + var task = Task.Factory.StartNew (() => mre.Wait (200)); + var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted); + var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled); + var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion); + + mre.Set (); + contSuccess.Wait (100); + + Assert.True (contSuccess.IsCompleted, "contSuccess.IsCompleted"); + Assert.True (contFailed.IsCompleted, "contFailed.IsCompleted"); + Assert.True (contCanceled.IsCompleted, "contCanceled.IsCompleted"); + Assert.False (contSuccess.IsCanceled, "contSuccess.IsCanceled"); + Assert.True (contFailed.IsCanceled, "contFailed.IsCanceled"); + Assert.True (contCanceled.IsCanceled, "contCanceled.IsCanceled"); + } + + [Test] + public void ContinueWhenAll_WithMixedCompletionState () + { + TaskScheduler.UnobservedTaskException += (obj, evt) => evt.SetObserved (); + var mre = new ManualResetEventSlim (); + var task = Task.Factory.StartNew (() => mre.Wait (200)); + var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted); + var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled); + var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion); + bool ran = false; + + var cont = Task.Factory.ContinueWhenAll (new Task[] { contFailed, contCanceled, contSuccess }, _ => ran = true); + + mre.Set (); + cont.Wait (200); + + Assert.True (ran, "ran"); + Assert.That (cont.Status, Is.EqualTo (TaskStatus.RanToCompletion), "Status"); + } + } +} \ No newline at end of file diff --git a/tests/link sdk/extra-linker-defs-tvos.xml b/tests/link sdk/extra-linker-defs-tvos.xml new file mode 100644 index 000000000000..f21bf88c53f0 --- /dev/null +++ b/tests/link sdk/extra-linker-defs-tvos.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/link sdk/extra-linker-defs-unified.xml b/tests/link sdk/extra-linker-defs-unified.xml new file mode 100644 index 000000000000..e45255620cdb --- /dev/null +++ b/tests/link sdk/extra-linker-defs-unified.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/link sdk/extra-linker-defs-watchos.xml b/tests/link sdk/extra-linker-defs-watchos.xml new file mode 100644 index 000000000000..0e8a78f7adfd --- /dev/null +++ b/tests/link sdk/extra-linker-defs-watchos.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/link sdk/extra-linker-defs.xml b/tests/link sdk/extra-linker-defs.xml new file mode 100644 index 000000000000..f102f5906ae5 --- /dev/null +++ b/tests/link sdk/extra-linker-defs.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/link sdk/link sdk.csproj b/tests/link sdk/link sdk.csproj new file mode 100644 index 000000000000..223a20565e8f --- /dev/null +++ b/tests/link sdk/link sdk.csproj @@ -0,0 +1,123 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linksdk + link sdk + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + __MOBILE__;__IOS__;DEBUG; + prompt + 4 + False + True + + + -v -v -disable-thread-check -xml=${ProjectDir}/extra-linker-defs.xml + i386 + + + none + False + bin\iPhoneSimulator\Release + prompt + 4 + False + -v -v -xml=${ProjectDir}/extra-linker-defs.xml + + + i386 + __MOBILE__;__IOS__;DO_NOT_REMOVE; + + + True + full + False + bin\iPhone\Debug + DEBUG;XAMARIN_APPLETLS; + prompt + 4 + False + True + iPhone Developer + -v -v -xml=${ProjectDir}/extra-linker-defs.xml "--dlsym:-link sdk" + True + ARMv7 + true + + + none + False + bin\iPhone\Release + prompt + 4 + False + iPhone Developer + -v -v -xml=${ProjectDir}/extra-linker-defs.xml "--dlsym:-link sdk" + True + ARMv7 + + + DO_NOT_REMOVE;XAMARIN_APPLETLS; + + + + + + + + + + + + support.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D} + BundledResources + + + + \ No newline at end of file diff --git a/tests/link sdk/support.dll b/tests/link sdk/support.dll new file mode 100644 index 000000000000..df2e52773a36 Binary files /dev/null and b/tests/link sdk/support.dll differ diff --git a/tests/link sdk/support.il b/tests/link sdk/support.il new file mode 100644 index 000000000000..67dd10d130fd --- /dev/null +++ b/tests/link sdk/support.il @@ -0,0 +1,11 @@ +// ilasm -dll support.il + +.assembly support { } + +.class public support { + .method static public void throw_object () { + newobj instance void class [mscorlib]System.Object::'.ctor'() + throw + ret + } +} diff --git a/tests/mac-api-sharpie/Makefile b/tests/mac-api-sharpie/Makefile new file mode 100644 index 000000000000..4d41391dfb36 --- /dev/null +++ b/tests/mac-api-sharpie/Makefile @@ -0,0 +1,22 @@ +TOP = ../.. + +include $(TOP)/Make.config +include $(TOP)/mk/rules.mk + +SHARPIE_INSTALLED = $(shell which sharpie) + +clean-local:: + @rm -rf ./build + +ifeq ($(SHARPIE_INSTALLED),) +$(warning Sharpie not installed, skipping test.) +all-local:: +else +all-local:: + mkdir -p build + rm -rf ./build/SDKs + sharpie sdk-db -sdk macosx10.10 -o build/SDKs -arch x86_64 + cd src; nuget restore -PackagesDirectory ../build/test/packages -NonInteractive + xbuild src/test.csproj + sharpie ./build/test/Sharpie.APITestTool.dll APITest build/SDKs/macosx10.10-x86_64.pch $(TOP)/_mac-build/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/x86_64/mobile/Xamarin.Mac.dll +endif diff --git a/tests/mac-api-sharpie/src/Helpers.cs b/tests/mac-api-sharpie/src/Helpers.cs new file mode 100644 index 000000000000..0459548e8095 --- /dev/null +++ b/tests/mac-api-sharpie/src/Helpers.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; + +namespace Extrospection { + + // Stolen from Sebastien's introspection work because it is awesome + public static class Helpers { + + // the original name can be lost and, if not registered (e.g. enums), might not be available + static Dictionary map = new Dictionary () { + { "GKErrorCode", "GKError" }, + { "HMCharacteristicValueLockMechanismLastKnownAction", "HMCharacteristicValueLockMechanism" }, + { "HMErrorCode", "HMError" }, + { "LAError", "LAStatus" }, + { "MCErrorCode", "MCError" }, + { "MTLCPUCacheMode", "MTLCpuCacheMode" }, + { "NEVPNError", "NEVpnError" }, + { "NEVPNIKEAuthenticationMethod", "NEVpnIkeAuthenticationMethod" }, + { "NEVPNIKEv2CertificateType", "NEVpnIke2CertificateType" }, + { "NEVPNIKEv2DeadPeerDetectionRate", "NEVpnIke2DeadPeerDetectionRate" }, + { "NEVPNIKEv2DiffieHellmanGroup", "NEVpnIke2DiffieHellman" }, + { "NEVPNIKEv2EncryptionAlgorithm", "NEVpnIke2EncryptionAlgorithm" }, + { "NEVPNIKEv2IntegrityAlgorithm", "NEVpnIke2IntegrityAlgorithm" }, + { "NEVPNStatus", "NEVpnStatus" }, + { "NSLineBreakMode", "UILineBreakMode" }, + { "NSTextAlignment", "UITextAlignment" }, + { "NSURLBookmarkCreationOptions", "NSUrlBookmarkCreationOptions" }, + { "NSURLBookmarkResolutionOptions", "NSUrlBookmarkResolutionOptions" }, + { "NSURLCacheStoragePolicy", "NSUrlCacheStoragePolicy" }, + { "NSURLCredentialPersistence", "NSUrlCredentialPersistence" }, + { "NSURLRelationship", "NSUrlRelationship" }, + { "NSURLRequestCachePolicy", "NSUrlRequestCachePolicy" }, + { "NSURLRequestNetworkServiceType", "NSUrlRequestNetworkServiceType" }, + { "NSURLSessionAuthChallengeDisposition", "NSUrlSessionAuthChallengeDisposition" }, + { "NSURLSessionResponseDisposition", "NSUrlSessionResponseDisposition" }, + { "NSURLSessionTaskState", "NSUrlSessionTaskState" }, + { "SSReadingListErrorCode", "SSReadingListError" }, + { "UIDataDetectorTypes", "UIDataDetectorType" }, + { "WatchKitErrorCode", "WKErrorCode" }, // WebKit already had that name + }; + + public static string GetManagedName (string nativeName) + { + string result; + map.TryGetValue (nativeName, out result); + return result ?? nativeName; + } + } +} + diff --git a/tests/mac-api-sharpie/src/PropertyArgumentSemanticVisitor.cs b/tests/mac-api-sharpie/src/PropertyArgumentSemanticVisitor.cs new file mode 100644 index 000000000000..230f3f843945 --- /dev/null +++ b/tests/mac-api-sharpie/src/PropertyArgumentSemanticVisitor.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; + +using Clang; +using Clang.Ast; + +using Sharpie; +using Sharpie.Tooling; +using Sharpie.Bind; +using Sharpie.Mono.CSharp; + + +namespace APITestTool +{ + class PropertyArgumentSemanticVisitor : TestVistorBase + { + protected int GetArgumentSemantic (MethodInfo p) + { + if (p == null) + return 0; + + System.Attribute attr = System.Attribute.GetCustomAttributes (p).FirstOrDefault (x => x.GetType().Name == "ExportAttribute"); + if (attr != null) + return (int)attr.GetType().GetProperty("ArgumentSemantic").GetValue(attr, null); + return 0; + } + + void ReportError (string typeName, string propertyName, int managedSetSemantic, ObjCPropertySetterKind nativeSetSemantic) + { + Console.WriteLine ("Possibly Incorrect Managed ArgumentSemantic: {0} on {1} has {2} but native value is {3}", propertyName, typeName, managedSetSemantic, nativeSetSemantic); + } + + public override void VisitObjCPropertyDecl (ObjCPropertyDecl decl) + { + if (currentInterfaceDecl == null || currentType == null) + return; + + PropertyInfo managedProperty = FindProperty (decl); + if (managedProperty == null) + return; + + bool nativeHasSetter = decl.Setter != null; + bool managedHasSetter = managedProperty.CanWrite; + + if (nativeHasSetter && managedHasSetter) { + ObjCPropertySetterKind nativeSetSemantic = decl.SetterKind; + + // Read as int so we don't have to depend on XM assembly for type + // public enum ArgumentSemantic : int { + // None = -1, + // Assign = 0, + // Copy = 1, + // Retain = 2, + // Weak = 3, + // Strong = Retain, + // UnsafeUnretained = Assign, + // } + int managedSetSemantic = GetArgumentSemantic (managedProperty.GetSetMethod ()); + + // If our data type is string or string [], we _better_ be Copy on the native side. + // Since we copy to/from .NET strings, ignore these to reduce noise + if (nativeSetSemantic == ObjCPropertySetterKind.Copy && + (managedProperty.PropertyType == typeof (string) || managedProperty.PropertyType == typeof (string []))) + return; + + switch (nativeSetSemantic) + { + case ObjCPropertySetterKind.Assign: + if (managedSetSemantic != 0 && managedSetSemantic != -1) // None maps to Assign + ReportError (currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); + break; + case ObjCPropertySetterKind.Retain: + if (managedSetSemantic != 2) + ReportError (currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); + break; + case ObjCPropertySetterKind.Copy: + if (managedSetSemantic != 1) + ReportError (currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); + break; + case ObjCPropertySetterKind.Weak: + if (managedSetSemantic != 3) + ReportError (currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); + break; + default: + throw new InvalidOperationException (string.Format ("PropertyArgumentSemanticVisitor - Unknown semantic")); + } + } + } + } +} \ No newline at end of file diff --git a/tests/mac-api-sharpie/src/PropertyGetSetMismatchVisitor.cs b/tests/mac-api-sharpie/src/PropertyGetSetMismatchVisitor.cs new file mode 100644 index 000000000000..dd87ec90b6a1 --- /dev/null +++ b/tests/mac-api-sharpie/src/PropertyGetSetMismatchVisitor.cs @@ -0,0 +1,173 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; + +using Clang; +using Clang.Ast; + +using Sharpie; +using Sharpie.Tooling; +using Sharpie.Bind; +using Sharpie.Mono.CSharp; + + +namespace APITestTool +{ + class PropertyGetSetMismatchVisitor : TestVistorBase + { + bool Skip (PropertyInfo managedProperty) + { + switch (currentType.Name) { + case "NSData": + if (managedProperty.Name == "Length") + return true; + return false; + case "NSObjectController": + case "NSTreeController": + if (managedProperty.Name == "SelectedObjects") + return true; + return false; + case "AVComposition": + if (managedProperty.Name == "NaturalSize") + return true; + return false; + case "AVVideoComposition": + if (managedProperty.Name == "CustomVideoCompositorClass") + return true; + return false; + case "AVVideoCompositionInstruction": + switch (managedProperty.Name) + { + case "TimeRange": + case "LayerInstructions": + case "EnablePostProcessing": + return true; + default: + return false; + } + case "AVMetadataItem": + switch (managedProperty.Name) + { + case "MetadataIdentifier": + case "ExtendedLanguageTag": + case "Locale": + case "Time": + case "Duration": + case "DataType": + case "Value": + case "ExtraAttributes": + return true; + default: + return false; + } + case "AVTimedMetadataGroup": + switch (managedProperty.Name) + { + case "TimeRange": + case "Items": + return true; + default: + return false; + } + case "CBService": + switch (managedProperty.Name) + { + case "Primary": + case "IncludedServices": + case "Characteristics": + return true; + default: + return false; + } + case "CBCharacteristic": + switch (managedProperty.Name) + { + case "UUID": + case "Properties": + case "Value": + case "Descriptors": + return true; + default: + return false; + } + case "GKAchievement": + if (managedProperty.Name == "LastReportedDate") + return true; + return false; + case "GKLeaderboard": + if (managedProperty.Name == "GroupIdentifier") + return true; + return false; + case "SKPayment": + if (managedProperty.Name == "RequestData") + return true; + return false; + case "NSParagraphStyle": + switch (managedProperty.Name) + { + case "Alignment": + case "BaseWritingDirection": + case "DefaultTabInterval": + case "FirstLineHeadIndent": + case "HeadIndent": + case "HeaderLevel": + case "HyphenationFactor": + case "LineBreakMode": + case "LineHeightMultiple": + case "LineSpacing": + case "MaximumLineHeight": + case "MinimumLineHeight": + case "ParagraphSpacing": + case "ParagraphSpacingBefore": + case "TabStops": + case "TailIndent": + case "TextBlocks": + case "TextLists": + case "TighteningFactorForTruncation": + return true; + default: + return false; + } + } + return false; + } + + void CheckPropertyStatus (bool hasNative, bool hasManaged, PropertyInfo managedProperty, string propertyErrorString) + { + if (hasNative != hasManaged) { + // If they don't match, we have two cases. + // Native has, we don't - Missing binding warning. + // Native doesn't have but managed does? Either: + // Has NotImplemented in binding (which we can't tell easily without walking generated code for thrown exception) + // An actual binding bug. We use a Skip list of manually verified properites + if (hasNative) { + throw new InvalidOperationException (string.Format("Possible missing binding - {0}", propertyErrorString)); + } + else { + if (!Skip (managedProperty)) + throw new InvalidOperationException (string.Format("Possible binding bug - {0}", propertyErrorString)); + } + } + } + + public override void VisitObjCPropertyDecl (ObjCPropertyDecl decl) + { + if (currentInterfaceDecl == null || currentType == null) + return; + + PropertyInfo managedProperty = FindProperty (decl); + if (managedProperty == null) + return; + + bool nativeHasGetter = decl.Getter != null; + bool nativeHasSetter = decl.Setter != null; + bool managedHasGetter = managedProperty.CanRead; + bool managedHasSetter = managedProperty.CanWrite; + CheckPropertyStatus (nativeHasGetter, managedHasGetter, managedProperty, string.Format ("{0} getter on {1}", decl, currentType.Name)); + CheckPropertyStatus (nativeHasSetter, managedHasSetter, managedProperty, string.Format ("{0} setter on {1}", decl, currentType.Name)); + } + } +} \ No newline at end of file diff --git a/tests/mac-api-sharpie/src/packages.config b/tests/mac-api-sharpie/src/packages.config new file mode 100644 index 000000000000..265cffbb78da --- /dev/null +++ b/tests/mac-api-sharpie/src/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tests/mac-api-sharpie/src/test.cs b/tests/mac-api-sharpie/src/test.cs new file mode 100644 index 000000000000..1e07449eaa27 --- /dev/null +++ b/tests/mac-api-sharpie/src/test.cs @@ -0,0 +1,101 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; + +using Clang; +using Clang.Ast; + +using Sharpie; +using Sharpie.Tooling; +using Sharpie.Bind; +using Sharpie.Mono.CSharp; + +namespace APITestTool +{ + [Tool ("APITest", "Test built Xamarin.Mac assembly against the headers", 500)] + public class APITestTool : CommonTool + { + public static Assembly XamarinMacAssembly { get; private set; } + + protected override void Run () + { + base.Run (); + + var pchFile = PositionalArguments.DequeueOrDefault (); + string xmPath = PositionalArguments.DequeueOrDefault (); + + if (pchFile == null || !File.Exists (pchFile)) + throw new ExitException ("PCH file must be specified"); + + if (xmPath == null || !File.Exists (xmPath)) + throw new ExitException ("Xamarin.Mac Assembly must be specified"); + + XamarinMacAssembly = Assembly.LoadFrom (xmPath); + if (XamarinMacAssembly == null) + throw new ExitException ("Unable to load Xamarin.Mac Assembly"); + + var reader = new AstReader (); + reader.TranslationUnitParsed += tu => tu.Accept (new PropertyGetSetMismatchVisitor ()); + reader.TranslationUnitParsed += tu => tu.Accept (new PropertyArgumentSemanticVisitor ()); + + if (!reader.Load (pchFile)) + throw new ExitException ("PCH file failed to load"); + } + } + + class TestVistorBase : AstVisitor + { + protected ObjCInterfaceDecl currentInterfaceDecl; + protected System.Type currentType; + + protected bool IsPrivate (string typeName) + { + // Let's skip anything that looks internal to test against + return typeName.Contains ("Private") || typeName.Contains ("Internal") || typeName.StartsWith ("_"); + } + + public override void VisitObjCInterfaceDecl (ObjCInterfaceDecl decl, VisitKind visitKind) + { + if (visitKind == VisitKind.Enter && !IsPrivate (decl.Name)) { + currentInterfaceDecl = decl; + currentType = APITestTool.XamarinMacAssembly.GetTypes ().FirstOrDefault (x => x.Name == Extrospection.Helpers.GetManagedName(decl.Name)); // Technically SingleOrDefault, but significantly slower + + // If we couldn't match up a type, we're going to skip testing for now. + if (currentType == null) + currentInterfaceDecl = null; + } + else { + currentInterfaceDecl = null; + currentType = null; + } + } + + protected string GetSelector (MethodInfo p) + { + if (p == null) + return null; + + System.Attribute attr = System.Attribute.GetCustomAttributes (p).FirstOrDefault (x => x.GetType().Name == "ExportAttribute"); + if (attr != null) + return (string)attr.GetType().GetProperty("Selector").GetValue(attr, null); + return null; + } + + protected PropertyInfo FindProperty (ObjCPropertyDecl prop) + { + string getNativeSelector = prop.Getter != null ? prop.Getter.Name : null; + string setNativeSelector = prop.Setter != null ? prop.Setter.Name : null; + foreach (PropertyInfo p in currentType.GetProperties ()) + { + string getManagedSelector = GetSelector (p.GetGetMethod ()); + string setManagedSelector = GetSelector (p.GetSetMethod ()); + if (getNativeSelector == getManagedSelector && setNativeSelector == setManagedSelector) + return p; + } + return null; + } + } +} diff --git a/tests/mac-api-sharpie/src/test.csproj b/tests/mac-api-sharpie/src/test.csproj new file mode 100644 index 000000000000..10220051ef30 --- /dev/null +++ b/tests/mac-api-sharpie/src/test.csproj @@ -0,0 +1,75 @@ + + + + Debug + x86 + {82712260-B857-4711-9830-4E9DAFD938BF} + Library + Sharpie.APITestTool + Sharpie.APITestTool + v4.5 + 8.0.30703 + 2.0 + + + true + full + false + ..\build\test + ..\build\test\obj + DEBUG; + prompt + 4 + x86 + false + + + + + \Library\Frameworks\ObjectiveSharpie.framework\Versions\Current\Clang.dll + + + \Library\Frameworks\ObjectiveSharpie.framework\Versions\Current\Sharpie.Core.dll + + + \Library\Frameworks\ObjectiveSharpie.framework\Versions\Current\Sharpie.Bind.dll + + + \Library\Frameworks\ObjectiveSharpie.framework\Versions\Current\Mono.CSharp.dll + + + ..\build\test\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.dll + + + ..\build\test\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.Mdb.dll + + + ..\build\test\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.Pdb.dll + + + ..\build\test\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.Rocks.dll + + + ..\build\test\packages\ICSharpCode.NRefactory.5.5.0\lib\Net40\ICSharpCode.NRefactory.dll + + + ..\build\test\packages\ICSharpCode.NRefactory.5.5.0\lib\Net40\ICSharpCode.NRefactory.Cecil.dll + + + ..\build\test\packages\ICSharpCode.NRefactory.5.5.0\lib\Net40\ICSharpCode.NRefactory.CSharp.dll + + + ..\build\test\packages\ICSharpCode.NRefactory.5.5.0\lib\Net40\ICSharpCode.NRefactory.Xml.dll + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/mac-binding-project/Makefile b/tests/mac-binding-project/Makefile new file mode 100644 index 000000000000..35463218b02f --- /dev/null +++ b/tests/mac-binding-project/Makefile @@ -0,0 +1,90 @@ +TOP=../../../xamarin-macios +include $(TOP)/Make.config + +export MD_APPLE_SDK_ROOT=$(shell dirname `dirname $(XCODE_DEVELOPER_ROOT)`) +export XBUILD_FRAMEWORK_FOLDERS_PATH=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks +export MSBuildExtensionsPath=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild +export XamarinMacFrameworkRoot=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current +export XAMMAC_FRAMEWORK_PATH=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current + +obj/SimpleClass.o: + $(Q) mkdir -p bin obj + $(Q) clang -c ../common/mac/SimpleClass.m -o obj/SimpleClass.o -std=gnu99 -mmacosx-version-min=10.9 + +bin/SimpleClassDylib.dylib: obj/SimpleClass.o + $(Q) xcrun libtool -dynamic obj/SimpleClass.o -o bin/SimpleClassDylib.dylib -framework Cocoa -lSystem -macosx_version_min 10.9 + +bin/SimpleClass\ Dylib.dylib: bin/SimpleClassDylib.dylib + $(Q) cp bin/SimpleClassDylib.dylib bin/SimpleClass\ Dylib.dylib + +bin/SimpleClassStatic.a: obj/SimpleClass.o + $(Q) xcrun libtool -static obj/SimpleClass.o -o bin/SimpleClassStatic.a + +bin/Mobile-dynamic/MobileBinding.dll: bin/SimpleClassDylib.dylib + $(Q) xbuild MobileBinding/MobileBinding_dynamic.csproj /verbosity:quiet /nologo + +bin/Mobile-dynamic-newstyle/MobileBinding.dll: bin/SimpleClassDylib.dylib + $(Q) xbuild MobileBinding/MobileBinding_dynamic_newstyle.csproj /verbosity:quiet /nologo + +bin/Mobile-dynamic-spaces/Mobile\ Binding.dll: bin/SimpleClass\ Dylib.dylib + $(Q) xbuild MobileBinding/MobileBinding_dynamic_spaces.csproj /verbosity:quiet /nologo + +bin/Mobile-static/MobileBinding.dll: bin/SimpleClassStatic.a + $(Q) xbuild MobileBinding/MobileBinding_static.csproj /verbosity:quiet /nologo + +bin/Mobile-static-newstyle/MobileBinding.dll: bin/SimpleClassStatic.a + $(Q) xbuild MobileBinding/MobileBinding_static_newstyle.csproj /verbosity:quiet /nologo + + +bin/Mobile-framework/MobileBinding.dll: + $(Q) xbuild MobileBinding/MobileBinding_framework.csproj /verbosity:quiet /nologo + + +bin/MobileTest-static/MobileTestApp.app: bin/Mobile-static/MobileBinding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_static.csproj /verbosity:quiet /nologo + +bin/MobileTest-static-newstyle/MobileTestApp.app: bin/Mobile-static-newstyle/MobileBinding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_static_newstyle.csproj /verbosity:quiet /nologo + +bin/MobileTest-withLinker/MobileTestApp.app: bin/Mobile-static/MobileBinding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_WithLinker.csproj /verbosity:quiet /nologo + +bin/MobileTest-dynamic/MobileTestApp.app: bin/Mobile-dynamic/MobileBinding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_dynamic.csproj /verbosity:quiet /nologo + +bin/MobileTest-dynamic-newstyle/MobileTestApp.app: bin/Mobile-dynamic-newstyle/MobileBinding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_dynamic_newstyle.csproj /verbosity:quiet /nologo + +bin/MobileTest-dynamic-spaces/MobileTestApp.app: bin/Mobile-dynamic-spaces/Mobile\ Binding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_dynamic_spaces.csproj /verbosity:quiet /nologo + +bin/MobileTest-framework/MobileTestApp.app: bin/Mobile-framework/MobileBinding.dll + $(Q) xbuild MobileTestApp/MobileTestApp_framework.csproj /verbosity:quiet /nologo + + + + +test-static:: bin/MobileTest-static/MobileTestApp.app bin/MobileTest-static-newstyle/MobileTestApp.app + $(Q) ./bin/MobileTest-static/MobileTestApp.app/Contents/MacOS/MobileTestApp 2>&1 | grep 42 > /dev/null + $(Q) ./bin/MobileTest-static-newstyle/MobileTestApp.app/Contents/MacOS/MobileTestApp 2>&1 | grep 42 > /dev/null + +test-dynamic:: bin/MobileTest-dynamic/MobileTestApp.app bin/MobileTest-dynamic-newstyle/MobileTestApp.app bin/MobileTest-dynamic-spaces/MobileTestApp.app + $(Q) ./bin/MobileTest-dynamic/MobileTestApp.app/Contents/MacOS/MobileTestApp 2>&1 | grep 42 > /dev/null + $(Q) test -e bin/MobileTest-dynamic/MobileTestApp.app/Contents/MonoBundle/SimpleClassDylib.dylib + $(Q) ./bin/MobileTest-dynamic-newstyle/MobileTestApp.app/Contents/MacOS/MobileTestApp 2>&1 | grep 42 > /dev/null + $(Q) test -e bin/MobileTest-dynamic-newstyle/MobileTestApp.app/Contents/MonoBundle/SimpleClassDylib.dylib + $(Q) ./bin/MobileTest-dynamic-spaces/MobileTestApp.app/Contents/MacOS/MobileTestApp 2>&1 | grep 42 > /dev/null + $(Q) test -e bin/MobileTest-dynamic-spaces/MobileTestApp.app/Contents/MonoBundle/SimpleClass\ Dylib.dylib + +test-framework:: bin/MobileTest-framework/MobileTestApp.app + $(Q) test -e bin/MobileTest-framework/MobileTestApp.app/Contents/Frameworks/iTunesLibrary.framework + +test-withLinker:: bin/MobileTest-withLinker/MobileTestApp.app + $(Q) ./bin/MobileTest-withLinker/MobileTestApp.app/Contents/MacOS/MobileTestApp 2>&1 | grep 42 > /dev/null + + + +all-local:: test-static test-dynamic test-framework test-withLinker + +clean-local:: + $(Q) rm -rf ./bin ./obj diff --git a/tests/mac-binding-project/MobileBinding/ApiDefinition.cs b/tests/mac-binding-project/MobileBinding/ApiDefinition.cs new file mode 100644 index 000000000000..026454f457d4 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/ApiDefinition.cs @@ -0,0 +1,9 @@ +using Foundation; + +namespace Simple { + [BaseType (typeof (NSObject))] + interface SimpleClass { + [Export ("doIt")] + int DoIt (); + } +} \ No newline at end of file diff --git a/tests/mac-binding-project/MobileBinding/Framework.linkwith.cs b/tests/mac-binding-project/MobileBinding/Framework.linkwith.cs new file mode 100644 index 000000000000..8c25cdb1c16a --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/Framework.linkwith.cs @@ -0,0 +1,3 @@ +using ObjCRuntime; + +[assembly: LinkWith ("iTunesLibrary.framework", SmartLink = true, ForceLoad = true)] diff --git a/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic.csproj b/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic.csproj new file mode 100644 index 000000000000..37fee389cad1 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic.csproj @@ -0,0 +1,46 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9B2BCC27-4807-4EF4-AA60-8D890AFAB9A5} + Library + MobileBinding + Resources + MobileBinding + + + true + full + false + ..\bin\Mobile-dynamic\ + ../obj/Mobile-dynamic/ + DEBUG; + prompt + 4 + false + + + + + + + + + + + + + + + + SimpleClassDylib.dylib + + + + + SimpleClassDylib.dylib + + + diff --git a/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic_newstyle.csproj b/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic_newstyle.csproj new file mode 100644 index 000000000000..815eb7f47067 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic_newstyle.csproj @@ -0,0 +1,44 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9B2BCC27-4807-4EF4-AA60-8D890AFAB9A5} + Library + MobileBinding + Resources + MobileBinding + + + true + full + false + ..\bin\Mobile-dynamic-newstyle\ + ../obj/Mobile-dynamic-newstyle/ + DEBUG; + prompt + 4 + false + + + + + + + + + + + + + + + + SimpleClassDylib.dylib + Dynamic + True + True + + + diff --git a/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic_spaces.csproj b/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic_spaces.csproj new file mode 100644 index 000000000000..3248ce176708 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/MobileBinding_dynamic_spaces.csproj @@ -0,0 +1,46 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9B2BCC27-4807-4EF4-AA60-8D890AFAB9A5} + Library + MobileBinding + Resources + Mobile Binding + + + true + full + false + ..\bin\Mobile-dynamic-spaces\ + ../obj/Mobile-dynamic-spaces/ + DEBUG; + prompt + 4 + false + + + + + + + + + + + + + + + + SimpleClass Dylib.dylib + + + + + SimpleClass Dylib.dylib + + + diff --git a/tests/mac-binding-project/MobileBinding/MobileBinding_framework.csproj b/tests/mac-binding-project/MobileBinding/MobileBinding_framework.csproj new file mode 100644 index 000000000000..f02581c1b9fc --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/MobileBinding_framework.csproj @@ -0,0 +1,44 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9B2BCC27-4807-4EF4-AA60-8D890AFAB9A5} + Library + MobileBinding + Resources + MobileBinding + + + true + full + false + ..\bin\Mobile-framework\ + ../obj/Mobile-framework/ + DEBUG; + prompt + 4 + false + + + + + + + + + + + + + + + + /Library/Frameworks/iTunesLibrary.framework + Framework + True + True + + + diff --git a/tests/mac-binding-project/MobileBinding/MobileBinding_static.csproj b/tests/mac-binding-project/MobileBinding/MobileBinding_static.csproj new file mode 100644 index 000000000000..422d1113fa85 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/MobileBinding_static.csproj @@ -0,0 +1,46 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9B2BCC27-4807-4EF4-AA60-8D890AFAB9A5} + Library + MobileBinding + Resources + MobileBinding + + + true + full + false + ..\bin\Mobile-static\ + ../obj/Mobile-static/ + DEBUG; + prompt + 4 + false + + + + + + + + + + + + + + + + SimpleClassStatic.a + + + + + SimpleClassStatic.a + + + diff --git a/tests/mac-binding-project/MobileBinding/MobileBinding_static_newstyle.csproj b/tests/mac-binding-project/MobileBinding/MobileBinding_static_newstyle.csproj new file mode 100644 index 000000000000..bc6171d6ff26 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/MobileBinding_static_newstyle.csproj @@ -0,0 +1,44 @@ + + + + Debug + AnyCPU + {810C163F-4746-4721-8B8E-88A3673A62EA};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9B2BCC27-4807-4EF4-AA60-8D890AFAB9A5} + Library + MobileBinding + Resources + MobileBinding + + + true + full + false + ..\bin\Mobile-static-newstyle\ + ../obj/Mobile-static-newstyle/ + DEBUG; + prompt + 4 + false + + + + + + + + + + + + + + + + SimpleClassStatic.a + Static + True + True + + + diff --git a/tests/mac-binding-project/MobileBinding/SimpleClassDynamic.linkwith.cs b/tests/mac-binding-project/MobileBinding/SimpleClassDynamic.linkwith.cs new file mode 100644 index 000000000000..a239cdbfbe12 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/SimpleClassDynamic.linkwith.cs @@ -0,0 +1,3 @@ +using ObjCRuntime; + +[assembly: LinkWith ("SimpleClassDylib.dylib", SmartLink = true, ForceLoad = true)] diff --git a/tests/mac-binding-project/MobileBinding/SimpleClassDynamic_spaces.linkwith.cs b/tests/mac-binding-project/MobileBinding/SimpleClassDynamic_spaces.linkwith.cs new file mode 100644 index 000000000000..d9fe8adf58d3 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/SimpleClassDynamic_spaces.linkwith.cs @@ -0,0 +1,3 @@ +using ObjCRuntime; + +[assembly: LinkWith ("SimpleClass Dylib.dylib", SmartLink = true, ForceLoad = true)] diff --git a/tests/mac-binding-project/MobileBinding/SimpleClassStatic.linkwith.cs b/tests/mac-binding-project/MobileBinding/SimpleClassStatic.linkwith.cs new file mode 100644 index 000000000000..680c5a27d2b2 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/SimpleClassStatic.linkwith.cs @@ -0,0 +1,3 @@ +using ObjCRuntime; + +[assembly: LinkWith ("SimpleClassStatic.a", SmartLink = true, ForceLoad = true)] diff --git a/tests/mac-binding-project/MobileBinding/StructsAndEnums.cs b/tests/mac-binding-project/MobileBinding/StructsAndEnums.cs new file mode 100644 index 000000000000..1d1a0a2df088 --- /dev/null +++ b/tests/mac-binding-project/MobileBinding/StructsAndEnums.cs @@ -0,0 +1,6 @@ +using System; +using ObjCRuntime; + +namespace MobileBinding +{ +} diff --git a/tests/mac-binding-project/MobileTestApp/Info.plist b/tests/mac-binding-project/MobileTestApp/Info.plist new file mode 100644 index 000000000000..dbbf5dd1111b --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleName + MobileTestApp + CFBundleIdentifier + com.companyname.mobiletestapp + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + CFBundleDevelopmentRegion + en + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + NSHumanReadableCopyright + donblas + NSPrincipalClass + NSApplication + NSMainNibFile + MainMenu + XSAppIconAssets + Resources/Images.xcassets/AppIcons.appiconset + + + diff --git a/tests/mac-binding-project/MobileTestApp/Main.cs b/tests/mac-binding-project/MobileTestApp/Main.cs new file mode 100644 index 000000000000..8b3c15f3b70c --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/Main.cs @@ -0,0 +1,30 @@ +using System; +using System.Reflection; +using System.IO; + +using AppKit; +using Simple; + +namespace MobileTestApp +{ + static class MainClass + { + // http://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in + public static string GetCurrentExecutingDirectory() + { + string filePath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath; + return Path.GetDirectoryName(filePath); + } + + static void Main (string[] args) + { +#pragma warning disable 0219 + var v = ObjCRuntime.Dlfcn.dlopen (GetCurrentExecutingDirectory () + "/SimpleClass.dylib", 0); +#pragma warning restore 0219 + + NSApplication.Init (); + SimpleClass c = new SimpleClass (); + Console.WriteLine (c.DoIt()); + } + } +} diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_WithLinker.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_WithLinker.csproj new file mode 100644 index 000000000000..e98a0912ef4c --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_WithLinker.csproj @@ -0,0 +1,53 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-withLinker\ + ../bin/MobileTest-withLinker/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + Full + x86_64 + + + + + + + ..\bin\Mobile-static\MobileBinding.dll + + + + + + + + + + diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic.csproj new file mode 100644 index 000000000000..414013807fa2 --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-dynamic\ + ../bin/MobileTest-dynamic/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + + + + + + + ..\bin\Mobile-dynamic\MobileBinding.dll + + + + + + + + + + diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic_newstyle.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic_newstyle.csproj new file mode 100644 index 000000000000..e4ce02099b73 --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic_newstyle.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-dynamic-newstyle\ + ../bin/MobileTest-dynamic-newstyle/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + + + + + + + ..\bin\Mobile-dynamic-newstyle\MobileBinding.dll + + + + + + + + + + diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic_spaces.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic_spaces.csproj new file mode 100644 index 000000000000..f544b8db7171 --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_dynamic_spaces.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-dynamic-spaces\ + ../bin/MobileTest-dynamic-spaces/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + + + + + + + ..\bin\Mobile-dynamic-spaces\Mobile Binding.dll + + + + + + + + + + diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_framework.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_framework.csproj new file mode 100644 index 000000000000..b474874e7e3a --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_framework.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-framework\ + ../bin/MobileTest-framework/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + + + + + + + ..\bin\Mobile-framework\MobileBinding.dll + + + + + + + + + + diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_static.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_static.csproj new file mode 100644 index 000000000000..eef653b677b0 --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_static.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-static\ + ../bin/MobileTest-static/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + + + + + + + ..\bin\Mobile-static\MobileBinding.dll + + + + + + + + + + diff --git a/tests/mac-binding-project/MobileTestApp/MobileTestApp_static_newstyle.csproj b/tests/mac-binding-project/MobileTestApp/MobileTestApp_static_newstyle.csproj new file mode 100644 index 000000000000..55d7fd71fa44 --- /dev/null +++ b/tests/mac-binding-project/MobileTestApp/MobileTestApp_static_newstyle.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {3A4614D1-D366-49CE-9F01-B5FBD4A996AD} + Exe + MobileTestApp + Resources + MobileTestApp + v2.0 + Xamarin.Mac + 8.0.30703 + 2.0 + + + true + full + false + ..\bin\MobileTest-static-newstyle\ + ../bin/MobileTest-static-newstyle/ + DEBUG; + prompt + 4 + false + true + true + true + false + false + Mac Developer + false + false + + + + + + + ..\bin\Mobile-static-newstyle\MobileBinding.dll + + + + + + + + + + diff --git a/tests/mini/AppDelegate.cs b/tests/mini/AppDelegate.cs new file mode 100644 index 000000000000..4274c536c5b2 --- /dev/null +++ b/tests/mini/AppDelegate.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +using MonoTouch.NUnit.UI; +using NUnit.Framework; +using NUnit.Framework.Internal.Filters; + +namespace mini +{ + [TestFixture] + class JitTests { + static string[] args = new string[] { "--exclude", "!FULLAOT", "--verbose" }; + + [Test] + public static void Basic () { + int res = TestDriver.RunTests (typeof (BasicTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Arrays () { + int res = TestDriver.RunTests (typeof (ArrayTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Calls () { + int res = TestDriver.RunTests (typeof (CallsTests), args); + Assert.AreEqual (0, res); + } + [Test] + public static void Float () { + int res = TestDriver.RunTests (typeof (FloatTests), args); + Assert.AreEqual (0, res); + } + [Test] + public static void Long () { + int res = TestDriver.RunTests (typeof (LongTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Math () { + int res = TestDriver.RunTests (typeof (MathTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Objects () { + int res = TestDriver.RunTests (typeof (ObjectTests.Tests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Generics () { + int res = TestDriver.RunTests (typeof (GenericsTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void GShared () { + int res = TestDriver.RunTests (typeof (GSharedTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Exceptions () { + int res = TestDriver.RunTests (typeof (ExceptionTests), args); + Assert.AreEqual (0, res); + } + + [Test] + public static void Aot () { + int res = TestDriver.RunTests (typeof (AotTests), args); + Assert.AreEqual (0, res); + } + } + +#if !__WATCHOS__ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + // class-level declarations + UIWindow window; + TouchRunner runner; + + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + window = new UIWindow (UIScreen.MainScreen.Bounds); + runner = new TouchRunner (window); + + runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); + + window.RootViewController = new UINavigationController (runner.GetViewController ()); + window.MakeKeyAndVisible (); + + return true; + } + } +#endif +} + diff --git a/tests/mini/Info.plist b/tests/mini/Info.plist new file mode 100644 index 000000000000..91810a5244e5 --- /dev/null +++ b/tests/mini/Info.plist @@ -0,0 +1,28 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + MinimumOSVersion + 5.1.1 + CFBundleIdentifier + com.xamarin.mini + + diff --git a/tests/mini/Main.cs b/tests/mini/Main.cs new file mode 100644 index 000000000000..d23faf18f639 --- /dev/null +++ b/tests/mini/Main.cs @@ -0,0 +1,21 @@ +#if XAMCORE_2_0 +using UIKit; +#else +using MonoTouch.UIKit; +#endif + +namespace mini +{ + public class Application + { +#if !__WATCHOS__ + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } +#endif + } +} diff --git a/tests/mini/Makefile b/tests/mini/Makefile new file mode 100644 index 000000000000..6f41f9dc5142 --- /dev/null +++ b/tests/mini/Makefile @@ -0,0 +1,53 @@ + +LIB=mini + +ifneq ($(RELEASE),) +CONFIG=Release +else +CONFIG=Debug +endif + +ifeq ($(TV),1) +CSPROJ_CONFIG=tvos +TARGET_SUFFIX=tvos +else +CSPROJ_CONFIG=dual +TARGET_SUFFIX=dual +endif + +all: build-dev + +clean: clean-dev + +install: install-dev + +exec: exec-dev + +debug: debug-dev + +build-dev: + make -C .. build-ios-devunified-mini + +clean-dev: + make -C .. clean-ios-devunified-mini + $(RM) -r obj + +install-dev: + make -C .. install-ios-devunified-mini + +exec-dev: + make -C .. exec-ios-devunified-mini + +debug-dev: + fruitstrap debug --bundle bin/iPhone/$(CONFIG)X/mini.app --args "-app-arg:-autostart" + +build-%: + $(MAKE) -C .. $@-$(LIB) +run-%: + $(MAKE) -C .. $@-$(LIB) +exec-%: + $(MAKE) -C .. $@-$(LIB) +install-%: + $(MAKE) -C .. $@-$(LIB) +clean-%: + $(MAKE) -C .. $@-$(LIB) diff --git a/tests/mini/mini.csproj b/tests/mini/mini.csproj new file mode 100644 index 000000000000..403ad82c02b2 --- /dev/null +++ b/tests/mini/mini.csproj @@ -0,0 +1,121 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + mini + Resources + mini + DEBUG;MOBILE; + -unsafe + MonoTouch + + + true + false + bin\iPhoneSimulator\Debug + prompt + 4 + false + None + true + + + i386 + true + + + true + bin\iPhoneSimulator\Release + prompt + 4 + false + None + true + + + true + false + bin\iPhone\Debug + prompt + 4 + false + true + iPhone Developer + + + ARMv7 + --nostrip --nosymbolstrip: --aot-options=-O=float32 + true + + + true + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + true + --nostrip --nosymbolstrip: --aot-options=-O=float32 + ARMv7 + + + + + + + + + + + + + + + + + + + arrays.cs + + + basic-calls.cs + + + basic-float.cs + + + basic-long.cs + + + basic-math.cs + + + basic.cs + + + TestDriver.cs + + + generics.cs + + + gshared.cs + + + objects.cs + + + exceptions.cs + + + aot-tests.cs + + + + diff --git a/tests/misc/.gitignore b/tests/misc/.gitignore new file mode 100644 index 000000000000..be29770ae2bf --- /dev/null +++ b/tests/misc/.gitignore @@ -0,0 +1,3 @@ +*.exe +*.xml +*.mdb diff --git a/tests/misc/Makefile b/tests/misc/Makefile new file mode 100644 index 000000000000..e1a7d29049a6 --- /dev/null +++ b/tests/misc/Makefile @@ -0,0 +1,6 @@ +# These tests were removed in 76900f9f104302058f2bad6eed81089972909ee2 but we can't +# keep wrench from calling due to C5 right now. Just stub to empty +run run-test run-tests: + @/usr/bin/true +clean: + @/usr/bin/true diff --git a/tests/mmptest/.gitignore b/tests/mmptest/.gitignore new file mode 100644 index 000000000000..0cef782ba01b --- /dev/null +++ b/tests/mmptest/.gitignore @@ -0,0 +1,2 @@ +TestResult* +build/ diff --git a/tests/mmptest/CustomBuildActions.targets b/tests/mmptest/CustomBuildActions.targets new file mode 100644 index 000000000000..28b5e37cf5ab --- /dev/null +++ b/tests/mmptest/CustomBuildActions.targets @@ -0,0 +1,11 @@ + + + + + $(CreateAppBundleDependsOn);CreateNativeLibs + + + + + + diff --git a/tests/mmptest/Info.plist b/tests/mmptest/Info.plist new file mode 100644 index 000000000000..803c7af5e180 --- /dev/null +++ b/tests/mmptest/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleDisplayName + apitest + CFBundleIdentifier + com.xamarin.apitest + CFBundleName + apitest + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/Makefile b/tests/mmptest/Makefile new file mode 100644 index 000000000000..fb4045d579dd --- /dev/null +++ b/tests/mmptest/Makefile @@ -0,0 +1,30 @@ +TOP = ../.. + +all-local:: regression run + +bin/: + mkdir bin + +bin/SimpleClass.dylib: bin/ + @clang -dynamiclib -std=gnu99 ../common/mac/SimpleClass.m -current_version 1.0 -compatibility_version 1.0 -fvisibility=hidden -framework Cocoa -o bin/SimpleClass.dylib + +bin/SimpleClassStatic.a: bin/ + $(Q) clang -c ../common/mac/SimpleClass.m -o bin/SimpleClass.o -std=gnu99 -mmacosx-version-min=10.7 + $(Q) xcrun libtool -static bin/SimpleClass.o -o bin/SimpleClassStatic.a + +regression:: +ifneq ($(SKIP_REGRESSION), 1) + $(MAKE) -C regression/ +endif + +bin/x86/Debug/mmptest.app: + xbuild mmptest.csproj + +native-deps:: bin/SimpleClass.dylib bin/SimpleClassStatic.a + +run:: bin/ bin/x86/Debug/mmptest.app native-deps + bin/x86/Debug/mmptest.app/Contents/MacOS/mmptest + +clean-local:: + @rm -rf ./obj + @rm -rf ./bin diff --git a/tests/mmptest/mmptest.csproj b/tests/mmptest/mmptest.csproj new file mode 100644 index 000000000000..ec5b43527cbb --- /dev/null +++ b/tests/mmptest/mmptest.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + mmptest + mmptest + v2.0 + Xamarin.Mac + Resources + + + true + full + false + bin\x86\Debug + __UNIFIED__;DEBUG;XAMCORE_2_0;MONOMAC;MMP_TEST + prompt + 4 + false + false + Mac Developer + false + false + false + true + true + true + x86 + + + true + bin\x86\Release + __UNIFIED__;XAMCORE_2_0;MONOMAC;MMP_TEST + prompt + 4 + false + true + Developer ID Application + true + false + true + true + true + SdkOnly + x86 + + + + + + + ..\..\..\xamarin-macios\external\guiunit\bin\xammac_mobile\GuiUnit.exe + + + + + + + + + + + + MacTestMain.cs + + + ProjectTestHelpers.cs + + + Configuration.cs + + + ErrorHelper.cs + + + RuntimeException.cs + + + + + + + + + {EACFD119-769E-4E6C-89B7-A6CE3757C431} + GuiUnit_xammac_mobile + + + + + diff --git a/tests/mmptest/regression/.gitignore b/tests/mmptest/regression/.gitignore new file mode 100644 index 000000000000..ccb49916312f --- /dev/null +++ b/tests/mmptest/regression/.gitignore @@ -0,0 +1,3 @@ +*.mlpd +*.log +*.dylib diff --git a/tests/mmptest/regression/Makefile b/tests/mmptest/regression/Makefile new file mode 100644 index 000000000000..c546876718d2 --- /dev/null +++ b/tests/mmptest/regression/Makefile @@ -0,0 +1,111 @@ +TOP = ../../../../xamarin-macios + +include $(TOP)/Make.config + +MMP=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/bin/mmp + +export MD_APPLE_SDK_ROOT=$(shell dirname `dirname $(XCODE_DEVELOPER_ROOT)`) +export XBUILD_FRAMEWORK_FOLDERS_PATH=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks +export MSBuildExtensionsPath=$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild +export XamarinMacFrameworkRoot=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current + + +TESTS_4_0 = \ + link-gdiplus-1 \ + link-gdiplus-2 \ + link-posix-1 \ + link-posix-2 \ + link-system.web-icalls \ + link-keep-resources-1 \ + link-keep-resources-2 \ + link-preserve-assembly \ + link-uithread-1 \ + link-uithread-2 \ + link-safe-1 \ + link-frameworks-1 \ + link-aes-1 \ + link-blocks-1 \ + link-preserve-calendar-1 \ + link-preserve-calendar-2 \ + link-typedescriptor-1 \ + link-typedescriptor-2 \ + embedded-mono \ + system-mono \ + embedded-mono-profile \ + system-mono-profile \ + +DISABLED_TESTS_MONO_4_2 = \ + link-data-contract-1 \ + link-webclient-2 \ + link-xml-serialization \ + +DISABLED_TESTS_MONO_4_4 = \ + link-webclient-1 \ + link-webclient-3 \ + link-remove-attributes-1 + +TESTS_UNIFIED = \ + custom-bundle-name + +TESTS_4_5 = \ + link-callfilepath-45 \ + +DISABLED_4_5_TESTS_MONO_4_2 = \ + link-httpclient-async \ + +ALL_TESTS = \ + $(TESTS_UNIFIED) \ + $(TESTS_4_0) \ + $(TESTS_4_5) + +all-local:: run + +remove-license: + rm -f ~/Library/Xamarin.Mac/License.trial + rm -f ~/Library/Xamarin.Mac/License + +embedded-mono/bin system-mono/bin embedded-mono-profile/bin system-mono-profile/bin $(foreach test,$(TESTS_UNIFIED),$(test)/bin): dylib/libTest.dylib + DEVELOPER_DIR=$(XCODE_DEVELOPER_ROOT) XAMMAC_FRAMEWORK_PATH=$(abspath $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)) $(SYSTEM_XBUILD) $(@D)/$(@D).csproj + +%/bin: remove-license dylib/libTest.dylib + DEVELOPER_DIR=$(XCODE_DEVELOPER_ROOT) XAMMAC_FRAMEWORK_PATH=$(abspath $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)) $(MDTOOL) build $*/$*.csproj + +dylib/libTest.dylib: dylib/src.c + clang $< -o$@ -arch i386 -arch x86_64 -shared + +build: $(foreach test,$(ALL_TESTS),$(test)/bin) + +run run-test run-tests: + $(MAKE) clean + $(MAKE) build + $(MAKE) exec + +exec-system-mono-profile exec-embedded-mono-profile: export MONO_ENV_OPTIONS=--profile=log:noalloc,nocalls,output=-output.mlpd + +exec-%: + @echo Executing $*... | tee $*/$@.log + @test -z $(BUILD_REVISION) || echo @MonkeyWrench: AddFile: $(CURDIR)/$*/$@.log + @cd $* && if ! bin/Debug/$*.app/Contents/MacOS/$* >> $@.log 2>&1; then echo "CRASHED" >> $@.log; fi + @if grep -q FAIL $*/exec-$*.log; then echo "Test $* failed"; fi + @if grep -q CRASHED $*/exec-$*.log; then echo "Test $* crashed"; fi + @echo Executed $* | tee -a $*/$@.log + @echo "" >> $*/$@.log + +exec: $(foreach test,$(ALL_TESTS),exec-$(test)) + @cat */exec-*.log > tests.log + @cat tests.log + @if grep -q CRASHED tests.log; then \ + echo Test run crashed; \ + exit 1; \ + elif grep -q FAIL tests.log; then \ + echo Test run failed; \ + exit 1; \ + else \ + echo Test run succeeded; \ + fi + +clean: + @rm -f tests.log + @for i in $(ALL_TESTS); do \ + rm -rf $(PWD)/$$i/{bin,obj}/; \ + done diff --git a/tests/mmptest/regression/common/MainMenu.xib b/tests/mmptest/regression/common/MainMenu.xib new file mode 100644 index 000000000000..649ebf343fdf --- /dev/null +++ b/tests/mmptest/regression/common/MainMenu.xib @@ -0,0 +1,4074 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + link-webclient-2 + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + MacCocoaApp + + YES + + + About link-webclient-2 + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide link-webclient-2 + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit link-webclient-2 + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + link-webclient-2 Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + NSFontManager + + + AppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + delegate + + + + 534 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 496 + + + YES + + + + + + 497 + + + YES + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + YES + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + YES + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 533 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBEditorWindowLastContentRect + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 507.IBPluginDependency + 508.IBEditorWindowLastContentRect + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{453, 408}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{613, 618}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{346, 722}, {402, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{563, 648}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{497, 648}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{580, 408}, {175, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{684, 668}, {142, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{674, 260}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{878, 180}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{355, 508}, {183, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{411, 488}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 534 + + + + YES + + AppDelegate + NSResponder + + IBUserSource + + + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../MacCocoaApp.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/tests/mmptest/regression/common/Test.cs b/tests/mmptest/regression/common/Test.cs new file mode 100644 index 000000000000..512b41483028 --- /dev/null +++ b/tests/mmptest/regression/common/Test.cs @@ -0,0 +1,47 @@ +// Copyright 2012 Xamarin Inc. All rights reserved. + +using System; +using System.IO; +using System.Reflection; +#if __UNIFIED__ +using Foundation; +using AppKit; +#else +using MonoMac.Foundation; +using MonoMac.AppKit; +#endif + +namespace Xamarin.Mac.Linker.Test { + + public static class Test { + + static TextWriter log; + + public static TextWriter Log { + get { + // if not defined the results will be inside Console.app + if (log == null) { + string logfile = Environment.GetEnvironmentVariable ("TEST_LOG_FILE"); + if (String.IsNullOrEmpty (logfile)) + log = Console.Out; + else + log = new StreamWriter (logfile, true); + } + return log; + } + } + + public static void EnsureLinker (bool enabled) + { + if ((Type.GetType ("MonoMac.CoreImage.CIColor, XamMac") != null) == enabled) { + Log.WriteLine ("[FAIL]\tThe linker was {0}enabled on this build", enabled ? "not " : String.Empty); + } + } + + public static void Terminate () + { + Log.Flush (); + NSApplication.SharedApplication.Terminate (new NSObject ()); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/custom-bundle-name/Info.plist b/tests/mmptest/regression/custom-bundle-name/Info.plist new file mode 100644 index 000000000000..9fe30d5a06ba --- /dev/null +++ b/tests/mmptest/regression/custom-bundle-name/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-nativebuilder-1 + CFBundleIdentifier + com.your-company.linknativebuilder1 + CFBundleName + link-nativebuilder-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/custom-bundle-name/custom-bundle-name.cs b/tests/mmptest/regression/custom-bundle-name/custom-bundle-name.cs new file mode 100644 index 000000000000..29ed25ebb529 --- /dev/null +++ b/tests/mmptest/regression/custom-bundle-name/custom-bundle-name.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +using AppKit; +using ObjCRuntime; +using Foundation; + + +namespace Xamarin.Mac.Linker.Test { + + class CustomBundleName { + static void Main (string[] args) + { + NSApplication.Init (); + + if (Directory.Exists (Path.Combine (NSBundle.MainBundle.BundlePath, "Contents", "CustomBundleName")) && + !Directory.Exists (Path.Combine (NSBundle.MainBundle.BundlePath, "Contents", "MonoBundle"))) + Test.Log.WriteLine ("[SUCCESS]"); + else + Test.Log.WriteLine ("[FAIL]"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/custom-bundle-name/custom-bundle-name.csproj b/tests/mmptest/regression/custom-bundle-name/custom-bundle-name.csproj new file mode 100644 index 000000000000..835645e905e1 --- /dev/null +++ b/tests/mmptest/regression/custom-bundle-name/custom-bundle-name.csproj @@ -0,0 +1,53 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5AB27219-C1A8-4BAB-AD23-57B807E701EE} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + CustomBundleName + Resources + custom-bundle-name + v2.0 + Xamarin.Mac + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + Mac Developer + false + false + Developer ID Installer + false + -custom_bundle_name=CustomBundleName + x86_64 + + + + + + + + + + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/dylib/src.c b/tests/mmptest/regression/dylib/src.c new file mode 100644 index 000000000000..68583dd3a50c --- /dev/null +++ b/tests/mmptest/regression/dylib/src.c @@ -0,0 +1,4 @@ +int the_answer () +{ + return 42; +} \ No newline at end of file diff --git a/tests/mmptest/regression/embedded-mono-profile/Info.plist b/tests/mmptest/regression/embedded-mono-profile/Info.plist new file mode 100644 index 000000000000..9fe30d5a06ba --- /dev/null +++ b/tests/mmptest/regression/embedded-mono-profile/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-nativebuilder-1 + CFBundleIdentifier + com.your-company.linknativebuilder1 + CFBundleName + link-nativebuilder-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/embedded-mono-profile/embedded-mono-profile.cs b/tests/mmptest/regression/embedded-mono-profile/embedded-mono-profile.cs new file mode 100644 index 000000000000..17867340594c --- /dev/null +++ b/tests/mmptest/regression/embedded-mono-profile/embedded-mono-profile.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +using AppKit; +using ObjCRuntime; + +namespace Xamarin.Mac.Linker.Test { + + class SystemMono { + static void Main (string[] args) + { + NSApplication.Init (); + + if (File.Exists ("output.mlpd")) { + Test.Log.WriteLine ("SUCCESS: log output exists"); + } else { + Test.Log.WriteLine ("FAIL: could not find 'output.mlpd'"); + } + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/embedded-mono-profile/embedded-mono-profile.csproj b/tests/mmptest/regression/embedded-mono-profile/embedded-mono-profile.csproj new file mode 100644 index 000000000000..f4d800d032f5 --- /dev/null +++ b/tests/mmptest/regression/embedded-mono-profile/embedded-mono-profile.csproj @@ -0,0 +1,53 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + embeddedmono + Resources + embedded-mono-profile + v2.0 + Xamarin.Mac + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + true + true + false + Mac Developer + false + false + Developer ID Installer + false + x86_64 + --profiling + + + + + + + + + + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/embedded-mono/Info.plist b/tests/mmptest/regression/embedded-mono/Info.plist new file mode 100644 index 000000000000..9fe30d5a06ba --- /dev/null +++ b/tests/mmptest/regression/embedded-mono/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-nativebuilder-1 + CFBundleIdentifier + com.your-company.linknativebuilder1 + CFBundleName + link-nativebuilder-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/embedded-mono/embedded-mono.cs b/tests/mmptest/regression/embedded-mono/embedded-mono.cs new file mode 100644 index 000000000000..ad9b000973dc --- /dev/null +++ b/tests/mmptest/regression/embedded-mono/embedded-mono.cs @@ -0,0 +1,52 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +using AppKit; +using ObjCRuntime; + +namespace Xamarin.Mac.Linker.Test { + + class SystemMono { + static void Main (string[] args) + { + NSApplication.Init (); + + TestDlopenSystem (); + TestDlopenEmbedded (); + + Test.Terminate (); + } + + [DllImport ("libSystem.dylib")] + public static extern IntPtr dlopen (string path, int mode); + + static void TestDlopenSystem () + { + try { + IntPtr h = dlopen ("libc.dylib", 0); + if (h == IntPtr.Zero) { + Test.Log.WriteLine ("[FAIL] TestDlopenSystem: Could not dlopen libc.dylib"); + } else { + Test.Log.WriteLine ("[SUCCESS] TestDlopenSystem: dlopen libc.dylib: 0x{0}", h.ToString ("x")); + Dlfcn.dlclose (h); + } + } catch (Exception ex) { + Test.Log.WriteLine ("[FAIL] TestDlopenSystem: {0}", ex); + } + } + [DllImport ("libTest.dylib")] + static extern int the_answer (); + + static void TestDlopenEmbedded () + { + try { + var a = the_answer (); + Test.Log.WriteLine ("[SUCCESS] TestDlopenEmbedded: {0}", a); + } catch (Exception ex) { + Test.Log.WriteLine ("[FAIL] TestDlopenEmbedded: {0}", ex); + } + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/embedded-mono/embedded-mono.csproj b/tests/mmptest/regression/embedded-mono/embedded-mono.csproj new file mode 100644 index 000000000000..9804b2490fd7 --- /dev/null +++ b/tests/mmptest/regression/embedded-mono/embedded-mono.csproj @@ -0,0 +1,60 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {B211EB73-67F5-40C0-9030-F91385DFF077} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + embeddedmono + Resources + embedded-mono + v2.0 + Xamarin.Mac + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + false + + + x86_64 + + + + + + + + + + + + + + Test.cs + + + + + + False + Dynamic + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-aes-1/Info.plist b/tests/mmptest/regression/link-aes-1/Info.plist new file mode 100644 index 000000000000..5bf17be0d9a2 --- /dev/null +++ b/tests/mmptest/regression/link-aes-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-aes-1 + CFBundleIdentifier + com.your-company.linkaes1 + CFBundleName + link-aes-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-aes-1/LinkAes1.cs b/tests/mmptest/regression/link-aes-1/LinkAes1.cs new file mode 100644 index 000000000000..f573dccde360 --- /dev/null +++ b/tests/mmptest/regression/link-aes-1/LinkAes1.cs @@ -0,0 +1,39 @@ +using System; +using System.Security.Cryptography; +using MonoMac.AppKit; + +// Test +// * application calls Aes.Create where Aes now (4.0+) resides in mscorlib.dll +// * AesCryptoServiceProvider however still resides in System.Core.dll +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class Crypto { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + Aes aes = null; + string msg = "is null"; + + try { + aes = Aes.Create (); + if (aes != null) + msg = "usable as " + aes.GetType ().FullName; + } + catch (Exception e) { + msg = "throwed " + e.ToString (); + } + + Test.Log.WriteLine ("[{0}]\tAES {1}", aes == null ? "FAIL" : "PASS", msg); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-aes-1/link-aes-1.csproj b/tests/mmptest/regression/link-aes-1/link-aes-1.csproj new file mode 100644 index 000000000000..77e683593643 --- /dev/null +++ b/tests/mmptest/regression/link-aes-1/link-aes-1.csproj @@ -0,0 +1,92 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {12A3E976-A434-4512-8579-CA395923874D} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkaes1 + Resources + link-aes-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-blocks-1/Info.plist b/tests/mmptest/regression/link-blocks-1/Info.plist new file mode 100644 index 000000000000..12c0e4900870 --- /dev/null +++ b/tests/mmptest/regression/link-blocks-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-blocks-1 + CFBundleIdentifier + com.your-company.linkblocks1 + CFBundleName + link-blocks-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-blocks-1/LinkBlocks1.cs b/tests/mmptest/regression/link-blocks-1/LinkBlocks1.cs new file mode 100644 index 000000000000..ce92a6583c7e --- /dev/null +++ b/tests/mmptest/regression/link-blocks-1/LinkBlocks1.cs @@ -0,0 +1,45 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using MonoMac.AppKit; +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; + +// Test +// * application uses Blocks and BlockLiteral fields must be preserved +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class NativeBuilder { + + static void Check (string name, MemberInfo mi) + { + Test.Log.WriteLine ("{0}\t{1}", mi != null ? "[PASS]" : "[FAIL]", name); + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + int i = 0; + string b = null; + NSSet s = new NSSet ("a", "b", "c"); + s.Enumerate (delegate (NSObject obj, ref bool stop) { + stop = i++ == 1; + b = obj.ToString (); + }); + // test behavior (we did not break anything) + Test.Log.WriteLine ("[{0}]\tBehavior: Stop at item '{1}'", b == "b" ? "PASS" : "FAIL", b); + // test that BlockLiteral is fully preserved + int size = Marshal.SizeOf (typeof (BlockLiteral)); // e.g. unused 'reserved' must not be removed + Test.Log.WriteLine ("[{0}]\tBlockLiteral is {1} bytes", size == 28 ? "PASS" : "FAIL", size); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-blocks-1/link-blocks-1.csproj b/tests/mmptest/regression/link-blocks-1/link-blocks-1.csproj new file mode 100644 index 000000000000..5f821d7c92a3 --- /dev/null +++ b/tests/mmptest/regression/link-blocks-1/link-blocks-1.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {26634789-2957-4A78-BBF0-929BCA74440F} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkblocks1 + Resources + link-blocks-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-callfilepath-45/Info.plist b/tests/mmptest/regression/link-callfilepath-45/Info.plist new file mode 100644 index 000000000000..5063a8056135 --- /dev/null +++ b/tests/mmptest/regression/link-callfilepath-45/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-callfilepath-45 + CFBundleName + link-callfilepath-45 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-callfilepath-45/LinkCallFilePath.cs b/tests/mmptest/regression/link-callfilepath-45/LinkCallFilePath.cs new file mode 100644 index 000000000000..cdd57bc57feb --- /dev/null +++ b/tests/mmptest/regression/link-callfilepath-45/LinkCallFilePath.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using MonoMac.Foundation; +using MonoMac.AppKit; + +// Test +// * application references [CallerFilePath] which is new in .NET 4.5 +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class CallFilePath { + + // https://bugzilla.xamarin.com/show_bug.cgi?id=7114 + public static void Bug7114 ([CallerFilePath] string filePath = null) + { + Test.Log.WriteLine ("{0}\tCallerFilePath = {1}", filePath != null ? "[PASS]" : "[FAIL]", filePath); + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + Bug7114 (); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-callfilepath-45/link-callfilepath-45.csproj b/tests/mmptest/regression/link-callfilepath-45/link-callfilepath-45.csproj new file mode 100644 index 000000000000..b94597fcb410 --- /dev/null +++ b/tests/mmptest/regression/link-callfilepath-45/link-callfilepath-45.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkcallfilepath45 + Resources + link-callfilepath-45 + v4.5 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-data-contract-1/Info.plist b/tests/mmptest/regression/link-data-contract-1/Info.plist new file mode 100644 index 000000000000..9a91e666042a --- /dev/null +++ b/tests/mmptest/regression/link-data-contract-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-data-contract-1 + CFBundleIdentifier + com.your-company.linkdatacontract1 + CFBundleName + link-data-contract-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-data-contract-1/LinkDataContract1.cs b/tests/mmptest/regression/link-data-contract-1/LinkDataContract1.cs new file mode 100644 index 000000000000..4467d2040c7f --- /dev/null +++ b/tests/mmptest/regression/link-data-contract-1/LinkDataContract1.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Xml; +using MonoMac.AppKit; +using MonoMac.Foundation; + +// Test +// * application roundtrip some data using DataContract +// * Adapted from iOS linkall.app, based on bug #11135 +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + [DataContract(Namespace = "mb")][Flags] + public enum SomeTypes { + [Preserve (AllMembers = true)][EnumMember] None = 0, + [Preserve (AllMembers = true)][EnumMember] Image = 1, + [Preserve (AllMembers = true)][EnumMember] Audio = 2, + [Preserve (AllMembers = true)][EnumMember] Video = 4, + [Preserve (AllMembers = true)][EnumMember] Document = 8 + } + + public class TestClass + { + public TestClass (SomeTypes types) + { + Types = types; + } + + public SomeTypes Types { get; set; } + } + + class DataContract { + + public static string ToXml (T obj) + { + var sb = new StringBuilder(); + using (var x = XmlWriter.Create (sb, new XmlWriterSettings ())) { + var s = new DataContractSerializer (typeof (T)); + s.WriteObject(x, obj); + } + return sb.ToString(); + } + + public static T FromXml (string xml) + { + using (var r = XmlReader.Create (new StringReader (xml))) { + var s = new DataContractSerializer (typeof (T)); + return (T) s.ReadObject (r); + } + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + var t1 = new TestClass (SomeTypes.Audio | SomeTypes.Image); + var st = ToXml (t1); + var t2 = FromXml (st); + bool success = t2.Types == t1.Types; + + Test.Log.WriteLine ("[{0}]\tDataContract roundtrip", success ? "PASS" : "FAIL"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-data-contract-1/link-data-contract-1.csproj b/tests/mmptest/regression/link-data-contract-1/link-data-contract-1.csproj new file mode 100644 index 000000000000..9876ade88292 --- /dev/null +++ b/tests/mmptest/regression/link-data-contract-1/link-data-contract-1.csproj @@ -0,0 +1,96 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {CCE59D9C-CA71-4DB8-8156-98D7A9428534} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkdatacontract1 + Resources + link-data-contract-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-frameworks-1/Info.plist b/tests/mmptest/regression/link-frameworks-1/Info.plist new file mode 100644 index 000000000000..04ad310150df --- /dev/null +++ b/tests/mmptest/regression/link-frameworks-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-frameworks-1 + CFBundleIdentifier + com.your-company.linkframeworks1 + CFBundleName + link-frameworks-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-frameworks-1/LinkFrameworks1.cs b/tests/mmptest/regression/link-frameworks-1/LinkFrameworks1.cs new file mode 100644 index 000000000000..bf4a9e6f55d8 --- /dev/null +++ b/tests/mmptest/regression/link-frameworks-1/LinkFrameworks1.cs @@ -0,0 +1,63 @@ +using System; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; + +// Test +// * application .exe only depends on Foundation and AppKit +// +// Requirement +// * Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class Framework { + + static FieldInfo[] fields; + + static void Check (string framework, string fieldName, bool exists) + { + bool found = false; + foreach (var fi in fields) { + if (fi.Name == fieldName) { + found = true; + break; + } + } + Test.Log.WriteLine ("[{0}] {1} is {2}", found == exists ? "PASS" : "FAIL", framework, exists ? "present" : "absent"); + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + fields = typeof(NSObject).GetFields (BindingFlags.NonPublic | BindingFlags.Static); + + // Foundation, AppKit will be present (would be hard to remove) + Check ("Foundation", "fl", true); + Check ("AppKit", "al", true); + // Otherwise we should be able to eliminate the others + Check ("AddressBook", "ab", false); + Check ("CoreText", "ct", false); + Check ("WebKit", "wl", false); + Check ("Quartz", "zl", false); // CoreAnimation + Check ("QTKit", "ql", false); + Check ("Security", "ll", false); + Check ("QuartzComposer", "zc", false); + Check ("CoreWlan", "cw", false); + Check ("PdfKit", "pk", false); + Check ("ImageKit", "ik", false); + Check ("ScriptingBridge", "sb", false); + Check ("AVFoundation", "av", false); + // not everyone of them are in NSObjectMac.cs + Check ("SceneKit", "sk", false); + Check ("CoreBluetooth", "bl", false); + Check ("StoreKit", "st", false); + Check ("GameKit", "gk", false); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-frameworks-1/link-frameworks-1.csproj b/tests/mmptest/regression/link-frameworks-1/link-frameworks-1.csproj new file mode 100644 index 000000000000..c7f25611cfa9 --- /dev/null +++ b/tests/mmptest/regression/link-frameworks-1/link-frameworks-1.csproj @@ -0,0 +1,95 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkframeworks1 + Resources + link-frameworks-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-gdiplus-1/Info.plist b/tests/mmptest/regression/link-gdiplus-1/Info.plist new file mode 100644 index 000000000000..d3d96cfcece8 --- /dev/null +++ b/tests/mmptest/regression/link-gdiplus-1/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-gdiplus-1 + CFBundleName + link-gdiplus-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-gdiplus-1/LinkGdiPlus1.cs b/tests/mmptest/regression/link-gdiplus-1/LinkGdiPlus1.cs new file mode 100644 index 000000000000..7a75a77f513d --- /dev/null +++ b/tests/mmptest/regression/link-gdiplus-1/LinkGdiPlus1.cs @@ -0,0 +1,46 @@ +using System; +using System.Drawing; +using System.IO; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application references System.Drawing +// * application creates a Bitmap which pinvoke into gdiplus +// * linker includes libgdiplus.dylib in the application bundle +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class GdiPlus1 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + bool gdiplus = false; + string msg = "Bitmap created"; + try { + Bitmap b = new Bitmap (32, 32); + gdiplus = (b != null); + } + catch (Exception e) { + msg = e.ToString (); + } + + Test.Log.WriteLine ("{0}\t{1}", gdiplus ? "[PASS]" : "[FAIL]", msg); + + string path = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location); + bool bundled = File.Exists (Path.Combine (path, "libgdiplus.dylib")); + Test.Log.WriteLine ("{0}\t{1}", bundled ? "[PASS]" : "[FAIL]", "libgdiplus present in bundle"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-gdiplus-1/link-gdiplus-1.csproj b/tests/mmptest/regression/link-gdiplus-1/link-gdiplus-1.csproj new file mode 100644 index 000000000000..d3f5431d91f1 --- /dev/null +++ b/tests/mmptest/regression/link-gdiplus-1/link-gdiplus-1.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkgdiplus1 + Resources + link-gdiplus-1 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + + Test.cs + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-gdiplus-2/Info.plist b/tests/mmptest/regression/link-gdiplus-2/Info.plist new file mode 100644 index 000000000000..e618844f63e1 --- /dev/null +++ b/tests/mmptest/regression/link-gdiplus-2/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-gdiplus-2 + CFBundleName + link-gdiplus-2 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-gdiplus-2/LinkGdiPlus2.cs b/tests/mmptest/regression/link-gdiplus-2/LinkGdiPlus2.cs new file mode 100644 index 000000000000..cf839872cd39 --- /dev/null +++ b/tests/mmptest/regression/link-gdiplus-2/LinkGdiPlus2.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing.Imaging; +using System.IO; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application references System.Drawing.BitmapData +// * linker must include all the private fields of the class (used or not) +// * linker does NOT include libgdiplus.dylib in the application bundle +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class GdiPlus2 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + int fcount = typeof (BitmapData).GetFields (BindingFlags.NonPublic | BindingFlags.Instance).Length; + Test.Log.WriteLine ("{0}\tBitmapData {1}/17 fields protected by linker", fcount == 17 ? "[PASS]" : "[FAIL]", fcount); + + // there's no [DllImport] on BitmapData so libgdiplus.dylib should not be copied into the bundle + string path = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location); + bool bundled = File.Exists (Path.Combine (path, "libgdiplus.dylib")); + Test.Log.WriteLine ("{0}\t{1}", !bundled ? "[PASS]" : "[FAIL]", "libgdiplus not present in bundle"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-gdiplus-2/link-gdiplus-2.csproj b/tests/mmptest/regression/link-gdiplus-2/link-gdiplus-2.csproj new file mode 100644 index 000000000000..14a9886dc7e2 --- /dev/null +++ b/tests/mmptest/regression/link-gdiplus-2/link-gdiplus-2.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkgdiplus2 + Resources + link-gdiplus-2 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-httpclient-async/Info.plist b/tests/mmptest/regression/link-httpclient-async/Info.plist new file mode 100644 index 000000000000..822ba78dee6e --- /dev/null +++ b/tests/mmptest/regression/link-httpclient-async/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-httpclient-async + CFBundleName + link-httpclient-async + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-httpclient-async/LinkHttpClientAsync.cs b/tests/mmptest/regression/link-httpclient-async/LinkHttpClientAsync.cs new file mode 100644 index 000000000000..806207d51cd6 --- /dev/null +++ b/tests/mmptest/regression/link-httpclient-async/LinkHttpClientAsync.cs @@ -0,0 +1,45 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using MonoMac.Foundation; +using MonoMac.AppKit; + +// Test +// * application references [CallerFilePath] which is new in .NET 4.5 +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class HttpClientAsync { + + static bool waited = false; + + // http://blogs.msdn.com/b/csharpfaq/archive/2012/06/26/understanding-a-simple-async-program.aspx + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7114 + // CS4009 entry point cannot be async + static async Task GetWebPageAsync () + { + Task getWebPageTask = new HttpClient ().GetStringAsync ("http://msdn.microsoft.com"); + string content = await getWebPageTask; + waited = true; + bool success = !String.IsNullOrEmpty (content); + Test.Log.WriteLine ("{0}\treceived {1} bytes", success ? "[PASS]" : "[FAIL]", success ? content.Length : 0); + } + + static void Main (string[] args) + { + NSApplication.Init (); + // we do not want the async code to get back to the AppKit thread, hanging the process + SynchronizationContext.SetSynchronizationContext (null); + + Test.EnsureLinker (true); + GetWebPageAsync ().Wait (); + + Test.Log.WriteLine ("{0}\tasync / await worked", waited ? "[PASS]" : "[FAIL]"); + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-httpclient-async/link-httpclient-async.csproj b/tests/mmptest/regression/link-httpclient-async/link-httpclient-async.csproj new file mode 100644 index 000000000000..4e961fe2c7ec --- /dev/null +++ b/tests/mmptest/regression/link-httpclient-async/link-httpclient-async.csproj @@ -0,0 +1,96 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkhttpclientasync + Resources + link-httpclient-async + v4.5 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-keep-resources-1/Info.plist b/tests/mmptest/regression/link-keep-resources-1/Info.plist new file mode 100644 index 000000000000..c86c2fcff0ac --- /dev/null +++ b/tests/mmptest/regression/link-keep-resources-1/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-keep-resources-1 + CFBundleName + link-keep-resources-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-keep-resources-1/LinkKeepResources1.cs b/tests/mmptest/regression/link-keep-resources-1/LinkKeepResources1.cs new file mode 100644 index 000000000000..51e073fdcb7c --- /dev/null +++ b/tests/mmptest/regression/link-keep-resources-1/LinkKeepResources1.cs @@ -0,0 +1,44 @@ +// Copyright 2012 Xamarin Inc. All rights reserved. + +using System; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application is linked with i18n CJK support +// * application uses SystemSounds +// * linker includes resources for all .wav (System) and i18n + CJK +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class KeepResources1 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + int cjk = 0; + string [] resources = typeof (int).Assembly.GetManifestResourceNames (); + foreach (string name in resources) { + if (name.Contains ("cjk")) + cjk++; + } + Test.Log.WriteLine ("{0}\tCJK {1}/5 data files present", cjk == 5 ? "[PASS]" : "[FAIL]", cjk); + + var ss = typeof (System.Media.SystemSounds); + resources = ss.Assembly.GetManifestResourceNames (); + Test.Log.WriteLine ("{0}\tSystemSounds {1}/5 .wav files present", resources.Length == 5 ? "[PASS]" : "[FAIL]", resources.Length); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-keep-resources-1/link-keep-resources-1.csproj b/tests/mmptest/regression/link-keep-resources-1/link-keep-resources-1.csproj new file mode 100644 index 000000000000..fe2af517be8f --- /dev/null +++ b/tests/mmptest/regression/link-keep-resources-1/link-keep-resources-1.csproj @@ -0,0 +1,96 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkkeepresources1 + Resources + link-keep-resources-1 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + False + True + False + False + Mac Developer + False + False + x86 + Developer ID Installer + cjk + Full + false + + + none + True + bin\Release + prompt + 4 + Full + False + True + False + True + Developer ID Application + True + False + x86 + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + False + True + 3rd Party Mac Developer Installer + False + True + 3rd Party Mac Developer Application + True + True + x86 + false + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-keep-resources-2/Info.plist b/tests/mmptest/regression/link-keep-resources-2/Info.plist new file mode 100644 index 000000000000..5808ea21304e --- /dev/null +++ b/tests/mmptest/regression/link-keep-resources-2/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-keep-resources-2 + CFBundleName + link-keep-resources-2 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-keep-resources-2/LinkKeepResources2.cs b/tests/mmptest/regression/link-keep-resources-2/LinkKeepResources2.cs new file mode 100644 index 000000000000..a0820d1e18c6 --- /dev/null +++ b/tests/mmptest/regression/link-keep-resources-2/LinkKeepResources2.cs @@ -0,0 +1,44 @@ +// Copyright 2012 Xamarin Inc. All rights reserved. + +using System; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application is linked without any i18n support +// * application uses SystemIcons +// * linker includes resources for all .ico (System.Drawing) +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class KeepResources2 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + string [] resources = typeof (int).Assembly.GetManifestResourceNames (); + Test.Log.WriteLine ("{0}\ti18n {1}/2 data files present: {2}", resources.Length <= 3 ? "[PASS]" : "[FAIL]", resources.Length, string.Join (", ", resources)); + + var ss = typeof (System.ComponentModel.TypeConverter); + resources = ss.Assembly.GetManifestResourceNames (); + Test.Log.WriteLine ("{0}\tSystemSounds {1}/0 .wav files present", resources.Length == 0 ? "[PASS]" : "[FAIL]", resources.Length); + + var si = typeof (System.Drawing.SystemIcons); + resources = si.Assembly.GetManifestResourceNames (); + // Mono 2.10 ships with 5 .ico while Mono 3.0 provides 6 .ico resource files + Test.Log.WriteLine ("{0}\tSystemIcons {1}/[5-6] .ico files present", resources.Length >= 5 ? "[PASS]" : "[FAIL]", resources.Length); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-keep-resources-2/link-keep-resources-2.csproj b/tests/mmptest/regression/link-keep-resources-2/link-keep-resources-2.csproj new file mode 100644 index 000000000000..ac91a26be32a --- /dev/null +++ b/tests/mmptest/regression/link-keep-resources-2/link-keep-resources-2.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {9D5EA758-05CE-416C-B2D1-523E481C0DCD} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkkeepresources2 + Resources + link-keep-resources-2 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-posix-1/Info.plist b/tests/mmptest/regression/link-posix-1/Info.plist new file mode 100644 index 000000000000..6271ab2e8d51 --- /dev/null +++ b/tests/mmptest/regression/link-posix-1/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-posix-1 + CFBundleName + link-posix-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-posix-1/LinkPosix1.cs b/tests/mmptest/regression/link-posix-1/LinkPosix1.cs new file mode 100644 index 000000000000..2c2d81e58b87 --- /dev/null +++ b/tests/mmptest/regression/link-posix-1/LinkPosix1.cs @@ -0,0 +1,47 @@ +// Copyright 2012 Xamarin Inc. All rights reserved. + +using System; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application does not reference assembly Mono.Posix.dll +// * application call method which pinvoke into libMonoPosixHelper.dylib +// * linker includes libMonoPosixHelper.dylib in the application bundle +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class Posix1 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + bool gzip = false; + try { + GZipStream gz = new GZipStream (Stream.Null, CompressionMode.Compress); + gz.WriteByte (0); + gz.Close (); + gzip = true; + } + catch { + } + Test.Log.WriteLine ("{0}\t{1}", gzip ? "[PASS]" : "[FAIL]", "GZipStream support"); + + string path = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location); + bool bundled = File.Exists (Path.Combine (path, "libMonoPosixHelper.dylib")); + Test.Log.WriteLine ("{0}\t{1}", bundled ? "[PASS]" : "[FAIL]", "MonoPosixHelper present in bundle"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-posix-1/link-posix-1.csproj b/tests/mmptest/regression/link-posix-1/link-posix-1.csproj new file mode 100644 index 000000000000..b0dfce96dddb --- /dev/null +++ b/tests/mmptest/regression/link-posix-1/link-posix-1.csproj @@ -0,0 +1,94 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkposix1 + Resources + link-posix-1 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + Test.cs + + + + + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-posix-2/Info.plist b/tests/mmptest/regression/link-posix-2/Info.plist new file mode 100644 index 000000000000..06f63441437b --- /dev/null +++ b/tests/mmptest/regression/link-posix-2/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-posix-2 + CFBundleName + link-posix-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-posix-2/LinkPosix2.cs b/tests/mmptest/regression/link-posix-2/LinkPosix2.cs new file mode 100644 index 000000000000..42905df2be0b --- /dev/null +++ b/tests/mmptest/regression/link-posix-2/LinkPosix2.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; +using System.Reflection; +using Mono.Posix; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application references Mono.Posix +// * application call method which pinvoke into libc +// * linker does not include libMonoPosixHelper.dylib in the application bundle +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class Posix2 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + +#pragma warning disable 618 + var host = Syscall.GetHostName (); +#pragma warning restore 618 + Test.Log.WriteLine ("{0}\t{1} {2}", !String.IsNullOrEmpty (host) ? "[PASS]" : "[FAIL]", "Syscall.GetHostName returned", host); + + string path = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location); + string dylib = Path.Combine (path, "libMonoPosixHelper.dylib"); + bool bundled = File.Exists (dylib); + Test.Log.WriteLine ("{0}\t{1} : {2}", !bundled ? "[PASS]" : "[FAIL]", "MonoPosixHelper not present in bundle", dylib); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-posix-2/link-posix-2.csproj b/tests/mmptest/regression/link-posix-2/link-posix-2.csproj new file mode 100644 index 000000000000..10f13925b966 --- /dev/null +++ b/tests/mmptest/regression/link-posix-2/link-posix-2.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {141239A4-4094-4349-A3F3-00CD16643226} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkposix2 + Resources + link-posix-2 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + Test.cs + + + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-preserve-assembly/Info.plist b/tests/mmptest/regression/link-preserve-assembly/Info.plist new file mode 100644 index 000000000000..82bbda9348a9 --- /dev/null +++ b/tests/mmptest/regression/link-preserve-assembly/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-preserve-assembly + CFBundleName + link-preserve-assembly + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-preserve-assembly/LinkPreserveAssembly.cs b/tests/mmptest/regression/link-preserve-assembly/LinkPreserveAssembly.cs new file mode 100644 index 000000000000..31c093c5dbe0 --- /dev/null +++ b/tests/mmptest/regression/link-preserve-assembly/LinkPreserveAssembly.cs @@ -0,0 +1,44 @@ +using System; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application .exe is decorated with [Preserve] +// * the decorated (main .exe) assembly is not linked +// * other assemblies are linked +// +// Requirement +// * Link All must be enabled + +[assembly: Preserve] + +namespace Xamarin.Mac.Linker.Test { + + class PreserveAssembly { + + static int UnusedProperty { + get; set; + } + + public void UnusedMethod () + { + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + int pcount = typeof (PreserveAssembly).GetProperties (BindingFlags.NonPublic | BindingFlags.Static).Length; + Test.Log.WriteLine ("{0}\tUnused property ({1}/1) was preserved by linker", pcount == 1 ? "[PASS]" : "[FAIL]", pcount); + + bool m = typeof (PreserveAssembly).GetMethod ("UnusedMethod", BindingFlags.Public | BindingFlags.Instance) != null; + Test.Log.WriteLine ("{0}\tUnused method was preserved by linker", m ? "[PASS]" : "[FAIL]"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-preserve-assembly/link-preserve-assembly.csproj b/tests/mmptest/regression/link-preserve-assembly/link-preserve-assembly.csproj new file mode 100644 index 000000000000..4f0a041e7450 --- /dev/null +++ b/tests/mmptest/regression/link-preserve-assembly/link-preserve-assembly.csproj @@ -0,0 +1,96 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkpreserveassembly + Resources + link-preserve-assembly + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + x86 + False + False + False + False + Mac Developer + Developer ID Installer + + + Full + false + + + none + True + bin\Release + prompt + 4 + False + True + x86 + Full + True + False + False + True + Developer ID Application + false + + + none + True + bin\x86\AppStore + prompt + 4 + False + True + x86 + Full + 3rd Party Mac Developer Installer + True + False + True + True + 3rd Party Mac Developer Application + false + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-preserve-calendar-1/Info.plist b/tests/mmptest/regression/link-preserve-calendar-1/Info.plist new file mode 100644 index 000000000000..ca320a33ffa2 --- /dev/null +++ b/tests/mmptest/regression/link-preserve-calendar-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-preserve-calendar-1 + CFBundleIdentifier + com.your-company.linkpreservecalendar1 + CFBundleName + link-preserve-calendar-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-preserve-calendar-1/LinkPreserveCalendar1.cs b/tests/mmptest/regression/link-preserve-calendar-1/LinkPreserveCalendar1.cs new file mode 100644 index 000000000000..fe494ace02ac --- /dev/null +++ b/tests/mmptest/regression/link-preserve-calendar-1/LinkPreserveCalendar1.cs @@ -0,0 +1,36 @@ +using System; +using MonoMac.AppKit; + +// Test +// * application .exe does not *directly* use any Calendar +// * only the default GregorianCalendar is linked in +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class PreserveCalendar { + + static void Check (string calendarName, bool present) + { + var type = Type.GetType ("System.Globalization." + calendarName); + bool success = present == (type != null); + Test.Log.WriteLine ("[{0}]\t{1} {2}", success ? "PASS" : "FAIL", calendarName, present ? "present" : "absent"); + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + Check ("GregorianCalendar", true); + Check ("UmAlQuraCalendar", false); + Check ("HijriCalendar", false); + Check ("ThaiBuddhistCalendar", false); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-preserve-calendar-1/link-preserve-calendar-1.csproj b/tests/mmptest/regression/link-preserve-calendar-1/link-preserve-calendar-1.csproj new file mode 100644 index 000000000000..b04d624ee705 --- /dev/null +++ b/tests/mmptest/regression/link-preserve-calendar-1/link-preserve-calendar-1.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {910B8B76-46C3-4550-AB5C-BD813F053A98} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkpreservecalendar1 + Resources + link-preserve-calendar-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-preserve-calendar-2/Info.plist b/tests/mmptest/regression/link-preserve-calendar-2/Info.plist new file mode 100644 index 000000000000..b61aa72cb5be --- /dev/null +++ b/tests/mmptest/regression/link-preserve-calendar-2/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-preserve-calendar-2 + CFBundleIdentifier + com.your-company.linkpreservecalendar2 + CFBundleName + link-preserve-calendar-2 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-preserve-calendar-2/LinkPreserveCalendar2.cs b/tests/mmptest/regression/link-preserve-calendar-2/LinkPreserveCalendar2.cs new file mode 100644 index 000000000000..e4cb7c4d15bc --- /dev/null +++ b/tests/mmptest/regression/link-preserve-calendar-2/LinkPreserveCalendar2.cs @@ -0,0 +1,36 @@ +using System; +using MonoMac.AppKit; + +// Test +// * application .exe does not *directly* use any Calendar +// * -i18n option is used to keep MidEast and Other so their calendars are also preserved +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class PreserveCalendar { + + static void Check (string calendarName, bool present) + { + var type = Type.GetType ("System.Globalization." + calendarName); + bool success = present == (type != null); + Test.Log.WriteLine ("[{0}]\t{1} {2}", success ? "PASS" : "FAIL", calendarName, present ? "present" : "absent"); + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + Check ("GregorianCalendar", true); + Check ("UmAlQuraCalendar", true); + Check ("HijriCalendar", true); + Check ("ThaiBuddhistCalendar", true); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-preserve-calendar-2/link-preserve-calendar-2.csproj b/tests/mmptest/regression/link-preserve-calendar-2/link-preserve-calendar-2.csproj new file mode 100644 index 000000000000..d56f9596a718 --- /dev/null +++ b/tests/mmptest/regression/link-preserve-calendar-2/link-preserve-calendar-2.csproj @@ -0,0 +1,98 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkpreservecalendar2 + Resources + link-preserve-calendar-2 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + mideast,other + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + Developer ID Installer + mideast,other + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + + + false + + + + + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-remove-attributes-1/Info.plist b/tests/mmptest/regression/link-remove-attributes-1/Info.plist new file mode 100644 index 000000000000..cda5b19e17eb --- /dev/null +++ b/tests/mmptest/regression/link-remove-attributes-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-remove-attributes-1 + CFBundleIdentifier + com.your-company.linkremoveattributes1 + CFBundleName + link-remove-attributes-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-remove-attributes-1/LinkRemoveAttributes.cs b/tests/mmptest/regression/link-remove-attributes-1/LinkRemoveAttributes.cs new file mode 100644 index 000000000000..49298ddd6280 --- /dev/null +++ b/tests/mmptest/regression/link-remove-attributes-1/LinkRemoveAttributes.cs @@ -0,0 +1,125 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml; +using MonoMac.AppKit; + +// Test +// * application use some attributes that the linker will remove (unneeded at runtime) +// * Application is build in debug mode so the [System.Diagnostics.Debug*] attributes are kept +// +// Requirement +// * Link SDK or Link All must be enabled +// * Debug mode + +// removed in release builds only +[assembly: Debuggable (DebuggableAttribute.DebuggingModes.Default)] + +[assembly: MonoMac.Foundation.LinkerSafe] + +// not removed +[assembly: AssemblyCompany ("Xamarin Inc.")] + +namespace Xamarin.Mac.Linker.Test { + +// [System.MonoDocumentationNote] +// [System.MonoExtension] +// [System.MonoLimitation] +// [System.MonoNotSupported] +// [System.MonoTODO] + [System.Obsolete] +// [System.Xml.MonoFIX] + + [MonoMac.ObjCRuntime.Availability] + [MonoMac.ObjCRuntime.Lion] + [MonoMac.ObjCRuntime.MountainLion] + [MonoMac.ObjCRuntime.Mavericks] + [MonoMac.ObjCRuntime.Since (5,0)] + [MonoMac.ObjCRuntime.ThreadSafe] + + [DebuggerDisplay ("")] + [DebuggerNonUserCode] + [DebuggerTypeProxy ("")] + [DebuggerVisualizer ("")] + + // not removed + [Guid ("20f66ee8-2ddc-4fc3-b690-82e1e43a93c7")] + class DebugLinkRemoveAttributes { + + // will be removed - but the instance field will be kept + [MonoMac.Foundation.Preserve] + // removed in release builds only + [DebuggerBrowsable (DebuggerBrowsableState.Never)] + XmlDocument document; + + [MonoMac.Foundation.Advice ("")] + // removed in release builds only + [DebuggerHidden] + [DebuggerStepperBoundary] + [DebuggerStepThrough] + // not removed + [LoaderOptimization (LoaderOptimization.SingleDomain)] + static void CheckPresence (ICustomAttributeProvider provider, string typeName, bool expected) + { + // the linker should have removed the *attributes* - maybe not the type + bool success = !expected; + foreach (var ca in provider.GetCustomAttributes (false)) { + if (ca.GetType ().FullName.StartsWith (typeName, StringComparison.Ordinal)) + success = expected; + } + Test.Log.WriteLine ("{0}\t{1} {2}", success ? "[PASS]" : "[FAIL]", typeName, expected ? "present" : "absent"); + } + +#if DEBUG + const bool debug = true; +#else + const bool debug = false; +#endif + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + try { + var type = typeof (DebugLinkRemoveAttributes); + CheckPresence (type, "System.ObsoleteAttribute", false); + CheckPresence (type, "MonoMac.Foundation.AdviceAttribute", false); + CheckPresence (type, "MonoMac.ObjCRuntime.AvailabilityAttribute", false); + CheckPresence (type, "MonoMac.ObjCRuntime.LionAttribute", false); + CheckPresence (type, "MonoMac.ObjCRuntime.MountainLionAttribute", false); + CheckPresence (type, "MonoMac.ObjCRuntime.MavericksAttribute", false); + CheckPresence (type, "MonoMac.ObjCRuntime.SinceAttribute", false); + CheckPresence (type, "MonoMac.ObjCRuntime.ThreadSafeAttribute", false); + CheckPresence (type, "System.Diagnostics.DebuggerDisplay", debug); + CheckPresence (type, "System.Diagnostics.DebuggerNonUserCode", debug); + CheckPresence (type, "System.Diagnostics.DebuggerTypeProxy", debug); + CheckPresence (type, "System.Diagnostics.DebuggerVisualizer", debug); + CheckPresence (type, "System.Runtime.InteropServices.GuidAttribute", true); + + var assembly = type.Assembly; + CheckPresence (assembly, "MonoMac.Foundation.LinkerSafeAttribute", false); + CheckPresence (assembly, "System.Diagnostics.DebuggableAttribute", debug); + CheckPresence (assembly, "System.Reflection.AssemblyCompanyAttribute", true); + + var method = type.GetMethod ("CheckPresence", BindingFlags.Static | BindingFlags.NonPublic); + CheckPresence (method, "MonoMac.Foundation.AdviceAttribute", false); + CheckPresence (method, "System.Diagnostics.DebuggerHiddenAttribute", debug); + CheckPresence (method, "System.Diagnostics.DebuggerStepperBoundaryAttribute", debug); + CheckPresence (method, "System.Diagnostics.DebuggerStepThroughAttribute", debug); + CheckPresence (method, "System.LoaderOptimizationAttribute", true); + + var field = type.GetField ("document", BindingFlags.Instance| BindingFlags.NonPublic); + CheckPresence (field, "MonoMac.Foundation.PreserveAttribute", false); + CheckPresence (field, "System.Diagnostics.DebuggerBrowsableAttribute", debug); + } + finally { + Test.Terminate (); + } + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-remove-attributes-1/link-remove-attributes-1.csproj b/tests/mmptest/regression/link-remove-attributes-1/link-remove-attributes-1.csproj new file mode 100644 index 000000000000..6d32b4e28765 --- /dev/null +++ b/tests/mmptest/regression/link-remove-attributes-1/link-remove-attributes-1.csproj @@ -0,0 +1,98 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {F977D041-B0A5-49DE-815E-B210DBE140A5} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkremoveattributes1 + Resources + link-remove-attributes-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + false + false + Developer ID Installer + + + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-safe-1/Info.plist b/tests/mmptest/regression/link-safe-1/Info.plist new file mode 100644 index 000000000000..f4386018e415 --- /dev/null +++ b/tests/mmptest/regression/link-safe-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-safe-1 + CFBundleIdentifier + com.your-company.linksafe1 + CFBundleName + link-safe-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-safe-1/LinkSafeAssembly.cs b/tests/mmptest/regression/link-safe-1/LinkSafeAssembly.cs new file mode 100644 index 000000000000..9bce63cb5594 --- /dev/null +++ b/tests/mmptest/regression/link-safe-1/LinkSafeAssembly.cs @@ -0,0 +1,44 @@ +using System; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application .exe is decorated with [LinkerSafe] +// * the decorated (main .exe) assembly is linked (even with Link SDK) +// * other assemblies are linked +// +// Requirement +// * Link SDK (not All) must be enabled + +[assembly: LinkerSafe] + +namespace Xamarin.Mac.Linker.Test { + + class SafeToLinkAssembly { + + static int UnusedProperty { + get; set; + } + + public void UnusedMethod () + { + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + int pcount = typeof (SafeToLinkAssembly).GetProperties (BindingFlags.NonPublic | BindingFlags.Static).Length; + Test.Log.WriteLine ("{0}\tUnused property ({1}/0) was preserved by linker", pcount == 0 ? "[PASS]" : "[FAIL]", pcount); + + bool m = typeof (SafeToLinkAssembly).GetMethod ("UnusedMethod", BindingFlags.Public | BindingFlags.Instance) == null; + Test.Log.WriteLine ("{0}\tUnused method was preserved by linker", m ? "[PASS]" : "[FAIL]"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-safe-1/link-safe-1.csproj b/tests/mmptest/regression/link-safe-1/link-safe-1.csproj new file mode 100644 index 000000000000..fdaeb5fdc394 --- /dev/null +++ b/tests/mmptest/regression/link-safe-1/link-safe-1.csproj @@ -0,0 +1,98 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linksafe1 + Resources + link-safe-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + SdkOnly + false + + + full + true + bin\Release + prompt + 4 + false + SdkOnly + false + true + false + Developer ID Application + true + true + Developer ID Installer + + + false + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + false + + + + + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-system.web-icalls/Info.plist b/tests/mmptest/regression/link-system.web-icalls/Info.plist new file mode 100644 index 000000000000..0ab4aefc6e2e --- /dev/null +++ b/tests/mmptest/regression/link-system.web-icalls/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-system.web-icalls + CFBundleName + link-system.web-icalls + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-system.web-icalls/LinkSysWebIcalls.cs b/tests/mmptest/regression/link-system.web-icalls/LinkSysWebIcalls.cs new file mode 100644 index 000000000000..1ce4a32f4583 --- /dev/null +++ b/tests/mmptest/regression/link-system.web-icalls/LinkSysWebIcalls.cs @@ -0,0 +1,36 @@ +using System; +using System.Web; +using System.IO; +using System.Reflection; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application references System.Web.dll +// * linker _must_ include all icalls +// ? that's what the mmp linker did, not clear (no history) why ? I could not find reflection usage of them ?!? +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class GdiPlus2 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); +#pragma warning disable 219 + // that will ensure System.Web reference is not removed + var sw = typeof (HttpApplication); +#pragma warning restore 219 + int mcount = Type.GetType ("System.Web.Util.ICalls, System.Web").GetMethods (BindingFlags.Public | BindingFlags.Static).Length; + Test.Log.WriteLine ("{0}\tSystem.Web.Util.ICalls {1}/3 icalls protected by linker", mcount == 3 ? "[PASS]" : "[FAIL]", mcount); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-system.web-icalls/link-system.web-icalls.csproj b/tests/mmptest/regression/link-system.web-icalls/link-system.web-icalls.csproj new file mode 100644 index 000000000000..db7367d3f915 --- /dev/null +++ b/tests/mmptest/regression/link-system.web-icalls/link-system.web-icalls.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linksystem.webicalls + Resources + link-system.web-icalls + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-typedescriptor-1/Info.plist b/tests/mmptest/regression/link-typedescriptor-1/Info.plist new file mode 100644 index 000000000000..a5ab15703670 --- /dev/null +++ b/tests/mmptest/regression/link-typedescriptor-1/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-typedescriptor-1 + CFBundleIdentifier + com.your-company.linktypedescriptor1 + CFBundleName + link-typedescriptor-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-typedescriptor-1/LinkTypeDescriptor1.cs b/tests/mmptest/regression/link-typedescriptor-1/LinkTypeDescriptor1.cs new file mode 100644 index 000000000000..85b4cf75b9bd --- /dev/null +++ b/tests/mmptest/regression/link-typedescriptor-1/LinkTypeDescriptor1.cs @@ -0,0 +1,66 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.ComponentModel; +using MonoMac.AppKit; + +// Test +// * Application use System.ComponentModel.TypeDescriptor +// * Application includes every *default* converter (see TypeDescriptor.cs) +// * Application does not include CustomConverter as it's not used by the application +// +// Requirement +// * Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + public class CustomConverter : TypeConverter { + } + + class TypeDescriptorTest { + + static void Check (string typeName) + { + var t = Type.GetType (typeName + ", System", false); + Test.Log.WriteLine ("{0}\t{1}", t != null ? "[PASS]" : "[FAIL]", typeName); + } + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + TypeDescriptor td = null; + Test.Log.WriteLine ("{0}\tTypeDescriptor", td == null ? "[PASS]" : "[FAIL]"); + + Check ("System.ComponentModel.BooleanConverter"); + Check ("System.ComponentModel.ByteConverter"); + Check ("System.ComponentModel.SByteConverter"); + Check ("System.ComponentModel.StringConverter"); + Check ("System.ComponentModel.CharConverter"); + Check ("System.ComponentModel.Int16Converter"); + Check ("System.ComponentModel.Int32Converter"); + Check ("System.ComponentModel.Int64Converter"); + Check ("System.ComponentModel.UInt16Converter"); + Check ("System.ComponentModel.UInt32Converter"); + Check ("System.ComponentModel.UInt64Converter"); + Check ("System.ComponentModel.SingleConverter"); + Check ("System.ComponentModel.DoubleConverter"); + Check ("System.ComponentModel.DecimalConverter"); + Check ("System.ComponentModel.TypeConverter"); + Check ("System.ComponentModel.ArrayConverter"); + Check ("System.ComponentModel.CultureInfoConverter"); + Check ("System.ComponentModel.DateTimeConverter"); + Check ("System.ComponentModel.GuidConverter"); + Check ("System.ComponentModel.TimeSpanConverter"); + Check ("System.ComponentModel.CollectionConverter"); + Check ("System.ComponentModel.EnumConverter"); + + var t = Type.GetType ("Xamarin.Mac.Linker.Test.CustomConverter", false); + Test.Log.WriteLine ("{0}\tXamarin.Mac.Linker.Test.CustomConverter", t == null ? "[PASS]" : "[FAIL]"); + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-typedescriptor-1/link-typedescriptor-1.csproj b/tests/mmptest/regression/link-typedescriptor-1/link-typedescriptor-1.csproj new file mode 100644 index 000000000000..0f3ae8dcbef2 --- /dev/null +++ b/tests/mmptest/regression/link-typedescriptor-1/link-typedescriptor-1.csproj @@ -0,0 +1,88 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {0AA2D44B-E4C6-4FC3-B49E-30ED3D744823} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linktypedescriptor1 + Resources + link-typedescriptor-1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-typedescriptor-2/Info.plist b/tests/mmptest/regression/link-typedescriptor-2/Info.plist new file mode 100644 index 000000000000..f2f7ec215584 --- /dev/null +++ b/tests/mmptest/regression/link-typedescriptor-2/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-typedescriptor-2 + CFBundleIdentifier + com.your-company.linktypedescriptor2 + CFBundleName + link-typedescriptor-2 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-typedescriptor-2/LinkTypeDescriptor2.cs b/tests/mmptest/regression/link-typedescriptor-2/LinkTypeDescriptor2.cs new file mode 100644 index 000000000000..5aaf89013f3d --- /dev/null +++ b/tests/mmptest/regression/link-typedescriptor-2/LinkTypeDescriptor2.cs @@ -0,0 +1,66 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.ComponentModel; +using MonoMac.AppKit; + +// Test +// * Application use [TypeConverter] on a custom (non default) TypeConverter +// * Application includes CustomConverter as it is used by the application +// +// Requirement +// * Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + public class CustomConverter : TypeConverter { + // note: the default ctor will be preserved by the linker because it's used in a [TypeConverter] attribute + } + + [TypeConverter (typeof (BooleanConverter))] + public class BuiltInConverter { + } + + [TypeConverter (typeof (CustomConverter))] + class TypeDescriptorTest { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + TypeConverter converter = null; + string msg = "BooleanConverter"; + + try { + converter = TypeDescriptor.GetConverter (new BuiltInConverter ()); + msg = (typeof (BuiltInConverter).GetCustomAttributes (false) [0] as TypeConverterAttribute).ConverterTypeName; + } + catch (Exception e) { + msg = e.ToString (); + } + finally { + Test.Log.WriteLine ("[{0}]\tTypeDescriptor.GetConverter BooleanConverter", converter != null ? "PASS" : "FAIL"); + bool success = msg == "System.ComponentModel.BooleanConverter, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + Test.Log.WriteLine ("[{0}]\t{1}", success ? "PASS" : "FAIL", msg); + } + + msg = "CustomConverter"; + try { + converter = TypeDescriptor.GetConverter (new TypeDescriptorTest ()); + msg = (typeof (TypeDescriptorTest).GetCustomAttributes (false) [0] as TypeConverterAttribute).ConverterTypeName; + } + catch (Exception e) { + msg = e.ToString (); + } + finally { + Test.Log.WriteLine ("[{0}]\tTypeDescriptor.GetConverter CustomConverter", converter != null ? "PASS" : "FAIL"); + bool success = msg == "Xamarin.Mac.Linker.Test.CustomConverter, link-typedescriptor-2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"; + Test.Log.WriteLine ("[{0}]\t{1}", success ? "PASS" : "FAIL", msg); + } + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-typedescriptor-2/link-typedescriptor-2.csproj b/tests/mmptest/regression/link-typedescriptor-2/link-typedescriptor-2.csproj new file mode 100644 index 000000000000..44eeb8494f84 --- /dev/null +++ b/tests/mmptest/regression/link-typedescriptor-2/link-typedescriptor-2.csproj @@ -0,0 +1,88 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {3FF064DE-5B37-404B-9FD1-234361AD3DB8} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linktypedescriptor2 + Resources + link-typedescriptor-2 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + true + false + Mac Developer + false + false + Developer ID Installer + + + Full + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + + + + + + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-uithread-1/Info.plist b/tests/mmptest/regression/link-uithread-1/Info.plist new file mode 100644 index 000000000000..89158585b83d --- /dev/null +++ b/tests/mmptest/regression/link-uithread-1/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-uithread-1 + CFBundleName + link-uithread-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-uithread-1/LinkUiThread.cs b/tests/mmptest/regression/link-uithread-1/LinkUiThread.cs new file mode 100644 index 000000000000..48e78ccabb85 --- /dev/null +++ b/tests/mmptest/regression/link-uithread-1/LinkUiThread.cs @@ -0,0 +1,72 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Threading; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * By default a DEBUG build will have a it thread checks enabled +// * link-uithread-1 defines DEBUG (and has debug symbols) +// * link-uithread-2 does not defined DEBUG (and no debug symbol) +// * so same source, two test cases +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class Tester : NSObject { + public static ManualResetEvent mre; + public static bool success; + + [CompilerGenerated] + [Export ("foo")] + public static void Test () + { + try { + NSApplication.EnsureUIThread (); +#if !DEBUG + success = true; +#endif + } + catch (AppKitThreadAccessException) { +#if DEBUG + success = true; +#endif + } + catch { + } + finally { + mre.Set (); + } + } + } + + class UiThread { + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + // works on main/ui thread + NSApplication.EnsureUIThread (); + + Tester.mre = new ManualResetEvent (false); + ThreadPool.QueueUserWorkItem ((v) => Tester.Test ()); + Tester.mre.WaitOne (); + Test.Log.WriteLine ("{0}\tEnsureUIThread {1} on non-ui thread: {2}", Tester.success ? "[PASS]" : "[FAIL]", +#if DEBUG + "enabled", +#else + "disabled", +#endif + Tester.success); + Test.Terminate (); + } + } +} diff --git a/tests/mmptest/regression/link-uithread-1/link-uithread-1.csproj b/tests/mmptest/regression/link-uithread-1/link-uithread-1.csproj new file mode 100644 index 000000000000..2cbae4c74c0c --- /dev/null +++ b/tests/mmptest/regression/link-uithread-1/link-uithread-1.csproj @@ -0,0 +1,98 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkuithread1 + Resources + link-uithread-1 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + False + true + False + False + Mac Developer + False + False + x86 + Developer ID Installer + + + Full + false + + + none + True + bin\Release + prompt + 4 + Full + False + True + False + True + Developer ID Application + True + False + x86 + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + False + True + 3rd Party Mac Developer Installer + False + True + 3rd Party Mac Developer Application + True + True + x86 + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-uithread-2/Info.plist b/tests/mmptest/regression/link-uithread-2/Info.plist new file mode 100644 index 000000000000..2b46663ae100 --- /dev/null +++ b/tests/mmptest/regression/link-uithread-2/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-uithread-2 + CFBundleName + link-uithread-2 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-uithread-2/link-uithread-2.csproj b/tests/mmptest/regression/link-uithread-2/link-uithread-2.csproj new file mode 100644 index 000000000000..e99444fd0042 --- /dev/null +++ b/tests/mmptest/regression/link-uithread-2/link-uithread-2.csproj @@ -0,0 +1,101 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {26909B1A-21F0-484A-9DD0-EE5F612FB91B} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkuithread2 + Resources + link-uithread-2 + + + none + True + bin\Debug + prompt + 4 + False + true + False + False + Mac Developer + False + False + x86 + Developer ID Installer + + + Full + false + + + none + True + bin\Release + prompt + 4 + Full + False + True + False + True + Developer ID Application + True + False + x86 + Developer ID Installer + + + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + False + True + 3rd Party Mac Developer Installer + False + True + 3rd Party Mac Developer Application + True + True + x86 + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + + + + Test.cs + + + LinkUiThread.cs + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-webclient-1/Info.plist b/tests/mmptest/regression/link-webclient-1/Info.plist new file mode 100644 index 000000000000..fe90ee60ade6 --- /dev/null +++ b/tests/mmptest/regression/link-webclient-1/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-webclient-1 + CFBundleName + link-webclient-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-webclient-1/LinkWebClient1.cs b/tests/mmptest/regression/link-webclient-1/LinkWebClient1.cs new file mode 100644 index 000000000000..67641d7404ba --- /dev/null +++ b/tests/mmptest/regression/link-webclient-1/LinkWebClient1.cs @@ -0,0 +1,42 @@ +// Copyright 2012-2013 Xamarin Inc. All rights reserved. + +using System; +using System.Net; +using MonoMac.AppKit; + +// Test +// * application use WebClient which uses HttpWeb[Request|Response] which depends on System.Configuration +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class WebClient1 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + bool success = false; + string message; + + try { + string url = "http://www.google.com"; + WebClient wc = new WebClient (); + string data = wc.DownloadString (url); + + success = !String.IsNullOrEmpty (data); + message = String.Format ("WebClient on '{0}' {1}.", url, success ? "succeeded" : "FAILED"); + } + catch (Exception e) { + message = e.ToString (); + } + + Test.Log.WriteLine ("{0}\t{1}", success ? "[PASS]" : "[FAIL]", message); + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-webclient-1/link-webclient-1.csproj b/tests/mmptest/regression/link-webclient-1/link-webclient-1.csproj new file mode 100644 index 000000000000..b377d4dc6598 --- /dev/null +++ b/tests/mmptest/regression/link-webclient-1/link-webclient-1.csproj @@ -0,0 +1,94 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {148DC17B-B29F-48A7-97CD-EECE26015B25} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkwebclient1 + Resources + link-webclient-1 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + + Test.cs + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-webclient-2/Info.plist b/tests/mmptest/regression/link-webclient-2/Info.plist new file mode 100644 index 000000000000..1171e1671c6d --- /dev/null +++ b/tests/mmptest/regression/link-webclient-2/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-webclient-2 + CFBundleName + link-webclient-2 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-webclient-2/LinkWebClient2.cs b/tests/mmptest/regression/link-webclient-2/LinkWebClient2.cs new file mode 100644 index 000000000000..7b76d0a46711 --- /dev/null +++ b/tests/mmptest/regression/link-webclient-2/LinkWebClient2.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using System.Net; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application use WebClient which uses HttpWeb[Request|Response] which depends on System.Configuration +// * application use HTTPS to ensure the SSL/TLS stack in included +// * dependencies check will include Mono.Security.dll for SSL/TLS support +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class WebClient2 { + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + bool success = false; + string message; + + try { + string url = "https://mail.google.com"; + WebClient wc = new WebClient (); + string data = wc.DownloadString (url); + + success = !String.IsNullOrEmpty (data); + message = String.Format ("WebClient on '{0}' {1}.", url, success ? "succeeded" : "FAILED"); + } + catch (Exception e) { + message = e.ToString (); + } + + Test.Log.WriteLine ("{0}\t{1}", success ? "[PASS]" : "[FAIL]", message); + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-webclient-2/link-webclient-2.csproj b/tests/mmptest/regression/link-webclient-2/link-webclient-2.csproj new file mode 100644 index 000000000000..f6a306e87fe4 --- /dev/null +++ b/tests/mmptest/regression/link-webclient-2/link-webclient-2.csproj @@ -0,0 +1,94 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {FA5882C9-C02D-4C7B-963B-AEA929D01390} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkwebclient2 + Resources + link-webclient-2 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + Test.cs + + + + + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-webclient-3/Info.plist b/tests/mmptest/regression/link-webclient-3/Info.plist new file mode 100644 index 000000000000..a7b425d91401 --- /dev/null +++ b/tests/mmptest/regression/link-webclient-3/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + com.yourcompany.link-webclient-3 + CFBundleName + link-webclient-3 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-webclient-3/LinkWebClientAsync.cs b/tests/mmptest/regression/link-webclient-3/LinkWebClientAsync.cs new file mode 100644 index 000000000000..9b1ba30eda76 --- /dev/null +++ b/tests/mmptest/regression/link-webclient-3/LinkWebClientAsync.cs @@ -0,0 +1,47 @@ +// Copyright 2012 Xamarin Inc. All rights reserved. + +using System; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +// Test +// * application use WebClient which uses HttpWeb[Request|Response] which depends on System.Configuration +// * use the new, .NET 4.5, async API +// +// Requirement +// * Link SDK or Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + class WebClientAsync { + + static bool success = false; + + static async Task GetWebPage (string url) + { + WebClient wc = new WebClient (); + Task task = wc.DownloadStringTaskAsync (new Uri (url)); + string data = await task; + success = !String.IsNullOrEmpty (data); + } + + static void Main (string[] args) + { + NSApplication.Init (); + // we do not want the async code to get back to the AppKit thread, hanging the process + SynchronizationContext.SetSynchronizationContext (null); + + Test.EnsureLinker (true); + + string url = "http://www.google.com"; + GetWebPage (url).Wait (); + + Test.Log.WriteLine ("{0}\tWebClient async on {1}", success ? "[PASS]" : "[FAIL]", url); + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-webclient-3/link-webclient-3.csproj b/tests/mmptest/regression/link-webclient-3/link-webclient-3.csproj new file mode 100644 index 000000000000..48d83b8463ee --- /dev/null +++ b/tests/mmptest/regression/link-webclient-3/link-webclient-3.csproj @@ -0,0 +1,95 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkwebclient3 + Resources + link-webclient-3 + v4.5 + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + True + False + False + Mac Developer + False + False + x86 + 3rd Party Mac Developer Installer + + + Full + false + false + + + none + True + bin\Release + prompt + 4 + Full + False + False + False + Mac Developer + False + False + x86 + false + false + + + none + True + bin\x86\AppStore + prompt + 4 + Full + True + 3rd Party Mac Developer Installer + True + True + 3rd Party Mac Developer Application + True + False + x86 + false + false + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + MainMenu.xib + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/link-xml-serialization/Info.plist b/tests/mmptest/regression/link-xml-serialization/Info.plist new file mode 100644 index 000000000000..01d7b902cb80 --- /dev/null +++ b/tests/mmptest/regression/link-xml-serialization/Info.plist @@ -0,0 +1,16 @@ + + + + + CFBundleName + link-xml-serialization + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/link-xml-serialization/LinkXmlSerialization.cs b/tests/mmptest/regression/link-xml-serialization/LinkXmlSerialization.cs new file mode 100644 index 000000000000..95ca0e38f159 --- /dev/null +++ b/tests/mmptest/regression/link-xml-serialization/LinkXmlSerialization.cs @@ -0,0 +1,57 @@ +// Copyright 2013 Xamarin Inc. All rights reserved. + +using System; +using System.IO; +using System.Xml; +using System.Xml.Serialization; +using MonoMac.AppKit; + +// Test +// * application use XML serialization +// * the [Xml*Attribute] also serve as a [Preserve] attribute +// +// Requirement +// * Link All must be enabled + +namespace Xamarin.Mac.Linker.Test { + + public class SerializeMe { + + [XmlAttribute] + public int SetMe { get; set; } + + public SerializeMe () + { + SetMe = 1; + } + } + + class XmlSerialization { + + const string xml = "" + + "" + + ""; + + static void Main (string[] args) + { + NSApplication.Init (); + + Test.EnsureLinker (true); + + bool success = false; + + try { + using (var sr = new StringReader (xml)) + using (var xr = new XmlTextReader (sr)) { + var xs = new XmlSerializer (typeof (SerializeMe)); + SerializeMe item = xs.Deserialize (xr) as SerializeMe; + success = item.SetMe == 2; + } + } + finally { + Test.Log.WriteLine ("{0}\tXmlSerialization", success ? "[PASS]" : "[FAIL]"); + Test.Terminate (); + } + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/link-xml-serialization/Main.cs b/tests/mmptest/regression/link-xml-serialization/Main.cs new file mode 100644 index 000000000000..024dc9b65dca --- /dev/null +++ b/tests/mmptest/regression/link-xml-serialization/Main.cs @@ -0,0 +1,18 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace linkxmlserialization +{ + class MainClass + { + static void Main (string [] args) + { + NSApplication.Init (); + NSApplication.Main (args); + } + } +} + diff --git a/tests/mmptest/regression/link-xml-serialization/link-xml-serialization.csproj b/tests/mmptest/regression/link-xml-serialization/link-xml-serialization.csproj new file mode 100644 index 000000000000..ed94e95b7b05 --- /dev/null +++ b/tests/mmptest/regression/link-xml-serialization/link-xml-serialization.csproj @@ -0,0 +1,92 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {6223332F-517A-43D0-9BCC-037645A24E97} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + linkxmlserialization + Resources + link-xml-serialization + + + true + false + bin\Debug + DEBUG; + prompt + 4 + false + true + false + false + Mac Developer + false + false + x86 + Developer ID Installer + + + Full + false + + + true + bin\Release + prompt + 4 + Full + false + true + false + true + Developer ID Application + true + false + x86 + false + + + true + bin\x86\AppStore + prompt + 4 + Full + false + true + 3rd Party Mac Developer Installer + false + true + 3rd Party Mac Developer Application + true + true + x86 + false + + + + + + ..\..\..\..\src\build\compat\XamMac.dll + + + + + + + + + + Test.cs + + + + + + MainMenu.xib + + + \ No newline at end of file diff --git a/tests/mmptest/regression/system-mono-profile/Info.plist b/tests/mmptest/regression/system-mono-profile/Info.plist new file mode 100644 index 000000000000..9fe30d5a06ba --- /dev/null +++ b/tests/mmptest/regression/system-mono-profile/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-nativebuilder-1 + CFBundleIdentifier + com.your-company.linknativebuilder1 + CFBundleName + link-nativebuilder-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/system-mono-profile/system-mono-profile.cs b/tests/mmptest/regression/system-mono-profile/system-mono-profile.cs new file mode 100644 index 000000000000..1662f33dc60d --- /dev/null +++ b/tests/mmptest/regression/system-mono-profile/system-mono-profile.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +using AppKit; +using ObjCRuntime; + +namespace Xamarin.Mac.Linker.Test { + + class SystemMono { + static void Main (string[] args) + { + NSApplication.Init (); + + if (File.Exists ("output.mlpd")) { + Test.Log.WriteLine ("SUCCESS: log output exists"); + } else { + Test.Log.WriteLine ("FAIL: could not find 'output.mlpd'"); + } + + Test.Terminate (); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/system-mono-profile/system-mono-profile.csproj b/tests/mmptest/regression/system-mono-profile/system-mono-profile.csproj new file mode 100644 index 000000000000..74263ae4a5ba --- /dev/null +++ b/tests/mmptest/regression/system-mono-profile/system-mono-profile.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + systemmono + Resources + system-mono-profile + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + Mac Developer + false + false + Developer ID Installer + false + --embed-mono=no + x86_64 + + + + + + + + + + + + + + Test.cs + + + + \ No newline at end of file diff --git a/tests/mmptest/regression/system-mono/Info.plist b/tests/mmptest/regression/system-mono/Info.plist new file mode 100644 index 000000000000..9fe30d5a06ba --- /dev/null +++ b/tests/mmptest/regression/system-mono/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + link-nativebuilder-1 + CFBundleIdentifier + com.your-company.linknativebuilder1 + CFBundleName + link-nativebuilder-1 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/mmptest/regression/system-mono/system-mono.cs b/tests/mmptest/regression/system-mono/system-mono.cs new file mode 100644 index 000000000000..de71d4ef5c69 --- /dev/null +++ b/tests/mmptest/regression/system-mono/system-mono.cs @@ -0,0 +1,53 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +using AppKit; +using ObjCRuntime; + +namespace Xamarin.Mac.Linker.Test { + + class SystemMono { + static void Main (string[] args) + { + NSApplication.Init (); + + TestDlopenSystem (); + TestDlopenEmbedded (); + + Test.Terminate (); + } + + [DllImport ("libSystem.dylib")] + public static extern IntPtr dlopen (string path, int mode); + + static void TestDlopenSystem () + { + try { + IntPtr h = dlopen ("libc.dylib", 0); + if (h == IntPtr.Zero) { + Test.Log.WriteLine ("[FAIL] TestDlopenSystem: Could not dlopen libc.dylib"); + } else { + Test.Log.WriteLine ("[SUCCESS] TestDlopenSystem: dlopen libc.dylib: 0x{0}", h.ToString ("x")); + Dlfcn.dlclose (h); + } + } catch (Exception ex) { + Test.Log.WriteLine ("[FAIL] TestDlopenSystem: {0}", ex); + } + } + [DllImport ("libTest.dylib")] + static extern int the_answer (); + + static void TestDlopenEmbedded () + { + try { + var a = the_answer (); + Test.Log.WriteLine ("[SUCCESS] TestDlopenEmbedded: {0}", a); + } catch (Exception ex) { + Test.Log.WriteLine ("[FAIL] TestDlopenEmbedded: {0}", ex); + } + } + } +} \ No newline at end of file diff --git a/tests/mmptest/regression/system-mono/system-mono.csproj b/tests/mmptest/regression/system-mono/system-mono.csproj new file mode 100644 index 000000000000..5eb29d848f8b --- /dev/null +++ b/tests/mmptest/regression/system-mono/system-mono.csproj @@ -0,0 +1,57 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5AB27219-C1A8-4BAB-AD23-57B807E701EE} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + systemmono + Resources + system-mono + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + Mac Developer + false + false + Developer ID Installer + false + --embed-mono=no + x86_64 + + + + + + + + + + + + + + Test.cs + + + + + + False + Dynamic + + + \ No newline at end of file diff --git a/tests/mmptest/regression/tests.sln b/tests/mmptest/regression/tests.sln new file mode 100644 index 000000000000..a4d312039fdf --- /dev/null +++ b/tests/mmptest/regression/tests.sln @@ -0,0 +1,244 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-posix-1", "link-posix-1\link-posix-1.csproj", "{BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-posix-2", "link-posix-2\link-posix-2.csproj", "{141239A4-4094-4349-A3F3-00CD16643226}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-gdiplus-1", "link-gdiplus-1\link-gdiplus-1.csproj", "{150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-webclient-1", "link-webclient-1\link-webclient-1.csproj", "{148DC17B-B29F-48A7-97CD-EECE26015B25}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-webclient-2", "link-webclient-2\link-webclient-2.csproj", "{FA5882C9-C02D-4C7B-963B-AEA929D01390}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-callfilepath-45", "link-callfilepath-45\link-callfilepath-45.csproj", "{ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-httpclient-async", "link-httpclient-async\link-httpclient-async.csproj", "{CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-webclient-3", "link-webclient-3\link-webclient-3.csproj", "{359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-gdiplus-2", "link-gdiplus-2\link-gdiplus-2.csproj", "{CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-system.web-icalls", "link-system.web-icalls\link-system.web-icalls.csproj", "{6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-keep-resources-1", "link-keep-resources-1\link-keep-resources-1.csproj", "{0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-keep-resources-2", "link-keep-resources-2\link-keep-resources-2.csproj", "{9D5EA758-05CE-416C-B2D1-523E481C0DCD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-preserve-assembly", "link-preserve-assembly\link-preserve-assembly.csproj", "{39DD1BD5-1204-4D9E-A460-3A532DB3A797}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-uithread-1", "link-uithread-1\link-uithread-1.csproj", "{1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-uithread-2", "link-uithread-2\link-uithread-2.csproj", "{26909B1A-21F0-484A-9DD0-EE5F612FB91B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-xml-serialization", "link-xml-serialization\link-xml-serialization.csproj", "{6223332F-517A-43D0-9BCC-037645A24E97}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-remove-attributes-1", "link-remove-attributes-1\link-remove-attributes-1.csproj", "{F977D041-B0A5-49DE-815E-B210DBE140A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-safe-1", "link-safe-1\link-safe-1.csproj", "{F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-frameworks-1", "link-frameworks-1\link-frameworks-1.csproj", "{842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-aes-1", "link-aes-1\link-aes-1.csproj", "{12A3E976-A434-4512-8579-CA395923874D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-data-contract-1", "link-data-contract-1\link-data-contract-1.csproj", "{CCE59D9C-CA71-4DB8-8156-98D7A9428534}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-nativebuilder-1", "link-nativebuilder-1\link-nativebuilder-1.csproj", "{D37FC010-0D17-4B68-ABA8-33BA599CD94C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-blocks-1", "link-blocks-1\link-blocks-1.csproj", "{26634789-2957-4A78-BBF0-929BCA74440F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-preserve-calendar-1", "link-preserve-calendar-1\link-preserve-calendar-1.csproj", "{910B8B76-46C3-4550-AB5C-BD813F053A98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link-preserve-calendar-2", "link-preserve-calendar-2\link-preserve-calendar-2.csproj", "{88BD48BB-BF1C-40B2-90C0-3C2C644E3037}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "system-mono", "system-mono\system-mono.csproj", "{5AB27219-C1A8-4BAB-AD23-57B807E701EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "embedded-mono", "embedded-mono\embedded-mono.csproj", "{B211EB73-67F5-40C0-9030-F91385DFF077}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "system-mono-profile", "system-mono-profile\system-mono-profile.csproj", "{93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "embedded-mono-profile", "embedded-mono-profile\embedded-mono-profile.csproj", "{7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + AppStore|x86 = AppStore|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}.AppStore|x86.ActiveCfg = AppStore|x86 + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}.AppStore|x86.Build.0 = AppStore|x86 + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}.Debug|x86.ActiveCfg = Debug|x86 + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}.Debug|x86.Build.0 = Debug|x86 + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}.Release|x86.ActiveCfg = Release|x86 + {0A4EBB71-92E1-448C-BAA6-DFFB9491D8A0}.Release|x86.Build.0 = Release|x86 + {12A3E976-A434-4512-8579-CA395923874D}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {12A3E976-A434-4512-8579-CA395923874D}.AppStore|x86.Build.0 = AppStore|Any CPU + {12A3E976-A434-4512-8579-CA395923874D}.Debug|x86.ActiveCfg = Debug|Any CPU + {12A3E976-A434-4512-8579-CA395923874D}.Debug|x86.Build.0 = Debug|Any CPU + {12A3E976-A434-4512-8579-CA395923874D}.Release|x86.ActiveCfg = Release|Any CPU + {12A3E976-A434-4512-8579-CA395923874D}.Release|x86.Build.0 = Release|Any CPU + {141239A4-4094-4349-A3F3-00CD16643226}.AppStore|x86.ActiveCfg = AppStore|x86 + {141239A4-4094-4349-A3F3-00CD16643226}.AppStore|x86.Build.0 = AppStore|x86 + {141239A4-4094-4349-A3F3-00CD16643226}.Debug|x86.ActiveCfg = Debug|x86 + {141239A4-4094-4349-A3F3-00CD16643226}.Debug|x86.Build.0 = Debug|x86 + {141239A4-4094-4349-A3F3-00CD16643226}.Release|x86.ActiveCfg = Release|x86 + {141239A4-4094-4349-A3F3-00CD16643226}.Release|x86.Build.0 = Release|x86 + {148DC17B-B29F-48A7-97CD-EECE26015B25}.AppStore|x86.ActiveCfg = AppStore|x86 + {148DC17B-B29F-48A7-97CD-EECE26015B25}.AppStore|x86.Build.0 = AppStore|x86 + {148DC17B-B29F-48A7-97CD-EECE26015B25}.Debug|x86.ActiveCfg = Debug|x86 + {148DC17B-B29F-48A7-97CD-EECE26015B25}.Debug|x86.Build.0 = Debug|x86 + {148DC17B-B29F-48A7-97CD-EECE26015B25}.Release|x86.ActiveCfg = Release|x86 + {148DC17B-B29F-48A7-97CD-EECE26015B25}.Release|x86.Build.0 = Release|x86 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}.AppStore|x86.ActiveCfg = AppStore|x86 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}.AppStore|x86.Build.0 = AppStore|x86 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}.Debug|x86.ActiveCfg = Debug|x86 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}.Debug|x86.Build.0 = Debug|x86 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}.Release|x86.ActiveCfg = Release|x86 + {150FA3E6-0AFA-417E-A7FA-B13E95B46CF0}.Release|x86.Build.0 = Release|x86 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}.AppStore|x86.ActiveCfg = AppStore|x86 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}.AppStore|x86.Build.0 = AppStore|x86 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}.Debug|x86.ActiveCfg = Debug|x86 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}.Debug|x86.Build.0 = Debug|x86 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}.Release|x86.ActiveCfg = Release|x86 + {1F4422A4-C6B2-49B5-BB1D-6CA4676397CA}.Release|x86.Build.0 = Release|x86 + {26634789-2957-4A78-BBF0-929BCA74440F}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {26634789-2957-4A78-BBF0-929BCA74440F}.AppStore|x86.Build.0 = AppStore|Any CPU + {26634789-2957-4A78-BBF0-929BCA74440F}.Debug|x86.ActiveCfg = Debug|Any CPU + {26634789-2957-4A78-BBF0-929BCA74440F}.Debug|x86.Build.0 = Debug|Any CPU + {26634789-2957-4A78-BBF0-929BCA74440F}.Release|x86.ActiveCfg = Release|Any CPU + {26634789-2957-4A78-BBF0-929BCA74440F}.Release|x86.Build.0 = Release|Any CPU + {26909B1A-21F0-484A-9DD0-EE5F612FB91B}.AppStore|x86.ActiveCfg = AppStore|x86 + {26909B1A-21F0-484A-9DD0-EE5F612FB91B}.AppStore|x86.Build.0 = AppStore|x86 + {26909B1A-21F0-484A-9DD0-EE5F612FB91B}.Debug|x86.ActiveCfg = Debug|x86 + {26909B1A-21F0-484A-9DD0-EE5F612FB91B}.Debug|x86.Build.0 = Debug|x86 + {26909B1A-21F0-484A-9DD0-EE5F612FB91B}.Release|x86.ActiveCfg = Release|x86 + {26909B1A-21F0-484A-9DD0-EE5F612FB91B}.Release|x86.Build.0 = Release|x86 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}.AppStore|x86.ActiveCfg = AppStore|x86 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}.AppStore|x86.Build.0 = AppStore|x86 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}.Debug|x86.ActiveCfg = Debug|x86 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}.Debug|x86.Build.0 = Debug|x86 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}.Release|x86.ActiveCfg = Release|x86 + {359E3AA4-A0E2-41A5-A5C5-03D322B71FE4}.Release|x86.Build.0 = Release|x86 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797}.AppStore|x86.ActiveCfg = AppStore|x86 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797}.AppStore|x86.Build.0 = AppStore|x86 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797}.Debug|x86.ActiveCfg = Debug|x86 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797}.Debug|x86.Build.0 = Debug|x86 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797}.Release|x86.ActiveCfg = Release|x86 + {39DD1BD5-1204-4D9E-A460-3A532DB3A797}.Release|x86.Build.0 = Release|x86 + {5AB27219-C1A8-4BAB-AD23-57B807E701EE}.AppStore|x86.ActiveCfg = Debug|Any CPU + {5AB27219-C1A8-4BAB-AD23-57B807E701EE}.AppStore|x86.Build.0 = Debug|Any CPU + {5AB27219-C1A8-4BAB-AD23-57B807E701EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {5AB27219-C1A8-4BAB-AD23-57B807E701EE}.Debug|x86.Build.0 = Debug|Any CPU + {5AB27219-C1A8-4BAB-AD23-57B807E701EE}.Release|x86.ActiveCfg = Debug|Any CPU + {5AB27219-C1A8-4BAB-AD23-57B807E701EE}.Release|x86.Build.0 = Debug|Any CPU + {6223332F-517A-43D0-9BCC-037645A24E97}.AppStore|x86.ActiveCfg = AppStore|x86 + {6223332F-517A-43D0-9BCC-037645A24E97}.AppStore|x86.Build.0 = AppStore|x86 + {6223332F-517A-43D0-9BCC-037645A24E97}.Debug|x86.ActiveCfg = Debug|x86 + {6223332F-517A-43D0-9BCC-037645A24E97}.Debug|x86.Build.0 = Debug|x86 + {6223332F-517A-43D0-9BCC-037645A24E97}.Release|x86.ActiveCfg = Release|x86 + {6223332F-517A-43D0-9BCC-037645A24E97}.Release|x86.Build.0 = Release|x86 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}.AppStore|x86.ActiveCfg = AppStore|x86 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}.AppStore|x86.Build.0 = AppStore|x86 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}.Debug|x86.ActiveCfg = Debug|x86 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}.Debug|x86.Build.0 = Debug|x86 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}.Release|x86.ActiveCfg = Release|x86 + {6F2CC0E5-BE6A-4B96-AEDE-1A6EFE517166}.Release|x86.Build.0 = Release|x86 + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}.AppStore|x86.ActiveCfg = Debug|Any CPU + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}.AppStore|x86.Build.0 = Debug|Any CPU + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}.Debug|x86.Build.0 = Debug|Any CPU + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}.Release|x86.ActiveCfg = Debug|Any CPU + {7B6ECB8B-ED54-4687-A8BE-7ADA22973F3F}.Release|x86.Build.0 = Debug|Any CPU + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}.AppStore|x86.Build.0 = AppStore|Any CPU + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}.Debug|x86.ActiveCfg = Debug|Any CPU + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}.Debug|x86.Build.0 = Debug|Any CPU + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}.Release|x86.ActiveCfg = Release|Any CPU + {842CDD77-7FC8-4BAB-AF69-C6C0D9DB217C}.Release|x86.Build.0 = Release|Any CPU + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037}.AppStore|x86.Build.0 = AppStore|Any CPU + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037}.Debug|x86.ActiveCfg = Debug|Any CPU + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037}.Debug|x86.Build.0 = Debug|Any CPU + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037}.Release|x86.ActiveCfg = Release|Any CPU + {88BD48BB-BF1C-40B2-90C0-3C2C644E3037}.Release|x86.Build.0 = Release|Any CPU + {910B8B76-46C3-4550-AB5C-BD813F053A98}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {910B8B76-46C3-4550-AB5C-BD813F053A98}.AppStore|x86.Build.0 = AppStore|Any CPU + {910B8B76-46C3-4550-AB5C-BD813F053A98}.Debug|x86.ActiveCfg = Debug|Any CPU + {910B8B76-46C3-4550-AB5C-BD813F053A98}.Debug|x86.Build.0 = Debug|Any CPU + {910B8B76-46C3-4550-AB5C-BD813F053A98}.Release|x86.ActiveCfg = Release|Any CPU + {910B8B76-46C3-4550-AB5C-BD813F053A98}.Release|x86.Build.0 = Release|Any CPU + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}.AppStore|x86.ActiveCfg = Debug|Any CPU + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}.AppStore|x86.Build.0 = Debug|Any CPU + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}.Debug|x86.ActiveCfg = Debug|Any CPU + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}.Debug|x86.Build.0 = Debug|Any CPU + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}.Release|x86.ActiveCfg = Debug|Any CPU + {93DA5A65-BA7F-4E75-AD7A-588ABC9834BB}.Release|x86.Build.0 = Debug|Any CPU + {9D5EA758-05CE-416C-B2D1-523E481C0DCD}.AppStore|x86.ActiveCfg = AppStore|x86 + {9D5EA758-05CE-416C-B2D1-523E481C0DCD}.AppStore|x86.Build.0 = AppStore|x86 + {9D5EA758-05CE-416C-B2D1-523E481C0DCD}.Debug|x86.ActiveCfg = Debug|x86 + {9D5EA758-05CE-416C-B2D1-523E481C0DCD}.Debug|x86.Build.0 = Debug|x86 + {9D5EA758-05CE-416C-B2D1-523E481C0DCD}.Release|x86.ActiveCfg = Release|x86 + {9D5EA758-05CE-416C-B2D1-523E481C0DCD}.Release|x86.Build.0 = Release|x86 + {B211EB73-67F5-40C0-9030-F91385DFF077}.AppStore|x86.ActiveCfg = Debug|Any CPU + {B211EB73-67F5-40C0-9030-F91385DFF077}.AppStore|x86.Build.0 = Debug|Any CPU + {B211EB73-67F5-40C0-9030-F91385DFF077}.Debug|x86.ActiveCfg = Debug|Any CPU + {B211EB73-67F5-40C0-9030-F91385DFF077}.Debug|x86.Build.0 = Debug|Any CPU + {B211EB73-67F5-40C0-9030-F91385DFF077}.Release|x86.ActiveCfg = Debug|Any CPU + {B211EB73-67F5-40C0-9030-F91385DFF077}.Release|x86.Build.0 = Debug|Any CPU + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}.AppStore|x86.ActiveCfg = AppStore|x86 + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}.AppStore|x86.Build.0 = AppStore|x86 + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}.Debug|x86.ActiveCfg = Debug|x86 + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}.Debug|x86.Build.0 = Debug|x86 + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}.Release|x86.ActiveCfg = Release|x86 + {BB0442BD-28A5-4F1E-8101-F5060AB9E8D2}.Release|x86.Build.0 = Release|x86 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}.AppStore|x86.ActiveCfg = AppStore|x86 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}.AppStore|x86.Build.0 = AppStore|x86 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}.Debug|x86.ActiveCfg = Debug|x86 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}.Debug|x86.Build.0 = Debug|x86 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}.Release|x86.ActiveCfg = Release|x86 + {CA9DCC2E-8DD6-4E73-A5E4-980028A9436C}.Release|x86.Build.0 = Release|x86 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}.AppStore|x86.ActiveCfg = AppStore|x86 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}.AppStore|x86.Build.0 = AppStore|x86 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}.Debug|x86.ActiveCfg = Debug|x86 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}.Debug|x86.Build.0 = Debug|x86 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}.Release|x86.ActiveCfg = Release|x86 + {CB3AC1BE-2C81-4CAF-A9AA-5838816CA705}.Release|x86.Build.0 = Release|x86 + {CCE59D9C-CA71-4DB8-8156-98D7A9428534}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {CCE59D9C-CA71-4DB8-8156-98D7A9428534}.AppStore|x86.Build.0 = AppStore|Any CPU + {CCE59D9C-CA71-4DB8-8156-98D7A9428534}.Debug|x86.ActiveCfg = Debug|Any CPU + {CCE59D9C-CA71-4DB8-8156-98D7A9428534}.Debug|x86.Build.0 = Debug|Any CPU + {CCE59D9C-CA71-4DB8-8156-98D7A9428534}.Release|x86.ActiveCfg = Release|Any CPU + {CCE59D9C-CA71-4DB8-8156-98D7A9428534}.Release|x86.Build.0 = Release|Any CPU + {D37FC010-0D17-4B68-ABA8-33BA599CD94C}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {D37FC010-0D17-4B68-ABA8-33BA599CD94C}.AppStore|x86.Build.0 = AppStore|Any CPU + {D37FC010-0D17-4B68-ABA8-33BA599CD94C}.Debug|x86.ActiveCfg = Debug|Any CPU + {D37FC010-0D17-4B68-ABA8-33BA599CD94C}.Debug|x86.Build.0 = Debug|Any CPU + {D37FC010-0D17-4B68-ABA8-33BA599CD94C}.Release|x86.ActiveCfg = Release|Any CPU + {D37FC010-0D17-4B68-ABA8-33BA599CD94C}.Release|x86.Build.0 = Release|Any CPU + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}.AppStore|x86.ActiveCfg = AppStore|x86 + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}.AppStore|x86.Build.0 = AppStore|x86 + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}.Debug|x86.ActiveCfg = Debug|x86 + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}.Debug|x86.Build.0 = Debug|x86 + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}.Release|x86.ActiveCfg = Release|x86 + {ECD8A26B-F82B-45E1-A96C-0D97EDD3372B}.Release|x86.Build.0 = Release|x86 + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}.AppStore|x86.Build.0 = AppStore|Any CPU + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}.Debug|x86.ActiveCfg = Debug|Any CPU + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}.Debug|x86.Build.0 = Debug|Any CPU + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}.Release|x86.ActiveCfg = Release|Any CPU + {F81E9BA8-5CEC-4A39-AC70-44DFA9C405DB}.Release|x86.Build.0 = Release|Any CPU + {F977D041-B0A5-49DE-815E-B210DBE140A5}.AppStore|x86.ActiveCfg = AppStore|Any CPU + {F977D041-B0A5-49DE-815E-B210DBE140A5}.AppStore|x86.Build.0 = AppStore|Any CPU + {F977D041-B0A5-49DE-815E-B210DBE140A5}.Debug|x86.ActiveCfg = Debug|Any CPU + {F977D041-B0A5-49DE-815E-B210DBE140A5}.Debug|x86.Build.0 = Debug|Any CPU + {F977D041-B0A5-49DE-815E-B210DBE140A5}.Release|x86.ActiveCfg = Release|Any CPU + {F977D041-B0A5-49DE-815E-B210DBE140A5}.Release|x86.Build.0 = Release|Any CPU + {FA5882C9-C02D-4C7B-963B-AEA929D01390}.AppStore|x86.ActiveCfg = AppStore|x86 + {FA5882C9-C02D-4C7B-963B-AEA929D01390}.AppStore|x86.Build.0 = AppStore|x86 + {FA5882C9-C02D-4C7B-963B-AEA929D01390}.Debug|x86.ActiveCfg = Debug|x86 + {FA5882C9-C02D-4C7B-963B-AEA929D01390}.Debug|x86.Build.0 = Debug|x86 + {FA5882C9-C02D-4C7B-963B-AEA929D01390}.Release|x86.ActiveCfg = Release|x86 + {FA5882C9-C02D-4C7B-963B-AEA929D01390}.Release|x86.Build.0 = Release|x86 + EndGlobalSection +EndGlobal diff --git a/tests/mmptest/src/ClassicTests.cs b/tests/mmptest/src/ClassicTests.cs new file mode 100644 index 000000000000..ba75120af79f --- /dev/null +++ b/tests/mmptest/src/ClassicTests.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Reflection; + +namespace Xamarin.MMP.Tests +{ + public partial class MMPTests + { + bool ShouldSkipClassicTest + { + get + { + return TI.FindMonoVersion () < new Version ("4.3") || !PlatformHelpers.CheckSystemVersion (10, 10); // mdtool build requires us to be on a version that XS supports + } + } + + [Test] + public void Classic_SmokeTest () + { + if (ShouldSkipClassicTest) + return; + + RunMMPTest (tmpDir => { + TI.TestClassicExecutable (tmpDir); + }); + } + + [Test] + public void Classic_IntPtr_BindingTest () // Desk 88943, bug 22729, bug 22714 + { + if (ShouldSkipClassicTest) + return; + + const string IntPtrTestCase = @"NSDictionary d = new NSDictionary (); + NSObject o = d; + NSObject v = o.ValueForKey ((NSString)""count"");"; + RunMMPTest (tmpDir => { + TI.TestClassicExecutable (tmpDir, IntPtrTestCase); + }); + } + + [Test] + public void Classic_NewRefCount_Warns () + { + if (ShouldSkipClassicTest) + return; + + RunMMPTest (tmpDir => { + string buildOutput = TI.TestClassicExecutable (tmpDir, csprojConfig : "true--new-refcount=false"); + Assert.IsTrue (buildOutput.Contains ("Disabling the new refcount logic is deprecated"), "Classic_NewRefCount_Warns did not warn as expected:\n\n", buildOutput); + }); + } + } +} diff --git a/tests/mmptest/src/ExtensionTests.cs b/tests/mmptest/src/ExtensionTests.cs new file mode 100644 index 000000000000..2053605a4a85 --- /dev/null +++ b/tests/mmptest/src/ExtensionTests.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Reflection; + +namespace Xamarin.MMP.Tests +{ + [TestFixture] + public partial class MMPTests + { + [Test] + public void TodayExtension_SmokeTest () + { + RunMMPTest (tmpDir => + { + string testPath = Path.Combine (TI.FindSourceDirectory (), @"Today/TodayExtensionTest.csproj"); + TI.BuildProject (testPath, true, false); + }); + } + + [Test] + public void FinderExtension_SmokeTest () + { + RunMMPTest (tmpDir => + { + string testPath = Path.Combine (TI.FindSourceDirectory (), @"Finder/FinderExtensionTest.csproj"); + TI.BuildProject (testPath, true, false); + }); + } + + [Test] + public void ShareExtension_SmokeTest () + { + RunMMPTest (tmpDir => + { + string testPath = Path.Combine (TI.FindSourceDirectory (), @"Share/ShareExtensionTest.csproj"); + TI.BuildProject (testPath, true, false); + }); + } + } +} diff --git a/tests/mmptest/src/MMPTest.cs b/tests/mmptest/src/MMPTest.cs new file mode 100644 index 000000000000..c8d8bdc988d5 --- /dev/null +++ b/tests/mmptest/src/MMPTest.cs @@ -0,0 +1,309 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Reflection; + +namespace Xamarin.MMP.Tests +{ + [TestFixture] + public partial class MMPTests + { + void RunMMPTest (Action test) + { + string tmpDir = Path.Combine (Path.GetTempPath (), "mmp-test-dir"); + try { + Directory.CreateDirectory (tmpDir); + test (tmpDir); + } + finally { + Directory.Delete (tmpDir, true); + } + } + + [Test] + public void CollisionsBetweenLibraryNameAndEXE_ShouldFailBuild () + { + RunMMPTest (tmpDir => { + Action testCore = (projectName, assemblyName, XM45) => { + // Build a library with the conflicting name + TI.UnifiedTestConfig libConfig = new TI.UnifiedTestConfig (tmpDir) { XM45 = XM45, ProjectName = projectName, AssemblyName = assemblyName }; + string csprojTarget = TI.GenerateUnifiedLibraryProject (libConfig); + TI.BuildProject (csprojTarget, isUnified : true); + + // Build an exe using that library, it should fail the build + string referenceCode = string.Format (@"{0}", Path.Combine (tmpDir, "bin/Debug", assemblyName + ".dll")); + + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = XM45, References = referenceCode }; + TI.TestUnifiedExecutable (test, shouldFail : true); + }; + // These library assembly names conflict with the exe name + testCore ("UnifiedLibrary", "UnifiedExample", false); + testCore ("XM45Library", "XM45Example", true); + }); + } + + [Test] + public void CollisionBetweenEXEAndSDKAssembly_ShouldFailBuild () + { + RunMMPTest (tmpDir => { + Action testCore = (assemblyName, XM45) => { + // Build a library with the conflicting name + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { XM45 = XM45, AssemblyName = assemblyName }; + TI.TestUnifiedExecutable (test, shouldFail : true); + }; + // These library assembly names conflict with the exe name + testCore ("Xamarin.Mac", false); + testCore ("Xamarin.Mac", true); + + testCore ("System.Xml", false); + testCore ("System.Xml", true); + }); + } + + [Test] + public void Unified_Static_RegistrarTest () + { + if (!PlatformHelpers.CheckSystemVersion (10, 11)) + return; + + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "--registrar=static" }; + // Mobile + TI.TestUnifiedExecutable (test); + // XM45 + test.XM45 = true; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void XM_45_NotAddingIncorrectDependencies_LicenseTest () + { + RunMMPTest (tmpDir => { + TI.TestUnifiedExecutable (new TI.UnifiedTestConfig (tmpDir) { XM45 = true }); + + // XM 4.5 projects were accidently pulling in every assembly in the 4.5 folder. Assert that isn't happening again. + string monoBundlePath = Path.Combine (tmpDir, "bin/Debug/XM45Example.app/Contents/MonoBundle/"); + Assert.IsFalse (Directory.GetFiles (monoBundlePath).Any (x => x.Contains ("FSharp.Core.dll")), "F# was pulled in?"); + }); + } + + [Test] + public void Unified_SmokeTest () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir); + // Mobile + TI.TestUnifiedExecutable (test); + // XM45 + test.XM45 = true; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void FSharp_SmokeTest () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { FSharp = true }; + // Mobile + TI.TestUnifiedExecutable (test); + // XM45 + test.XM45 = true; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void Mobile_SmokeTest_LinkSDK () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "SdkOnly" }; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void Mobile_SmokeTest_LinkAll () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "Full" }; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void Mobile_NewRefCount_Warns () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "--new-refcount=false" }; + string buildOutput = TI.TestUnifiedExecutable (test); + Assert.IsTrue (buildOutput.Contains ("Disabling the new refcount logic is deprecated"), "Mobile_NewRefCount_Warns did not warn as expected:\n\n", buildOutput); + }); + } + + [Test] + public void Mobile_Verbose_Test () + { + RunMMPTest (tmpDir => { + // Just make sure we accept the option and it doesn't crash + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "-v -v" }; + TI.TestUnifiedExecutable (test); + }); + } + + // The check for name collisions between the root executable and other assemblies was mistakenly comparing against the entire path, not just the assembly name. + // This meant that an assembly located in a folder/subfolder with a name matching the root executable name would incorrectly report as an error. + [Test] + public void FilePathCollisionShouldNotFailBuild () + { + RunMMPTest (tmpDir => { + var libraryDirectory = tmpDir + "/UnifiedExample/"; + var libraryName = "UnifiedLibrary"; + Directory.CreateDirectory (libraryDirectory); + + TI.UnifiedTestConfig libConfig = new TI.UnifiedTestConfig (libraryDirectory) { ProjectName = libraryName }; + string csprojTarget = TI.GenerateUnifiedLibraryProject (libConfig); + + TI.BuildProject (csprojTarget, isUnified : true); + + string referenceCode = string.Format (@"{0}", Path.Combine (libraryDirectory, "bin/Debug/", $"{libraryName}.dll")); + + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { References = referenceCode }; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void Unified_HelloWorld_ShouldHaveNoWarnings () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir); + // Mobile + string buildResults = TI.TestUnifiedExecutable (test); + Assert.IsTrue (!buildResults.Contains ("warning"), "Unified_HelloWorld_ShouldHaveNoWarnings - Mobile had warning: \n" + buildResults); + + // XM45 + test.XM45 = true; + buildResults = TI.TestUnifiedExecutable (test); + Assert.IsTrue (!buildResults.Contains ("warning"), "Unified_HelloWorld_ShouldHaveNoWarnings - XM45 had warning: \n" + buildResults); + }); + } + + [Test] + public void SystemMono_SmokeTest () + { + if (TI.FindMonoVersion () < new Version ("4.3")) + return; + + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir); + TI.TestSystemMonoExecutable (test); + + test.SystemMonoVersion = "4.5"; + TI.TestSystemMonoExecutable (test); + + test.SystemMonoVersion = "4.5.1"; + TI.TestSystemMonoExecutable (test); + + test.SystemMonoVersion = "4.6"; + TI.TestSystemMonoExecutable (test); + + test.SystemMonoVersion = "4.6.1"; + TI.TestSystemMonoExecutable (test); + }); + } + + [Test] + public void BuildUnifiedMobile_Program_WithNonASCIIName () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { AssemblyName = "piñata" }; + TI.TestUnifiedExecutable (test); + + test = new TI.UnifiedTestConfig (tmpDir) { AssemblyName = "你好世界" }; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void BuildUnifiedMobile_Program_WithSpace () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { AssemblyName = "Test With Space" }; + TI.TestUnifiedExecutable (test); + }); + } + + [Test] + public void BuildUnified45_ShouldNotAllowReferenceToSystemDrawing () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { References = " ", TestCode = "System.Drawing.RectangleF f = new System.Drawing.RectangleF ();", XM45 = true}; + TI.TestUnifiedExecutable (test, shouldFail : true); + }); + } + + [Test] + public void Dontlink_AllowsUnresolvableReferences () + { + var sb = new StringBuilder (); + RunMMPTest (tmpDir => + { + // build b.dll + sb.Clear (); + sb.AppendFormat ("-target:library -out:{0}/b.dll {0}/b.cs", tmpDir); + File.WriteAllText (Path.Combine (tmpDir, "b.cs"), "public class B { }"); + TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mcs", sb, "b"); + + // build a.dll + sb.Clear (); + sb.AppendFormat ("-target:library -out:{0}/a.dll {0}/a.cs -r:{0}/b.dll", tmpDir); + File.WriteAllText (Path.Combine (tmpDir, "a.cs"), "public class A { public A () { System.Console.WriteLine (typeof (B)); }}"); + TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mcs", sb, "a"); + + File.Delete (Path.Combine (tmpDir, "b.dll")); + + // build project referencing a.dll + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) + { + References = string.Format (" {0}/a.dll ", tmpDir), + TestCode = "System.Console.WriteLine (typeof (A));", + }; + TI.BuildUnifiedExecutable (test, shouldFail: false); + }); + } + + [Test] + public void Dontlink_Allow_ReadonlyAssembly () + { + var sb = new StringBuilder (); + RunMMPTest (tmpDir => + { + // build b.dll + sb.Clear (); + string assemblyPath = string.Format ("{0}/b.dll", tmpDir); + sb.AppendFormat ("-target:library -out:{0} {1}/b.cs", assemblyPath, tmpDir); + File.WriteAllText (Path.Combine (tmpDir, "b.cs"), "public class B { }"); + TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mcs", sb, "b"); + + File.SetAttributes (assemblyPath, FileAttributes.ReadOnly); + + // build project referencing a.dll + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) + { + References = string.Format (" {0} ", assemblyPath), + TestCode = "System.Console.WriteLine (typeof (B));", + }; + TI.BuildUnifiedExecutable (test, shouldFail: false); + + test.CSProjConfig = "SdkOnly"; + TI.BuildUnifiedExecutable (test, shouldFail: false); + }); + } + } +} \ No newline at end of file diff --git a/tests/mmptest/src/NativeReferencesTests.cs b/tests/mmptest/src/NativeReferencesTests.cs new file mode 100644 index 000000000000..0706da90585f --- /dev/null +++ b/tests/mmptest/src/NativeReferencesTests.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Reflection; + +namespace Xamarin.MMP.Tests +{ + public partial class MMPTests + { + const string NativeReferenceTemplate = @"False{1}"; + + public string SimpleDylibPath + { + get + { + string rootDir = TI.FindRootDirectory (); + string buildLibPath = Path.Combine (rootDir, "mmptest/bin/SimpleClass.dylib"); + Assert.IsTrue (File.Exists (buildLibPath), string.Format ("SimpleDylibPath missing? {0}", buildLibPath)); + return buildLibPath; + } + } + + public string SimpleStaticPath + { + get + { + string rootDir = TI.FindRootDirectory (); + string buildLibPath = Path.Combine (rootDir, "mmptest/bin/SimpleClassStatic.a"); + Assert.IsTrue (File.Exists (buildLibPath), string.Format ("SimpleStaticPath missing? {0}", buildLibPath)); + return buildLibPath; + } + } + + [Test] + public void Unified_WithNativeReferences_InMainProjectWorks () + { + RunMMPTest (tmpDir => { + // Could be any dylib not in /System + const string SystemLibPath = "/Library/Frameworks/Mono.framework/Versions/Current/lib/libsqlite3.0.dylib"; + + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ItemGroup = string.Format (NativeReferenceTemplate, SystemLibPath, "Dynamic") }; + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - System", "libsqlite3.0.dylib", true); + + test.ItemGroup = string.Format (NativeReferenceTemplate, Path.GetFullPath (SimpleDylibPath), "Dynamic"); + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - Local", "SimpleClass.dylib", true); + + test.ItemGroup = string.Format (NativeReferenceTemplate, Path.GetFullPath (SimpleStaticPath), "Static"); + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - Static", null, true); + + test.ItemGroup = string.Format (NativeReferenceTemplate, "/Library/Frameworks/iTunesLibrary.framework", "Framework"); + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - Framework", null, true); + }); + } + + [Test] + public void Unified_WithStaticNativeRef_ClangIncludesOurStaticLib () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ItemGroup = string.Format (NativeReferenceTemplate, SimpleStaticPath, "Static") }; + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - Static", null, true, false, s => + { + string clangLine = s.Split ('\n').First (x => x.Contains ("xcrun -sdk macosx clang")); + return clangLine.Contains ("SimpleClassStatic.a"); + }); + }); + } + + [Test] + public void Unified_WithNativeReferences_MissingLibrariesActAsExpected () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ItemGroup = string.Format (NativeReferenceTemplate, "/Library/Frameworks/ALibThatDoesNotExist.dylib", "Dynamic") }; + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_MissingLibrariesActAsExpected - Nonexistant", null, false); + + // Test a system dylib. Does not matter which one + test.ItemGroup = string.Format (NativeReferenceTemplate, "/System/Library/Frameworks/MapKit.framework/Versions/A/Resources/BridgeSupport/MapKit.dylib", "Dynamic"); + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_MissingLibrariesActAsExpected - System", null, true); + + // Test one of the ignored libs + test.ItemGroup = string.Format (NativeReferenceTemplate, "cups", "Dynamic"); + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_MissingLibrariesActAsExpected - Ignored", null, true); + }); + } + + [Test] + public void Unified_WithNativeReferences_IgnoredWorks () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { + ItemGroup = string.Format (NativeReferenceTemplate, Path.GetFullPath (SimpleDylibPath), "Dynamic"), + CSProjConfig = string.Format (@"--ignore-native-library=""{0}""", Path.GetFullPath (SimpleDylibPath)) + }; + + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_InMainProjectWorks - Local", null, true, true); + }); + } + + [Test] + public void Unified_WithNativeReferences_ReadOnlyNativeLib () + { + RunMMPTest (tmpDir => { + string dylibPath = Path.Combine (tmpDir, "dll/"); + string filePath = Path.Combine (dylibPath, "SimpleClassDylib.dylib"); + Directory.CreateDirectory (dylibPath); + File.Copy (Path.Combine (TI.AssemblyDirectory, TI.TestDirectory + "mac-binding-project/bin/SimpleClassDylib.dylib"), filePath ); + File.SetAttributes (filePath, FileAttributes.ReadOnly); + + string itemGroup = " FalseDynamic "; + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedExample.csproj", ItemGroup = itemGroup }; + + NativeReferenceTestCore (tmpDir, test, "Unified_WithNativeReferences_ReadOnlyLib", null, true, true); + }); + } + + void NativeReferenceTestCore (string tmpDir, TI.UnifiedTestConfig test, string testName, string libraryName, bool buildShouldBeSuccessful, bool libraryShouldNotBeCopied = false, Func processBuildOutput = null) + { + // Mobile + test.XM45 = false; + string buildResults = TI.TestUnifiedExecutable (test, false); + Assert.IsTrue (!buildShouldBeSuccessful || !buildResults.Contains ("MM2006"), string.Format ("{0} - Mobile had MM2006 state {1} not match expected\n{2}", testName, buildShouldBeSuccessful, buildResults)); + if (processBuildOutput != null) + Assert.IsTrue (processBuildOutput (buildResults), string.Format ("{0} - Mobile - We did not see our expected item in the build output: {1}", testName, libraryName)); + + string mobileBundlePath = Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MonoBundle/"); + if (libraryName != null) + Assert.IsTrue (Directory.GetFiles (mobileBundlePath).Any (x => x.Contains (libraryName) == !libraryShouldNotBeCopied), string.Format ("{0} - Mobile - We did not pull in native lib: {1}", testName, libraryName)); + + // XM45 + test.XM45 = true; + buildResults = TI.TestUnifiedExecutable (test, false); + Assert.IsTrue (!buildShouldBeSuccessful || !buildResults.Contains ("MM2006"), string.Format ("{0} - XM45 had MM2006 state {1} not match expected\n{2}", testName, buildShouldBeSuccessful, buildResults)); + if (processBuildOutput != null) + Assert.IsTrue (processBuildOutput (buildResults), string.Format ("{0} - Mobile - We did not see our expected item in the build output: {1}", testName, libraryName)); + + string xm45BundlePath = Path.Combine (tmpDir, "bin/Debug/XM45Example.app/Contents/MonoBundle/"); + if (libraryName != null) + Assert.IsTrue (Directory.GetFiles (xm45BundlePath).Any (x => x.Contains (libraryName) == !libraryShouldNotBeCopied), string.Format ("{0} - XM45 - We did not pull in native lib: {1}", testName, libraryName)); + } + } +} diff --git a/tests/mmptest/src/XM45Example.csproj b/tests/mmptest/src/XM45Example.csproj new file mode 100644 index 000000000000..a471f9b9ab73 --- /dev/null +++ b/tests/mmptest/src/XM45Example.csproj @@ -0,0 +1,43 @@ + + + + Debug + AnyCPU + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {2EEDEBA4-9A84-4CD3-A66F-01379993A637} + Exe + XM45Example + Resources + XM45Example + 8.0.30703 + 2.0 + true + + + bin\Debug + false + false + false + false + false + false + 4 + false +%CODE% + false + + + + + + + + + + + + + + + + diff --git a/tests/monotouch-test/AVFoundation/AVAssetDownloadUrlSessionTests.cs b/tests/monotouch-test/AVFoundation/AVAssetDownloadUrlSessionTests.cs new file mode 100644 index 000000000000..55fe17be87de --- /dev/null +++ b/tests/monotouch-test/AVFoundation/AVAssetDownloadUrlSessionTests.cs @@ -0,0 +1,71 @@ +// +// Unit tests for AVAssetImageGenerator +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using AVFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.AVFoundation; +#endif +using NUnit.Framework; + +namespace monotouchtest { + [TestFixture] + [Preserve (AllMembers = true)] + public class AVAssetDownloadUrlSessionTests { + + [Test] + public void AVAssetDownloadUrlSessionStaticNotSupported () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AVAssetDownloadUrlSession tests: Requires iOS9+"); + + Assert.Throws (() => { var x = AVAssetDownloadUrlSession.SharedSession; }, "SharedSession should throw NotSupportedException"); + Assert.Throws (() => AVAssetDownloadUrlSession.FromConfiguration (NSUrlSessionConfiguration.DefaultSessionConfiguration), "FromConfiguration should throw NotSupportedException"); + Assert.Throws (() => AVAssetDownloadUrlSession.FromConfiguration (NSUrlSessionConfiguration.DefaultSessionConfiguration, new NSUrlSessionDelegate (), null), "FromConfiguration should throw NotSupportedException"); + Assert.Throws (() => AVAssetDownloadUrlSession.FromWeakConfiguration (NSUrlSessionConfiguration.DefaultSessionConfiguration, new NSObject (), null), "FromWeakConfiguration should throw NotSupportedException"); + } + + // FIXME: Disabling this test from now, will reenable once apple releases docs on what is ecpected to have this entitlement key + // Reason: Creating an AVAssetDownloadURLSession requires the com.apple.developer.media-asset-download entitlement +// [Test] +// public void AVAssetDownloadUrlSessionNotSupported () +// { +// if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) +// Assert.Ignore ("Ignoring AVAssetDownloadUrlSession tests: Requires iOS9+"); +// +// var session = AVAssetDownloadUrlSession.CreateSession (NSUrlSessionConfiguration.BackgroundSessionConfiguration ("XamFoo"), null, null); +// +// Assert.Throws (() => session.CreateDataTask (new NSUrlRequest ()), "CreateDataTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDataTask (new NSUrl ("http://google.com")), "CreateDataTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateUploadTask (new NSUrlRequest (), new NSUrl ("http://google.com")), "CreateUploadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateUploadTask (new NSUrlRequest (), new NSData ()), "CreateUploadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateUploadTask (new NSUrlRequest ()), "CreateUploadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDownloadTask (new NSUrlRequest ()), "CreateDownloadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDownloadTask (new NSUrl ("http://google.com")), "CreateDownloadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDownloadTask (new NSData ()), "CreateDownloadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDataTask (new NSUrlRequest (), (data, response, error) => {}), "CreateDataTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDataTask (new NSUrl ("http://google.com"), (data, response, error) => {}), "CreateDataTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateUploadTask (new NSUrlRequest (), new NSUrl ("http://google.com"), (data, response, error) => {}), "CreateUploadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateUploadTask (new NSUrlRequest (), new NSData (), (data, response, error) => {}), "CreateUploadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDownloadTask (new NSUrlRequest (), (NSUrl location, NSUrlResponse response, NSError error) => {}), "CreateDownloadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDownloadTask (new NSUrl ("http://google.com"), (NSUrl location, NSUrlResponse response, NSError error) => {}), "CreateDownloadTask should throw NotSupportedException"); +// Assert.Throws (() => session.CreateDownloadTaskFromResumeData (new NSData (), (NSUrl location, NSUrlResponse response, NSError error) => {}), "CreateDownloadTask should throw NotSupportedException"); +// +// } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/AVAssetImageGeneratorTest.cs b/tests/monotouch-test/AVFoundation/AVAssetImageGeneratorTest.cs new file mode 100644 index 000000000000..f1c3c191aefa --- /dev/null +++ b/tests/monotouch-test/AVFoundation/AVAssetImageGeneratorTest.cs @@ -0,0 +1,157 @@ +// +// Unit tests for AVAssetImageGenerator +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using AVFoundation; +using CoreMedia; +#else +using MonoTouch.AVFoundation; +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AVAssetImageGeneratorTest { + + [Test] + public void Defaults () + { + using (NSUrl video_url = NSUrl.FromFilename (video_asset_path)) + using (AVAsset video_asset = AVAsset.FromUrl (video_url)) + using (AVAssetImageGenerator aig = new AVAssetImageGenerator (video_asset)) { + Assert.Null (aig.ApertureMode, "ApertureMode"); + Assert.False (aig.AppliesPreferredTrackTransform, "AppliesPreferredTrackTransform"); + Assert.That (aig.MaximumSize, Is.EqualTo (SizeF.Empty), "MaximumSize"); + Assert.True (aig.RequestedTimeToleranceAfter.IsPositiveInfinity, "RequestedTimeToleranceAfter"); + Assert.True (aig.RequestedTimeToleranceBefore.IsPositiveInfinity, "RequestedTimeToleranceBefore"); + } + } + + [Test] + public void AppliesPreferredTrackTransform () + { + using (NSUrl video_url = NSUrl.FromFilename (video_asset_path)) + using (AVAsset video_asset = AVAsset.FromUrl (video_url)) + using (AVAssetImageGenerator aig = new AVAssetImageGenerator (video_asset)) { + // setter was missing see https://bugzilla.xamarin.com/show_bug.cgi?id=5216 + aig.AppliesPreferredTrackTransform = true; + Assert.True (aig.AppliesPreferredTrackTransform, "AppliesPreferredTrackTransform"); + } + } + + [Test] + public void CopyCGImageAtTime () + { + // Mp4 file is supported by CopyCGImageAtTime so we can test out actual param + using (NSUrl video_url = NSUrl.FromFilename (video_asset_path)) + using (AVAsset video_asset = AVAsset.FromUrl (video_url)) + using (AVAssetImageGenerator aig = new AVAssetImageGenerator (video_asset)) { + // signature errors see https://bugzilla.xamarin.com/show_bug.cgi?id=5218 + CMTime actual; + NSError error; + var img = aig.CopyCGImageAtTime (CMTime.Zero, out actual, out error); + Assert.NotNull (img, "CopyCGImageAtTime"); + Assert.False (actual.IsInvalid, "actual"); + Assert.Null (error, "error"); + } + } + + [Test] + public void CopyCGImageAtTime_Invalid () + { + // Mov file is not supported by CopCGImageAtTime so we can test out error param + using (NSUrl video_url = NSUrl.FromFilename (does_not_exists_asset_path)) + using (AVAsset video_asset = AVAsset.FromUrl (video_url)) + using (AVAssetImageGenerator aig = new AVAssetImageGenerator (video_asset)) { + // signature errors see https://bugzilla.xamarin.com/show_bug.cgi?id=5218 + CMTime actual; + NSError error; + var img = aig.CopyCGImageAtTime (CMTime.Zero, out actual, out error); + Assert.Null (img, "missing"); + Assert.True (actual.IsInvalid, "actual"); + Assert.NotNull (error, "error"); + } + } + + string does_not_exists_asset_path = Path.Combine (NSBundle.MainBundle.BundlePath, "xamarin.mov"); + string video_asset_path = Path.Combine (NSBundle.MainBundle.BundlePath, "xamvideotest.mp4"); + bool handled; + ManualResetEvent mre; + + [Test] + public void GenerateCGImagesAsynchronously () + { + handled = false; + mre = new ManualResetEvent (false); + ThreadStart main = () => { + using (NSUrl video_url = NSUrl.FromFilename (video_asset_path)) + using (AVAsset video_asset = AVAsset.FromUrl (video_url)) + using (AVAssetImageGenerator aig = new AVAssetImageGenerator (video_asset)) { + NSValue[] values = new NSValue[] { NSValue.FromCMTime (CMTime.Zero) }; + aig.GenerateCGImagesAsynchronously (values, handler); + mre.WaitOne (); + } + }; + var asyncResult = main.BeginInvoke (null, null); + main.EndInvoke (asyncResult); + Assert.True (mre.WaitOne (2000), "wait"); + Assert.True (handled, "handled"); + } + +#if !XAMCORE_2_0 + [Test] + public void GenerateCGImagesAsynchronously_Compat () + { + handled = false; + mre = new ManualResetEvent (false); + ThreadStart main = () => { + using (NSUrl video_url = NSUrl.FromFilename (video_asset_path)) + using (AVAsset video_asset = AVAsset.FromUrl (video_url)) + using (AVAssetImageGenerator aig = new AVAssetImageGenerator (video_asset)) { + aig.GenerateCGImagesAsynchronously (NSValue.FromCMTime (CMTime.Zero), handler); + mre.WaitOne (); + } + }; + var asyncResult = main.BeginInvoke (null, null); + main.EndInvoke (asyncResult); + Assert.True (mre.WaitOne (2000)); + Assert.True (handled, "handled"); + } +#endif + + void handler (CMTime requestedTime, IntPtr imageRef, CMTime actualTime, AVAssetImageGeneratorResult result, NSError error) + { + handled = true; + mre.Set (); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs b/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs new file mode 100644 index 000000000000..49c3a986bc3e --- /dev/null +++ b/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for AVAudioPlayer +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using AVFoundation; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioPlayerTest { + + [Test] + public void FromUrl () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "Hand.wav"); + Assert.True (File.Exists (file), file); + NSError error; + using (var url = new NSUrl (file, false)) + using (var ap = AVAudioPlayer.FromUrl (url, out error)) { + Assert.NotNull (ap, "AVAudioPlayer"); + Assert.Null (error, "NSError"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/AudioRecorderTest.cs b/tests/monotouch-test/AVFoundation/AudioRecorderTest.cs new file mode 100644 index 000000000000..78f3a574d1ef --- /dev/null +++ b/tests/monotouch-test/AVFoundation/AudioRecorderTest.cs @@ -0,0 +1,66 @@ +// Unit test for AVAudioRecorder +// Authors: +// Paola Villarreal (paola.villarreal@xamarin.com) +// Copyright 2014 Xamarin Inc. All rights reserved. + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using AudioToolbox; +using AVFoundation; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +using MonoTouch.AudioToolbox; +#endif +using NUnit.Framework; +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioRecorderTest { + NSObject[] Values = new NSObject[] + { + NSNumber.FromFloat ((float)44100), //Sample Rate + NSNumber.FromInt32 ((int)AudioFormatType.AppleLossless), //AVFormat + NSNumber.FromInt32 (2), + NSNumber.FromInt32 ((int)AVAudioQuality.Min) + }; + + NSObject[] Keys = new NSObject[] + { + AVAudioSettings.AVSampleRateKey, + AVAudioSettings.AVFormatIDKey, + AVAudioSettings.AVNumberOfChannelsKey, + AVAudioSettings.AVEncoderAudioQualityKey + }; + [Test] + public void Create () + { + var url = NSUrl.FromFilename ("/dev/null"); + NSError error; + var audioSettings = new AudioSettings (NSDictionary.FromObjectsAndKeys (Values, Keys)); + + using (var recorder = AVAudioRecorder.Create (url, audioSettings, out error)) { + Assert.NotNull (recorder); + Assert.Null (error); + } + } + [Test] + public void CreateWithError () + { + var url = NSUrl.FromFilename ("/dev/fake.wav"); + NSError error; + var audioSettings = new AudioSettings (NSDictionary.FromObjectsAndKeys (Values, Keys)); + using (var recorder = AVAudioRecorder.Create (url, audioSettings, out error)) { + Assert.Null (recorder); + Assert.NotNull (error); + } + } + + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/CaptureMetadataOutputTest.cs b/tests/monotouch-test/AVFoundation/CaptureMetadataOutputTest.cs new file mode 100644 index 000000000000..3c2379b17e04 --- /dev/null +++ b/tests/monotouch-test/AVFoundation/CaptureMetadataOutputTest.cs @@ -0,0 +1,131 @@ +// +// Unit tests for AVMetadataObject +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using AVFoundation; +using CoreMedia; +using ObjCRuntime; +#else +using MonoTouch.AVFoundation; +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CaptureMetadataOutputTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Ignore ("requires iOS6+"); + + using (var obj = new AVCaptureMetadataOutput ()) { +#if XAMCORE_2_0 + Assert.AreEqual (AVMetadataObjectType.None, obj.AvailableMetadataObjectTypes, "AvailableMetadataObjectTypes"); + Assert.AreEqual (AVMetadataObjectType.None, obj.MetadataObjectTypes, "MetadataObjectTypes"); + + Assert.IsNotNull (obj.WeakAvailableMetadataObjectTypes, "WeakAvailableMetadataObjectTypes"); + Assert.AreEqual (0, obj.WeakAvailableMetadataObjectTypes.Length, "WeakAvailableMetadataObjectTypes#"); + Assert.IsNotNull (obj.WeakMetadataObjectTypes, "WeakMetadataObjectTypes"); + Assert.AreEqual (0, obj.WeakMetadataObjectTypes.Length, "WeakMetadataObjectTypes#"); +#else + Assert.IsNotNull (obj.AvailableMetadataObjectTypes, "AvailableMetadataObjectTypes"); + Assert.AreEqual (0, obj.AvailableMetadataObjectTypes.Length, "AvailableMetadataObjectTypes#"); + Assert.IsNotNull (obj.MetadataObjectTypes, "MetadataObjectTypes"); + Assert.AreEqual (0, obj.MetadataObjectTypes.Length, "MetadataObjectTypes#"); +#endif + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.AreEqual (new RectangleF (0, 0, 1, 1), obj.RectOfInterest, "RectOfInterest"); + +#if XAMCORE_2_0 + obj.WeakMetadataObjectTypes = null; + Assert.AreEqual (AVMetadataObjectType.None, obj.MetadataObjectTypes, "MetadataObjectTypes"); + obj.MetadataObjectTypes = AVMetadataObjectType.None; + Assert.AreEqual (AVMetadataObjectType.None, obj.MetadataObjectTypes, "MetadataObjectTypes"); +#else + obj.MetadataObjectTypes = null; + Assert.IsNotNull (obj.MetadataObjectTypes, "MetadataObjectTypes"); + Assert.AreEqual (0, obj.MetadataObjectTypes.Length, "MetadataObjectTypes#"); +#endif + obj.SetDelegate (null, null); + } + } + +#if XAMCORE_2_0 + [Test] + public void MetadataObjectTypesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Test only works correctly in iOS 8+"); + + if (Runtime.Arch != Arch.DEVICE) + Assert.Ignore ("This test only runs on device (requires camera access)"); + + var auth = AVCaptureDevice.GetAuthorizationStatus (AVMediaType.Video); + switch (auth) { + case AVAuthorizationStatus.Restricted: + case AVAuthorizationStatus.Denied: + Assert.Fail ("This test requires access to the camera, but the app has been denied access."); + break; + } + + using (var captureSession = new AVCaptureSession ()) { + using (var videoDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video)) { + + NSError error; + using (var videoInput = new AVCaptureDeviceInput (videoDevice, out error)) { + if (captureSession.CanAddInput (videoInput)) + captureSession.AddInput (videoInput); + + using (var metadataOutput = new AVCaptureMetadataOutput ()) { + + if (captureSession.CanAddOutput (metadataOutput)) + captureSession.AddOutput (metadataOutput); + + AVMetadataObjectType all = AVMetadataObjectType.None; + foreach (AVMetadataObjectType val in Enum.GetValues (typeof (AVMetadataObjectType))) { + metadataOutput.MetadataObjectTypes = val; + all |= val; + Assert.AreEqual (val, metadataOutput.MetadataObjectTypes, val.ToString ()); + } + metadataOutput.MetadataObjectTypes = all; + Assert.AreEqual (all, metadataOutput.MetadataObjectTypes, all.ToString ()); + } + } + } + } + } +#endif + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/MetadataObjectTest.cs b/tests/monotouch-test/AVFoundation/MetadataObjectTest.cs new file mode 100644 index 000000000000..2f67921894ad --- /dev/null +++ b/tests/monotouch-test/AVFoundation/MetadataObjectTest.cs @@ -0,0 +1,76 @@ +// +// Unit tests for AVMetadataObject +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using AVFoundation; +using CoreMedia; +#else +using MonoTouch.AVFoundation; +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MetadataObjectTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Test only works correctly in iOS 8+"); + + using (var obj = new AVMetadataFaceObject ()) { + Assert.AreEqual (0, obj.FaceID, "FaceID"); + Assert.AreEqual (false, obj.HasRollAngle, "HasRollAngle"); + Assert.AreEqual (false, obj.HasYawAngle, "HasYawAngle"); +#if XAMCORE_2_0 + Assert.AreEqual (AVMetadataObjectType.Face, obj.Type, "Type"); + Assert.AreEqual (AVMetadataObject.TypeFace, obj.WeakType, "WeakType"); +#else + Assert.AreEqual (AVMetadataObject.TypeFace, obj.Type, "Type"); +#endif + } + + using (var obj = new AVMetadataMachineReadableCodeObject ()) { + Assert.IsNotNull (obj.Corners, "Corners"); + Assert.AreEqual (0, obj.Corners.Length, "Corners"); + Assert.IsNull (obj.StringValue, "StringValue"); +#if XAMCORE_2_0 + Assert.AreEqual (AVMetadataObjectType.None, obj.Type, "Type"); + Assert.IsNull (obj.WeakType, "WeakType"); +#else + Assert.IsNull (obj.Type, "Type"); +#endif + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/PlayerItemTest.cs b/tests/monotouch-test/AVFoundation/PlayerItemTest.cs new file mode 100644 index 000000000000..f0d223a769bf --- /dev/null +++ b/tests/monotouch-test/AVFoundation/PlayerItemTest.cs @@ -0,0 +1,42 @@ +// +// Unit tests for AVPlayerItem +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using AVFoundation; +using Foundation; +using UIKit; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PlayerItemTest { + + [Test] + public void FromAssert_Null () + { + // Apple's AVCustomEdit samples calls this with `nil` + Assert.Null (AVPlayerItem.FromAsset (null), "1"); + + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Null (AVPlayerItem.FromAsset (null, null), "2"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/QueuePlayerTest.cs b/tests/monotouch-test/AVFoundation/QueuePlayerTest.cs new file mode 100644 index 000000000000..927a45e654d0 --- /dev/null +++ b/tests/monotouch-test/AVFoundation/QueuePlayerTest.cs @@ -0,0 +1,41 @@ +// +// Unit tests for AVQueuePlayer +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using AVFoundation; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class QueuePlayerTest { + [Test] + public void NullAllowedTest () + { + using (var player = new AVQueuePlayer ()) { + using (var item = new AVPlayerItem (NSUrl.FromString ("http://example.org"))) { + player.CanInsert (item, null); + player.InsertItem (item, null); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/SpeechSynthesisVoiceTest.cs b/tests/monotouch-test/AVFoundation/SpeechSynthesisVoiceTest.cs new file mode 100644 index 000000000000..42dc43bbaba5 --- /dev/null +++ b/tests/monotouch-test/AVFoundation/SpeechSynthesisVoiceTest.cs @@ -0,0 +1,60 @@ +// +// Unit tests for AVSpeechSynthesisVoice +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using AVFoundation; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + [TestFixture] + public class SpeechSynthesisVoiceTest { + + [Test] + public void Default () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS 7.0+"); + + // it's not clear that `init` should be called... it works (as it does not crash) but you can't set anything + using (var ssv = new AVSpeechSynthesisVoice ()) { + Assert.Null (ssv.Language, "Language"); + } + } + + [Test] + public void Static () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS 7.0+"); + + Assert.NotNull (AVSpeechSynthesisVoice.CurrentLanguageCode, "CurrentLanguageCode"); + foreach (var ssv in AVSpeechSynthesisVoice.GetSpeechVoices ()) { + Assert.NotNull (ssv.Language, ssv.Language); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/UtilitiesTest.cs b/tests/monotouch-test/AVFoundation/UtilitiesTest.cs new file mode 100644 index 000000000000..8c7496af65e5 --- /dev/null +++ b/tests/monotouch-test/AVFoundation/UtilitiesTest.cs @@ -0,0 +1,54 @@ +// +// Unit tests for AVUtilities.h helpers +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AVFoundation; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + [TestFixture] + public class UtilitiesTest { + + [Test] + public void AspectRatio () + { + var r = RectangleF.Empty.WithAspectRatio (SizeF.Empty); + Assert.True (nfloat.IsNaN (r.Top), "Top"); + Assert.That (nfloat.IsNaN (r.Left), "Left"); + Assert.That (nfloat.IsNaN (r.Width), "Width"); + Assert.That (nfloat.IsNaN (r.Height), "Height"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVFoundation/VideoCompositionInstructionTest.cs b/tests/monotouch-test/AVFoundation/VideoCompositionInstructionTest.cs new file mode 100644 index 000000000000..2b322e6b2e23 --- /dev/null +++ b/tests/monotouch-test/AVFoundation/VideoCompositionInstructionTest.cs @@ -0,0 +1,58 @@ +// +// Unit tests for AVVideoCompositionInstruction +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AVFoundation; +#else +using MonoTouch.AVFoundation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + [TestFixture] + public class VideoCompositionInstructionTest { + + [Test] + public void Defaults () + { + using (var i = new AVVideoCompositionInstruction ()) { + Assert.Null (i.BackgroundColor, "BackgroundColor"); + Assert.True (i.EnablePostProcessing, "EnablePostProcessing"); + Assert.Null (i.LayerInstructions, "LayerInstructions"); + Assert.True (i.TimeRange.Start.IsInvalid, "TimeRange.Start"); + Assert.True (i.TimeRange.Duration.IsInvalid, "TimeRange.Duration"); + } + } + + [Test] + public void Seven () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS7"); + + using (var i = new AVVideoCompositionInstruction ()) { + Assert.False (i.ContainsTweening, "ContainsTweening"); + Assert.That (i.PassthroughTrackID, Is.EqualTo (0), "PassthroughTrackID"); + Assert.That (i.RequiredSourceTrackIDs.Length, Is.EqualTo (0), "RequiredSourceTrackIDs"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AVKit/PlayerViewControllerTest.cs b/tests/monotouch-test/AVKit/PlayerViewControllerTest.cs new file mode 100644 index 000000000000..dbbf2e03a06a --- /dev/null +++ b/tests/monotouch-test/AVKit/PlayerViewControllerTest.cs @@ -0,0 +1,53 @@ +// +// Unit tests for AVPlayerViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using AVKit; +using Foundation; +using UIKit; +using iAd; +#else +using MonoTouch.AVKit; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.iAd; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AVKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PlayerViewControllerTest { + +#if !XAMCORE_2_0 + [Test] + public void PreparePrerollAds_Old () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (8,0)) + Assert.Inconclusive ("Requires 8.0+"); + + (null as AVPlayerViewController).PreparePrerollAds (); + } +#endif + [Test] + public void PreparePrerollAds_New () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (8,0)) + Assert.Inconclusive ("Requires 8.0+"); + + AVPlayerViewController.PrepareForPrerollAds (); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AdSupport/IdentifierManagerTest.cs b/tests/monotouch-test/AdSupport/IdentifierManagerTest.cs new file mode 100644 index 000000000000..18f668eef09e --- /dev/null +++ b/tests/monotouch-test/AdSupport/IdentifierManagerTest.cs @@ -0,0 +1,42 @@ +// +// Unit tests for ASIdentifierManager +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012,2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AdSupport; +#else +using MonoTouch.Foundation; +using MonoTouch.AdSupport; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AdSupport { + + [TestFixture] + [Preserve (AllMembers = true)] + public class IdentifierManagerTest { + + [Test] + public void SharedManager () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("AdSupport is new in 6.0"); + + // IsAdvertisingTrackingEnabled - device specific config + Assert.NotNull (ASIdentifierManager.SharedManager.AdvertisingIdentifier, "AdvertisingIdentifier"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AddressBook/AddressBookTest.cs b/tests/monotouch-test/AddressBook/AddressBookTest.cs new file mode 100644 index 000000000000..eb1fdac8bf79 --- /dev/null +++ b/tests/monotouch-test/AddressBook/AddressBookTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for ABSource +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AddressBook; +using ObjCRuntime; +#else +using MonoTouch.AddressBook; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AddressBook { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AddressBookTest { + + // very general ABSource related tests (works on both simulator and devices) + + [Test] + public void GetAllSources () + { + ABAddressBook ab = new ABAddressBook (); + var sources = ab.GetAllSources (); + int value = Runtime.Arch == Arch.DEVICE || TestRuntime.CheckSystemAndSDKVersion (7,0) ? 0 : 1; + Assert.That (sources.Length, Is.GreaterThanOrEqualTo (value), "GetAllSources"); + } + + [Test] + public void GetDefaultSource () + { + ABAddressBook ab = new ABAddressBook (); + Assert.NotNull (ab.GetDefaultSource (), "GetDefaultSource"); + } + + [Test] + public void GetSource () + { + ABAddressBook ab = new ABAddressBook (); + Assert.Null (ab.GetSource (-1), "-1"); + // GetSource(0) is not reliable across device/simulator and iOS versions + Assert.Null (ab.GetSource (Int32.MaxValue), "MaxValue"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AddressBook/PersonTest.cs b/tests/monotouch-test/AddressBook/PersonTest.cs new file mode 100644 index 000000000000..e2064e5811e8 --- /dev/null +++ b/tests/monotouch-test/AddressBook/PersonTest.cs @@ -0,0 +1,69 @@ +// +// Unit tests for ABPerson +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AddressBook; +using ObjCRuntime; +#else +using MonoTouch.AddressBook; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AddressBook { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PersonTest { + + [Test] + public void UpdateAddressLine () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("System.EntryPointNotFoundException : ABAddressBookCreateWithOptions before 6.0"); + + NSError err; + var ab = ABAddressBook.Create (out err); + Assert.IsNotNull (ab, "#1"); + + var people = ab.GetPeople (); + if (people.Length < 1) { + // TODO: + return; + } + + var p = people[0]; + + var all = p.GetAllAddresses (); + var mutable = all.ToMutableMultiValue (); + if (mutable.Count < 1) { + // TODO: + return; + } + + var multi = mutable [0]; + var addr = multi.Value; + addr.Zip = "78972"; + multi.Value = addr; + p.SetAddresses (mutable); + + Assert.IsTrue (ab.HasUnsavedChanges); + ab.Save (); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AddressBook/SourceTest.cs b/tests/monotouch-test/AddressBook/SourceTest.cs new file mode 100644 index 000000000000..b786a8b332f9 --- /dev/null +++ b/tests/monotouch-test/AddressBook/SourceTest.cs @@ -0,0 +1,51 @@ +// +// Unit tests for ABSource +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AddressBook; +using ObjCRuntime; +#else +using MonoTouch.AddressBook; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AddressBook { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SourceTest { + + [Test] + public void Default () + { + if (Runtime.Arch != Arch.SIMULATOR) + return; + + // we assume the simulator defaults (e.g. after a reset) + ABSource source = new ABAddressBook ().GetDefaultSource (); + Assert.Null (source.Name, "Name"); + Assert.That (source.SourceType, Is.EqualTo (ABSourceType.Local), "SourceType"); + + // ABRecord + // some bots returns -1 (invalid) and I get 0 after a reset (maybe permission related?) + Assert.That (source.Id, Is.LessThanOrEqualTo (0), "Id"); + Assert.That (source.Type, Is.EqualTo (ABRecordType.Source), "Type"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AddressBookUI/AddressFormattingTest.cs b/tests/monotouch-test/AddressBookUI/AddressFormattingTest.cs new file mode 100644 index 000000000000..bdc256d0a211 --- /dev/null +++ b/tests/monotouch-test/AddressBookUI/AddressFormattingTest.cs @@ -0,0 +1,72 @@ +// +// Unit tests for ABAddressFormatting +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014, 2016 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Globalization; +#if XAMCORE_2_0 +using Foundation; +using AddressBookUI; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.AddressBookUI; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AddressBookUI { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ABAddressFormattingTest { + + [Test] + public void ChateauFrontenac () + { + using (NSMutableDictionary dict = new NSMutableDictionary () { + { new NSString ("Street"), new NSString ("1–3 Rue Des Carrières") }, + { new NSString ("SubAdministrativeArea"), new NSString ("Québec") }, + { new NSString ("Thoroughfare"), new NSString ("Rue Des Carrières") }, + { new NSString ("ZIP"), new NSString ("G1R 5J5") }, + { new NSString ("Name"), new NSString ("1–3 Rue Des Carrières") }, + { new NSString ("City"), new NSString ("Quebec City") }, + { new NSString ("State"), new NSString ("Quebec") }, + { new NSString ("SubLocality"), new NSString ("Vieux-Quebec") }, + { new NSString ("SubThoroughfare"), new NSString ("1-3") }, + { new NSString ("CountryCode"), new NSString ("CA") }, + }) { + string expected = "1–3 Rue Des Carrières\nQuebec City‎ Quebec‎ G1R 5J5"; + string s = ABAddressFormatting.ToString (dict, false); + Assert.That (s, Is.EqualTo (expected), "false"); + // country names can be translated, e.g. chinese, so we can't compare it + s = ABAddressFormatting.ToString (dict, true); + Assert.True (s.StartsWith (expected, StringComparison.Ordinal), "prefix"); + + // Apple broke this again (8.0.x are hard to predict) - test will fail once it's corrected + // iOS 8.1.2 device: working + // iOS 8.0 (12A365) simulator (Xcode 6.0.1): working + // iOS 8.1 (12B411) simulator (Xcode 6.1): broken + // iOS 8.2 beta 5 (12D5480a) simulator (Xcode 6.2 beta 5): working + + // we don't check before 8.2 - where both device and simulators works again properly + if (!UIDevice.CurrentDevice.CheckSystemVersion (8,2)) + return; + + Assert.That (s [expected.Length], Is.EqualTo ('\n'), "newline"); + Assert.That (s.Length > expected.Length + 1, "country"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AppDelegate.cs b/tests/monotouch-test/AppDelegate.cs new file mode 100644 index 000000000000..98744af2f1cb --- /dev/null +++ b/tests/monotouch-test/AppDelegate.cs @@ -0,0 +1,125 @@ +#if !__WATCHOS__ +using System; +using System.Collections.Generic; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; +using NUnit.Framework.Internal; + +namespace MonoTouchFixtures { + + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate { + // class-level declarations + static UIWindow window; + TouchRunner runner; + +#if !__TVOS__ + public override bool AccessibilityPerformMagicTap () + { + try { + runner.OpenWriter ("Magic Tap"); + runner.Run (runner.LoadedTest as TestSuite); + } + finally { + runner.CloseWriter (); + } + return true; + } +#endif + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + // create a new window instance based on the screen size + window = new UIWindow (UIScreen.MainScreen.Bounds); + runner = new TouchRunner (window); + + // tests can be inside the main assembly + runner.Add (Assembly.GetExecutingAssembly ()); + runner.Add (typeof(EmbeddedResources.ResourcesTest).Assembly); + runner.Add (typeof(Xamarin.BindingTests.ProtocolTest).Assembly); + + window.RootViewController = new UINavigationController (runner.GetViewController ()); + // make the window visible + window.MakeKeyAndVisible (); + + return true; + } + + public static void PresentModalViewController (UIViewController vc, double duration) + { + var bckp = window.RootViewController; + window.RootViewController = vc; + try { + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (duration)); + } finally { + window.RootViewController = bckp; + } + } + + public static bool RunAsync (DateTime timeout, Action action, Func check_completed) + { + var vc = new AsyncController (action); + var bckp = window.RootViewController; + window.RootViewController = vc; + try { + do { + if (timeout < DateTime.Now) + return false; + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (0.1)); + } while (!check_completed ()); + } finally { + window.RootViewController = bckp; + } + + return true; + } + } + + class AsyncController : UIViewController { + Action action; + static int counter; + + public AsyncController (Action action) + { + this.action = action; + counter++; + } + + public override void ViewDidLoad () + { + base.ViewDidLoad (); + + switch (counter % 2) { + case 0: + View.BackgroundColor = UIColor.Yellow; + break; + default: + View.BackgroundColor = UIColor.LightGray; + break; + } +#if XAMCORE_2_0 + NSTimer.CreateScheduledTimer (0.01, (v) => action ()); +#else + NSTimer.CreateScheduledTimer (0.01, () => action ()); +#endif + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/Asserts.cs b/tests/monotouch-test/Asserts.cs new file mode 100644 index 000000000000..1a9eb5c1a8b6 --- /dev/null +++ b/tests/monotouch-test/Asserts.cs @@ -0,0 +1,57 @@ +using System; +#if XAMCORE_2_0 +#if !__WATCHOS__ +using ModelIO; +#endif +#else +using MonoTouch.ModelIO; +#endif +using OpenTK; +using NUnit.Framework; + +public static class Asserts +{ +#if !__WATCHOS__ + public static void AreEqual (Vector2 expected, Vector2 actual, string message) + { + Assert.AreEqual (expected.X, actual.X, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, message + " (Y)"); + } + + public static void AreEqual (Vector3 expected, Vector3 actual, string message) + { + Assert.AreEqual (expected.X, actual.X, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, message + " (Y)"); + Assert.AreEqual (expected.Z, actual.Z, message + " (Z)"); + } + + public static void AreEqual (Vector4 expected, Vector4 actual, string message) + { + Assert.AreEqual (expected.X, actual.X, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, message + " (Y)"); + Assert.AreEqual (expected.Z, actual.Z, message + " (Z)"); + Assert.AreEqual (expected.W, actual.W, message + " (W)"); + } + + public static void AreEqual (Matrix4 expected, Matrix4 actual, string message) + { + AreEqual (expected.Column0, actual.Column0, message + " (Col0)"); + AreEqual (expected.Column1, actual.Column1, message + " (Col1)"); + AreEqual (expected.Column2, actual.Column2, message + " (Col2)"); + AreEqual (expected.Column3, actual.Column3, message + " (Col3)"); + } + + public static void AreEqual (Vector2i expected, Vector2i actual, string message) + { + Assert.AreEqual (expected.X, actual.X, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, message + " (Y)"); + } + + public static void AreEqual (MDLAxisAlignedBoundingBox expected, MDLAxisAlignedBoundingBox actual, string message) + { + AreEqual (expected.MaxBounds, actual.MaxBounds, message + " (MaxBounds)"); + AreEqual (expected.MinBounds, actual.MinBounds, message + " (MinBounds)"); + } +#endif // !__WATCHOS__ +} + diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/Contents.json b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/Contents.json new file mode 100644 index 000000000000..6be52c8f7640 --- /dev/null +++ b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/Contents.json @@ -0,0 +1,221 @@ +{ + "images": [ + { + "size": "29x29", + "scale": "1x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "3x", + "idiom": "iphone" + }, + { + "filename": "icon-app-57.png", + "size": "57x57", + "scale": "1x", + "idiom": "iphone" + }, + { + "filename": "icon-app-57@2x.png", + "size": "57x57", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "icon-app-60@2x.png", + "size": "60x60", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "icon-app-60@3x.png", + "size": "60x60", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "icon-app-83.5@2x.png", + "size": "83.5x83.5", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "icon-app-72.png", + "size": "72x72", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "icon-app-72@2x.png", + "size": "72x72", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "icon-app-76.png", + "size": "76x76", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "icon-app-76@2x.png", + "size": "76x76", + "scale": "2x", + "idiom": "ipad" + }, + { + "role": "notificationCenter", + "size": "24x24", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "notificationCenter", + "size": "27.5x27.5", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "companionSettings", + "size": "29x29", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "companionSettings", + "size": "29x29", + "scale": "3x", + "idiom": "watch" + }, + { + "role": "appLauncher", + "size": "40x40", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "longLook", + "size": "44x44", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "86x86", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "98x98", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "size": "16x16", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "16x16", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "32x32", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "32x32", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "128x128", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "128x128", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "256x256", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "256x256", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "512x512", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "512x512", + "scale": "2x", + "idiom": "mac" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/Icon-app-60@3x.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/Icon-app-60@3x.png new file mode 100644 index 000000000000..45342a7513b6 Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/Icon-app-60@3x.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-57.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-57.png new file mode 100644 index 000000000000..ce1d9df94d4f Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-57.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-57@2x.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-57@2x.png new file mode 100644 index 000000000000..d34d9c694d3f Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-57@2x.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-60@2x.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-60@2x.png new file mode 100644 index 000000000000..4409624b29d9 Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-60@2x.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-72.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-72.png new file mode 100644 index 000000000000..9a77ea277312 Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-72.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-72@2x.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-72@2x.png new file mode 100644 index 000000000000..32f57d7d89da Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-72@2x.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-76.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-76.png new file mode 100644 index 000000000000..12db0c47cc4e Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-76.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-76@2x.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-76@2x.png new file mode 100644 index 000000000000..163f1c7f0f18 Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-76@2x.png differ diff --git a/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-83.5@2x.png b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-83.5@2x.png new file mode 100644 index 000000000000..0bac1da399b5 Binary files /dev/null and b/tests/monotouch-test/Assets.xcassets/AppIcons.appiconset/icon-app-83.5@2x.png differ diff --git a/tests/monotouch-test/AudioToolbox/1.caf b/tests/monotouch-test/AudioToolbox/1.caf new file mode 100644 index 000000000000..d33809c4169b Binary files /dev/null and b/tests/monotouch-test/AudioToolbox/1.caf differ diff --git a/tests/monotouch-test/AudioToolbox/AudioBalanceFadeTest.cs b/tests/monotouch-test/AudioToolbox/AudioBalanceFadeTest.cs new file mode 100644 index 000000000000..938fb35da1db --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioBalanceFadeTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for AudioBalanceFade +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; +using System.Threading; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioBalanceFadeTest + { + [Test] + public void GetBalanceFade () + { + var acl = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.AudioUnit_6_1); + var abf = new AudioBalanceFade (acl); + Assert.IsNotNull (abf.GetBalanceFade ()); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioChannelLayoutTest.cs b/tests/monotouch-test/AudioToolbox/AudioChannelLayoutTest.cs new file mode 100644 index 000000000000..0e5f546fb778 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioChannelLayoutTest.cs @@ -0,0 +1,94 @@ +// +// Unit tests for AudioChannelLayout +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; +using System.Threading; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioChannelLayoutTest + { + [Test] + public void Validate () + { + var acl = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.AudioUnit_6_1); + Assert.AreEqual (AudioFormatError.None, AudioChannelLayout.Validate (acl)); + } + + [Test] + public void FromAudioChannelBitmap () + { + var bitmap = AudioChannelLayoutTag.AudioUnit_7_1_Front.ToAudioChannel (); + Assert.IsNotNull (AudioChannelLayout.FromAudioChannelBitmap (bitmap.Value)); + } + + [Test] + public void FromAudioChannelLayoutTag () + { + Assert.IsNotNull (AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.AudioUnit_6_1)); + } + + [Test] + public void GetTagForChannelLayout () + { + var acl = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.AudioUnit_6_1); + Assert.That (AudioChannelLayout.GetTagForChannelLayout (acl), Is.EqualTo (AudioChannelLayoutTag.AudioUnit_6_1)); + } + + [Test] + public void GetNumberOfChannels () + { + var acl = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.MPEG_7_1_B); + Assert.That (AudioChannelLayout.GetNumberOfChannels (acl), Is.EqualTo (8)); + } + + [Test] + public void GetChannelMap () + { + var acl1 = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.AudioUnit_6_1); + var acl2 = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.MPEG_7_1_B); + + Assert.IsNotNull (AudioChannelLayout.GetChannelMap (acl1, acl2)); + } + + [Test] + public void GetTagsForNumberOfChannels () + { + Assert.IsNotNull (AudioChannelLayout.GetTagsForNumberOfChannels (4)); + } + + [Test] + public void GetMatrixMixMap () + { + var acl1 = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.AudioUnit_6_1); + var acl2 = AudioChannelLayout.FromAudioChannelLayoutTag (AudioChannelLayoutTag.MPEG_7_1_B); + + Assert.IsNotNull (AudioChannelLayout.GetMatrixMixMap (acl1, acl2)); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioFileGlobalInfoTest.cs b/tests/monotouch-test/AudioToolbox/AudioFileGlobalInfoTest.cs new file mode 100644 index 000000000000..86072e0f4b58 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioFileGlobalInfoTest.cs @@ -0,0 +1,50 @@ +// +// Unit tests for AudioFileGlobalInfo +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif + +using NUnit.Framework; +using System.Threading; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioFileGlobalInfoTest + { + [Test] + public void Properties () + { + var a1 = AudioFileGlobalInfo.ReadableTypes; + var a2 = AudioFileGlobalInfo.GetFileTypeName (AudioFileType.MP2); + var a3 = AudioFileGlobalInfo.GetAvailableFormats (AudioFileType.MPEG4); + var a4 = AudioFileGlobalInfo.GetAvailableStreamDescriptions (AudioFileType.MPEG4, AudioFormatType.MPEG4AAC); + var a5 = AudioFileGlobalInfo.AllExtensions; + var a6 = AudioFileGlobalInfo.GetExtensions (AudioFileType.MPEG4); + var a7 = AudioFileGlobalInfo.GetMIMETypes (AudioFileType.MPEG4); + var a8 = AudioFileGlobalInfo.GetUTIs (AudioFileType.MPEG4); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioFileStreamTest.cs b/tests/monotouch-test/AudioToolbox/AudioFileStreamTest.cs new file mode 100644 index 000000000000..81e126fc239d --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioFileStreamTest.cs @@ -0,0 +1,108 @@ +// +// Unit tests for AudioFileStream +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioFileStreamTest { + + string FourCC (int value) + { + return new string (new char [] { + (char) (byte) (value >> 24), + (char) (byte) (value >> 16), + (char) (byte) (value >> 8), + (char) (byte) value }); + } + + [Test] + public void FourCC () + { + Assert.That (FourCC ((int) AudioFileProperty.AudioDataByteCount), Is.EqualTo ("bcnt"), "AudioDataByteCount"); + Assert.That (FourCC ((int) AudioFileProperty.AudioDataPacketCount), Is.EqualTo ("pcnt"), "AudioDataPacketCount"); + Assert.That (FourCC ((int) AudioFileProperty.BitRate), Is.EqualTo ("brat"), "BitRate"); + Assert.That (FourCC ((int) AudioFileProperty.ByteToPacket), Is.EqualTo ("bypk"), "ByteToPacket"); + Assert.That (FourCC ((int) AudioFileProperty.ChannelLayout), Is.EqualTo ("cmap"), "ChannelLayout"); + Assert.That (FourCC ((int) AudioFileProperty.DataFormat), Is.EqualTo ("dfmt"), "DataFormat"); + Assert.That (FourCC ((int) AudioFileProperty.DataOffset), Is.EqualTo ("doff"), "DataOffset"); + Assert.That (FourCC ((int) AudioFileProperty.FileFormat), Is.EqualTo ("ffmt"), "FileFormat"); + Assert.That (FourCC ((int) AudioFileProperty.FormatList), Is.EqualTo ("flst"), "FormatList"); + Assert.That (FourCC ((int) AudioFileProperty.FrameToPacket), Is.EqualTo ("frpk"), "FrameToPacket"); + Assert.That (FourCC ((int) AudioFileProperty.MagicCookieData), Is.EqualTo ("mgic"), "MagicCookieData"); + Assert.That (FourCC ((int) AudioFileProperty.MaximumPacketSize), Is.EqualTo ("psze"), "MaximumPacketSize"); + Assert.That (FourCC ((int) AudioFileProperty.PacketSizeUpperBound), Is.EqualTo ("pkub"), "PacketSizeUpperBound"); + Assert.That (FourCC ((int) AudioFileProperty.PacketTableInfo), Is.EqualTo ("pnfo"), "PacketTableInfo"); + Assert.That (FourCC ((int) AudioFileProperty.PacketToByte), Is.EqualTo ("pkby"), "PacketToByte"); + Assert.That (FourCC ((int) AudioFileProperty.PacketToFrame), Is.EqualTo ("pkfr"), "PacketToFrame"); + // were missing - part of https://developer.apple.com/library/ios/#documentation/MusicAudio/Reference/AudioStreamReference/Reference/reference.html + Assert.That (FourCC ((int) AudioFileProperty.ReadyToProducePackets), Is.EqualTo ("redy"), "AverageBytesPerPacket"); + Assert.That (FourCC ((int) AudioFileProperty.AverageBytesPerPacket), Is.EqualTo ("abpp"), "ReadyToProducePackets"); + } + + // not defined in https://developer.apple.com/library/ios/#documentation/MusicAudio/Reference/AudioStreamReference/Reference/reference.html + [Test] + public void UndocumentedFourCC () + { + Assert.That (FourCC ((int) AudioFileProperty.AlbumArtwork), Is.EqualTo ("aart"), "AlbumArtwork"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.ChunkIDs), Is.EqualTo ("chid"), "ChunkIDs"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.DataFormatName), Is.EqualTo ("fnme"), "DataFormatName"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.DeferSizeUpdates), Is.EqualTo ("dszu"), "DeferSizeUpdates"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.EstimatedDuration), Is.EqualTo ("edur"), "EstimatedDuration"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.ID3Tag), Is.EqualTo ("id3t"), "ID3Tag"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.InfoDictionary), Is.EqualTo ("info"), "InfoDictionary"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.IsOptimized), Is.EqualTo ("optm"), "IsOptimized"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.MarkerList), Is.EqualTo ("mkls"), "MarkerList"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.RegionList), Is.EqualTo ("rgls"), "RegionList"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.ReserveDuration), Is.EqualTo ("rsrv"), "ReserveDuration"); // ? reference ? + Assert.That (FourCC ((int) AudioFileProperty.SourceBitDepth), Is.EqualTo ("sbtd"), "SourceBitDepth"); // ? reference ? + } + + [Test] + public void CafNoData () + { + using (AudioFileStream afs = new AudioFileStream (AudioFileType.CAF)) { + Assert.That (afs.StreamBasicDescription.BitsPerChannel, Is.EqualTo (0), "StreamBasicDescription.BitsPerChannel"); + Assert.That (afs.StreamBasicDescription.BytesPerFrame, Is.EqualTo (0), "StreamBasicDescription.BytesPerFrame"); + Assert.That (afs.StreamBasicDescription.BytesPerPacket, Is.EqualTo (0), "StreamBasicDescription.BytesPerPacket"); + Assert.That (afs.StreamBasicDescription.ChannelsPerFrame, Is.EqualTo (0), "StreamBasicDescription.ChannelsPerFrame"); + Assert.That (afs.StreamBasicDescription.Format, Is.EqualTo ((AudioFormatType) 0), "StreamBasicDescription.Format"); + Assert.That (afs.StreamBasicDescription.FormatFlags, Is.EqualTo ((AudioFormatFlags) 0), "StreamBasicDescription.FormatFlags"); + Assert.That (afs.StreamBasicDescription.FramesPerPacket, Is.EqualTo (0), "StreamBasicDescription.FramesPerPacket"); + Assert.That (afs.StreamBasicDescription.Reserved, Is.EqualTo (0), "StreamBasicDescription.Reserved"); + Assert.That (afs.StreamBasicDescription.SampleRate, Is.EqualTo (0), "StreamBasicDescription.SampleRate"); + + int offset; + var packet = afs.FrameToPacket (0, out offset); + Assert.That (packet, Is.LessThanOrEqualTo (0), "FrameToPacket"); // -1 on first run + Assert.That (offset, Is.EqualTo (0), "offset"); + + long frame = afs.PacketToFrame (packet); + Assert.That (frame, Is.LessThanOrEqualTo (0), "PacketToFrame"); // -1 on first run + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioFileTest.cs b/tests/monotouch-test/AudioToolbox/AudioFileTest.cs new file mode 100644 index 000000000000..92fc3c96fa90 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioFileTest.cs @@ -0,0 +1,48 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioFileTest { + + [Test] + public void ReadTest () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + var af = AudioFile.Open (CFUrl.FromFile (path), AudioFilePermission.Read, AudioFileType.CAF); + + int len; + long current = 0; + long size = 1024; + byte [] buffer = new byte [size]; + while ((len = af.Read (current, buffer, 0, buffer.Length, false)) != -1) { + current += len; + } + + var full_len = new FileInfo (path).Length; + int header = 4096; + Assert.That (header + current == full_len, "#1"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioFormatAvailabilityTest.cs b/tests/monotouch-test/AudioToolbox/AudioFormatAvailabilityTest.cs new file mode 100644 index 000000000000..bfcc6d95eca8 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioFormatAvailabilityTest.cs @@ -0,0 +1,41 @@ +// +// Unit tests for AudioFormatAvailabilityTest +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +#if XAMCORE_2_0 +using Foundation; +using AudioToolbox; +#else +using MonoTouch.Foundation; +using MonoTouch.AudioToolbox; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioFormatAvailabilityTest + { + [Test] + public void GetDecoders () + { + Assert.IsNotNull (AudioFormatAvailability.GetDecoders (AudioFormatType.LinearPCM)); + } + + [Test] + public void GetEncoders () + { + Assert.IsNotNull (AudioFormatAvailability.GetEncoders (AudioFormatType.AC3)); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioFormatTest.cs b/tests/monotouch-test/AudioToolbox/AudioFormatTest.cs new file mode 100644 index 000000000000..ec9cda503764 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioFormatTest.cs @@ -0,0 +1,47 @@ +// +// Unit tests for AudioFormat +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; +using System.Threading; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioFormatTest + { + [Test] + public void GetFirstPlayableFormat () + { + var asbd = new AudioStreamBasicDescription (AudioFormatType.MPEG4AAC); + AudioStreamBasicDescription.GetFormatInfo (ref asbd); + + var ofl = asbd.GetOutputFormatList (); + + Assert.IsNotNull (AudioFormat.GetFirstPlayableFormat (ofl)); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioQueueTest.cs b/tests/monotouch-test/AudioToolbox/AudioQueueTest.cs new file mode 100644 index 000000000000..99dbeb2c97eb --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioQueueTest.cs @@ -0,0 +1,85 @@ +// +// Unit tests for AudioQueue +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using MediaPlayer; +using AudioToolbox; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioQueueTest + { + [Test] + public void Properties () + { + var b = new InputAudioQueue (AudioStreamBasicDescription.CreateLinearPCM ()); + b.HardwareCodecPolicy = AudioQueueHardwareCodecPolicy.PreferHardware; + + Assert.That (b.HardwareCodecPolicy, Is.EqualTo (AudioQueueHardwareCodecPolicy.PreferHardware), "#1"); + } + + [Test] + public void ChannelAssignments () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("Requires iOS 6"); + + var aq = new OutputAudioQueue (AudioStreamBasicDescription.CreateLinearPCM ()); + + Assert.AreEqual (AudioQueueStatus.Ok, aq.SetChannelAssignments ( + new AudioQueueChannelAssignment ("11", 0), + new AudioQueueChannelAssignment ("22", 1) + )); + } + + [Test][Ignore ("Fails on some machines with undefined error code 5")] + public void ProcessingTap () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("AudioQueueProcessingTapNew requires iOS 6"); + + var aq = new InputAudioQueue (AudioStreamBasicDescription.CreateLinearPCM ()); + AudioQueueStatus ret; + bool called = false; + + using (var tap = aq.CreateProcessingTap ( + delegate(AudioQueueProcessingTap audioQueueTap, uint numberOfFrames, ref AudioTimeStamp timeStamp, ref AudioQueueProcessingTapFlags flags, AudioBuffers data) { + called = true; + return 33; + }, AudioQueueProcessingTapFlags.PreEffects, out ret)) { + Assert.AreEqual (AudioQueueStatus.Ok, ret, "#1"); + + unsafe { + AudioQueueBuffer* buffer; + Assert.AreEqual (AudioQueueStatus.Ok, aq.AllocateBuffer (5000, out buffer), "#2"); + Assert.AreEqual (AudioQueueStatus.Ok, aq.EnqueueBuffer (buffer), "#3"); + //Assert.AreEqual (AudioQueueStatus.Ok, aq.Start (), "#4"); + } + } + + //Assert.That (called, Is.True, "#10"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioSessionTest.cs b/tests/monotouch-test/AudioToolbox/AudioSessionTest.cs new file mode 100644 index 000000000000..1dcc5f7aa71c --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioSessionTest.cs @@ -0,0 +1,55 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioSessionTest { + + public AudioSessionTest () + { + AudioSession.Initialize (); + } + + [Test] + public void Properties () + { + var input = AudioSession.InputRoute; + + Assert.That (Enum.IsDefined (typeof (AudioSessionInputRouteKind), input), "InputRoute"); + if (Runtime.Arch == Arch.DEVICE) { + // Apparently my iPad2 doesn't have microphone ?!? + //Assert.That (input != AudioSessionInputRouteKind.None, "All known devices has microphones"); + } + + var outputs = AudioSession.OutputRoutes; + if (outputs != null) { + foreach (var output in outputs) + Assert.That (Enum.IsDefined (typeof (AudioSessionOutputRouteKind), output), "Output: " + output.ToString ()); + } + + if (Runtime.Arch == Arch.DEVICE) { + Assert.That (outputs != null && outputs.Length > 0, "All known devices have at least speakers #1"); + Assert.That (outputs [0] != AudioSessionOutputRouteKind.None, "All known devices have at least speakers #2"); + } + } + } +} +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/AudioStreamBasicDescriptionTest.cs b/tests/monotouch-test/AudioToolbox/AudioStreamBasicDescriptionTest.cs new file mode 100644 index 000000000000..11b7350c5c1d --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/AudioStreamBasicDescriptionTest.cs @@ -0,0 +1,62 @@ +// +// Unit tests for AudioStreamBasicDescription +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; +using System.Threading; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioStreamBasicDescriptionTest + { + [Test] + public void CreateLinearPCM () + { + var pcm = AudioStreamBasicDescription.CreateLinearPCM (); + Assert.IsNotNull (pcm.FormatName); + Assert.IsFalse (pcm.IsVariableBitrate); + } + + [Test] + public void VBR () + { + var mp3 = new AudioStreamBasicDescription (AudioFormatType.MPEGLayer3); + Assert.IsTrue (mp3.IsVariableBitrate); + } + + [Test] + public void GetFormatInfo () + { + var asbd = new AudioStreamBasicDescription (AudioFormatType.MPEG4AAC); + Assert.AreEqual (AudioFormatError.None, AudioStreamBasicDescription.GetFormatInfo (ref asbd)); + + Assert.IsNotNull (AudioStreamBasicDescription.GetAvailableEncodeChannelLayoutTags (asbd)); + Assert.IsNotNull (AudioStreamBasicDescription.GetAvailableEncodeNumberChannels (asbd)); + Assert.IsNotNull (asbd.GetOutputFormatList ()); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/FourCCTest.cs b/tests/monotouch-test/AudioToolbox/FourCCTest.cs new file mode 100644 index 000000000000..6cfa26c68476 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/FourCCTest.cs @@ -0,0 +1,100 @@ +// +// FourCC Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using AudioToolbox; +using ObjCRuntime; +#else +using MonoTouch.AudioToolbox; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FourCCTests { + + public static string FourCC (int value) + { + return new string (new char [] { + (char) (byte) (value >> 24), + (char) (byte) (value >> 16), + (char) (byte) (value >> 8), + (char) (byte) value }); + } + + public static int FourCC (string s) + { + return (((int)s [0]) << 24 | + ((int)s [1]) << 16 | + ((int)s [2]) << 8 | + ((int)s [3])); + } + + [Test] + public void AudioFormatTypeTest () + { + Assert.That ((int) AudioFormatType.MPEG4AAC_ELD_V2, Is.EqualTo (FourCC ("aacg")), "MPEG4AAC_ELD_V2"); + } + + [Test] + public void AudioFilePropertyTest () + { + Assert.That ((int) AudioFileProperty.AudioTrackCount, Is.EqualTo (FourCC ("atct")), "AudioTrackCount"); + Assert.That ((int) AudioFileProperty.UseAudioTrack, Is.EqualTo (FourCC ("uatk")), "UseAudioTrack"); + } + + [Test] + public void AudioFileStreamPropertyTest () + { + Assert.That ((int) AudioFileStreamProperty.InfoDictionary, Is.EqualTo (FourCC ("info")), "InfoDictionary"); + } + + [Test] + public void AudioQueuePropertyTest () + { + Assert.That ((int) AudioQueueProperty.EnableTimePitch, Is.EqualTo (FourCC ("q_tp")), "EnableTimePitch"); + Assert.That ((int) AudioQueueProperty.TimePitchAlgorithm, Is.EqualTo (FourCC ("qtpa")), "TimePitchAlgorithm"); + Assert.That ((int) AudioQueueProperty.TimePitchBypass, Is.EqualTo (FourCC ("qtpb")), "TimePitchBypass"); + } + + [Test] + public void AudioQueueTimePitchAlgorithmtest () + { + Assert.That ((int) AudioQueueTimePitchAlgorithm.Spectral, Is.EqualTo (FourCC ("spec")), "Spectral"); + Assert.That ((int) AudioQueueTimePitchAlgorithm.TimeDomain, Is.EqualTo (FourCC ("tido")), "TimeDomain"); + Assert.That ((int) AudioQueueTimePitchAlgorithm.LowQualityZeroLatency, Is.EqualTo (FourCC ("lqzl")), "LowQualityZeroLatency"); + Assert.That ((int) AudioQueueTimePitchAlgorithm.Varispeed, Is.EqualTo (FourCC ("vspd")), "Varispeed"); + } + + [Test] + public void MusicSequenceFileTypeIDTest () + { + Assert.That ((int) MusicSequenceFileTypeID.Midi, Is.EqualTo (FourCC ("midi")), "Midi"); + Assert.That ((int) MusicSequenceFileTypeID.iMelody, Is.EqualTo (FourCC ("imel")), "iMelody"); + } + + [Test] + public void MusicSequenceTypeTest () + { + Assert.That ((int) MusicSequenceType.Beats, Is.EqualTo (FourCC ("beat")), "Beats"); + Assert.That ((int) MusicSequenceType.Seconds, Is.EqualTo (FourCC ("secs")), "Seconds"); + Assert.That ((int) MusicSequenceType.Samples, Is.EqualTo (FourCC ("samp")), "Samples"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/MusicSequenceTest.cs b/tests/monotouch-test/AudioToolbox/MusicSequenceTest.cs new file mode 100644 index 000000000000..872362319efe --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/MusicSequenceTest.cs @@ -0,0 +1,60 @@ +// +// MusicSequence unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using AudioToolbox; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.AudioToolbox; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MusicSequenceTest { + + [Test] + public void Defaults () + { + using (var ms = new MusicSequence ()) { + Assert.NotNull (ms.AUGraph, "AUGraph"); + Assert.That (ms.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (ms.SequenceType, Is.EqualTo (MusicSequenceType.Beats), "SequenceType"); + Assert.That (ms.TrackCount, Is.EqualTo (0), "TrackCount"); + } + } + + [Test] + public void SMPTEResolution () + { + // calls are CF_INLINE (in header files) which means it can't be p/invoked + // it will throw EntryPointNotFoundException since it's not part of the library + using (var ms = new MusicSequence ()) { + sbyte fps; + byte ticks; + ms.GetSmpteResolution (Int16.MaxValue, out fps, out ticks); + Assert.That (fps, Is.EqualTo (127), "fps"); + Assert.That (ticks, Is.EqualTo (127), "ticks"); + + // not a roundtip - but identical to ObjC results + Assert.That (ms.SetSmpteResolution (fps, ticks), Is.EqualTo (-32385), "set"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/SoundBankTest.cs b/tests/monotouch-test/AudioToolbox/SoundBankTest.cs new file mode 100644 index 000000000000..615218076659 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/SoundBankTest.cs @@ -0,0 +1,115 @@ +// +// SoundBank unit tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using AudioToolbox; +using CoreFoundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SoundBankTest { + + const string local_dls = "file:///System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls"; + + [Test] + public void GetName () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS 7"); + + Assert.Throws (delegate { SoundBank.GetName (null); }, "null"); + + using (NSUrl url = new NSUrl ("http://www.xamarin.com")) { + Assert.Null (SoundBank.GetName (url), "Not a SoundBank"); + } + } + + [Test] + public void GetName_DLS_SimOnly () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS 7"); + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Use local file system (need a smaller sample)"); + + using (NSUrl url = new NSUrl (local_dls)) { + Assert.That (SoundBank.GetName (url), Is.EqualTo ("QuickTime Music Synthesizer "), "Name"); + } + } + + [Test] + public void GetInstrumentInfo () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS 7"); + + Assert.Throws (delegate { SoundBank.GetInstrumentInfo (null); }, "null"); + + using (NSUrl url = new NSUrl ("http://www.xamarin.com")) { + Assert.Null (SoundBank.GetInstrumentInfo (url), "Not a SoundBank"); + } + } + + [Test] + public void GetInstrumentInfo_DLS_SimOnly () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS 7"); + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Use local file system (need a smaller sample)"); + + using (NSUrl url = new NSUrl (local_dls)) { + var info = SoundBank.GetInstrumentInfo (url); + Assert.That (info.Length, Is.EqualTo (235), "Length"); + + var first = info [0]; + Assert.That (first.Dictionary.Count, Is.EqualTo ((nuint) 4), "first.Count"); + Assert.That (first.Name, Is.EqualTo ("Piano 1 "), "first.name"); + Assert.That (first.MSB, Is.EqualTo (121), "first.MSB"); + Assert.That (first.LSB, Is.EqualTo (0), "first.LSB"); + Assert.That (first.Program, Is.EqualTo (0), "first.program"); + + var last = info [234].Dictionary; + Assert.That (last.Count, Is.EqualTo ((nuint) 4), "last.Count"); + Assert.That (last [InstrumentInfo.NameKey].ToString (), Is.EqualTo ("SFX "), "last.Name"); + Assert.That ((last [InstrumentInfo.MSBKey] as NSNumber).Int32Value, Is.EqualTo (120), "last.MSB"); + Assert.That ((last [InstrumentInfo.LSBKey] as NSNumber).Int32Value, Is.EqualTo (0), "last.LSB"); + Assert.That ((last [InstrumentInfo.ProgramKey] as NSNumber).Int32Value, Is.EqualTo (56), "last.Program"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioToolbox/SystemSoundTest.cs b/tests/monotouch-test/AudioToolbox/SystemSoundTest.cs new file mode 100644 index 000000000000..8d578b13245a --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/SystemSoundTest.cs @@ -0,0 +1,113 @@ +// +// Unit tests for SystemSound +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using AudioToolbox; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.AudioToolbox; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; +using System.Threading; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SystemSoundTest + { + [Test] + public void FromFile () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + + using (var ss = SystemSound.FromFile (NSUrl.FromFilename (path))) { + Assert.AreEqual (AudioServicesError.None, ss.AddSystemSoundCompletion (delegate { + })); + + ss.PlaySystemSound (); + } + } + + [Test] + public void Properties () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + + using (var ss = SystemSound.FromFile (NSUrl.FromFilename (path))) { + Assert.That (ss.IsUISound, Is.True, "#1"); + Assert.That (ss.CompletePlaybackIfAppDies, Is.False, "#2"); + } + } + + [Test] + public void TestCallbackPlaySystem () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Inconclusive ("requires iOS9"); + + string path = Path.Combine (NSBundle.MainBundle.ResourcePath, "drum01.mp3"); + + using (var ss = SystemSound.FromFile (NSUrl.FromFilename (path))) { + + var completed = false; + const int timeout = 10; + + completed = false; + Assert.IsTrue (MonoTouchFixtures.AppDelegate.RunAsync (DateTime.Now.AddSeconds (timeout), async () => + ss.PlaySystemSound (() => { completed = true; } + ), () => completed), "TestCallbackPlaySystem"); + } + } + + [Test] + public void TestCallbackPlayAlert () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Inconclusive ("requires iOS9"); + + string path = Path.Combine (NSBundle.MainBundle.ResourcePath, "drum01.mp3"); + + using (var ss = SystemSound.FromFile (NSUrl.FromFilename (path))) { + + var completed = false; + const int timeout = 10; + + completed = false; + Assert.IsTrue (MonoTouchFixtures.AppDelegate.RunAsync (DateTime.Now.AddSeconds (timeout), async () => + ss.PlayAlertSound (() => { completed = true; } + ), () => completed), "TestCallbackPlayAlert"); + } + } + + [Test] + public void DisposeTest () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + + var ss = SystemSound.FromFile (NSUrl.FromFilename (path)); + Assert.That (ss.Handle, Is.Not.EqualTo (IntPtr.Zero), "DisposeTest"); + + ss.Dispose (); + // Handle prop checks NotDisposed and throws if it is + Assert.Throws (() => ss.Handle.ToString (), "DisposeTest"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioUnit/AUAudioUnitFactoryTest.cs b/tests/monotouch-test/AudioUnit/AUAudioUnitFactoryTest.cs new file mode 100644 index 000000000000..45f3b002bdc2 --- /dev/null +++ b/tests/monotouch-test/AudioUnit/AUAudioUnitFactoryTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for AUAudioUnitFactory +// +// Authors: +// Oleg Demchenko (oleg.demchenko@xamarin.com) +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ && XAMCORE_2_0 + +using System; + +using NUnit.Framework; + +using Foundation; +using AudioUnit; + +namespace MonoTouchFixtures.AudioUnit { + [TestFixture] + [Preserve (AllMembers = true)] + public class AUAudioUnitFactoryTest { + [Test] + public void CreateAudioUnit () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AudioUnitv3 tests: Requires iOS9+"); + + const string expectedManufacturer = "Apple"; + var desc = new AudioComponentDescription { + ComponentType = AudioComponentType.Output, + ComponentSubType = 0x72696f63, // Remote_IO + ComponentManufacturer = AudioComponentManufacturerType.Apple + }; + + using (var auFactory = new CustomAudioUnitFactory ()) { + NSError error; + using (var audioUnit = auFactory.CreateAudioUnit (desc, out error)) { + Assert.True (audioUnit != null, "CustomAudioUnitFactory returned null object for valid component description"); + Assert.True (audioUnit.ManufacturerName == expectedManufacturer, + $"CustomAudioUnitFactory returned audio unit with incorrect manufacturer. Expected - {expectedManufacturer}, actual - {audioUnit.ManufacturerName}"); + } + } + } + + public class CustomAudioUnitFactory : NSObject, IAUAudioUnitFactory { + public AUAudioUnit CreateAudioUnit (AudioComponentDescription desc, out NSError error) + { + var audioUnit = new AUAudioUnit (desc, out error); + return audioUnit; + } + + public void BeginRequestWithExtensionContext (NSExtensionContext context) + { + throw new NotImplementedException (); + } + } + } +} + +#endif // !__WATCHOS__ && XAMCORE_2_0 diff --git a/tests/monotouch-test/AudioUnit/AUGraphTest.cs b/tests/monotouch-test/AudioUnit/AUGraphTest.cs new file mode 100644 index 000000000000..64d47246c1e3 --- /dev/null +++ b/tests/monotouch-test/AudioUnit/AUGraphTest.cs @@ -0,0 +1,121 @@ +// +// Unit tests for AUGraph +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ +using System; +using System.Runtime.InteropServices; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using AudioUnit; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.AudioUnit; +using MonoTouch.ObjCRuntime; +#endif + +namespace MonoTouchFixtures.AudioUnit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AUGraphTest + { + [Test] + public void BasicOperations () + { + using (var aug = new AUGraph ()) { + aug.Open (); + Assert.IsTrue (aug.IsOpen, "#0"); + Assert.IsFalse (aug.IsInitialized, "#0a"); + Assert.IsFalse (aug.IsRunning, "#0b"); + + var node = aug.AddNode (AudioComponentDescription.CreateOutput (AudioTypeOutput.Generic)); + int count; + Assert.AreEqual (AUGraphError.OK, aug.GetNodeCount (out count), "#1"); + Assert.AreEqual (1, count, "#2"); + + var info = aug.GetNodeInfo (node); + Assert.IsNotNull (info, "#3"); + + int node2; + Assert.AreEqual (AUGraphError.OK, aug.GetNode (0, out node2), "#4"); + Assert.AreEqual (1, node2, "#4a"); + + float max_load; + Assert.AreEqual (AUGraphError.OK, aug.GetMaxCPULoad (out max_load)); + } + } + + [Test] + public void Connections () + { + using (var aug = new AUGraph ()) { + aug.Open (); + + var node_1 = aug.AddNode (AudioComponentDescription.CreateGenerator (AudioTypeGenerator.AudioFilePlayer)); + var node_2 = aug.AddNode (AudioComponentDescription.CreateOutput (AudioTypeOutput.Generic)); + + Assert.AreEqual (AUGraphError.OK, aug.ConnnectNodeInput (node_1, 0, node_2, 0), "#1"); + uint count; + aug.GetNumberOfInteractions (out count); + Assert.AreEqual (1, count, "#2"); + + Assert.AreEqual (AUGraphError.OK, aug.Initialize (), "#3"); + + Assert.AreEqual (AUGraphError.OK, aug.ClearConnections (), "#4"); + aug.GetNumberOfInteractions (out count); + Assert.AreEqual (0, count, "#5"); + } + } + + [Test] + public void CreateTest () + { + int errCode; + using (var aug = AUGraph.Create (out errCode)) { + Assert.NotNull (aug, "CreateTest"); + Assert.AreEqual (0, errCode, "CreateTest"); + + // Make sure it is a working instance + aug.Open (); + Assert.IsTrue (aug.IsOpen, "CreateTest #0"); + Assert.IsFalse (aug.IsInitialized, "CreateTest #0a"); + Assert.IsFalse (aug.IsRunning, "CreateTest #0b"); + } + } + + [DllImport (Constants.AudioToolboxLibrary, EntryPoint = "NewAUGraph")] + static extern int NewAUGraph (ref IntPtr outGraph); + + [Test] + public void GetNativeTest () + { + IntPtr ret = IntPtr.Zero; + var errCode = NewAUGraph (ref ret); + Assert.AreEqual (0, errCode, "GetNativeTest"); + Assert.That (ret, Is.Not.EqualTo (IntPtr.Zero), "ret"); + + using (var aug = Runtime.GetINativeObject (ret, true)) { + Assert.NotNull (aug, "CreateTest"); + Assert.That (aug.Handle, Is.EqualTo (ret), "Handle"); + + // Make sure it is a working instance + aug.Open (); + Assert.IsTrue (aug.IsOpen, "CreateTest #0"); + Assert.IsFalse (aug.IsInitialized, "CreateTest #0a"); + Assert.IsFalse (aug.IsRunning, "CreateTest #0b"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioUnit/AUParameterNodeTest.cs b/tests/monotouch-test/AudioUnit/AUParameterNodeTest.cs new file mode 100644 index 000000000000..52ea9489caf8 --- /dev/null +++ b/tests/monotouch-test/AudioUnit/AUParameterNodeTest.cs @@ -0,0 +1,192 @@ +// +// Unit tests for AUParameterNode +// +// Authors: +// Oleg Demchenko (oleg.demchenko@xamarin.com) +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ && XAMCORE_2_0 + +using System; +using System.Threading; + +using NUnit.Framework; + +using Foundation; +using AudioUnit; + +namespace monotouchtest { + [TestFixture] + [Preserve (AllMembers = true)] + public class AUParameterNodeTest { + [Test] + public void CreateTokenByAddingParameterRecordingObserver () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AudioUnitv3 tests: Requires iOS9+"); + + const ulong address = 0; + const float newValue = 10f; + + bool recordingObserverInvoked = false; + var completion = new ManualResetEvent (false); + + using (var parameter = CreateAUParameter ()) { + using (var tree = AUParameterTree.CreateTree (new AUParameterNode[] { parameter })) { + var recordingObserver = tree.CreateTokenByAddingParameterRecordingObserver ((nint numberOfEvents, ref AURecordedParameterEvent events) => { + Assert.True (numberOfEvents == 1, + $"Number of events was wrong. Expected {1} but was {numberOfEvents}"); + + Assert.True (events.Address == address, + $"Address was wrong. Expected {address} but was {events.Address}"); + + Assert.True (events.Value == newValue, + $"Value was wrong. Expected {newValue} but was {events.Value}"); + + recordingObserverInvoked = true; + completion.Set (); + }); + + Assert.True (recordingObserver.ObserverToken != IntPtr.Zero, "TokenByAddingParameterRecordingObserver return zero pointer for recording observer."); + parameter.Value = newValue; + + completion.WaitOne (TimeSpan.FromSeconds (1)); + Assert.True (recordingObserverInvoked, "Recording observer was not invoked when paramter value was changed."); + } + } + } + + [Test] + public void RemoveParameterObserver () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AudioUnitv3 tests: Requires iOS9+"); + + const ulong address = 0; + const float newValue = 10f; + + bool recordingObserverInvoked = false; + var completion = new ManualResetEvent (false); + + using (var parameter = CreateAUParameter ()) { + using (var tree = AUParameterTree.CreateTree (new AUParameterNode[] { parameter })) { + var recordingObserver = tree.CreateTokenByAddingParameterRecordingObserver ((nint numberOfEvents, ref AURecordedParameterEvent events) => { + recordingObserverInvoked = true; + completion.Set (); + }); + + tree.RemoveParameterObserver (recordingObserver); + + Assert.True (recordingObserver.ObserverToken != IntPtr.Zero, "TokenByAddingParameterRecordingObserver return zero pointer for recording observer."); + parameter.Value = newValue; + + completion.WaitOne (TimeSpan.FromSeconds (1)); + Assert.False (recordingObserverInvoked, "Recording observer was invoked however observer it should be removed already."); + } + } + } + + [Test] + public void ImplementorStringFromValueCallback () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AudioUnitv3 tests: Requires iOS9+"); + + const float floatValue = 10f; + const string expectedStringValue = "10"; + + bool implementorCallbackInvoked = false; + + using (var parameter = CreateAUParameter ()) { + parameter.ImplementorStringFromValueCallback = new AUImplementorStringFromValueCallback ((AUParameter param, ref float? value) => { + Assert.True (floatValue == value.Value, + $"Passed float value was incorrect. Expected {floatValue} but was {value}"); + + Assert.True (param.Identifier == parameter.Identifier, + $"Passed AUParameter was incorrect. Expected {parameter.Identifier} but was {param.Identifier}"); + + implementorCallbackInvoked = true; + return value.ToString (); + }); + + var str = parameter.GetString (floatValue); + + Assert.True (implementorCallbackInvoked, "StringValueFrom callback was not invoked."); + Assert.True (str == expectedStringValue, + $"String doesn't match. Expected {expectedStringValue}, actual {str}"); + } + } + + [Test] + public void ImplementorValueFromStringCallback () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AudioUnitv3 tests: Requires iOS9+"); + + const float expectedValue = 10f; + const string stringValue = "10"; + + bool implementorCallbackInvoked = false; + + using (var parameter = CreateAUParameter ()) { + parameter.ImplementorValueFromStringCallback = new AUImplementorValueFromStringCallback ((param, str) => { + Assert.True (str == stringValue, + $"Passed string value was incorrect. Expected {stringValue} but was {str}"); + + Assert.True (param.Identifier == parameter.Identifier, + $"Passed AUParameter was incorrect. Expected {parameter.Identifier} but was {param.Identifier}"); + + implementorCallbackInvoked = true; + return Single.Parse (str); + }); + + var value = parameter.GetValue (stringValue); + + Assert.True (implementorCallbackInvoked, "ValueFromString callback was not invoked."); + Assert.False (Math.Abs (value - expectedValue) > float.Epsilon, + $"Values doesn't match. Expected {expectedValue}, actual {value}"); + } + } + + // TODO: Test temporary ignored. + // Reason: ImplementorDisplayNameWithLengthCallback never invoked when user requests truncated version of node's name. + // Objc/Swift code demosntrates the same behavior. + // Waiting for comments/fix from Apple. + [Test, Ignore] + public void ImplementorDisplayNameWithLengthCallback () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring AudioUnitv3 tests: Requires iOS9+"); + + const string displayName = "Resonance"; + const int length = 5; + + bool implementorCallbackInvoked = false; + string expectedTruncatedName = displayName.Substring (0, length); + + using (var parameter = CreateAUParameter ()) { + parameter.ImplementorDisplayNameWithLengthCallback = new AUImplementorDisplayNameWithLengthCallback ((node, desiredLength) => { + Assert.True (length == desiredLength, "Passed length value is incorrect."); + Assert.True (node.Identifier == parameter.Identifier, + $"Passed AUParameterNode was incorrect. Expected {parameter.Identifier} but was {node.Identifier}"); + + implementorCallbackInvoked = true; + return node.DisplayName.Substring (0, (int)desiredLength); + }); + + var s = parameter.GetDisplayName (length); + Assert.True (implementorCallbackInvoked, "Display name callback was not invoked."); + Assert.True (expectedTruncatedName == s, $"Truncated node display name was incorrect. Expected {expectedTruncatedName} but was {s}"); + } + } + + static AUParameter CreateAUParameter () + { + return AUParameterTree.CreateParameter ("resonance", "Resonance", 0, -20, 20, AudioUnitParameterUnit.Decibels, null, (AudioUnitParameterOptions)0, null, null); + } + } +} + +#endif // !__WATCHOS__ && XAMCORE_2_0 diff --git a/tests/monotouch-test/AudioUnit/AudioUnitTest.cs b/tests/monotouch-test/AudioUnit/AudioUnitTest.cs new file mode 100644 index 000000000000..276d32637065 --- /dev/null +++ b/tests/monotouch-test/AudioUnit/AudioUnitTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for AudioUnit +// + +#if !__WATCHOS__ + +using System; +using NUnit.Framework; +using System.Runtime.InteropServices; + + +#if XAMCORE_2_0 +using Foundation; +using AudioUnit; +using AudioToolbox; +using ObjCRuntime; +#else +using MonoTouch.AudioUnit; +using MonoTouch.AudioToolbox; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch; +#endif + +namespace MonoTouchFixtures.AudioUnit +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioUnitTest + { + [Test] + public void DisposeMethodTest () + { + // Test case from bxc #5410 + + // Create instance of AudioUnit object + AudioComponentDescription cd = new AudioComponentDescription () + { + ComponentType = AudioComponentType.Output, + ComponentSubType = 0x72696f63, // Remote_IO + ComponentManufacturer = AudioComponentManufacturerType.Apple + }; + AudioComponent component = AudioComponent.FindComponent (ref cd); + var audioUnit = component.CreateAudioUnit (); + + audioUnit.Dispose (); + } + + [Test] + public void GetElementCount () + { + var graph = new AUGraph (); + var mixerNode = graph.AddNode (AudioComponentDescription.CreateMixer (AudioTypeMixer.MultiChannel)); + graph.Open (); + var mixer = graph.GetNodeInfo (mixerNode); + Assert.AreEqual (1, mixer.GetElementCount (AudioUnitScopeType.Global)); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/AudioUnit/ExtAudioFileTest.cs b/tests/monotouch-test/AudioUnit/ExtAudioFileTest.cs new file mode 100644 index 000000000000..2104bcda5468 --- /dev/null +++ b/tests/monotouch-test/AudioUnit/ExtAudioFileTest.cs @@ -0,0 +1,75 @@ +// +// Unit tests for ExtAudioFile +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using NUnit.Framework; +#if XAMCORE_2_0 +using Foundation; +using AudioUnit; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.AudioUnit; +using MonoTouch.CoreFoundation; +#endif +using System.IO; + +namespace MonoTouchFixtures.AudioUnit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ExtAudioFileTest + { + [Test] + public void WrapAudioFileID () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + using (var file = ExtAudioFile.OpenUrl (CFUrl.FromFile (path))) { + Assert.IsNotNull (file.AudioFile, "#1"); + + ExtAudioFile f2; + Assert.AreEqual (ExtAudioFileError.OK, ExtAudioFile.WrapAudioFileID (file.AudioFile.Value, true, out f2)); + } + } + + [Test] + public void ClientDataFormat () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + using (var file = ExtAudioFile.OpenUrl (CFUrl.FromFile (path))) { + var fmt = file.ClientDataFormat; + } + } + + [Test] + public void OpenNSUrlTest () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + ExtAudioFileError err; + using (var file = ExtAudioFile.OpenUrl (NSUrl.FromFilename (path), out err)) { + Assert.IsTrue (err == ExtAudioFileError.OK, "OpenNSUrlTest"); + Assert.IsNotNull (file.AudioFile, "OpenNSUrlTest"); + } + } + + [Test] + public void OpenCFUrlTest () + { + var path = Path.GetFullPath (Path.Combine ("AudioToolbox", "1.caf")); + ExtAudioFileError err; + using (var file = ExtAudioFile.OpenUrl (CFUrl.FromFile (path), out err)) { + Assert.IsTrue (err == ExtAudioFileError.OK, "OpenCFUrlTest"); + Assert.IsNotNull (file.AudioFile, "OpenCFUrlTest"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/BoardingPass.pkpass b/tests/monotouch-test/BoardingPass.pkpass new file mode 100644 index 000000000000..153137b8af66 Binary files /dev/null and b/tests/monotouch-test/BoardingPass.pkpass differ diff --git a/tests/monotouch-test/Contacts/ContactFetchRequestTest.cs b/tests/monotouch-test/Contacts/ContactFetchRequestTest.cs new file mode 100644 index 000000000000..0aa06824d82f --- /dev/null +++ b/tests/monotouch-test/Contacts/ContactFetchRequestTest.cs @@ -0,0 +1,70 @@ +// +// Unit tests for CNContactFetchRequest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ +#if XAMCORE_2_0 // The Contacts framework is Unified only + +using System; +#if XAMCORE_2_0 +using Contacts; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Contacts; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Contacts { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ContactFetchRequestTest { + + [SetUp] + public void MinimumSdkCheck () + { + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Inconclusive ("Requires 9.0+"); + } + + [Test] + public void Ctor_ICNKeyDescriptorArray () + { + var keys = new [] { CNContactVCardSerialization.GetDescriptorFromRequiredKeys () }; + using (var cfr = new CNContactFetchRequest (keys)) { + Assert.That (keys [0].Description, Is.EqualTo (cfr.KeysToFetch.GetItem (0).Description), "KeysToFetch"); + } + } + + [Test] + public void Ctor_NSString () + { + var keys = new [] { CNContactKey.GivenName }; + using (var cfr = new CNContactFetchRequest (keys)) { + Assert.That (keys [0].Description, Is.EqualTo (cfr.KeysToFetch.GetItem (0).Description), "KeysToFetch"); + } + } + + [Test] + public void Ctor_Mixed () + { + var keys = new INativeObject [] { CNContactKey.GivenName, CNContactVCardSerialization.GetDescriptorFromRequiredKeys () }; + using (var cfr = new CNContactFetchRequest (keys)) { + Assert.That (2, Is.EqualTo (cfr.KeysToFetch.Count), "KeysToFetch"); + } + } + } +} + +#endif // XAMCORE_2_0 +#endif // !__TVOS__ diff --git a/tests/monotouch-test/Contacts/ContactFormatterTest.cs b/tests/monotouch-test/Contacts/ContactFormatterTest.cs new file mode 100644 index 000000000000..45beaa6f9915 --- /dev/null +++ b/tests/monotouch-test/Contacts/ContactFormatterTest.cs @@ -0,0 +1,65 @@ +// +// Unit tests for CNContactFormatter +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ +#if XAMCORE_2_0 // The Contacts framework is Unified only + +using System; +#if XAMCORE_2_0 +using Contacts; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Contacts; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Contacts { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ContactFormatterTest { + + [SetUp] + public void MinimumSdkCheck () + { + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Inconclusive ("Requires 9.0+"); + } + + [Test] + public void GetDescriptorForRequiredKeys_FullName () + { + var keys = CNContactFormatter.GetDescriptorForRequiredKeys (CNContactFormatterStyle.FullName); + // while most input for ICNKeyDescriptor are done with NSString + // the output is opaque and an internal type + // note: this is not very robust - but I want to know if this changes during the next betas + Assert.True (keys.Description.StartsWith (" +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ +#if XAMCORE_2_0 // The Contacts framework is Unified only + +using System; +#if XAMCORE_2_0 +using Contacts; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Contacts { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ContactStoreTest { + + [SetUp] + public void MinimumSdkCheck () + { + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Inconclusive ("Requires 9.0+"); + } + + [Test] + public void GetUnifiedContacts () + { + string identifier = null; + + var fetchKeys = new [] { CNContactKey.Identifier, CNContactKey.GivenName, CNContactKey.FamilyName }; + NSError error; + using (var predicate = CNContact.GetPredicateForContacts ("Appleseed")) + using (var store = new CNContactStore ()) { + var contacts = store.GetUnifiedContacts (predicate, fetchKeys, out error); + // we can't be sure what's on devices, so check there's no error is the only thing we do + Assert.Null (error, "error"); + // but it's in the default simulator build + if (Runtime.Arch == Arch.SIMULATOR) { + Assert.That (contacts.Length, Is.EqualTo (1), "Length"); + } + } + + // if we can't find the previous contact then we don't have an identifier for the GetUnifiedContact API + // and we can't hardcode one as each simulator instance has a different identifier... + if (identifier == null) + return; + + using (var store = new CNContactStore ()) { + var contact = store.GetUnifiedContact (identifier, fetchKeys, out error); + // it's in the default simulator build + if (Runtime.Arch == Arch.SIMULATOR) { + Assert.Null (error, "error"); + Assert.NotNull (contact, "contact"); + Assert.False (contact.AreKeysAvailable (CNContactOptions.OrganizationName | CNContactOptions.Note), "AreKeysAvailable-1"); + Assert.True (contact.AreKeysAvailable (CNContactOptions.None), "AreKeysAvailable-2"); + Assert.True (contact.AreKeysAvailable (fetchKeys), "AreKeysAvailable-3"); + } else { + // and it's a safe bet that id does not exists on any device + Assert.NotNull (error, "error"); // Updated Record Does Not Exist + } + } + } + } +} + +#endif // XAMCORE_2_0 +#endif // !__TVOS__ diff --git a/tests/monotouch-test/Contacts/ContactTest.cs b/tests/monotouch-test/Contacts/ContactTest.cs new file mode 100644 index 000000000000..71a6343b53cb --- /dev/null +++ b/tests/monotouch-test/Contacts/ContactTest.cs @@ -0,0 +1,90 @@ +// +// Unit tests for CNContact +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ +#if XAMCORE_2_0 // The Contacts framework is Unified only + +using System; +#if XAMCORE_2_0 +using Contacts; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Contacts; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Contacts { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ContactTest { + + [SetUp] + public void MinimumSdkCheck () + { + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Inconclusive ("Requires 9.0+"); + } + + [Test] + public void DescriptorForAllComparatorKeys () + { + var keys = CNContact.GetDescriptorForAllComparatorKeys (); + // while most input for ICNKeyDescriptor are done with NSString + // the output is opaque and an internal type + // note: this is not very robust - but I want to know if this changes during the next betas + Assert.True (keys.Description.StartsWith (" +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ +#if XAMCORE_2_0 // The Contacts framework is Unified only + +using System; +#if XAMCORE_2_0 +using Contacts; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Contacts; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Contacts { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ContactVCardSerializationTest { + + [SetUp] + public void MinimumSdkCheck () + { + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Inconclusive ("Requires 9.0+"); + } + + [Test] + public void GetDescriptorFromRequiredKeys () + { + var keys = CNContactVCardSerialization.GetDescriptorFromRequiredKeys (); + // while most input for ICNKeyDescriptor are done with NSString + // the output is opaque and an internal type + // note: this is not very robust - but I want to know if this changes during the next betas + Assert.True (keys.Description.StartsWith (" +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +#if XAMCORE_2_0 + +using System; +#if XAMCORE_2_0 +using Contacts; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Contacts; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Contacts { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MutableContactTest { + + [SetUp] + public void MinimumSdkCheck () + { + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Inconclusive ("Requires 9.0+"); + } + + [Test] + public void Properties () + { + using (var contact = new CNMutableContact ()) { + Assert.IsNull (contact.Birthday, "Birthday"); + Assert.AreEqual (0, contact.ContactRelations.Length, "ContactRelations"); + Assert.AreEqual (CNContactType.Person, contact.ContactType, "ContactType"); + Assert.AreEqual (0, contact.Dates.Length, "Dates"); + Assert.AreEqual (string.Empty, contact.DepartmentName, "DepartmentName"); + Assert.AreEqual (0, contact.EmailAddresses.Length, "EmailAddresses"); + Assert.AreEqual (string.Empty, contact.FamilyName, "FamilyName"); + Assert.AreEqual (string.Empty, contact.GivenName, "GivenName"); + Assert.AreNotEqual (string.Empty, contact.Identifier, "Identifier"); + Assert.IsNull (contact.ImageData, "ImageData"); + Assert.IsFalse (contact.ImageDataAvailable, "ImageDataAvailable"); + Assert.AreEqual (0, contact.InstantMessageAddresses.Length, "InstantMessageAddresses"); + Assert.AreEqual (string.Empty, contact.JobTitle, "JobTitle"); + Assert.AreEqual (string.Empty, contact.MiddleName, "MiddleName"); + Assert.AreEqual (string.Empty, contact.NamePrefix, "NamePrefix"); + Assert.AreEqual (string.Empty, contact.NameSuffix, "NameSuffix"); + Assert.AreEqual (string.Empty, contact.Nickname, "Nickname"); + Assert.IsNull (contact.NonGregorianBirthday, "NonGregorianBirthday"); + Assert.AreEqual (string.Empty, contact.Note, "Note"); + Assert.AreEqual (string.Empty, contact.OrganizationName, "OrganizationName"); + Assert.AreEqual (0, contact.PhoneNumbers.Length, "PhoneNumbers"); + Assert.AreEqual (string.Empty, contact.PhoneticFamilyName, "PhoneticFamilyName"); + Assert.AreEqual (string.Empty, contact.PhoneticGivenName, "PhoneticGivenName"); + Assert.AreEqual (string.Empty, contact.PhoneticMiddleName, "PhoneticMiddleName"); + Assert.AreEqual (0, contact.PostalAddresses.Length, "PostalAddresses"); + Assert.AreEqual (string.Empty, contact.PreviousFamilyName, "PreviousFamilyName"); + Assert.AreEqual (0, contact.SocialProfiles.Length, "SocialProfiles"); + Assert.IsNull (contact.ThumbnailImageData, "ThumbnailImageData"); + Assert.AreEqual (0, contact.UrlAddresses.Length, "UrlAddresses"); + + contact.Birthday = new NSDateComponents () { + Year = 1980 + }; + Assert.AreEqual (1980, contact.Birthday.Year, "Birthday"); + + contact.ContactRelations = new CNLabeledValue [] { + new CNLabeledValue ("label", new CNContactRelation ("relation")) + }; + Assert.AreEqual (1, contact.ContactRelations.Length, "ContactRelations"); + + contact.ContactType = CNContactType.Organization; + Assert.AreEqual (CNContactType.Organization, contact.ContactType, "ContactType"); + + contact.Dates = new CNLabeledValue [] { + new CNLabeledValue ("label", new NSDateComponents () { + Month = 6 + }) + }; + Assert.AreEqual (1, contact.Dates.Length, "Dates"); + + contact.DepartmentName = "department"; + Assert.AreEqual ("department", contact.DepartmentName, "DepartmentName"); + + contact.EmailAddresses = new CNLabeledValue [] { + new CNLabeledValue ("label", (NSString) "foo@bar.com") + }; + Assert.AreEqual (1, contact.EmailAddresses.Length, "EmailAddresses"); + + contact.FamilyName = "familyName"; + Assert.AreEqual ("familyName", contact.FamilyName, "FamilyName"); + + contact.GivenName = "givenName"; + Assert.AreEqual ("givenName", contact.GivenName, "GivenName"); + + Assert.AreNotEqual (string.Empty, contact.Identifier, "Identifier"); + + contact.ImageData = new NSData (); + Assert.IsNotNull (contact.ImageData, "ImageData"); + Assert.IsFalse (contact.ImageDataAvailable, "ImageDataAvailable"); + + contact.InstantMessageAddresses = new CNLabeledValue [] { + new CNLabeledValue ("label", new CNInstantMessageAddress ("user", "service")), + }; + Assert.AreEqual (1, contact.InstantMessageAddresses.Length, "InstantMessageAddresses"); + + contact.JobTitle = "title"; + Assert.AreEqual ("title", contact.JobTitle, "JobTitle"); + + contact.MiddleName = "middleName"; + Assert.AreEqual ("middleName", contact.MiddleName, "MiddleName"); + + contact.NamePrefix = "namePrefix"; + Assert.AreEqual ("namePrefix", contact.NamePrefix, "NamePrefix"); + + contact.NameSuffix = "nameSuffix"; + Assert.AreEqual ("nameSuffix", contact.NameSuffix, "NameSuffix"); + + contact.Nickname = "nickname"; + Assert.AreEqual ("nickname", contact.Nickname, "Nickname"); + + contact.NonGregorianBirthday = new NSDateComponents () { + Year = 2099, + }; + Assert.AreEqual (2099, contact.NonGregorianBirthday.Year, "NonGregorianBirthday"); + + contact.Note = "note"; + Assert.AreEqual ("note", contact.Note, "Note"); + + contact.OrganizationName = "organizationName"; + Assert.AreEqual ("organizationName", contact.OrganizationName, "OrganizationName"); + + contact.PhoneNumbers = new CNLabeledValue [] { + new CNLabeledValue ("label", new CNPhoneNumber ("123-345-456")) + }; + Assert.AreEqual (1, contact.PhoneNumbers.Length, "PhoneNumbers"); + + contact.PhoneticFamilyName = "phoneticFamilyName"; + Assert.AreEqual ("phoneticFamilyName", contact.PhoneticFamilyName, "PhoneticFamilyName"); + + contact.PhoneticGivenName = "phoneticGivenName"; + Assert.AreEqual ("phoneticGivenName", contact.PhoneticGivenName, "PhoneticGivenName"); + + contact.PhoneticMiddleName = "phoneticMiddleName"; + Assert.AreEqual ("phoneticMiddleName", contact.PhoneticMiddleName, "PhoneticMiddleName"); + + contact.PostalAddresses = new CNLabeledValue [] { + new CNLabeledValue ("label", new CNMutablePostalAddress () + { + Street = "my Street", + }) + }; + Assert.AreEqual (1, contact.PostalAddresses.Length, "PostalAddresses"); + + contact.PreviousFamilyName = "previousFamilyName"; + Assert.AreEqual ("previousFamilyName", contact.PreviousFamilyName, "PreviousFamilyName"); + + contact.SocialProfiles = new CNLabeledValue [] { + new CNLabeledValue ("label", new CNSocialProfile ("url", "username", "useridentifier", "service")) + }; + Assert.AreEqual (1, contact.SocialProfiles.Length, "SocialProfiles"); + + contact.UrlAddresses = new CNLabeledValue [] { + new CNLabeledValue ("label", (NSString) "url@address.com") + }; + Assert.AreEqual (1, contact.UrlAddresses.Length, "UrlAddresses"); + } + } + } +} + +#endif // XAMCORE_2_0 +#endif // !__TVOS__ diff --git a/tests/monotouch-test/CoreAnimation/EmitterBehaviorTest.cs b/tests/monotouch-test/CoreAnimation/EmitterBehaviorTest.cs new file mode 100644 index 000000000000..ae089097041a --- /dev/null +++ b/tests/monotouch-test/CoreAnimation/EmitterBehaviorTest.cs @@ -0,0 +1,88 @@ +// +// Unit tests for CAEmitterBehavior +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreAnimation; +using UIKit; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreAnimation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EmitterBehaviorTest { + + [Test] + public void AllBehaviorTypes () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS 7.0"); + + // turns out there's 2 undocumented behaviors: colorOverDistance and valueOverDistance + foreach (var type in CAEmitterBehavior.BehaviorTypes) { + using (var eb = CAEmitterBehavior.Create (type)) { + Assert.True (eb.Enabled, type + ".Enabled"); + Assert.Null (eb.Name, type + ".Name"); + Assert.That (eb.Type, Is.EqualTo ((string) type), type + ".Type"); + } + } + } + + [Test] + public void ColorOverDistance () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS 7.0"); + + // undocumented - we'll track it over the betas :) + using (var eb = CAEmitterBehavior.Create ((NSString) "colorOverDistance")) { + Assert.True (eb.Enabled, "Enabled.1"); + eb.Enabled = false; + Assert.False (eb.Enabled, "Enabled.2"); + + Assert.Null (eb.Name, "Name.1"); + eb.Name = "Xamarin"; + Assert.That (eb.Name, Is.EqualTo ("Xamarin"), "Name.2"); + + Assert.That (eb.Type, Is.EqualTo ("colorOverDistance"), "Type"); + } + } + + [Test] + public void ValueOverDistance () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS 7.0"); + + // undocumented - we'll track it over the betas :) + using (var eb = CAEmitterBehavior.Create ((NSString) "valueOverDistance")) { + Assert.True (eb.Enabled, "Enabled.1"); + eb.Enabled = false; + Assert.False (eb.Enabled, "Enabled.2"); + + Assert.Null (eb.Name, "Name.1"); + eb.Name = "Xamarin"; + Assert.That (eb.Name, Is.EqualTo ("Xamarin"), "Name.2"); + + Assert.That (eb.Type, Is.EqualTo ("valueOverDistance"), "Type"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreAnimation/EmitterCellTest.cs b/tests/monotouch-test/CoreAnimation/EmitterCellTest.cs new file mode 100644 index 000000000000..4823bd7e8a44 --- /dev/null +++ b/tests/monotouch-test/CoreAnimation/EmitterCellTest.cs @@ -0,0 +1,46 @@ +// +// Unit tests for CAEmitterCell +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreAnimation; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreAnimation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EmitterCellTest { + + [Test] + public void XEmitterCellTest () + { + using (var ec = new CAEmitterCell ()) { + // ICAMediaTiming + Assert.That (ec.BeginTime, Is.EqualTo (0.0d), "BeginTime"); + Assert.True (Double.IsInfinity (ec.Duration), "Duration"); + Assert.That (ec.Speed, Is.EqualTo (1.0f), "Speed"); + Assert.That (ec.TimeOffset, Is.EqualTo (0.0d), "TimeOffset"); + Assert.That (ec.RepeatCount, Is.EqualTo (0.0f), "RepeatCount"); + Assert.That (ec.RepeatDuration, Is.EqualTo (0.0d), "RepeatDuration"); + Assert.False (ec.AutoReverses, "AutoReverses"); + Assert.That (ec.FillMode, Is.EqualTo ("removed"), "FillMode"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreAnimation/LayerTest.cs b/tests/monotouch-test/CoreAnimation/LayerTest.cs new file mode 100644 index 000000000000..e4c05463c36f --- /dev/null +++ b/tests/monotouch-test/CoreAnimation/LayerTest.cs @@ -0,0 +1,214 @@ +// +// Unit tests for CALayer +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2011 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using CoreAnimation; +using UIKit; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreAnimation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LayerTest { + + [Test] + public void Mask () + { + using (CALayer layer = new CALayer ()) { + Assert.Null (layer.Mask, "Mask/default"); + layer.Mask = new CALayer (); + Assert.NotNull (layer.Mask, "Mask/assigned"); + layer.Mask = null; + Assert.Null (layer.Mask, "Mask/nullable"); + } + } + + [Test] + public void CAActionTest () + { + // bug 2441 + CAActionTestClass obj = new CAActionTestClass (); + Assert.That (null == obj.ActionForKey ("animation"), "a"); + Assert.That (null == obj.Actions, "b"); + Assert.That (null == CAActionTestClass.DefaultActionForKey ("animation"), "c"); + + var animationKey = new NSString ("animation"); + var basicAnimationKey = new NSString ("basicAnimation"); + var dict = NSDictionary.FromObjectsAndKeys ( + new NSObject [] { new CABasicAnimation (), new CAAnimation () }, + new NSObject [] { basicAnimationKey, animationKey } + ); + obj.Actions = dict; + Assert.That (obj.Actions == dict, "d"); + + Assert.That (obj.ActionForKey ("animation") == dict [animationKey], "e"); + Assert.That (obj.ActionForKey ("basicAnimation") == dict [basicAnimationKey], "f"); + Assert.That (null == CAActionTestClass.DefaultActionForKey ("animation"), "g"); + Assert.That (null == CALayer.DefaultActionForKey ("animation"), "h"); + } + + class CAActionTestClass : CALayer { + + } + + [Test] + public void ConvertPoint () + { + using (CALayer layer = new CALayer ()) { + Assert.True (layer.ConvertPointFromLayer (PointF.Empty, null).IsEmpty, "From/Empty/null"); + Assert.True (layer.ConvertPointToLayer (PointF.Empty, null).IsEmpty, "To/Empty/null"); + } + } + + [Test] + public void ConvertRect () + { + using (CALayer layer = new CALayer ()) { + Assert.True (layer.ConvertRectFromLayer (RectangleF.Empty, null).IsEmpty, "From/Empty/null"); + Assert.True (layer.ConvertRectToLayer (RectangleF.Empty, null).IsEmpty, "To/Empty/null"); + } + } + + [Test] + public void ConvertTime () + { + using (CALayer layer = new CALayer ()) { + Assert.That (layer.ConvertTimeFromLayer (0.0d, null), Is.EqualTo (0.0d), "From/0.0d/null"); + Assert.That (layer.ConvertTimeToLayer (0.0d, null), Is.EqualTo (0.0d), "To/0.0d/null"); + } + } + + [Test] + public void AddAnimation () + { + using (var layer = new CALayer ()) { + var animation = new CABasicAnimation (); + Assert.IsNull (layer.AnimationForKey ("key"), "#key A"); + layer.AddAnimation (animation, "key"); + Assert.IsNotNull (layer.AnimationForKey ("key"), "#key B"); + } + } + + + static int TextLayersDisposed; + static int Generation; + [Test] + public void TestBug26532() + { + TextLayersDisposed = 0; + Generation++; + + const int layerCount = 50; + var thread = new Thread (() => { + var frame = new RectangleF (0, 0, 200, 200); + using (var layer = new CALayer ()) { + for (int i = 0; i < layerCount; i++) { + TextCALayer textLayer = new TextCALayer () { + Secret = "42", + }; + layer.AddSublayer (textLayer); + } + + GC.Collect (); + + foreach (var slayer in layer.Sublayers.OfType ()) { + Assert.AreEqual ("42", slayer.Secret); + } + + foreach (var slayer in layer.Sublayers.OfType ()) + slayer.RemoveFromSuperLayer (); + } + }); + thread.Start (); + thread.Join (); + + var watch = new Stopwatch (); + watch.Start (); + while (watch.ElapsedMilliseconds < 2000 && TextLayersDisposed < layerCount / 2) { + GC.Collect (); + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (0.05)); + } + + Assert.That (TextLayersDisposed, Is.AtLeast (layerCount / 2), "disposed text layers"); + } + + public class TextCALayer : CALayer + { + public string Secret; + public int generation; + + public TextCALayer () + { + generation = Generation; + } + + protected override void Dispose (bool disposing) + { + if (generation == Generation) { + TextLayersDisposed++; + } else { + Console.WriteLine ("TextCALayer.Dispose called for an object from a previous test run."); + } + base.Dispose (disposing); + } + } + + class Layer : CALayer { } + class LayerDelegate : CALayerDelegate { } + + [Test] + public void TestCALayerDelegateDispose () + { + var del = new LayerDelegate (); + var t = new Thread (() => + { + var l = new Layer (); + l.Delegate = del; + l.Dispose (); + }) + { + IsBackground = true, + }; + t.Start (); + t.Join (); + GC.Collect (); + + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (0.1)); + + GC.Collect (); + del.Dispose (); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreAnimation/MediaTimingFunctionTest.cs b/tests/monotouch-test/CoreAnimation/MediaTimingFunctionTest.cs new file mode 100644 index 000000000000..16775c444446 --- /dev/null +++ b/tests/monotouch-test/CoreAnimation/MediaTimingFunctionTest.cs @@ -0,0 +1,178 @@ +// +// Unit tests for CAMediaTimingFunction +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreAnimation; +using ObjCRuntime; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreMotion { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MediaTimingFunctionTest { + +#if !XAMCORE_2_0 // the default ctor has been removed. + [Test] + public void DefaultCtor () + { + // invalid default .ctor exposed, now marked as [Obsolete] + using (CAMediaTimingFunction mtf = new CAMediaTimingFunction ()) { + // invalid instance, we only verify it does not crash when called + Assert.True (mtf.GetControlPoint (0).IsEmpty, "0"); + Assert.True (mtf.GetControlPoint (1).IsEmpty, "1"); + Assert.True (mtf.GetControlPoint (2).IsEmpty, "2"); + Assert.True (mtf.GetControlPoint (3).IsEmpty, "3"); + Assert.That (mtf.ToString (), Is.EqualTo ("MonoTouch.CoreAnimation.CAMediaTimingFunction"), "ToString"); + } + } +#endif + + [Test] + public void GetControlPoint () + { + using (CAMediaTimingFunction mtf = CAMediaTimingFunction.FromControlPoints (0.1f, 0.2f, 0.3f, 0.4f)) { + Assert.Throws (delegate { mtf.GetControlPoint (-1); }); + Assert.That (mtf.GetControlPoint (0), Is.EqualTo (new PointF (0.0f, 0.0f)), "0"); + Assert.That (mtf.GetControlPoint (1), Is.EqualTo (new PointF (0.1f, 0.2f)), "1"); + Assert.That (mtf.GetControlPoint (2), Is.EqualTo (new PointF (0.3f, 0.4f)), "2"); + Assert.That (mtf.GetControlPoint (3), Is.EqualTo (new PointF (1.0f, 1.0f)), "3"); + Assert.Throws (delegate { mtf.GetControlPoint (4); }); + } + } + + [Test] + public void Default () + { + using (CAMediaTimingFunction mtf1 = new CAMediaTimingFunction (0.25f, 0.1f, 0.25f, 1f)) +#if !XAMCORE_2_0 + using (CAMediaTimingFunction mtf2 = CAMediaTimingFunction.FromName ((string) CAMediaTimingFunction.Default)) +#endif + using (CAMediaTimingFunction mtf3 = CAMediaTimingFunction.FromName (CAMediaTimingFunction.Default)) { +#if !XAMCORE_2_0 + Assert.That (mtf2.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0a"); + Assert.That (mtf2.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1a"); + Assert.That (mtf2.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2a"); + Assert.That (mtf2.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3a"); +#endif + Assert.That (mtf3.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0b"); + Assert.That (mtf3.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1b"); + Assert.That (mtf3.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2b"); + Assert.That (mtf3.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3b"); + } + } + + [Test] + public void EaseIn () + { + using (CAMediaTimingFunction mtf1 = new CAMediaTimingFunction (0.42f, 0f, 1f, 1f)) +#if !XAMCORE_2_0 + using (CAMediaTimingFunction mtf2 = CAMediaTimingFunction.FromName ((string) CAMediaTimingFunction.EaseIn)) +#endif + using (CAMediaTimingFunction mtf3 = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseIn)) { +#if !XAMCORE_2_0 + Assert.That (mtf2.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0a"); + Assert.That (mtf2.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1a"); + Assert.That (mtf2.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2a"); + Assert.That (mtf2.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3a"); +#endif + Assert.That (mtf3.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0b"); + Assert.That (mtf3.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1b"); + Assert.That (mtf3.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2b"); + Assert.That (mtf3.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3b"); + } + } + + [Test] + public void EaseOut () + { + using (CAMediaTimingFunction mtf1 = new CAMediaTimingFunction (0f, 0f, 0.58f, 1f)) +#if !XAMCORE_2_0 + using (CAMediaTimingFunction mtf2 = CAMediaTimingFunction.FromName ((string) CAMediaTimingFunction.EaseOut)) +#endif + using (CAMediaTimingFunction mtf3 = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseOut)) { +#if !XAMCORE_2_0 + Assert.That (mtf2.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0a"); + Assert.That (mtf2.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1a"); + Assert.That (mtf2.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2a"); + Assert.That (mtf2.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3a"); +#endif + Assert.That (mtf3.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0b"); + Assert.That (mtf3.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1b"); + Assert.That (mtf3.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2b"); + Assert.That (mtf3.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3b"); + } + } + + [Test] + public void EaseInEaseOut () + { + using (CAMediaTimingFunction mtf1 = new CAMediaTimingFunction (0.42f, 0f, 0.58f, 1f)) +#if !XAMCORE_2_0 + using (CAMediaTimingFunction mtf2 = CAMediaTimingFunction.FromName ((string) CAMediaTimingFunction.EaseInEaseOut)) +#endif + using (CAMediaTimingFunction mtf3 = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseInEaseOut)) { +#if !XAMCORE_2_0 + Assert.That (mtf2.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0a"); + Assert.That (mtf2.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1a"); + Assert.That (mtf2.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2a"); + Assert.That (mtf2.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3a"); +#endif + Assert.That (mtf3.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0b"); + Assert.That (mtf3.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1b"); + Assert.That (mtf3.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2b"); + Assert.That (mtf3.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3b"); + } + } + + [Test] + public void Linear () + { + using (CAMediaTimingFunction mtf1 = new CAMediaTimingFunction (0f, 0f, 1f, 1f)) +#if !XAMCORE_2_0 + using (CAMediaTimingFunction mtf2 = CAMediaTimingFunction.FromName ((string) CAMediaTimingFunction.Linear)) +#endif + using (CAMediaTimingFunction mtf3 = CAMediaTimingFunction.FromName (CAMediaTimingFunction.Linear)) { +#if !XAMCORE_2_0 + Assert.That (mtf2.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0a"); + Assert.That (mtf2.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1a"); + Assert.That (mtf2.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2a"); + Assert.That (mtf2.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3a"); +#endif + Assert.That (mtf3.GetControlPoint (0), Is.EqualTo (mtf1.GetControlPoint (0)), "0b"); + Assert.That (mtf3.GetControlPoint (1), Is.EqualTo (mtf1.GetControlPoint (1)), "1b"); + Assert.That (mtf3.GetControlPoint (2), Is.EqualTo (mtf1.GetControlPoint (2)), "2b"); + Assert.That (mtf3.GetControlPoint (3), Is.EqualTo (mtf1.GetControlPoint (3)), "3b"); + } + } + } +} + +#endif // !__WATCHOS__ + diff --git a/tests/monotouch-test/CoreAnimation/ShapeLayerTest.cs b/tests/monotouch-test/CoreAnimation/ShapeLayerTest.cs new file mode 100644 index 000000000000..f3fc5141ef46 --- /dev/null +++ b/tests/monotouch-test/CoreAnimation/ShapeLayerTest.cs @@ -0,0 +1,56 @@ +// +// Unit tests for CAShapeLayer +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreAnimation; +using CoreGraphics; +using UIKit; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreAnimation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ShapeLayerTest { + [Test] + public void NullableProperties () + { + var sl = new CAShapeLayer (); + Assert.NotNull (sl.FillColor, "FillColor"); + sl.FillColor = null; + Assert.Null (sl.Path, "Path"); + sl.Path = null; + Assert.Null (sl.LineDashPattern, "LineDashPattern"); + sl.LineDashPattern = null; + Assert.Null (sl.StrokeColor, "StrokeColor"); + sl.StrokeColor = null; + + sl.FillColor = UIColor.Black.CGColor; + Assert.NotNull (sl.FillColor, "FillColor"); + sl.Path = new CGPath (); + Assert.NotNull (sl.Path, "Path"); + sl.LineDashPattern = new [] { new NSNumber (5), new NSNumber (10) }; + Assert.NotNull (sl.LineDashPattern, "LineDashPattern"); + sl.StrokeColor = UIColor.White.CGColor; + Assert.NotNull (sl.StrokeColor, "StrokeColor"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreAnimation/TransactionTest.cs b/tests/monotouch-test/CoreAnimation/TransactionTest.cs new file mode 100644 index 000000000000..4bb932720aee --- /dev/null +++ b/tests/monotouch-test/CoreAnimation/TransactionTest.cs @@ -0,0 +1,48 @@ +// +// Unit tests for CATransaction +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreAnimation; +using Foundation; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreAnimation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TransactionTest { + + [Test] + public void CompletionBlock_Null () + { + // NULL is not specified in Apple doc but googling returns a lot of + // cases where stuff like "[self setCompletionBlock:nil];" is done + CATransaction.CompletionBlock = null; + Assert.NotNull (CATransaction.CompletionBlock, "CompletionBlock"); + } + + [Test] + public void AnimationTimingFunction_Null () + { + // NULL is not specified in Apple doc + // but since it's the default value it makes sense to be able to set it back + CATransaction.AnimationTimingFunction = null; + Assert.Null (CATransaction.AnimationTimingFunction, "AnimationTimingFunction"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreAudioKit/AUViewController.cs b/tests/monotouch-test/CoreAudioKit/AUViewController.cs new file mode 100644 index 000000000000..bfb924ed622b --- /dev/null +++ b/tests/monotouch-test/CoreAudioKit/AUViewController.cs @@ -0,0 +1,42 @@ +// +// Unit tests for AUViewController +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ && !__TVOS__ + +using System; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using CoreAudioKit; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreAudioKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreAudioKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AUViewControllerTest + { + [Test] + public void Ctor () + { + // this tests that mtouch properly links with CoreAudioKit + // when not using the simlauncher (since monotouch-test + // uses native libraries, which prevents mtouch from building + // monotouch-test using simlauncher). + using (var obj = new AUViewController ()) { + } + } + } +} + +#endif // !__WATCHOS__ && !__TVOS__ \ No newline at end of file diff --git a/tests/monotouch-test/CoreBluetooth/CentralManagerTest.cs b/tests/monotouch-test/CoreBluetooth/CentralManagerTest.cs new file mode 100644 index 000000000000..32aa9fd3bbcd --- /dev/null +++ b/tests/monotouch-test/CoreBluetooth/CentralManagerTest.cs @@ -0,0 +1,140 @@ +// +// Unit tests for CBCentralManager +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreBluetooth; +using CoreFoundation; +#else +using MonoTouch.CoreBluetooth; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreBluetooth { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CBCentralManagerTest { + + class ManagerDelegate : CBCentralManagerDelegate { + public AutoResetEvent Event { get; private set; } + + public ManagerDelegate (AutoResetEvent e) : base () + { + Event = e; + } + + #region implemented abstract members of MonoTouch.CoreBluetooth.CBCentralManagerDelegate + public override void UpdatedState (CBCentralManager central) + { + Event.Set (); + } + +#if !XAMCORE_3_0 + public override void RetrievedPeripherals (CBCentralManager central, CBPeripheral[] peripherals) + { + } + + public override void RetrievedConnectedPeripherals (CBCentralManager central, CBPeripheral[] peripherals) + { + } +#endif // !XAMCORE_3_0 + + public override void DiscoveredPeripheral (CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI) + { + } + + public override void ConnectedPeripheral (CBCentralManager central, CBPeripheral peripheral) + { + } + + public override void FailedToConnectPeripheral (CBCentralManager central, CBPeripheral peripheral, NSError error) + { + } + + public override void DisconnectedPeripheral (CBCentralManager central, CBPeripheral peripheral, NSError error) + { + } + #endregion + } + + CBCentralManager mgr; + ManagerDelegate mgrDelegate; + + [SetUp] + public void SetUp () + { + var e = new AutoResetEvent (false); + mgrDelegate = new ManagerDelegate (e); + mgr = new CBCentralManager (mgrDelegate, new DispatchQueue ("com.xamarin.tests." + TestContext.CurrentContext.Test.Name)); + } + + [TearDown] + public void TearDown () + { + // should dispose the delegate + mgr.Dispose (); + } + + [Test, Timeout (5000)] + public void Constructors () + { + if (mgr.State == CBCentralManagerState.Unknown) { + // ensure we do get called + mgrDelegate.Event.WaitOne (); + } + + // Manager creates it, we'll simply check it has a non-null delegate + Assert.NotNull (mgr.Delegate, "Delegate"); + } + + [Test, Timeout (5000)] + public void ScanForPeripherals () + { + if (mgr.State == CBCentralManagerState.Unknown) { + // ensure we do get called + mgrDelegate.Event.WaitOne (); + } + if (mgr.State != CBCentralManagerState.PoweredOn) + Assert.Inconclusive ("Bluetooth is off and therefore the test cannot be ran. State == {0}.", mgr.State); + mgr.ScanForPeripherals ((CBUUID[])null, (NSDictionary)null); + } + +#if !XAMCORE_3_0 + [Test, Timeout (5000)] + public void RetrievePeripherals () + { + if (mgr.State == CBCentralManagerState.Unknown) { + // ensure we do get called + mgrDelegate.Event.WaitOne (); + } + if (mgr.State != CBCentralManagerState.PoweredOn) + Assert.Inconclusive ("Bluetooth is off and therefore the test cannot be ran. State == {0}.", mgr.State); + if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) { + using (var uuid = new NSUuid ("B9401000-F5F8-466E-AFF9-25556B57FE6D")) + mgr.RetrievePeripheralsWithIdentifiers (uuid); + } else { + // that API was deprecated in 7.0 and removed from 9.0 + using (var uuid = CBUUID.FromString ("B9401000-F5F8-466E-AFF9-25556B57FE6D")) + mgr.RetrievePeripherals (uuid); + } + } +#endif // !XAMCORE_3_0 + } +} + +#endif // !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/CoreBluetooth/ErrorTest.cs b/tests/monotouch-test/CoreBluetooth/ErrorTest.cs new file mode 100644 index 000000000000..e6c147cb71c5 --- /dev/null +++ b/tests/monotouch-test/CoreBluetooth/ErrorTest.cs @@ -0,0 +1,43 @@ +// +// Unit tests for CB[ATT]Error enums +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using CoreBluetooth; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreBluetooth; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreBluetooth { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ErrorTest { + + [Test] + public void ErrorDomain () + { + Assert.That (CBError.None.GetDomain ().ToString (), Is.EqualTo ("CBErrorDomain"), "Domain"); + } + + [Test] + public void AttErrorDomain () + { + Assert.That (CBATTError.Success.GetDomain ().ToString (), Is.EqualTo ("CBATTErrorDomain"), "Domain"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreBluetooth/PeerTest.cs b/tests/monotouch-test/CoreBluetooth/PeerTest.cs new file mode 100644 index 000000000000..e1fc2e56d638 --- /dev/null +++ b/tests/monotouch-test/CoreBluetooth/PeerTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for CBPeer +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreBluetooth; +#else +using MonoTouch.CoreBluetooth; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreBluetooth { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CBPeerTest { + [Test] + public void Constructor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Ignore ("This requires at least iOS 8.0"); + + // crash at dispose time in beta 4 (and 5) + // the type is undocumented but I think it's should be abstract (not user creatable) +// using (var p = new CBPeer ()) { +// Assert.NotNull (p); +// } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreBluetooth/PeripheralScanningOptionsTest.cs b/tests/monotouch-test/CoreBluetooth/PeripheralScanningOptionsTest.cs new file mode 100644 index 000000000000..15fed6c5cf39 --- /dev/null +++ b/tests/monotouch-test/CoreBluetooth/PeripheralScanningOptionsTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for PeripheralScanningOptions +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreBluetooth; +using UIKit; +#else +using MonoTouch.CoreBluetooth; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreBluetooth { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PeripheralScanningOptionsTest { + + [Test] + public void Defaults () + { + var options = new PeripheralScanningOptions (); + Assert.That (options.Dictionary.Count, Is.EqualTo (0), "Count"); + Assert.False (options.AllowDuplicatesKey, "AllowDuplicatesKey"); + } + + [Test] + public void AllowDuplicatesKey_True () + { + var options = new PeripheralScanningOptions () { + AllowDuplicatesKey = true + }; + Assert.That (options.Dictionary.Count, Is.EqualTo (1), "Count"); + Assert.True (options.AllowDuplicatesKey, "AllowDuplicatesKey"); + } + + [Test] + public void AllowDuplicatesKey_False () + { + var options = new PeripheralScanningOptions () { + AllowDuplicatesKey = false + }; + Assert.That (options.Dictionary.Count, Is.EqualTo (1), "Count"); + Assert.False (options.AllowDuplicatesKey, "AllowDuplicatesKey"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreBluetooth/UuidTest.cs b/tests/monotouch-test/CoreBluetooth/UuidTest.cs new file mode 100644 index 000000000000..4e360082f8e3 --- /dev/null +++ b/tests/monotouch-test/CoreBluetooth/UuidTest.cs @@ -0,0 +1,181 @@ +// +// Unit tests for CBUUID +// +// Authors: +// Sebastien Pouliot +// Aaron Bockover +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreBluetooth; +using UIKit; +#else +using MonoTouch.CoreBluetooth; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreBluetooth { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UuidTest { + + [Test] + public void Roundtrip_16bits () + { + using (CBUUID uuid = CBUUID.FromString ("1234")) { + Assert.That (uuid.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.IsNotNull (uuid.Data, "Data"); + var expected = UIDevice.CurrentDevice.CheckSystemVersion (7,1) ? "1234" : "Unknown (<1234>)"; + Assert.That (uuid.Description, Is.EqualTo (expected), "Description"); + Assert.That (uuid.ToString (false), Is.EqualTo ("1234"), "ToString(false)"); + Assert.That (uuid.ToString (true), Is.EqualTo ("00001234-0000-1000-8000-00805f9b34fb"), "ToString(true)"); + using (CBUUID u2 = CBUUID.FromString (uuid.ToString ())) { + Assert.That (u2.ToString (), Is.EqualTo (uuid.ToString ()), "Roundtrip"); + } + } + } + + [Test] + public void Roundtrip_128bits () + { + using (CBUUID uuid = CBUUID.FromString ("12345678-90AB-CDEF-cafe-c80c20443d0b")) { + Assert.That (uuid.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.IsNotNull (uuid.Data, "Data"); + var expected = UIDevice.CurrentDevice.CheckSystemVersion (7, 1) ? "12345678-90AB-CDEF-CAFE-C80C20443D0B" : "Unknown (<12345678 90abcdef cafec80c 20443d0b>)"; + Assert.That (uuid.Description, Is.EqualTo (expected), "Description"); + Assert.That (uuid.ToString (false), Is.EqualTo (uuid.ToString (true)), "ToString"); + using (CBUUID u2 = CBUUID.FromString (uuid.ToString ())) { + Assert.That (u2.ToString (), Is.EqualTo (uuid.ToString ()), "Roundtrip"); + } + } + } + + static CBUUID MakeFull (byte a, byte b) + { + return MakeFull (0, 0, a, b); + } + + static CBUUID MakeFull (byte a, byte b, byte c, byte d) + { + return CBUUID.FromBytes (new byte [] { + a, b, c, d, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb + }); + } + + [Test] + public void Equality_Null () + { + Assert.That (null as CBUUID, Is.Null); + Assert.That (null as CBUUID, Is.EqualTo (null as CBUUID)); + } + + [Test] + public void Equality_FullRandomEquals () + { + var guid = Guid.NewGuid (); + Assert.That (CBUUID.FromBytes (guid.ToByteArray ()), + Is.EqualTo (CBUUID.FromBytes (guid.ToByteArray ()))); + } + + [Test] + public void Equality_FullRandomNotEqual () + { + Assert.That (CBUUID.FromBytes (Guid.NewGuid ().ToByteArray ()), + Is.Not.EqualTo (CBUUID.FromBytes (Guid.NewGuid ().ToByteArray ()))); + } + + [Test] + public void Equality_PartialEquals () + { + var guid = new byte [] { 0xaa, 0xbb }; + using (var u1 = CBUUID.FromBytes (guid)) + using (var u2 = CBUUID.FromBytes (guid)) { + Assert.True (u1.Equals ((object) u2), "Equals-1a"); + Assert.True (u1.Equals ((NSObject) u2), "Equals-1b"); + Assert.True (u1.Equals ((CBUUID) u2), "Equals-1b"); + Assert.That (u1.GetHashCode (), Is.EqualTo (u2.GetHashCode ()), "GetHashCode-1"); + } + + using (var u1 = CBUUID.FromPartial (0x1234)) + using (var u2 = CBUUID.FromPartial (0x1234)) { + Assert.True (u1.Equals ((object) u2), "Equals-2a"); + Assert.True (u1.Equals ((NSObject) u2), "Equals-2b"); + Assert.True (u1.Equals ((CBUUID) u2), "Equals-2b"); + Assert.That (u1.GetHashCode (), Is.EqualTo (u2.GetHashCode ()), "GetHashCode-2"); + } + + using (var u1 = CBUUID.FromString ("1234")) + using (var u2 = CBUUID.FromBytes (new byte [] { 0x12, 0x34 })) { + Assert.True (u1.Equals ((object) u2), "Equals-3a"); + Assert.True (u1.Equals ((NSObject) u2), "Equals-3b"); + Assert.True (u1.Equals ((CBUUID) u2), "Equals-3b"); + Assert.That (u1.GetHashCode (), Is.EqualTo (u2.GetHashCode ()), "GetHashCode-3"); + } +#if MONOMAC + guid = new byte [] { 0xaa, 0xbb, 0xcc, 0xdd }; + Assert.That (CBUUID.FromBytes (guid), + Is.EqualTo (CBUUID.FromBytes (guid))); + + Assert.That (CBUUID.FromString ("12345678"), + Is.EqualTo (CBUUID.FromBytes (new byte [] { 0x12, 0x34, 0x56, 0x78 }))); +#endif + } + + [Test] + public void Equality_PartialEqualsFull () + { + using (var u1 = CBUUID.FromPartial (0x0127)) + using (var u2 = MakeFull (0x01, 0x27)) { + Assert.True (u1.Equals ((object) u2), "Equals-1a"); + Assert.True (u1.Equals ((NSObject) u2), "Equals-1b"); + Assert.True (u1.Equals ((CBUUID) u2), "Equals-1b"); + Assert.That (u1.GetHashCode (), Is.EqualTo (u2.GetHashCode ()), "GetHashCode-1"); + } + + using (var u1 = CBUUID.FromBytes (new byte [] { 0xab, 0xcd })) + using (var u2 = MakeFull (0xab, 0xcd)) { + Assert.True (u1.Equals ((object) u2), "Equals-2a"); + Assert.True (u1.Equals ((NSObject) u2), "Equals-2b"); + Assert.True (u1.Equals ((CBUUID) u2), "Equals-2b"); + Assert.That (u1.GetHashCode (), Is.EqualTo (u2.GetHashCode ()), "GetHashCode-2"); + } + + using (var u1 = CBUUID.FromString ("1234")) + using (var u2 = CBUUID.FromString ("00001234-0000-1000-8000-00805f9b34fb")) { + Assert.True (u1.Equals ((object) u2), "Equals-3a"); + Assert.True (u1.Equals ((NSObject) u2), "Equals-3b"); + Assert.True (u1.Equals ((CBUUID) u2), "Equals-3b"); + Assert.That (u1.GetHashCode (), Is.EqualTo (u2.GetHashCode ()), "GetHashCode-3"); + } +#if MONOMAC + Assert.That (CBUUID.FromBytes (new byte [] { 0xab, 0xcd, 0xef, 0x12 }), + Is.EqualTo (MakeFull (0xab, 0xcd, 0xef, 0x12))); + + Assert.That (CBUUID.FromString ("12345678"), + Is.EqualTo (CBUUID.FromString ("12345678-0000-1000-8000-00805f9b34fb"))); +#endif + } + + [Test] + public void Equality_PartialsOfDifferentSizeNotEqual () + { +#if MONOMAC + Assert.That (CBUUID.FromPartial (0x1234), Is.Not.EqualTo ( + CBUUID.FromBytes (new byte [] { 0x12, 0x34, 0x56, 0x78 }))); +#endif + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreData/AttributeDescriptionTest.cs b/tests/monotouch-test/CoreData/AttributeDescriptionTest.cs new file mode 100644 index 000000000000..8f60ddce77f5 --- /dev/null +++ b/tests/monotouch-test/CoreData/AttributeDescriptionTest.cs @@ -0,0 +1,59 @@ +// +// Unit tests for NSAttributeDescriptionTest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2011-2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreData; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreData { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AttributeDescription { + + [Test] + public void WeakFramework () + { + NSAttributeDescription ad = new NSAttributeDescription (); + Assert.That (ad.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + // if CoreData is not linked then all related objects handle will be null + } + + [Test] + public void DefaultValue () + { + using (var ad = new NSAttributeDescription ()) + using (var o = new NSObject ()) { +#if XAMCORE_2_0 + ad.DefaultValue = o; +#else + ad.SetDefaultValue (o); +#endif + Assert.AreSame (o, ad.DefaultValue, "DefaultValue"); + } + } + + [Test] + public void GetSetRenamingIdentifier () + { + using (var ad = new NSAttributeDescription ()) { + Assert.IsNull (ad.RenamingIdentifier, "An unset RenamingIdentifier should be null."); + ad.RenamingIdentifier = "Foo"; + Assert.AreEqual ("Foo", ad.RenamingIdentifier, + "RenamingIndentifier was not corrently set."); + } + } + } +} diff --git a/tests/monotouch-test/CoreData/ExpressionDescriptionTest.cs b/tests/monotouch-test/CoreData/ExpressionDescriptionTest.cs new file mode 100644 index 000000000000..eb8f7ace1527 --- /dev/null +++ b/tests/monotouch-test/CoreData/ExpressionDescriptionTest.cs @@ -0,0 +1,50 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreData; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreData +{ + + [TestFixture] + [Preserve (AllMembers = true)] + public class ExpressionDescriptionTest + { + + [Test] + public void WeakFramework () + { + using (var exp = new NSExpressionDescription ()) + Assert.That (exp.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + + [Test] + public void GetSetExpression () + { + using (var exp = new NSExpressionDescription ()) { + exp.Name = "Test"; + Assert.IsNull (exp.Expression, "An unset Expression should be null."); + exp.Expression = new NSExpression (NSExpressionType.Block); + Assert.IsNotNull (exp.Expression, "Expression was not correctly set."); + } + } + + [Test] + public void GetSetResultType () + { + using (var exp = new NSExpressionDescription ()) { + exp.Name = "Test"; + Assert.AreEqual (exp.ResultType, NSAttributeType.Undefined, + "The default value of an unset ResultType should be 'Undefined'"); + exp.ResultType = NSAttributeType.Boolean; + Assert.AreEqual (NSAttributeType.Boolean, exp.ResultType, + "ResultType was not correctly set."); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreData/FetchRequestExpressionTest.cs b/tests/monotouch-test/CoreData/FetchRequestExpressionTest.cs new file mode 100644 index 000000000000..9eba27b4393a --- /dev/null +++ b/tests/monotouch-test/CoreData/FetchRequestExpressionTest.cs @@ -0,0 +1,60 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreData; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreData +{ + + [TestFixture] + [Preserve (AllMembers = true)] + public class FetchRequestExpressionTest + { + + [Test] + public void WeakFramework () + { + using (var exp = new NSExpression (NSExpressionType.Block)) + using (var context = new NSExpression (NSExpressionType.EvaluatedObject)) + using (var fetch = NSFetchRequestExpression.FromFetch (exp, context, false)) + Assert.That (exp.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + + [Test] + public void GetRequest () + { + using (var exp = new NSExpression (NSExpressionType.Block)) + using (var context = new NSExpression (NSExpressionType.EvaluatedObject)) + using (var fetch = NSFetchRequestExpression.FromFetch (exp, context, false)) + Assert.NotNull (fetch.Request); + } + + [Test] + public void GetContext () + { + using (var exp = new NSExpression (NSExpressionType.Block)) + using (var context = new NSExpression (NSExpressionType.EvaluatedObject)) + using (var fetch = NSFetchRequestExpression.FromFetch (exp, context, false)) + Assert.NotNull (fetch.Context); + } + + [Test] + public void GetIsCountOnly () + { + using (var exp = new NSExpression (NSExpressionType.Block)) + using (var context = new NSExpression (NSExpressionType.EvaluatedObject)) + using (var fetch = NSFetchRequestExpression.FromFetch (exp, context, false)) + Assert.IsFalse (fetch.IsCountOnly, "IsCountOnly was not correctly set to false."); + + using (var exp = new NSExpression (NSExpressionType.Block)) + using (var context = new NSExpression (NSExpressionType.EvaluatedObject)) + using (var fetch = NSFetchRequestExpression.FromFetch (exp, context, true)) + Assert.IsTrue (fetch.IsCountOnly, "IsCountOnly was not correctly set to true."); + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreData/FetchRequestTest.cs b/tests/monotouch-test/CoreData/FetchRequestTest.cs new file mode 100644 index 000000000000..41a205688e61 --- /dev/null +++ b/tests/monotouch-test/CoreData/FetchRequestTest.cs @@ -0,0 +1,89 @@ +// +// Unit tests for NSFetchRequest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using CoreData; +using Foundation; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreData { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FetchRequestTest { + + [Test] + public void DefaultValues () + { + using (var fr = new NSFetchRequest ()) { + Assert.Null (fr.AffectedStores, "AffectedStores"); + Assert.Null (fr.Entity, "Entity"); + Assert.Null (fr.EntityName, "EntityName"); + Assert.That (fr.FetchBatchSize, Is.EqualTo ((nint) 0), "FetchBatchSize"); + Assert.That (fr.FetchLimit, Is.EqualTo ((nuint) 0), "FetchLimit"); + Assert.That (fr.FetchOffset, Is.EqualTo ((nuint) 0), "FetchOffset"); + Assert.Null (fr.HavingPredicate, "HavingPredicate"); + Assert.True (fr.IncludesPendingChanges, "IncludesPendingChanges"); + Assert.True (fr.IncludesPropertyValues, "IncludesPropertyValues"); + Assert.True (fr.IncludesSubentities, "IncludesSubentities"); + Assert.Null (fr.Predicate, "Predicate"); + Assert.Null (fr.PropertiesToFetch, "PropertiesToFetch"); + Assert.Null (fr.PropertiesToGroupBy, "PropertiesToGroupBy"); + Assert.Null (fr.RelationshipKeyPathsForPrefetching, "RelationshipKeyPathsForPrefetching"); + Assert.That (fr.ResultType, Is.EqualTo (NSFetchRequestResultType.ManagedObject), "ResultType"); + Assert.False (fr.ReturnsDistinctResults, "ReturnsDistinctResults"); + Assert.True (fr.ReturnsObjectsAsFaults, "ReturnsObjectsAsFaults"); + Assert.False (fr.ShouldRefreshRefetchedObjects, "ShouldRefreshRefetchedObjects"); + Assert.Null (fr.SortDescriptors, "SortDescriptors"); + } + } + + [Test] + public void CtorString () + { + using (var fr = new NSFetchRequest ("entityName")) { + Assert.That (fr.EntityName, Is.EqualTo ("entityName"), "EntityName"); + // Entity is invalid (and throws) so we do not check it - except to see if we can set it to null + fr.Entity = null; + Assert.Null (fr.Entity, "Entity"); + } + } + + [Test] + public void SettersNull () + { + using (var fr = new NSFetchRequest ()) { + // bug #18153 + fr.Predicate = null; + // bug #18152 + fr.SortDescriptors = null; + // other properties that are null (by default) are likely accepting being set to null + fr.AffectedStores = fr.AffectedStores; + fr.HavingPredicate = fr.HavingPredicate; + fr.PropertiesToGroupBy = fr.PropertiesToGroupBy; + fr.RelationshipKeyPathsForPrefetching = fr.RelationshipKeyPathsForPrefetching; + } + } + } +} diff --git a/tests/monotouch-test/CoreData/FetchedResultsControllerTest.cs b/tests/monotouch-test/CoreData/FetchedResultsControllerTest.cs new file mode 100644 index 000000000000..70a87c20f60f --- /dev/null +++ b/tests/monotouch-test/CoreData/FetchedResultsControllerTest.cs @@ -0,0 +1,163 @@ +// +// Unit tests for NSFetchedResultsController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using CoreData; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreData { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FetchedResultsControllerTest { + + [TestFixtureSetUp] + public void Cache () + { + // null -> delete all cache + NSFetchedResultsController.DeleteCache (null); + } + + [Test] + public void Default () + { + using (NSFetchedResultsController frc = new NSFetchedResultsController ()) { + NSError e; + Assert.False (frc.PerformFetch (out e), "PerformFetch"); + Assert.Null (e, "NSError"); + } + } + + [Test] + public void PerformFetch_Minimal () + { + using (NSManagedObjectContext c = new NSManagedObjectContext (NSManagedObjectContextConcurrencyType.PrivateQueue)) + using (NSFetchRequest r = new NSFetchRequest ()) { + r.SortDescriptors = new NSSortDescriptor[] { + new NSSortDescriptor ("key", true) + }; + r.Entity = new NSEntityDescription (); + using (NSFetchedResultsController frc = new NSFetchedResultsController (r, c, null, null)) { + NSError e; + Assert.False (frc.PerformFetch (out e), "PerformFetch"); + } + } + } + + [Test] + public void Sections () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=13785 + + // use Caches directory so this works with tvOS on devices (as well as existing iOS devices) + string applicationDocumentsDirectory = NSSearchPath.GetDirectories (NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User, true).LastOrDefault (); + + using (var ManagedObjectModel = new NSManagedObjectModel ()) { + { + // create an entity description + NSEntityDescription entity = new NSEntityDescription (); + entity.Name = "Earthquake"; + + // create an attribute for the entity + NSAttributeDescription date = new NSAttributeDescription (); + date.AttributeType = NSAttributeType.Date; + date.Name = "date"; + date.Optional = false; + + NSAttributeDescription latitude = new NSAttributeDescription (); + latitude.AttributeType = NSAttributeType.Double; + latitude.Name = "latitude"; + latitude.Optional = false; + + NSAttributeDescription location = new NSAttributeDescription (); + location.AttributeType = NSAttributeType.String; + location.Name = "location"; + location.Optional = false; + + NSAttributeDescription longitude = new NSAttributeDescription (); + longitude.AttributeType = NSAttributeType.Double; + longitude.Name = "longitude"; + longitude.Optional = false; + + NSAttributeDescription magnitude = new NSAttributeDescription (); + magnitude.AttributeType = NSAttributeType.Float; + magnitude.Name = "magnitude"; + magnitude.Optional = false; + + NSAttributeDescription USGSWebLink = new NSAttributeDescription (); + USGSWebLink.AttributeType = NSAttributeType.String; + USGSWebLink.Name = "USGSWebLink"; + USGSWebLink.Optional = false; + + // assign the properties to the entity + entity.Properties = new NSPropertyDescription[] { + date, + latitude, + location, + longitude, + magnitude, + USGSWebLink + }; + + // add the entity to the model, and then add a configuration that + // contains the entities + ManagedObjectModel.Entities = new NSEntityDescription[] { entity }; + ManagedObjectModel.SetEntities (ManagedObjectModel.Entities, String.Empty); + } + + using (var PersistentStoreCoordinator = new NSPersistentStoreCoordinator (ManagedObjectModel)) { + { + var storePath = applicationDocumentsDirectory + "/Earthquakes.sqlite"; + var storeUrl = new NSUrl (storePath, false); + NSError error; + + if (PersistentStoreCoordinator.AddPersistentStoreWithType (NSPersistentStoreCoordinator.SQLiteStoreType, null, storeUrl, null, out error) == null) { + Assert.Fail ("Unresolved error " + error + ", " + error.UserInfo); + } + } + + using (var ManagedObjectContext = new NSManagedObjectContext ()) { + ManagedObjectContext.PersistentStoreCoordinator = PersistentStoreCoordinator; + + // NSNotificationCenter.DefaultCenter.AddObserver ( + // this, new MonoTouch.ObjCRuntime.Selector ("mergeChanges"), + // "NSManagedObjectContextDidSaveNotification", null); + + + NSFetchRequest fetchRequest = new NSFetchRequest (); + NSEntityDescription entity = NSEntityDescription.EntityForName ("Earthquake", ManagedObjectContext); + fetchRequest.Entity = entity; + + NSSortDescriptor sortDescriptor = new NSSortDescriptor ("date", false); + fetchRequest.SortDescriptors = new [] { sortDescriptor }; + + NSFetchedResultsController fetchedResultsController = new NSFetchedResultsController ( + fetchRequest, ManagedObjectContext, null, null); + + NSError error; + + if (!fetchedResultsController.PerformFetch (out error)) { + Assert.Fail ("Unresolved error: " + error + ", " + error.UserInfo); + } + + var sections = fetchedResultsController.Sections; + Assert.That (sections [0].GetType ().FullName, Is.StringEnding ("CoreData.NSFetchedResultsSectionInfoWrapper"), "Wrapper"); + } + } + } + } + } +} diff --git a/tests/monotouch-test/CoreData/ManagedObjectContextTest.cs b/tests/monotouch-test/CoreData/ManagedObjectContextTest.cs new file mode 100644 index 000000000000..3c39352d77b8 --- /dev/null +++ b/tests/monotouch-test/CoreData/ManagedObjectContextTest.cs @@ -0,0 +1,98 @@ +// +// Unit tests for NSManagedObjectContext +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreData; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreData { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ManagedObjectContextTest { + + void Default (NSManagedObjectContext moc) + { + Assert.That (moc.DeletedObjects.Count, Is.EqualTo ((nuint) 0), "DeletedObjects"); + Assert.False (moc.HasChanges, "HasChanges"); + Assert.That (moc.InsertedObjects.Count, Is.EqualTo ((nuint) 0), "InsertedObjects"); + Assert.That (moc.MergePolicy, Is.Not.EqualTo (IntPtr.Zero), "MergePolicy"); + Assert.Null (moc.ParentContext, "ParentContext"); + Assert.Null (moc.PersistentStoreCoordinator, "PersistentStoreCoordinator"); + Assert.That (moc.RegisteredObjects.Count, Is.EqualTo ((nuint) 0), "RegisteredObjects"); + Assert.False (moc.RetainsRegisteredObjects, "RetainsRegisteredObjects"); + Assert.That (moc.StalenessInterval, Is.EqualTo (-1), "StalenessInterval"); + Assert.Null (moc.UndoManager, "UndoManager"); + Assert.That (moc.UpdatedObjects.Count, Is.EqualTo ((nuint) 0), "UpdatedObjects"); + Assert.That (moc.UserInfo.Count, Is.EqualTo ((nuint) 0), "UserInfo"); + } + + [Test] + public void Default () + { + using (var moc = new NSManagedObjectContext ()) { + Assert.That (moc.ConcurrencyType, Is.EqualTo (NSManagedObjectContextConcurrencyType.Confinement), "ConcurrencyType"); + Default (moc); + } + } + + [Test] + public void Main () + { + using (var moc = new NSManagedObjectContext (NSManagedObjectContextConcurrencyType.MainQueue)) { + Assert.That (moc.ConcurrencyType, Is.EqualTo (NSManagedObjectContextConcurrencyType.MainQueue), "ConcurrencyType"); + Default (moc); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Perform_Null () + { + using (var moc = new NSManagedObjectContext (NSManagedObjectContextConcurrencyType.MainQueue)) { + // a NULL results in a native crash - but not immediate + moc.Perform (null); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void PerformAndWait_Null () + { + using (var moc = new NSManagedObjectContext (NSManagedObjectContextConcurrencyType.MainQueue)) { + // a NULL results in a *immediate* native crash + moc.PerformAndWait (null); + } + } + + [Test] + public void UndoManager_Null () + { + using (var moc = new NSManagedObjectContext (NSManagedObjectContextConcurrencyType.MainQueue)) { + moc.UndoManager = null; + } + } + } +} diff --git a/tests/monotouch-test/CoreData/ManagedObjectModelTest.cs b/tests/monotouch-test/CoreData/ManagedObjectModelTest.cs new file mode 100644 index 000000000000..ea609b580b7c --- /dev/null +++ b/tests/monotouch-test/CoreData/ManagedObjectModelTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for NSManagedObjectModel +// +// Authors: +// Rolf Bjarne Kvinge (rolf@xamarin.com) +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using CoreData; +using Foundation; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreData { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ManagedObjectModelTest { + + void Default (NSManagedObjectModel moc) + { + Assert.That (moc.EntitiesByName.Count, Is.EqualTo ((nuint) 0), "EntitiesByName"); + Assert.That (moc.Configurations.Length, Is.EqualTo (0), "Configurations"); + Assert.Null (moc.LocalizationDictionary, "LocalizationDictionary"); + Assert.That (moc.FetchRequestTemplatesByName.Count, Is.EqualTo ((nuint) 0), "FetchRequestTemplatesByName"); + Assert.That (moc.VersionIdentifiers.Count, Is.EqualTo ((nuint) 0), "VersionIdentifiers"); + Assert.That (moc.EntityVersionHashesByName.Count, Is.EqualTo ((nuint) 0), "EntityVersionHashesByName"); + } + + [Test] + public void IsConfiguration_Null () + { + using (var moc = new NSManagedObjectModel()) { + Assert.IsFalse (moc.IsConfiguration (null, new NSDictionary ()), "IsConfiguration"); + Default (moc); + } + } + } +} diff --git a/tests/monotouch-test/CoreData/PropertyDescriptionTest.cs b/tests/monotouch-test/CoreData/PropertyDescriptionTest.cs new file mode 100644 index 000000000000..0d84bbd4d3b5 --- /dev/null +++ b/tests/monotouch-test/CoreData/PropertyDescriptionTest.cs @@ -0,0 +1,67 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreData; +#else +using MonoTouch.CoreData; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreData { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PropertyDescriptionTest { + + [Test] + public void WeakFramework () + { + var pd = new NSPropertyDescription (); + Assert.That (pd.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + // if CoreData is not linked then all related objects handle will be null + } + + [Test] + public void GetSetName () + { + using (var pd = new NSPropertyDescription ()) { + Assert.IsNull (pd.Name, "An unset Name should be null"); + pd.Name = "Name"; + Assert.AreEqual ("Name", pd.Name, "Name was not corretly set."); + } + } + + [Test] + public void GetSetOpcional () + { + using (var pd = new NSPropertyDescription ()) { + Assert.IsTrue (pd.Optional, "A property should be Optional as default."); + pd.Optional = false; + Assert.IsFalse (pd.Optional , "Optional was not correctly set."); + } + } + + [Test] + public void GetSetTransient () + { + using (var pd = new NSPropertyDescription ()) { + Assert.IsFalse (pd.Transient, "A property should not be Transient by default."); + pd.Transient = true; + Assert.IsTrue (pd.Transient, "Transient was not correctly set."); + } + } + + [Test] + public void GetSetRenamingIdentifier () + { + using (var pd = new NSPropertyDescription ()) { + Assert.IsNull (pd.RenamingIdentifier, + "A property by default should have the RenamingIndentifier set to null"); + pd.RenamingIdentifier = "Foo"; + Assert.AreEqual ("Foo", pd.RenamingIdentifier, + "RenamingIdentifier was not correctly set."); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreFoundation/BundleTest.cs b/tests/monotouch-test/CoreFoundation/BundleTest.cs new file mode 100644 index 000000000000..638591e57324 --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/BundleTest.cs @@ -0,0 +1,347 @@ +// +// Copyright 2015 Xamarin Inc +// +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreFoundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BundleTest { + + [Test] + public void TestGetAll () + { + var bundles = CFBundle.GetAll (); + Assert.IsTrue (bundles.Length > 0); + foreach (CFBundle b in bundles) { + Assert.IsFalse (String.IsNullOrEmpty (b.Url.ToString ()), + String.Format("Found bundle with null url and id {0}", b.Identifier)); + } + } + + [Test] + public void TestGetBundleIdMissing () + { + var bundle = CFBundle.Get ("????"); + Assert.IsNull (bundle); + } + + [Test] + public void TestGetBundleId () + { + // grab all bundles and make sure we do get the correct ones using their id + var bundles = CFBundle.GetAll (); + Assert.IsTrue (bundles.Length > 0); + foreach (CFBundle b in bundles) { + var id = b.Identifier; + if (!String.IsNullOrEmpty (id)) { + var otherBundle = CFBundle.Get (id); + Assert.AreEqual (b.Info.Type, otherBundle.Info.Type, + String.Format("Found bundle with diff type and id {0}", id)); + Assert.AreEqual (b.Url.ToString (), otherBundle.Url.ToString (), + String.Format("Found bundle with diff url and id {0}", id)); + } + } + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestGetBundleIdNull (string id) + { + var bundle = CFBundle.Get (id); + } + + [Test] + public void TestGetMain () + { + var main = CFBundle.GetMain (); + Assert.AreEqual ("com.xamarin.monotouch-test", main.Identifier); + Assert.IsTrue (main.HasLoadedExecutable); + } + + [Test] + public void TestBuiltInPlugInsUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.BuiltInPlugInsUrl.ToString (), Contains.Substring ("PlugIns/")); + } + + [Test] + public void TestExecutableUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.ExecutableUrl.ToString (), Contains.Substring ("monotouchtest.app/monotouchtest")); + } + + [Test] + public void TestPrivateFrameworksUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.PrivateFrameworksUrl.ToString (), Contains.Substring ("Frameworks/")); + } + + [Test] + public void TestResourcesDirectoryUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.ResourcesDirectoryUrl.ToString (), Contains.Substring ("monotouchtest.app/")); + } + + [Test] + public void TestSharedFrameworksUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.SharedFrameworksUrl.ToString (), Contains.Substring ("SharedFrameworks/")); + } + + [Test] + public void TestSharedSupportUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.SharedSupportUrl.ToString (), Contains.Substring ("SharedSupport/")); + } + + [Test] + public void TestSupportFilesDirectoryUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.SupportFilesDirectoryUrl.ToString (), Contains.Substring ("monotouchtest.app/")); + } + + [Test] + public void TestArchitectures () + { + var main = CFBundle.GetMain (); + Assert.IsTrue (main.Architectures.Length > 0); + } + + [Test] + public void TestUrl () + { + var main = CFBundle.GetMain (); + Assert.That(main.Url.ToString (), Contains.Substring ("monotouchtest.app/")); + } + + [Test] + public void TestDevelopmentRegion () + { + var main = CFBundle.GetMain (); + Assert.IsFalse (String.IsNullOrEmpty (main.DevelopmentRegion)); + } + + [Test] + public void TestLocalizations () + { + var main = CFBundle.GetMain (); + var localizations = CFBundle.GetLocalizations (main.Url); + Assert.IsTrue (localizations.Length > 0); + Assert.That (localizations, Has.Exactly (1).EqualTo ("en")); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestLocalizationsNull () + { + var localizations = CFBundle.GetLocalizations (null); + } + + [Test] + public void TestPreferredLocalizations () + { + var preferred = new string [] {"en", "es"}; + var used = CFBundle.GetPreferredLocalizations (preferred); + Assert.IsTrue (used.Length > 0); + Assert.That (used, Has.Exactly (1).EqualTo ("en")); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestPreferredLocalizationsNull () + { + var used = CFBundle.GetPreferredLocalizations (null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestAuxiliaryExecutableUrlNull (string executable) + { + var main = CFBundle.GetMain (); + main.GetAuxiliaryExecutableUrl (executable); + } + + [Test] + public void TestGetAuxiliaryExecutableUrlNull () + { + var main = CFBundle.GetMain (); + var url = main.GetAuxiliaryExecutableUrl ("fake-exe"); + Assert.IsNull (url); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlNullName (string resourceName) + { + var main = CFBundle.GetMain (); + main.GetResourceUrl (resourceName, "type", null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlNullType (string resourceType) + { + var main = CFBundle.GetMain (); + main.GetResourceUrl ("resourceName", resourceType, null); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestStaticResourceUrlNull () + { + NSUrl url = null; + CFBundle.GetResourceUrl (url, "resourceName", "resourceType", null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestStaticResourceUrlNullName (string resourceName) + { + var main = CFBundle.GetMain (); + CFBundle.GetResourceUrl (main.Url, resourceName, "resourceType", null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestStaticResourceUrlNullType (string resourceType) + { + var main = CFBundle.GetMain (); + CFBundle.GetResourceUrl (main.Url, "resourceName", resourceType, null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlsNullType (string resourceType) + { + var main = CFBundle.GetMain (); + main.GetResourceUrls (resourceType, null); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestStaticResourceUrlsNullType () + { + NSUrl url = null; + CFBundle.GetResourceUrls (url, "resourceType", null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestStaticResourceUrlsNullType (string resourceType) + { + var main = CFBundle.GetMain (); + CFBundle.GetResourceUrls (main.Url, resourceType, null); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlLocalNameNullName (string resourceName) + { + var main = CFBundle.GetMain (); + main.GetResourceUrl (resourceName, "resourceType", null, "en"); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlLocalNameNullType (string resourceType) + { + var main = CFBundle.GetMain (); + main.GetResourceUrl ("resourceName", resourceType, null, "en"); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlLocalNameNullLocale (string locale) + { + var main = CFBundle.GetMain (); + main.GetResourceUrl ("resourceName", "resourceType", null, locale); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlsLocalNameNullType (string type) + { + var main = CFBundle.GetMain (); + main.GetResourceUrls (type, null, "en"); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestResourceUrlsLocalNameNullLocale (string locale) + { + var main = CFBundle.GetMain (); + main.GetResourceUrls ("jpg", null, locale); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestLocalizedStringNullKey (string key) + { + var main = CFBundle.GetMain (); + main.GetLocalizedString (key, null, "tableName"); + } + + [TestCase ("")] + [TestCase (null)] + [ExpectedException (typeof (ArgumentException))] + public void TestLocalizedStringNullTable (string tableName) + { + var main = CFBundle.GetMain (); + main.GetLocalizedString ("key", null, tableName); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestGetLocalizationsForPreferencesNullLocalArray () + { + CFBundle.GetLocalizationsForPreferences (null, new string [0]); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestGetLocalizationsForPreferencesNullPrefArray () + { + CFBundle.GetLocalizationsForPreferences (new string [0], null); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TestGetInfoDictionaryNull () + { + CFBundle.GetInfoDictionary (null); + } + } +} diff --git a/tests/monotouch-test/CoreFoundation/DispatchGroupTest.cs b/tests/monotouch-test/CoreFoundation/DispatchGroupTest.cs new file mode 100644 index 000000000000..65a27d5d50f7 --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/DispatchGroupTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for DispatchGroup +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; + +#if XAMCORE_2_0 +using Foundation; +using CoreFoundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DispatchGroupTest + { + [Test] + public void WaitTest () + { + using (var dg = DispatchGroup.Create ()) { + var dq = DispatchQueue.GetGlobalQueue (DispatchQueuePriority.Default); + + dg.DispatchAsync (dq, delegate { + Console.WriteLine ("Inside dispatch"); + }); + + Assert.IsTrue (dg.Wait (DispatchTime.Forever)); + dq.Dispose (); + } + } + + [Test] + public void EnterLeaveTest () + { + using (var dg = DispatchGroup.Create ()) { + dg.Enter (); + Assert.IsFalse (dg.Wait (new DispatchTime (1000 * 1000 * 1000)), "#1"); + dg.Leave (); + Assert.IsTrue (dg.Wait (DispatchTime.Forever), "#2"); + } + } + + } +} diff --git a/tests/monotouch-test/CoreFoundation/DispatchTests.cs b/tests/monotouch-test/CoreFoundation/DispatchTests.cs new file mode 100644 index 000000000000..f9a4e9844cf1 --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/DispatchTests.cs @@ -0,0 +1,255 @@ +// +// Unit tests for Dispatch +// +// Authors: +// Miguel de Icaza +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using CoreFoundation; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using System.Drawing; +using System.Threading; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DispatchTests { + + static bool RunningOnSnowLeopard { + get { + if (Runtime.Arch == Arch.DEVICE) + return false; + return !File.Exists ("/usr/lib/system/libsystem_kernel.dylib"); + } + } + + [Test] + public void MainQueueDispatch () + { +#if !DEBUG + Assert.Ignore ("UIKitThreadAccessException is not throw, by default, on release builds (removed by the linker)"); +#endif + if (RunningOnSnowLeopard) + Assert.Ignore ("this test crash when executed with the iOS simulator on Snow Leopard"); + + bool hit = false; + // We need to check the UIKitThreadAccessException, but there are very few API + // with that check on WatchOS. NSStringDrawing.WeakDrawString is one example, here we pass + // it null for the parameter so that it immediately returns with an ArgumentNullException + // instead of trying to load an image (which is not what we're testing). There + // is also a test to ensure UIKitThreadAccessException is thrown if not on + // the UI thread (so that we'll notice if the UIKitThreadAccessException is ever + // removed from NSStringDrawing.WeakDrawString). + var uiThread = Thread.CurrentThread; + Thread queueThread = null; + Thread mainQthread = null; + Exception ex = null; + Exception queue_ex = null; + + var defaultQ = DispatchQueue.GetGlobalQueue (DispatchQueuePriority.Default); + defaultQ.DispatchAsync (delegate { + try { + NSStringDrawing.WeakDrawString (null, PointF.Empty, null); + } catch (Exception e) { + queue_ex = e; + } + + queueThread = Thread.CurrentThread; + var mainQ = DispatchQueue.MainQueue; + mainQ.DispatchAsync (delegate { + mainQthread = Thread.CurrentThread; + try { + NSStringDrawing.WeakDrawString (null, PointF.Empty, null); + } catch (Exception e) { + ex = e; + } finally { + hit = true; + } + } ); + + } ); + + // Now wait for the above to actually run + while (hit == false){ + NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5)); + } + Assert.IsNotNull (ex, "main ex"); + Assert.That (ex.GetType (), Is.SameAs (typeof (ArgumentNullException)), "no thread check hit"); + Assert.IsNotNull (queue_ex, "queue ex"); + Assert.That (queue_ex.GetType (), Is.SameAs (typeof (UIKitThreadAccessException)), "thread check hit"); + Assert.That (uiThread, Is.EqualTo (mainQthread), "mainq thread is equal to uithread"); + Assert.That (queueThread, Is.Not.EqualTo (mainQthread), "queueThread is not the same as the UI thread"); + } + + [Test] + public void Current () + { + Assert.That (DispatchQueue.CurrentQueue.Label, Is.EqualTo ("com.apple.main-thread"), "Current"); + } + + [Test] + public void Default () + { + var qname = TestRuntime.CheckSystemAndSDKVersion (8, 0) ? "com.apple.root.default-qos" : "com.apple.root.default-priority"; + Assert.That (DispatchQueue.DefaultGlobalQueue.Label, Is.EqualTo (qname), "Default"); + } + + [Test] + public void SetTargetQueue () + { + int n = 0; + int ct = Thread.CurrentThread.ManagedThreadId; + int t0 = ct; + int t1 = ct; + int t2 = ct; + using (var q = new DispatchQueue ("my")) { + Console.WriteLine (); + q.DispatchAsync (delegate { + t0 = Thread.CurrentThread.ManagedThreadId; + n++; + }); + DispatchQueue.DefaultGlobalQueue.SetTargetQueue (DispatchQueue.MainQueue); + q.DispatchAsync (delegate { + t1 = Thread.CurrentThread.ManagedThreadId; + n++; + }); + DispatchQueue.DefaultGlobalQueue.SetTargetQueue (null); + q.DispatchAsync (delegate { + t2 = Thread.CurrentThread.ManagedThreadId; + n++; + }); + Assert.That (q.Label, Is.EqualTo ("my"), "label"); + } + while (n != 3) + NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (1.0)); + // ensure async dispatches were done on another thread + Assert.That (ct, Is.Not.EqualTo (t0), "t0"); + Assert.That (ct, Is.Not.EqualTo (t1), "t1"); + Assert.That (ct, Is.Not.EqualTo (t2), "t2"); + } + + [Test] + public void Main () + { + if (RunningOnSnowLeopard) + Assert.Ignore ("Shows corruption (missing first 4 chars) when executed the iOS simulator on Snow Leopard"); + Assert.That (DispatchQueue.MainQueue.Label, Is.EqualTo ("com.apple.main-thread"), "Main"); + } + + [Test] + public void GetGlobalQueue_Priority () + { + string qdefault, qlow, qhigh; + if (TestRuntime.CheckSystemAndSDKVersion (8, 0)) { + qdefault = "com.apple.root.default-qos"; + qlow = "com.apple.root.utility-qos"; + qhigh = "com.apple.root.user-initiated-qos"; + } else { + qdefault = "com.apple.root.default-priority"; + qlow = "com.apple.root.low-priority"; + qhigh = "com.apple.root.high-priority"; + } + Assert.That (DispatchQueue.GetGlobalQueue (DispatchQueuePriority.Default).Label, Is.EqualTo (qdefault), "Default"); + Assert.That (DispatchQueue.GetGlobalQueue (DispatchQueuePriority.Low).Label, Is.EqualTo (qlow), "Low"); + Assert.That (DispatchQueue.GetGlobalQueue (DispatchQueuePriority.High).Label, Is.EqualTo (qhigh), "High"); + } + + [Test] + public void NeverTooLate () + { + Assert.That (DispatchTime.Now.Nanoseconds, Is.EqualTo (0), "Now"); + Assert.That (DispatchTime.Forever.Nanoseconds, Is.EqualTo (unchecked ((ulong) ~0)), "Forever"); + + var dt = new DispatchTime (1); + Assert.That (dt.Nanoseconds, Is.EqualTo (1), "1"); + + dt = new DispatchTime (DispatchTime.Now, 0); + Assert.That (dt.Nanoseconds, Is.Not.EqualTo (0), "!0"); + + var dt2 = new DispatchTime (dt, Int32.MaxValue); + Assert.That (dt2.Nanoseconds, Is.GreaterThan (dt.Nanoseconds), "later"); + } + + [Test] + public void EverAfter () + { +#if !DEBUG + Assert.Ignore ("UIKitThreadAccessException is not throw, by default, on release builds (removed by the linker)"); +#endif + if (RunningOnSnowLeopard) + Assert.Ignore ("this test crash when executed with the iOS simulator on Snow Leopard"); + + bool hit = false; + // We need to check the UIKitThreadAccessException, but there are very few API + // with that check on WatchOS. NSStringDrawing.WeakDrawString is one example, here we pass + // it null for the parameter so that it immediately returns with an ArgumentNullException + // instead of trying to load an image (which is not what we're testing). There + // is also a test to ensure UIKitThreadAccessException is thrown if not on + // the UI thread (so that we'll notice if the UIKitThreadAccessException is ever + // removed from NSStringDrawing.WeakDrawString). + var uiThread = Thread.CurrentThread; + Thread queueThread = null; + Thread mainQthread = null; + Exception ex = null; + Exception queue_ex = null; + + var defaultQ = DispatchQueue.GetGlobalQueue (DispatchQueuePriority.Default); + defaultQ.DispatchAfter (new DispatchTime (DispatchTime.Now, 1000), delegate { + try { + NSStringDrawing.WeakDrawString (null, PointF.Empty, null); + } catch (Exception e) { + queue_ex = e; + } + + queueThread = Thread.CurrentThread; + var mainQ = DispatchQueue.MainQueue; + mainQ.DispatchAfter (DispatchTime.Now, delegate { + mainQthread = Thread.CurrentThread; + try { + NSStringDrawing.WeakDrawString (null, PointF.Empty, null); + } catch (Exception e) { + ex = e; + } finally { + hit = true; + } + } ); + } ); + + // Now wait for the above to actually run + while (hit == false){ + NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5)); + } + Assert.IsNotNull (ex, "main ex"); + Assert.That (ex.GetType (), Is.SameAs (typeof (ArgumentNullException)), "no thread check hit"); + Assert.IsNotNull (queue_ex, "queue ex"); + Assert.That (queue_ex.GetType (), Is.SameAs (typeof (UIKitThreadAccessException)), "thread check hit"); + Assert.That (uiThread, Is.EqualTo (mainQthread), "mainq thread is equal to uithread"); + Assert.That (queueThread, Is.Not.EqualTo (mainQthread), "queueThread is not the same as the UI thread"); + } + } +} diff --git a/tests/monotouch-test/CoreFoundation/NetworkTest.cs b/tests/monotouch-test/CoreFoundation/NetworkTest.cs new file mode 100644 index 000000000000..d3ddc3c056a9 --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/NetworkTest.cs @@ -0,0 +1,75 @@ +// +// Unit tests for CFNetwork +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; +using System.Threading.Tasks; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using CoreFoundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NetworkTest { + + const string bug4715_url = "http://192.168.1.94:8080/telehealth/Services/External/Recipient.svc/List?OrgId={FDB521B6-1ADA-40D3-8AE9-0F59B9F2DB11}&Ticket=84DDB35C66B7EEF59C8B31D072A71C01E2F81158E98827C983FAF18C8B9D261A2D75680BFD6050B975E9F77EEEF1E9B235E631B957BC31D6C84CBDA6219DB11B2BC9F6BD39546158683F67A86947B034326A48B6E9F50C77D9A1578F50F26C861E514D1CE4721D011F037A1D2B0C91B7D60736B1021B7AC1A387BE28256794C7CF907B57CF2CA30F5D5D26CDAB55A986EDD8D00B9A6BD25FBADA1C583D6A13326851A92137F35DC69D4C565519E95365E6CA37FB60A8480B2297B106CE6DF9AC2A082B90D2755C2F4D73074CAFE1030512FC3A35"; +#if !__TVOS__ && !__WATCHOS__ + CFProxySettings settings = CFNetwork.GetSystemProxySettings (); +#endif + Uri uri = new Uri (bug4715_url); + +#if !__TVOS__ && !__WATCHOS__ + [Test] + public void WebProxy () + { + IWebProxy proxy = CFNetwork.GetDefaultProxy (); + Assert.True (proxy.IsBypassed (uri), "IsBypassed"); + Assert.That (proxy.GetProxy (uri), Is.SameAs (uri), "GetProxy"); + } + + [Test] + public void GetProxiesForUri () + { + var proxies = CFNetwork.GetProxiesForUri (uri, settings); + Assert.That (proxies.Length, Is.EqualTo (1), "single"); + var p = proxies [0]; + Assert.Null (p.AutoConfigurationJavaScript, "AutoConfigurationJavaScript"); + Assert.Null (p.AutoConfigurationUrl, "AutoConfigurationUrl"); + Assert.Null (p.HostName, "HostName"); + Assert.That (p.Port, Is.EqualTo (0), "Port"); + Assert.Null (p.Password, "Password"); + Assert.That (p.ProxyType, Is.EqualTo (CFProxyType.None), "Type"); + Assert.Null (p.Username, "Username"); + } + + [Test] + public void Bug_7923 () + { + // Bug #7923 - crash when proxy is in effect. + var uri = new Uri ("http://www.google.com"); + + if (CFNetwork.GetProxiesForUri (uri, settings).Length <= 1) + Assert.Ignore ("Only run when proxy is configured."); + + var req = new HttpWebRequest (uri); + using (var rsp = req.GetResponse ()) + using (var str = new StreamReader (rsp.GetResponseStream ())) + Console.WriteLine (str.ReadToEnd ()); + } +#endif // !__TVOS__ + } +} diff --git a/tests/monotouch-test/CoreFoundation/NotificationCenterTest.cs b/tests/monotouch-test/CoreFoundation/NotificationCenterTest.cs new file mode 100644 index 000000000000..fbb20db7195e --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/NotificationCenterTest.cs @@ -0,0 +1,33 @@ +// +// Unit tests for CFNotificationCenter +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreFoundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NotificationCenterTest { + + [Test] + public void Static () + { + Assert.NotNull (CFNotificationCenter.Darwin, "Darwin"); + Assert.NotNull (CFNotificationCenter.Local, "Local"); + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreFoundation/ProxyTest.cs b/tests/monotouch-test/CoreFoundation/ProxyTest.cs new file mode 100644 index 000000000000..0f0347ab3c0e --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/ProxyTest.cs @@ -0,0 +1,46 @@ +// +// Unit tests for CFProxy[Settings] +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreFoundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ProxyTest { + + [Test] + public void Fields () + { + // documented but symbols are missing + // this test will fail if Apple decide to include them in the future + IntPtr lib = Dlfcn.dlopen (Constants.CoreFoundationLibrary, 0); + try { + // http://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFProxySupport/Reference/reference.html#//apple_ref/doc/c_ref/kCFProxyAutoConfigurationHTTPResponseKey + Assert.That (Dlfcn.dlsym (lib, "kCFProxyAutoConfigurationHTTPResponseKey"), Is.EqualTo (IntPtr.Zero), "kCFProxyAutoConfigurationHTTPResponseKey"); + // http://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFProxySupport/Reference/reference.html#//apple_ref/doc/c_ref/kCFNetworkProxiesProxyAutoConfigJavaScript + Assert.That (Dlfcn.dlsym (lib, "kCFNetworkProxiesProxyAutoConfigJavaScript"), Is.EqualTo (IntPtr.Zero), "kCFNetworkProxiesProxyAutoConfigJavaScript"); + } + finally { + Dlfcn.dlclose (lib); + } + } + } +} diff --git a/tests/monotouch-test/CoreFoundation/StringTest.cs b/tests/monotouch-test/CoreFoundation/StringTest.cs new file mode 100644 index 000000000000..ccd4e5eaa829 --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/StringTest.cs @@ -0,0 +1,40 @@ +// +// Unit tests for CFString +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreFoundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class StringTest { + + [Test] + public void ToString_ () + { + using (CFString str = new CFString ("string")) { + Assert.That (str.ToString (), Is.EqualTo ("string"), "ctor(string)"); + } + } + + [Test] + public void Null () + { + Assert.Throws (delegate { new CFString (null); }, "null"); + } + } +} diff --git a/tests/monotouch-test/CoreFoundation/UrlTest.cs b/tests/monotouch-test/CoreFoundation/UrlTest.cs new file mode 100644 index 000000000000..60269c3e5096 --- /dev/null +++ b/tests/monotouch-test/CoreFoundation/UrlTest.cs @@ -0,0 +1,54 @@ +// +// Unit tests for CFUrl +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreFoundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CFUrlTest { + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromFile_Null () + { + CFUrl.FromFile (null); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromUrlString_Null () + { + CFUrl.FromUrlString (null, CFUrl.FromFile ("/")); + } + + [Test] + public void ToString_ () + { + using (CFUrl url = CFUrl.FromFile ("/")) { + string value = TestRuntime.CheckSystemAndSDKVersion (7, 0) ? "file:///" : "file://localhost/"; + Assert.That (url.ToString (), Is.EqualTo (value), "FromFile"); + } + using (CFUrl url = CFUrl.FromUrlString ("/", null)) { + Assert.That (url.ToString (), Is.EqualTo ("/"), "FromUrlString"); + } + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs b/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs new file mode 100644 index 000000000000..0d2e3b43bfa6 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs @@ -0,0 +1,308 @@ +// +// Unit tests for CGAffineTransform +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AffineTransformTest { + [Test] + public void Ctor () + { + var transform = new CGAffineTransform (); + Assert.AreEqual ((nfloat) 0, transform.xx); + Assert.AreEqual ((nfloat) 0, transform.yx); + Assert.AreEqual ((nfloat) 0, transform.xy); + Assert.AreEqual ((nfloat) 0, transform.yy); + Assert.AreEqual ((nfloat) 0, transform.x0); + Assert.AreEqual ((nfloat) 0, transform.y0); + + transform = new CGAffineTransform (1, 2, 3, 4, 5, 6); + Assert.AreEqual ((nfloat) 1, transform.xx); + Assert.AreEqual ((nfloat) 2, transform.yx); + Assert.AreEqual ((nfloat) 3, transform.xy); + Assert.AreEqual ((nfloat) 4, transform.yy); + Assert.AreEqual ((nfloat) 5, transform.x0); + Assert.AreEqual ((nfloat) 6, transform.y0); + } + + [Test] + public void MakeIdentity () + { + var transform = CGAffineTransform.MakeIdentity (); + + Assert.AreEqual ((nfloat) 1, transform.xx, "xx"); + Assert.AreEqual ((nfloat) 0, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 0, transform.xy, "xy"); + Assert.AreEqual ((nfloat) 1, transform.yy, "yy"); + Assert.AreEqual ((nfloat) 0, transform.x0, "x0"); + Assert.AreEqual ((nfloat) 0, transform.y0, "y0"); + + Assert.IsTrue (transform.IsIdentity, "identity"); + } + + [Test] + public void MakeRotation () + { + var transform = CGAffineTransform.MakeRotation ((nfloat) Math.PI); + + Assert.AreEqual ((nfloat) (-1), transform.xx, "xx"); + Assert.That ((double) 0, Is.EqualTo ((double) transform.yx).Within (0.0000001), "yx"); + Assert.That ((double) 0, Is.EqualTo ((double) transform.xy).Within (0.0000001), "xy"); + Assert.AreEqual ((nfloat) (-1), transform.yy, "yy"); + Assert.That ((double) 0, Is.EqualTo ((double) transform.x0).Within (0.0000001), "x0"); + Assert.That ((double) 0, Is.EqualTo ((double) transform.y0).Within (0.0000001), "y0"); + } + + [Test] + public void MakeScale () + { + var transform = CGAffineTransform.MakeScale (314, 413); + Assert.AreEqual ((nfloat) 314, transform.xx); + Assert.AreEqual ((nfloat) 0, transform.yx); + Assert.AreEqual ((nfloat) 0, transform.xy); + Assert.AreEqual ((nfloat) 413, transform.yy); + Assert.AreEqual ((nfloat) 0, transform.x0); + Assert.AreEqual ((nfloat) 0, transform.y0); + } + + [Test] + public void MakeTranslation () + { + var transform = CGAffineTransform.MakeTranslation (12, 23); + + Assert.AreEqual ((nfloat) 1, transform.xx, "xx"); + Assert.AreEqual ((nfloat) 0, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 0, transform.xy, "xy"); + Assert.AreEqual ((nfloat) 1, transform.yy, "yy"); + Assert.AreEqual ((nfloat) 12, transform.x0, "x0"); + Assert.AreEqual ((nfloat) 23, transform.y0, "y0"); + } + + [Test] + public void Multiply () + { + var a = new CGAffineTransform (1, 2, 3, 4, 5, 6); + var transform = new CGAffineTransform (9, 8, 7, 6, 5, 4); + transform.Multiply (a); + + Assert.AreEqual ((nfloat) 33, transform.xx, "xx"); + Assert.AreEqual ((nfloat) 50, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 25, transform.xy, "xy"); + Assert.AreEqual ((nfloat) 38, transform.yy, "yy"); + Assert.AreEqual ((nfloat) 22, transform.x0, "x0"); + Assert.AreEqual ((nfloat) 32, transform.y0, "y0"); + } + + [Test] + public void StaticMultiply () + { + var a = new CGAffineTransform (1, 2, 3, 4, 5, 6); + var b = new CGAffineTransform (9, 8, 7, 6, 5, 4); + var transform = CGAffineTransform.Multiply (a, b); + + Assert.AreEqual ((nfloat) 23, transform.xx, "xx"); + Assert.AreEqual ((nfloat) 20, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 55, transform.xy, "xy"); + Assert.AreEqual ((nfloat) 48, transform.yy, "yy"); + Assert.AreEqual ((nfloat) 92, transform.x0, "x0"); + Assert.AreEqual ((nfloat) 80, transform.y0, "y0"); + } + [Test] + public void Scale () + { + var transform = CGAffineTransform.MakeTranslation (0, 200); + transform.Scale (1, -1); + + Assert.AreEqual ((nfloat) 1, transform.xx); + Assert.AreEqual ((nfloat) 0, transform.yx); + Assert.AreEqual ((nfloat) 0, transform.xy); + Assert.AreEqual ((nfloat) (-1), transform.yy); + Assert.AreEqual ((nfloat) 0, transform.x0); + Assert.AreEqual ((nfloat) (-200), transform.y0); + } + + [Test] + public void StaticScale () + { + var transformM = CGAffineTransform.Scale (CGAffineTransform.MakeTranslation (0, 200), 1, -1); + var transformN = CGAffineTransformScale (CGAffineTransform.MakeTranslation (0, 200), 1, -1); + + Assert.IsTrue (transformM == transformN, "1"); + + transformM = CGAffineTransform.Scale (CGAffineTransform.MakeTranslation (1, 2), -3, -4); + transformN = CGAffineTransformScale (CGAffineTransform.MakeTranslation (1, 2), -3, -4); + + Assert.IsTrue (transformM == transformN, "2"); + } + + [DllImport ("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")] + public extern static CGAffineTransform CGAffineTransformScale (CGAffineTransform t, nfloat sx, nfloat sy); + + [Test] + public void Translate () + { + var transform = CGAffineTransform.MakeIdentity (); + transform.Translate (1, -1); + + Assert.AreEqual ((nfloat) 1, transform.xx, "xx"); + Assert.AreEqual ((nfloat) 0, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 0, transform.xy, "xy"); + Assert.AreEqual ((nfloat) 1, transform.yy, "yy"); + Assert.AreEqual ((nfloat) 1, transform.x0, "x0"); + Assert.AreEqual ((nfloat) (-1), transform.y0, "y0"); + + transform = new CGAffineTransform (1, 2, 3, 4, 5, 6); + transform.Translate (2, -3); + + Assert.AreEqual ((nfloat) 1, transform.xx, "xx"); + Assert.AreEqual ((nfloat) 2, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 3, transform.xy, "xy"); + Assert.AreEqual ((nfloat) 4, transform.yy, "yy"); + Assert.AreEqual ((nfloat) 7, transform.x0, "x0"); + Assert.AreEqual ((nfloat) 3, transform.y0, "y0"); + } + + [Test] + public void StaticTranslate () + { + var origin = CGAffineTransform.MakeIdentity (); + var transformM = CGAffineTransform.Translate (origin, 1, -1); + var transformN = CGAffineTransformTranslate (origin, 1, -1); + + Assert.AreEqual ((nfloat) 1, transformM.xx, "xx"); + Assert.AreEqual ((nfloat) 0, transformM.yx, "yx"); + Assert.AreEqual ((nfloat) 0, transformM.xy, "xy"); + Assert.AreEqual ((nfloat) 1, transformM.yy, "yy"); + Assert.AreEqual ((nfloat) 1, transformM.x0, "x0"); + Assert.AreEqual ((nfloat) (-1), transformM.y0, "y0"); + Assert.IsTrue (transformN == transformM); + + origin = new CGAffineTransform (1, 2, 3, 4, 5, 6); + transformM = CGAffineTransform.Translate (origin, 2, -3); + transformN = CGAffineTransformTranslate (origin, 2, -3); + + Assert.AreEqual ((nfloat) 1, transformM.xx, "xx"); + Assert.AreEqual ((nfloat) 2, transformM.yx, "yx"); + Assert.AreEqual ((nfloat) 3, transformM.xy, "xy"); + Assert.AreEqual ((nfloat) 4, transformM.yy, "yy"); + Assert.AreEqual ((nfloat) (-2), transformM.x0, "x0"); + Assert.AreEqual ((nfloat) (-2), transformM.y0, "y0"); + Assert.IsTrue (transformN == transformM); + } + + [DllImport ("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")] + public extern static CGAffineTransform CGAffineTransformTranslate (CGAffineTransform t, nfloat sx, nfloat sy); + + [Test] + public void Rotate () + { + var transform = new CGAffineTransform (1, 2, 3, 4, 5, 6); + transform.Rotate ((nfloat) Math.PI); + + Assert.That ((double) (-1), Is.EqualTo ((double) transform.xx).Within (0.000001), "xx"); + Assert.That ((double) (-2), Is.EqualTo ((double) transform.yx).Within (0.000001), "yx"); + Assert.That ((double) (-3), Is.EqualTo ((double) transform.xy).Within (0.000001), "xy"); + Assert.That ((double) (-4), Is.EqualTo ((double) transform.yy).Within (0.000001), "yy"); + Assert.That ((double) (-5), Is.EqualTo ((double) transform.x0).Within (0.000001), "x0"); + Assert.That ((double) (-6), Is.EqualTo ((double) transform.y0).Within (0.000001), "y0"); + } + + [Test] + public void StaticRotate () + { + var transformM = CGAffineTransform.Rotate (new CGAffineTransform (1, 2, 3, 4, 5, 6), (nfloat) Math.PI); + var transformN = CGAffineTransformRotate (new CGAffineTransform (1, 2, 3, 4, 5, 6), (nfloat) Math.PI); + + Assert.That ((double) (-1), Is.EqualTo ((double) transformM.xx).Within (0.000001), "xx"); + Assert.That ((double) (-2), Is.EqualTo ((double) transformM.yx).Within (0.000001), "yx"); + Assert.That ((double) (-3), Is.EqualTo ((double) transformM.xy).Within (0.000001), "xy"); + Assert.That ((double) (-4), Is.EqualTo ((double) transformM.yy).Within (0.000001), "yy"); + Assert.That ((double) 5, Is.EqualTo ((double) transformM.x0).Within (0.000001), "x0"); + Assert.That ((double) 6, Is.EqualTo ((double) transformM.y0).Within (0.000001), "y0"); + + Assert.That ((double) transformN.xx, Is.EqualTo ((double) transformM.xx).Within (0.000001), "xx"); + Assert.That ((double) transformN.yx, Is.EqualTo ((double) transformM.yx).Within (0.000001), "yx"); + Assert.That ((double) transformN.xy, Is.EqualTo ((double) transformM.xy).Within (0.000001), "xy"); + Assert.That ((double) transformN.yy, Is.EqualTo ((double) transformM.yy).Within (0.000001), "yy"); + Assert.That ((double) 5, Is.EqualTo ((double) transformM.x0).Within (0.000001), "x0"); + Assert.That ((double) 6, Is.EqualTo ((double) transformM.y0).Within (0.000001), "y0"); + } + + [DllImport ("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")] + public extern static CGAffineTransform CGAffineTransformRotate (CGAffineTransform t, nfloat angle); + + [Test] + public void IsIdentity () + { + Assert.IsTrue (CGAffineTransform.MakeIdentity ().IsIdentity, "MakeIdentity"); + Assert.IsFalse (new CGAffineTransform (1, 2, 3, 4, 5, 6).IsIdentity, "123456"); + } + + [Test] + public void TransformPoint () + { + var transform = new CGAffineTransform (1, 2, 3, 4, 5, 6); + var point = transform.TransformPoint (new PointF (4, 5)); + + Assert.AreEqual ((nfloat) 24, point.X, "X"); + Assert.AreEqual ((nfloat) 34, point.Y, "Y"); + } + + [Test] + public void TransformRect () + { + var transform = new CGAffineTransform (1, 2, 3, 4, 5, 6); + var rect = transform.TransformRect (new RectangleF (4, 5, 6, 7)); + + Assert.AreEqual ((nfloat) 24, rect.X, "X"); + Assert.AreEqual ((nfloat) 34, rect.Y, "Y"); + Assert.AreEqual ((nfloat) 27, rect.Width, "Width"); + Assert.AreEqual ((nfloat) 40, rect.Height, "Height"); + } + + [Test] + public void Invert () + { + var transform = new CGAffineTransform (1, 2, 3, 4, 5, 6).Invert (); + + Assert.AreEqual ((nfloat) (-2), transform.xx, "xx"); + Assert.AreEqual ((nfloat) 1, transform.yx, "yx"); + Assert.AreEqual ((nfloat) 1.5, transform.xy, "xy"); + Assert.AreEqual ((nfloat) (-0.5), transform.yy, "yy"); + Assert.AreEqual ((nfloat) 1.0, transform.x0, "x0"); + Assert.AreEqual ((nfloat) (-2.0), transform.y0, "y0"); + } + } + + +} diff --git a/tests/monotouch-test/CoreGraphics/BitmapContextTest.cs b/tests/monotouch-test/CoreGraphics/BitmapContextTest.cs new file mode 100644 index 000000000000..89994de67ba0 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/BitmapContextTest.cs @@ -0,0 +1,120 @@ +// +// Unit tests for CGBitmapContext +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BitmapContextTest { + + [Test] + public void Ctor_CGBitmapFlags () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=7441 + byte[] data = new byte [400]; + using (CGColorSpace space = CGColorSpace.CreateDeviceRGB ()) { + // According to Apple "This value is equivalent to kCGImageAlphaNoneSkipLast" which is not true (at least in this "context" ;-) + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.None); }, "None"); + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedLast)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "PremultipliedLast"); + } + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedFirst)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "PremultipliedFirst"); + } + + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.Last); }, "Last"); + + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.First); }, "First"); + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.NoneSkipLast)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "NoneSkipLast"); + } + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.NoneSkipFirst)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "NoneSkipFirst"); + } + + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.Only); }, "Only"); + } + } + + [Test] + public void Ctor_CGImageAlphaInfo () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=7441 + byte[] data = new byte [400]; + using (CGColorSpace space = CGColorSpace.CreateDeviceRGB ()) { + // According to Apple "This value is equivalent to kCGImageAlphaNoneSkipLast" which is not true (at least in this "context" ;-) + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.None); }, "None"); + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.PremultipliedLast)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "PremultipliedLast"); + } + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.PremultipliedFirst)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "PremultipliedFirst"); + } + + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.Last); }, "Last"); + + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.First); }, "First"); + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.NoneSkipLast)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "NoneSkipLast"); + } + + using (CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.NoneSkipFirst)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "NoneSkipFirst"); + } + + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.Only); }, "Only"); + } + } + + [Test] + public void Ctor_CGColorSpace_Null () + { + byte[] data = new byte [400]; + // a null colorspace is not always accepted - that will return an invalid (IntPtr.Zero) handle and CGContext.set_Handle will throw + Assert.Throws (delegate { new CGBitmapContext (data, 10, 10, 8, 40, null, CGImageAlphaInfo.NoneSkipFirst); }, "null"); + + // OTOH a null colorspace is possible with the valid parameters, e.g. bug #25600, so we can't throw a ANE blindly + using (var context = new CGBitmapContext (null, 16, 32, 8, 0, null, CGImageAlphaInfo.Only)) { + Assert.That (context.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.Null (context.ColorSpace, "ColorSpace"); + } + } + + [Test] + public void ToImage () + { + byte[] data = new byte [400]; + using (CGColorSpace space = CGColorSpace.CreateDeviceRGB ()) { + CGBitmapContext c = new CGBitmapContext (data, 10, 10, 8, 40, space, CGImageAlphaInfo.PremultipliedLast); + using (var img = c.ToImage ()) + Assert.NotNull (img, "ToImage"); + c.Dispose (); // Handle is now 0x0 + Assert.Null (c.ToImage (), "ToImage/Disposed"); + } + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/CGImageTest.cs b/tests/monotouch-test/CoreGraphics/CGImageTest.cs new file mode 100644 index 000000000000..b181a6d63294 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/CGImageTest.cs @@ -0,0 +1,45 @@ +// +// Unit tests for CGImage +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// Sebastien Pouliot +// +// Copyright 2012-2013, 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CGImageTest { + + [Test] + public void FromPNG () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var dp = new CGDataProvider (file)) + using (var img = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) + using (var ui = new UIImage (img, 1.0f, UIImageOrientation.Up)) { + Assert.IsNotNull (ui.CGImage, "CGImage"); + + if (TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.That (img.UTType.ToString (), Is.EqualTo ("public.png"), "UTType"); + } + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/ColorConverterTest.cs b/tests/monotouch-test/CoreGraphics/ColorConverterTest.cs new file mode 100644 index 000000000000..bd5d2e460b09 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/ColorConverterTest.cs @@ -0,0 +1,157 @@ +// +// Unit tests for ColorConverterTest +// +// Authors: +// Vincent Dondain +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics +{ + [TestFixture] + public class ColorConverterTest + { + [Test] + public void CreateNone () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + Assert.Throws (() => new CGColorConverter (null, null), "null"); + Assert.Throws (() => new CGColorConverter (null, new CGColorConverterTriple [0]), "empty"); + } + + [Test] + public void CreateSingle () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + var triple = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericRgb (), + Intent = CGColorRenderingIntent.Default, + Transform = CGColorConverterTransformType.ApplySpace + }; + + using (var converter = new CGColorConverter (null, triple)) { + Assert.That (converter.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void CreateDual () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + var triple = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericRgb (), + Intent = CGColorRenderingIntent.Default, + Transform = CGColorConverterTransformType.ApplySpace + }; + + using (var converter = new CGColorConverter (null, triple, triple)) { + Assert.That (converter.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void CreateMax () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + var first = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericRgb (), + Intent = CGColorRenderingIntent.Default, + Transform = CGColorConverterTransformType.ApplySpace + }; + var second = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericGray (), + Intent = CGColorRenderingIntent.Perceptual, + Transform = CGColorConverterTransformType.FromSpace + }; + var third = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericXyz (), + Intent = CGColorRenderingIntent.Saturation, + Transform = CGColorConverterTransformType.ToSpace + }; + + using (var converter = new CGColorConverter (null, first, first, first)) { + Assert.That (converter.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void CreateTooMany () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + Assert.Throws (() => new CGColorConverter (null, new CGColorConverterTriple [4])); + } + +#if false + [Test] + public void CreateSimple () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + using (var from = CGColorSpace.CreateGenericGray ()) + using (var to = CGColorSpace.CreateGenericRgb ()) + using (var converter = new CGColorConverter (from, to)) { + Assert.That (converter.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [DllImport(Constants.CoreGraphicsLibrary)] + extern static IntPtr CGColorConverterCreateSimple (IntPtr from, IntPtr to); + + [Test] + public void CreateSimple_GetINativeObject () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + using (var from = CGColorSpace.CreateGenericGray ()) + using (var to = CGColorSpace.CreateGenericRgb ()) { + var handle = CGColorConverterCreateSimple (from == null ? IntPtr.Zero : from.Handle, + to == null ? IntPtr.Zero : to.Handle); + using (var o = Runtime.GetINativeObject (handle, false)) { + Assert.That (o.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + } + + [Test] + public void CreateSimple_DeviceColorSpace () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,3)) + Assert.Ignore ("requires iOS 9.3+"); + + // Requirements: CG color spaces must be calibrated + // (no Device{Gray,RGB,CMYK}, Indexed or DeviceN). + // This test lets us know if Apple changes that behavior. + using (var from = CGColorSpace.CreateDeviceGray ()) + using (var to = CGColorSpace.CreateDeviceRGB ()) { + Assert.Throws (() => new CGColorConverter (from, to)); + } + } +#endif + } +} + diff --git a/tests/monotouch-test/CoreGraphics/ColorSpaceTest.cs b/tests/monotouch-test/CoreGraphics/ColorSpaceTest.cs new file mode 100644 index 000000000000..0fc4ca17148a --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/ColorSpaceTest.cs @@ -0,0 +1,178 @@ +// +// Unit tests for CGColorSpace +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ColorSpaceTest { + + void CheckUnknown (CGColorSpace cs) + { + Assert.That (cs.Components, Is.EqualTo ((nint) 0), "Unknown-0"); + Assert.That (cs.Handle, Is.EqualTo (IntPtr.Zero), "Unknown-Handle"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.Unknown), "Unknown-Model"); + Assert.That (cs.GetColorTable ().Length, Is.EqualTo (0), "Unknown-GetColorTable"); + } + +#if !XAMCORE_3_0 + [Test] + public void Null () + { + CheckUnknown (CGColorSpace.Null); + } +#endif + + [Test] + public void CreateDeviceGray () + { + using (var cs = CGColorSpace.CreateDeviceGray ()) { + Assert.That (cs.Components, Is.EqualTo ((nint) 1), "1"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.Monochrome), "Monochrome"); + Assert.Null (cs.GetBaseColorSpace (), "GetBaseColorSpace"); + // not indexed so no color table + Assert.That (cs.GetColorTable ().Length, Is.EqualTo (0), "GetColorTable"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Null (cs.GetICCProfile (), "GetICCProfile"); + } + } + + [Test] + public void CreateDeviceRGB () + { + using (var cs = CGColorSpace.CreateDeviceRGB ()) { + Assert.That (cs.Components, Is.EqualTo ((nint) 3), "3"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.RGB), "RGB"); + Assert.Null (cs.GetBaseColorSpace (), "GetBaseColorSpace"); + // not indexed so no color table + Assert.That (cs.GetColorTable ().Length, Is.EqualTo (0), "GetColorTable"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Null (cs.GetICCProfile (), "GetICCProfile"); + } + } + + [Test] + public void CreateDeviceCMYK () + { + using (var cs = CGColorSpace.CreateDeviceCmyk ()) { + Assert.That (cs.Components, Is.EqualTo ((nint) 4), "4"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.CMYK), "CMYK"); + Assert.Null (cs.GetBaseColorSpace (), "GetBaseColorSpace"); + // not indexed so no color table + Assert.That (cs.GetColorTable ().Length, Is.EqualTo (0), "GetColorTable"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Null (cs.GetICCProfile (), "GetICCProfile"); + } + } + + [Test] + public void CreateIndexed () + { + // from: http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CGColorSpace/Reference/reference.html + // m is the number of color components in the base color space + nint m = 3; // RGB + const int lastIndex = 2; + // An array of m*(lastIndex+1) bytes + byte[] table = new byte [3 * (lastIndex + 1)] { 1, 2, 3, 4, 5, 6, 255, 255, 255 }; + using (var base_cs = CGColorSpace.CreateDeviceRGB ()) + using (var cs = CGColorSpace.CreateIndexed (base_cs, lastIndex, table)) { + Assert.That (cs.Components, Is.EqualTo ((nint) 1), "1"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.Indexed), "Indexed"); + var bcs = cs.GetBaseColorSpace (); + Assert.That (bcs.Components, Is.EqualTo (m), "Components"); + Assert.That (base_cs.Model, Is.EqualTo (bcs.Model), "GetBaseColorSpace"); + var new_table = cs.GetColorTable (); + Assert.That (table, Is.EqualTo (new_table), "GetColorTable"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Null (cs.GetICCProfile (), "GetICCProfile"); + } + } + + [Test] + public void CreateICCProfile () + { + // of all the .icc profiles I have on my Mac then only one I found working is + // for my old 15" sharp (secondary) display. Added it to the test suite + // that should work on the iOS simulator - at least some as I'm not sure every Mac + // has the file(s) so we're not trying (and fialing) to copy it into the bundle + using (var icc = NSData.FromFile (Path.Combine (NSBundle.MainBundle.ResourcePath, "LL-171A-B-B797E457-16AB-C708-1E0F-32C19DBD47B5.icc"))) + using (var cs = CGColorSpace.CreateICCProfile (icc)) { + Assert.That (cs.Components, Is.EqualTo ((nint) 3), "Components"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.RGB), "Model"); + Assert.Null (cs.GetBaseColorSpace (), "GetBaseColorSpace"); + // not indexed so no color table + Assert.That (cs.GetColorTable ().Length, Is.EqualTo (0), "GetColorTable"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + using (var icc_profile = cs.GetICCProfile ()) + Assert.That (icc_profile.Length, Is.EqualTo (3284), "GetICCProfile"); + } + } + } + + void CheckIndexedFile (CGImage img) + { + CGColorSpace cs = img.ColorSpace; + Assert.That (cs.Components, Is.EqualTo ((nint) 1), "Components"); + Assert.That (cs.Model, Is.EqualTo (CGColorSpaceModel.Indexed), "GetBaseColorSpace"); + var table = cs.GetColorTable (); + Assert.That (table.Length, Is.EqualTo (768), "GetColorTable"); + cs.Dispose (); + } + + [Test] + public void Indexed_UIImage () + { + // downloaded from http://www.schaik.com/pngsuite/#palette + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var img = UIImage.FromFile (file)) { + using (var cgimg = img.CGImage) + CheckIndexedFile (cgimg); + } + } + + [Test] + public void Indexed_Provider () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var dp = new CGDataProvider (file)) { + using (var img = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) { + CheckIndexedFile (img); + } + } + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/ColorTest.cs b/tests/monotouch-test/CoreGraphics/ColorTest.cs new file mode 100644 index 000000000000..277601d2acef --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/ColorTest.cs @@ -0,0 +1,91 @@ +// +// Unit tests for CGColor +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using CoreGraphics; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ColorTest { + +#if !XAMCORE_3_0 || MONOMAC + + // those API are not availably (officially) in iOS according to Apple header files + // still they do work which makes them _private_ API that we should not expose + + [Test] + public void GetConstantColor () + { + // !unknown-pinvoke! CGColorGetConstantColor bound + // CGColorGetConstantColor -> CG_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + // constants to be used are not available either (and not bound) + // kCGColorWhite, kCGColorBlack and kCGColorClear + + var lib = Dlfcn.dlopen (Constants.CoreGraphicsLibrary, 0); + var clear = Dlfcn.GetStringConstant (lib, "kCGColorClear"); // constant also marked as __IPHONE_NA + using (var c = new CGColor (clear)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "CGColorGetConstantColor"); + } + } + + [Test] + public void CreateGenericGray () + { + // !unknown-pinvoke! CGColorCreateGenericGray bound + // CGColorCreateGenericGray -> CG_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + using (var c = new CGColor (0.5f, 0.5f)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "CGColorCreateGenericGray"); + } + } + + [Test] + public void CreateGenericRGB () + { + // !unknown-pinvoke! CGColorCreateGenericRGB bound + // CGColorCreateGenericRGB -> CG_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + using (var c = new CGColor (0.5f, 0.5f, 0.5f, 0.5f)) { + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "CGColorCreateGenericRGB"); + } + } + + [Test] + public void ColorSpace () + { + using (var c = new CGColor (0.5f, 0.5f, 0.5f, 0.5f)) { + using (var spc = c.ColorSpace) + Assert.IsNotNull (spc, "ColorSpace"); + } + } +#endif + } +} + diff --git a/tests/monotouch-test/CoreGraphics/ContextTest.cs b/tests/monotouch-test/CoreGraphics/ContextTest.cs new file mode 100644 index 000000000000..3fbb7d6c9fb6 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/ContextTest.cs @@ -0,0 +1,58 @@ +// +// Unit tests for CGContext +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ContextTest { + + CGContext Create () + { + using (CGColorSpace space = CGColorSpace.CreateDeviceRGB ()) { + return new CGBitmapContext (null, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedLast); + } + } + + [Test] + public void SetLineDash () + { + var lengths = new nfloat [] { 1.0f, 2.0f, 3.0f }; + using (var c = Create ()) { + c.SetLineDash (1.0f, lengths); + c.SetLineDash (2.0f, null); + c.SetLineDash (3.0f, lengths, 2); + c.SetLineDash (4.0f, null, -1); + Assert.Throws (delegate { c.SetLineDash (5.0f, lengths, -1); }, "negative"); + Assert.Throws (delegate { c.SetLineDash (6.0f, lengths, Int32.MaxValue); }, "max"); + } + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/DataConsumerTest.cs b/tests/monotouch-test/CoreGraphics/DataConsumerTest.cs new file mode 100644 index 000000000000..3cede2438363 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/DataConsumerTest.cs @@ -0,0 +1,45 @@ +// +// Unit tests for CGDataConsumer +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DataConsumerTest { + + [DllImport (Constants.CoreGraphicsLibrary)] + extern static /* CGDataConsumerRef */ IntPtr CGDataConsumerCreateWithURL (/* CFURLRef */ IntPtr url); + + [DllImport (Constants.CoreGraphicsLibrary)] + extern static /* CGDataConsumerRef */ IntPtr CGDataConsumerCreateWithCFData (/* CFMutableDataRef */ IntPtr data); + + [Test] + public void Create_Nullable () + { + // the native API accept a nil argument but it returns nil, so we must keep our ArgumentNullException as + // a .NET constructor can't return null (and we don't want invalid managed instances) + Assert.That (CGDataConsumerCreateWithURL (IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGDataConsumerCreateWithURL"); + Assert.That (CGDataConsumerCreateWithCFData (IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGDataConsumerCreateWithCFData"); + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/DataProviderTest.cs b/tests/monotouch-test/CoreGraphics/DataProviderTest.cs new file mode 100644 index 000000000000..292178b08a28 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/DataProviderTest.cs @@ -0,0 +1,79 @@ +// +// Unit tests for CGDataProvider +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DataProviderTest { + + [Test] + public void FromPNG () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var dp = CGDataProvider.FromFile (file)) + using (var img = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) { + Assert.That ((int) img.Height, Is.EqualTo (32), "Height"); + Assert.That ((int) img.Width, Is.EqualTo (32), "Width"); + } + } + + [DllImport (Constants.CoreGraphicsLibrary)] + extern static /* CGDataProviderRef */ IntPtr CGDataProviderCreateWithFilename (/* const char* */ string filename); + + [DllImport (Constants.CoreGraphicsLibrary)] + static extern /* CGDataProviderRef */ IntPtr CGDataProviderCreateWithURL (/* CFURLRef __nullable */ IntPtr url); + + [DllImport (Constants.CoreGraphicsLibrary)] + static extern /* CGDataProviderRef */ IntPtr CGDataProviderCreateWithCFData (/* CFDataRef __nullable */ IntPtr data); + + [DllImport (Constants.CoreGraphicsLibrary)] + extern static IntPtr CGDataProviderCreateWithData (/* void* */ IntPtr info, /* const void* */ IntPtr data, /* size_t */ IntPtr size, /* CGDataProviderReleaseDataCallback */ IntPtr releaseData); + + [Test] + public void Create_Nullable () + { + // the native API accept a nil argument but it returns nil, so we must keep our ArgumentNullException as + // a .NET constructor can't return null (and we don't want invalid managed instances) + Assert.That (CGDataProviderCreateWithFilename (null), Is.EqualTo (IntPtr.Zero), "CGDataProviderCreateWithFilename"); + Assert.That (CGDataProviderCreateWithURL (IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGDataConsumerCreateWithURL"); + Assert.That (CGDataProviderCreateWithCFData (IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGDataProviderCreateWithCFData"); + Assert.That (CGDataProviderCreateWithData (IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGDataProviderCreateWithData"); + } + + [Test] + public void Create_ReleaseCallback () + { + IntPtr memory = Marshal.AllocHGlobal (20); + using (var provider = new CGDataProvider (memory, 20, ((IntPtr mem) => + { + Assert.AreEqual (memory, mem, "mem"); + Marshal.FreeHGlobal (mem); + memory = IntPtr.Zero; + }))) { + } + + Assert.AreEqual (IntPtr.Zero, memory, "mem freed"); + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/FontTest.cs b/tests/monotouch-test/CoreGraphics/FontTest.cs new file mode 100644 index 000000000000..d0107f36d056 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/FontTest.cs @@ -0,0 +1,67 @@ +// +// Unit tests for CGFont +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FontTest { + + [DllImport (Constants.CoreGraphicsLibrary)] + extern static /* CGFontRef */ IntPtr CGFontCreateWithDataProvider (/* CGDataProviderRef __nullable */ IntPtr provider); + + [DllImport (Constants.CoreGraphicsLibrary)] + extern static /* CGFontRef */ IntPtr CGFontCreateWithFontName (/* CFStringRef __nullable */ IntPtr name); + + [Test] + public void Nullable () + { + Assert.That (CGFontCreateWithDataProvider (IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGFontCreateWithDataProvider"); + Assert.That (CGFontCreateWithFontName (IntPtr.Zero), Is.EqualTo (IntPtr.Zero), "CGFontCreateWithFontName"); + } + + [Test] + public void CreateFromProvider () + { + Assert.Null (CGFont.CreateFromProvider (null), "CreateFromProvider"); + } + + [Test] + public void CreateWithFontName () + { + Assert.Null (CGFont.CreateWithFontName (null), "CreateWithFontName"); + } + + [Test] + public void GetGlyphWithGlyphName () + { + using (var f = CGFont.CreateWithFontName ("Courier New")) { + Assert.That (f.Handle, Is.Not.EqualTo (IntPtr.Zero), "CreateWithFontName"); + // note: the API is marked to accept a null CFStringRef but it currently (iOS9 beta 4) crash when provided one + Assert.Throws (() => f.GetGlyphWithGlyphName (null), "GetGlyphWithGlyphName"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/FunctionTest.cs b/tests/monotouch-test/CoreGraphics/FunctionTest.cs new file mode 100644 index 000000000000..12589d5e82d3 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/FunctionTest.cs @@ -0,0 +1,92 @@ +// +// Unit tests for CGFunction +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using UIKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FunctionTest { +#if !__WATCHOS__ // FIXME: It doesn't look like this test needs to use UIKit, so it might be possible to rewrite it to run on WatchOS as well. + [Test] + public void Test () + { + bool tested = false; + using (var vc = new UIViewController ()) { + vc.View = new CustomView () + { + BackgroundColor = UIColor.Green, + Shaded = () => tested = true, + }; + MonoTouchFixtures.AppDelegate.PresentModalViewController (vc, 0.1); + } + + if (!tested) + Assert.Inconclusive ("The Shading callback wasn't called."); + } + + class CustomView : UIView { + public Action Shaded; + public unsafe override void Draw (RectangleF rect) + { + var start = new PointF (rect.Left, rect.Bottom); + var end = new PointF (rect.Left, rect.Top); + + var domain = new nfloat[] {0f, 1f}; + var range = new nfloat[] {0f, 1f, 0f, 1f}; + using (var context = UIGraphics.GetCurrentContext ()) + using (var rgb = CGColorSpace.CreateDeviceGray()) + using (var shadingFunction = new CGFunction(domain, range, Shading)) + using (var shading = CGShading.CreateAxial (rgb, start, end, shadingFunction, true, false)) + { + context.DrawShading (shading); + } + + base.Draw (rect); + } + + public unsafe void Shading (nfloat* data, nfloat* outData) + { + var p = data[0]; + outData[0] = 0.0f; + outData[1] = (1.0f-Slope(p, 2.0f)) * 0.5f; + Shaded (); + } + + public nfloat Slope (nfloat x, nfloat A) + { + var p = Math.Pow(x, A); + return (nfloat)(p/(p + Math.Pow(1.0f-x, A))); + } + } +#endif // !__WATCHOS__ + } +} diff --git a/tests/monotouch-test/CoreGraphics/GeometryTest.cs b/tests/monotouch-test/CoreGraphics/GeometryTest.cs new file mode 100644 index 000000000000..2d217e5fd314 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/GeometryTest.cs @@ -0,0 +1,80 @@ +// +// Unit tests for CGGeometry (and related) +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GeometryTest { + + static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.CoreGraphicsLibrary, 0); + + public static RectangleF GetRect (string symbol) + { + var indirect = Dlfcn.dlsym (Handle, symbol); + if (indirect == IntPtr.Zero) + return RectangleF.Empty; + unsafe { + nfloat *ptr = (nfloat *) indirect; + return new RectangleF (ptr [0], ptr [1], ptr [2], ptr [3]); + } + } + + [Test] + public void Infinite () + { + var r = GetRect ("CGRectInfinite"); + Assert.False (r.IsEmpty, "IsEmpty"); + Assert.False (r.IsNull (), "IsNull"); + Assert.True (r.IsInfinite (), "IsInfinite"); + } + + [Test] + public void Null () + { + var r = GetRect ("CGRectNull"); + Assert.True (r.IsEmpty, "IsEmpty"); + Assert.True (r.IsNull (), "IsNull"); + Assert.False (r.IsInfinite (), "IsInfinite"); + } + + [Test] + public void Zero () + { + var r = GetRect ("CGRectZero"); + Assert.True (r.IsEmpty, "IsEmpty"); + Assert.False (r.IsNull (), "IsNull"); + Assert.False (r.IsInfinite (), "IsInfinite"); + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/GradientTest.cs b/tests/monotouch-test/CoreGraphics/GradientTest.cs new file mode 100644 index 000000000000..7300eb3c9e4a --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/GradientTest.cs @@ -0,0 +1,99 @@ +// +// Unit tests for CGGradient +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012, 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GradientTest { + + static CGColor [] array = { UIColor.Black.CGColor, UIColor.Clear.CGColor, UIColor.Blue.CGColor }; + + [Test] + public void Colorspace_Null () + { + using (var g = new CGGradient (null, array)) { + Assert.That (g.Handle, Is.Not.EqualTo (IntPtr.Zero), "null,CGColor[]"); + } + using (var g = new CGGradient (null, array, new nfloat [3] { 0f, 1f, 0.5f })) { + Assert.That (g.Handle, Is.Not.EqualTo (IntPtr.Zero), "null,CGColor[],float[]"); + } + + using (var g = new CGGradient (null, array, new nfloat [3] { 0f, 1f, 0.5f })) { + Assert.That (g.Handle, Is.Not.EqualTo (IntPtr.Zero), "null,CGColor[],float[]"); + } + } + + static CGColorSpace [] spaces = { + CGColorSpace.CreateDeviceGray (), + CGColorSpace.CreateDeviceRGB (), +#if !XAMCORE_3_0 + CGColorSpace.Null +#endif + }; + + [Test] + public void Colorspaces () + { + foreach (var cs in spaces) { + using (var g = new CGGradient (null, array, new nfloat [3] { 0f, 1f, 0.5f })) { + Assert.That (g.Handle, Is.Not.EqualTo (IntPtr.Zero), cs.ToString ()); + } + } + } + + [DllImport(Constants.CoreGraphicsLibrary)] + extern static /* CGGradientRef */ IntPtr CGGradientCreateWithColorComponents (/* CGColorSpaceRef */ IntPtr colorspace, /* CGFloat[] */ nfloat [] components, /* CGFloat[] */ nfloat [] locations, /* size_t */ nint count); + + [DllImport(Constants.CoreGraphicsLibrary)] + extern static /* CGGradientRef */ IntPtr CGGradientCreateWithColors (/* CGColorSpaceRef */ IntPtr space, /* CFArrayRef */ IntPtr colors, /* CGFloat[] */ nfloat [] locations); + + [Test] + public void Nullable () + { + // either a null CGColorSpace or a null CGFloat* array will return nil, i.e. not a valid instance + using (var cs = CGColorSpace.CreateDeviceGray ()) + Assert.That (CGGradientCreateWithColorComponents (cs.Handle, null, null, 0), Is.EqualTo (IntPtr.Zero), "CGGradientCreateWithColorComponents-1"); + Assert.That (CGGradientCreateWithColorComponents (IntPtr.Zero, new nfloat [3] { 0f, 1f, 0.5f }, null, 0), Is.EqualTo (IntPtr.Zero), "CGGradientCreateWithColorComponents-2"); + + // a null CFArray won't return a valid instance + using (var cs = CGColorSpace.CreateDeviceGray ()) + Assert.That (CGGradientCreateWithColors (cs.Handle, IntPtr.Zero, null), Is.EqualTo (IntPtr.Zero), "CGGradientCreateWithColors-1"); + + // a null CGColorSpace can return a valid instance + using (var a = NSArray.FromNSObjects (array)) + Assert.That (CGGradientCreateWithColors (IntPtr.Zero, a.Handle, null), Is.Not.EqualTo (IntPtr.Zero), "CGGradientCreateWithColors-2"); + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/PDFArrayTest.cs b/tests/monotouch-test/CoreGraphics/PDFArrayTest.cs new file mode 100644 index 000000000000..2840658dba89 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFArrayTest.cs @@ -0,0 +1,74 @@ +// +// Unit tests for CGPDFArray +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFArrayTest { + + [Test] + public void InvalidHandle () + { + var array = new CGPDFArray (IntPtr.Zero); + Assert.That (array.Count, Is.EqualTo ((nint) 0), "Count"); + + CGPDFArray a; + Assert.False (array.GetArray (0, out a), "GetArray"); + Assert.Null (a, "array"); + + bool b; + Assert.False (array.GetBoolean (0, out b), "GetBoolean"); + Assert.False (b, "bool"); + + CGPDFDictionary d; + Assert.False (array.GetDictionary (0, out d), "GetDictionary"); + Assert.Null (d, "dict"); + + nfloat f; + Assert.False (array.GetFloat (0, out f), "GetFloat"); + Assert.That (f, Is.EqualTo ((nfloat) 0f), "float"); + + nint i; + Assert.False (array.GetInt (0, out i), "GetInt"); + Assert.That (i, Is.EqualTo ((nint) 0), "int"); + + string str; + Assert.False (array.GetName (0, out str), "GetName"); + Assert.Null (str, "Name"); + + CGPDFStream stream; + Assert.False (array.GetStream (0, out stream), "GetStream"); + Assert.Null (stream, "Stream"); + + Assert.False (array.GetString (0, out str), "GetString"); + Assert.Null (str, "string"); + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/PDFContentStreamTest.cs b/tests/monotouch-test/CoreGraphics/PDFContentStreamTest.cs new file mode 100644 index 000000000000..36ec31b25055 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFContentStreamTest.cs @@ -0,0 +1,42 @@ +// +// Unit tests for CGPDFContentStream +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFContentStreamTest { + + [Test] + public void FromPage () + { + using (var doc = CGPDFDocument.FromFile ("Tamarin.pdf")) + using (var page = doc.GetPage (1)) + using (var cs = new CGPDFContentStream (page)) { + Assert.That (cs.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + + var streams = cs.GetStreams (); + Assert.That (streams.Length, Is.EqualTo (1), "GetStreams.Length"); + Assert.That (streams [0].Handle, Is.Not.EqualTo (cs.Handle), "GetStreams"); + + Assert.Null (cs.GetResource ("XObject", ""), "GetResource"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/PDFContextTest.cs b/tests/monotouch-test/CoreGraphics/PDFContextTest.cs new file mode 100644 index 000000000000..ea2856cc4815 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFContextTest.cs @@ -0,0 +1,78 @@ +// +// Unit tests for CGContextPDF +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +using System.IO; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFContextTest { + + static string filename; + + static PDFContextTest () + { + filename = Environment.GetFolderPath (Environment.SpecialFolder.CommonDocuments) + "/t.pdf"; + } + + [Test] + public void Context_Url () + { + using (var url = new NSUrl (filename)) + using (var ctx = new CGContextPDF (url)) { + ctx.BeginPage (PDFInfoTest.GetInfo ()); + ctx.SetUrl (url, RectangleF.Empty); + ctx.EndPage (); + } + } + + [Test] + public void Context_Url_Rect () + { + var rect = new RectangleF (10, 10, 100, 100); + using (var url = new NSUrl (filename)) + using (var ctx = new CGContextPDF (url, rect)) { + ctx.BeginPage ((CGPDFPageInfo) null); + ctx.SetDestination ("xamarin", rect); + ctx.EndPage (); + } + } + + [Test] + public void Context_Url_Rect_Info () + { + using (var url = new NSUrl (filename)) + using (var ctx = new CGContextPDF (url, new RectangleF (0, 0, 1000, 1000), PDFInfoTest.GetInfo ())) { + ctx.AddDestination ("monkey", PointF.Empty); + ctx.Close (); + } + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/PDFDocumentTest.cs b/tests/monotouch-test/CoreGraphics/PDFDocumentTest.cs new file mode 100644 index 000000000000..1b96bfe1e089 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFDocumentTest.cs @@ -0,0 +1,73 @@ +// +// Unit tests for CGPDFDocument +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFDocumentTest { + + [Test] + public void DataProvider () + { + using (CGDataProvider dp = new CGDataProvider ("Tamarin.pdf")) + using (CGPDFDocument doc = new CGPDFDocument (dp)) { + CheckTamarin (doc); + } + } + + [Test] + public void FromFile () + { + using (CGPDFDocument doc = CGPDFDocument.FromFile ("Tamarin.pdf")) { + CheckTamarin (doc); + } + } + + [Test] + public void FromUrl () + { + string url = NSBundle.MainBundle.BundleUrl + "/Tamarin.pdf"; + using (CGPDFDocument doc = CGPDFDocument.FromUrl (url)) { + CheckTamarin (doc); + } + } + + void CheckTamarin (CGPDFDocument pdf) + { + Assert.True (pdf.AllowsCopying, "AllowsCopying"); + Assert.True (pdf.AllowsPrinting, "AllowsPrinting"); + Assert.False (pdf.IsEncrypted, "IsEncrypted"); + Assert.True (pdf.IsUnlocked, "IsUnlocked"); + Assert.That (pdf.Pages, Is.EqualTo ((nint) 3), "Pages"); + + Assert.That (pdf.GetInfo ().Count, Is.EqualTo (7), "GetInfo"); + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/PDFInfoTest.cs b/tests/monotouch-test/CoreGraphics/PDFInfoTest.cs new file mode 100644 index 000000000000..1bb9036224fc --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFInfoTest.cs @@ -0,0 +1,64 @@ +// +// Unit tests for CGPDFInfo +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFInfoTest { + + static public CGPDFInfo GetInfo () + { + return new CGPDFInfo () { + AllowsCopying = true, + AllowsPrinting = true, + Author = "My Name", + Creator = "My Creator", + EncryptionKeyLength = 123, + Keywords = new string [] { "K1", "K2" }, + OwnerPassword = "My OwnerPassword", + Subject = "My Subject", + Title = "My Title", + UserPassword = "My UserPassword", + }; + } + + [Test] + public void ToDictionary () + { + // Bug #8879 + var info = GetInfo (); + UIGraphics.BeginPDFContext("file", RectangleF.Empty, info); + } + } +} diff --git a/tests/monotouch-test/CoreGraphics/PDFObjectTest.cs b/tests/monotouch-test/CoreGraphics/PDFObjectTest.cs new file mode 100644 index 000000000000..b23c4c73c217 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFObjectTest.cs @@ -0,0 +1,57 @@ +// +// Unit tests for CGPDFObject +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if !XAMCORE_2_0 +using nfloat=global::System.Single; +using nint=global::System.Int32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFObjectTest { + + [Test] + public void Zero () + { + // CGPDFObject is not a real "object" that you can retain/release - it's more a querying interface + var po = new CGPDFObject (IntPtr.Zero); + Assert.IsTrue (po.IsNull, "IsNull"); + Assert.That (po.Type == CGPDFObjectType.Null); + + CGPDFStream stream; + Assert.False (po.TryGetValue (out stream), "CGPDFStream"); + CGPDFDictionary dict; + Assert.False (po.TryGetValue (out dict), "CGPDFDictionary"); + CGPDFArray array; + Assert.False (po.TryGetValue (out array), "CGPDFArray"); + string s; + Assert.False (po.TryGetValue (out s), "string"); + nfloat f; + Assert.False (po.TryGetValue (out f), "nfloat"); + nint i; + Assert.False (po.TryGetValue (out i), "nint"); + bool b; + Assert.False (po.TryGetValue (out b), "bool"); + + Assert.False (po.TryGetName (out s), "name"); + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/PDFOperatorTableTest.cs b/tests/monotouch-test/CoreGraphics/PDFOperatorTableTest.cs new file mode 100644 index 000000000000..f7bfb46aa510 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFOperatorTableTest.cs @@ -0,0 +1,34 @@ +// +// Unit tests for CGPDFOperatorTable +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFOperatorTableTest { + + [Test] + public void Default () + { + using (var table = new CGPDFOperatorTable ()) { + Assert.That (table.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/PDFScannerTest.cs b/tests/monotouch-test/CoreGraphics/PDFScannerTest.cs new file mode 100644 index 000000000000..39ebe60fb678 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PDFScannerTest.cs @@ -0,0 +1,139 @@ +// +// Unit tests for CGPDFScanner +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PDFScannerTest { + + int bt_count; + int do_checks; + + [MonoPInvokeCallback (typeof (Action))] + static void BT (IntPtr reserved, IntPtr info) + { + // sadly the parameters are always identical and we can't know the operator name + // IOW we can NOT dispatch (internally) to a nice C# looking method + + // We do NOT want people to use the "obvious" new CGPDFScanner(reserved) because that will + // call retain (and this gets called a lot of time) + // So _a_ solution is to provide an helper method to give them what they want + var scanner = CGPDFOperatorTable.GetScannerFromInfo (info); + (scanner.UserInfo as PDFScannerTest).bt_count++; + } + + [MonoPInvokeCallback (typeof (Action))] + static void Do (IntPtr reserved, IntPtr info) + { + // sadly the parameters are always identical and we can't know the operator name + // IOW we can NOT dispatch (internally) to a nice C# looking method + + // We do NOT want people to use the "obvious" new CGPDFScanner(reserved) because that will + // call retain (and this gets called a lot of time) + // So _a_ solution is to provide an helper method to give them what they want + var scanner = CGPDFOperatorTable.GetScannerFromInfo (info); + string name; + if (!scanner.TryPopName (out name)) + return; + + var test = (scanner.UserInfo as PDFScannerTest); + test.do_checks--; + + var cs = scanner.GetContentStream (); + if (cs == null) + return; + test.do_checks--; + + var ro = cs.GetResource ("XObject", name); + if (ro.Type != CGPDFObjectType.Stream) + return; + test.do_checks--; + + CGPDFStream s; + if (!ro.TryGetValue (out s)) + return; + test.do_checks--; + + var dict = s.Dictionary; + if (dict == null) + return; + test.do_checks--; + + string dictname; + if (!dict.GetName ("Subtype", out dictname)) + return; + test.do_checks--; + + if (dictname != "Image") + return; + test.do_checks--; + } + + [Test] + public void Tamarin () + { + using (var table = new CGPDFOperatorTable ()) { + // note: the native API is horrible as we can't share the same callback and dispatch it to the right + // managed method. That force every operator to have one ugly, MonoPInvokeCallback-decorated, per + // operator +#if WE_HAD_A_NICE_API + table.SetCallback ("BT", delegate (CGPDFScanner scanner) { + bt_count++; + }); + + table.SetCallback ("Do", delegate (CGPDFScanner scanner) { + // ... drill down to the image + }); +#else + // BT == new paragraph + table.SetCallback ("BT", BT); + // Do == the image is inside it + table.SetCallback ("Do", Do); +#endif + using (var doc = CGPDFDocument.FromFile ("Tamarin.pdf")) + using (var page = doc.GetPage (1)) + using (var cs = new CGPDFContentStream (page)) + using (var scanner = new CGPDFScanner (cs, table, this)) { + Assert.That (scanner.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + + Assert.That (scanner.GetContentStream ().Handle, Is.EqualTo (cs.Handle), "GetContentStream"); + + bt_count = 0; + do_checks = 7; + Assert.True (scanner.Scan (), "Scan"); + Assert.That (bt_count, Is.EqualTo (45), "new paragraph"); + Assert.That (do_checks, Is.EqualTo (0), "found the image"); + } + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/CoreGraphics/PathTest.cs b/tests/monotouch-test/CoreGraphics/PathTest.cs new file mode 100644 index 000000000000..8bb11a9b91b4 --- /dev/null +++ b/tests/monotouch-test/CoreGraphics/PathTest.cs @@ -0,0 +1,250 @@ +// +// Unit tests for CGPath +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreGraphics { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PathTest { + + [Test] + public void EllipseFromRect () + { + var rect = new RectangleF (0, 0, 15, 15); + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p = CGPath.EllipseFromRect (rect, matrix)) { + Assert.IsNotNull (p, "non-null"); + } + } + + [Test] + public void CopyByDashingPath_18764 () + { + var identity = CGAffineTransform.MakeIdentity (); + using (var path = CGPath.EllipseFromRect (RectangleF.Empty, identity)) { + var lengths = new nfloat[] { 10, 10 }; + var phase = 2; + using (var d1 = path.CopyByDashingPath (lengths)) { + Assert.That (d1.Handle, Is.Not.EqualTo (IntPtr.Zero), "d1"); + } + using (var d2 = path.CopyByDashingPath (lengths, phase)) { + Assert.That (d2.Handle, Is.Not.EqualTo (IntPtr.Zero), "d2"); + } + using (var d3 = path.CopyByDashingPath (identity, lengths)) { + Assert.That (d3.Handle, Is.Not.EqualTo (IntPtr.Zero), "d3"); + } + using (var d4 = path.CopyByDashingPath (identity, lengths, phase)) { + Assert.That (d4.Handle, Is.Not.EqualTo (IntPtr.Zero), "d4"); + } + } + } + + [Test] + public void MoveToPoint () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.MoveToPoint (0, 0); + p2.MoveToPoint (matrix, 0, 0); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddLineToPoint () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.MoveToPoint (0, 0); + p1.AddLineToPoint (1, 1); + p2.MoveToPoint (matrix, 0, 0); + p2.AddLineToPoint (matrix, 1, 1); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddCurveToPoint () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.MoveToPoint (0, 0); + p1.AddCurveToPoint (1, 2, 3, 4, 5, 6); + p2.MoveToPoint (0, 0); + p2.AddCurveToPoint (matrix, 1, 2, 3, 4, 5, 6); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddQuadCurveToPoint () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.MoveToPoint (0, 0); + p1.AddQuadCurveToPoint (1, 2, 3, 4); + p1.CloseSubpath (); + p2.MoveToPoint (0, 0); + p2.AddQuadCurveToPoint (matrix, 1, 2, 3, 4); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.Not.EqualTo (p2), "CGPathEqualToPath-2"); + p2.CloseSubpath (); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddRect () + { + var rect = new RectangleF (0, 0, 15, 15); + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.AddRect (rect); + p2.AddRect (matrix, rect); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddRects () + { + var rect = new RectangleF (0, 0, 15, 15); + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.AddRects (new [] { rect, rect }, 1); + p2.AddRects (matrix, new [] { rect }, 1); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddLines () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.AddLines (new [] { PointF.Empty }); + p2.AddLines (matrix, new [] { PointF.Empty }); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddEllipseInRect () + { + var rect = new RectangleF (0, 0, 15, 15); + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.AddEllipseInRect (rect); + p2.AddEllipseInRect (matrix, rect); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddArc () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.AddArc (0, 0, 10, 0, 90, true); + p2.AddArc (matrix, 0, 0, 10, 0, 90, true); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddArcToPoint () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.MoveToPoint (0, 0); + p1.AddArcToPoint (0, 0, 10, 0, 90); + p2.MoveToPoint (0, 0); + p2.AddArcToPoint (matrix, 0, 0, 10, 0, 90); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddRelativeArc () + { + var matrix = CGAffineTransform.MakeIdentity (); + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + Assert.IsTrue (p1.IsEmpty, "IsEmpty-1"); + p1.MoveToPoint (0, 0); + p1.AddRelativeArc (0, 0, 10, 0, 90); + p2.MoveToPoint (0, 0); + p2.AddRelativeArc (matrix, 0, 0, 10, 0, 90); + Assert.IsFalse (p1.IsEmpty, "IsEmpty-2"); + Assert.That (p1, Is.EqualTo (p2), "CGPathEqualToPath"); + } + } + + [Test] + public void AddPath () + { + using (CGPath p1 = new CGPath ()) + using (CGPath p2 = new CGPath ()) { + p1.MoveToPoint (0, 0); + p2.AddPath (p1); + Assert.IsFalse (p2.IsEmpty, "IsEmpty"); + } + } + } +} diff --git a/tests/monotouch-test/CoreImage/CIKernelTests.cs b/tests/monotouch-test/CoreImage/CIKernelTests.cs new file mode 100644 index 000000000000..5b4dcb47d1eb --- /dev/null +++ b/tests/monotouch-test/CoreImage/CIKernelTests.cs @@ -0,0 +1,202 @@ +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using CoreImage; +using CoreGraphics; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.CoreImage; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreImage +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class CIKernelTests + { + const string NoOpColorKernel = @"kernel vec4 doNothing ( __sample s) { return s.rgba; }"; + const string NoOpWithParamColorKernel = @"kernel vec4 doNothingWithParam ( __sample s, float d) { return s.rgba; }"; + const string PositionColorKernel = @"kernel vec4 vignette ( __sample s, vec2 centerOffset, float radius ) +{ + vec2 vecFromCenter = destCoord () - centerOffset; + float distance = length ( vecFromCenter ); + float darken = 1.0 - (distance / radius); + return vec4 (s.rgb * darken, s.a); +}"; + const string NoOpWarpKernel = @"kernel vec2 doNothingWarp () { return destCoord (); }"; + + enum CustomerFilterType { NoOpColor, NoOpColorWithParam, ColorPositionKernel, NoOpWarpKernel }; + + class MyCustomFilter : CIFilter + { + public MyCustomFilter (CustomerFilterType type) + { + Type = type; +#if XAMCORE_2_0 + kernel = CIKernel.FromProgramSingle (GetKernelString ()); +#else + kernel = CIKernel.FromProgram (GetKernelString ()); +#endif + } + + public bool IsColorKernel + { + get + { + switch (Type) { + case CustomerFilterType.NoOpColor: + case CustomerFilterType.NoOpColorWithParam: + case CustomerFilterType.ColorPositionKernel: + return true; + case CustomerFilterType.NoOpWarpKernel: + return false; + } + throw new InvalidOperationException(); + } + } + + string GetKernelString () + { + switch (Type) { + case CustomerFilterType.NoOpColor: + return NoOpColorKernel; + case CustomerFilterType.NoOpColorWithParam: + return NoOpWithParamColorKernel; + case CustomerFilterType.ColorPositionKernel: + return PositionColorKernel; + case CustomerFilterType.NoOpWarpKernel: + return NoOpWarpKernel; + } + throw new InvalidOperationException(); + } + + NSObject [] GetParms () + { + switch (Type) { + case CustomerFilterType.NoOpColor: + return new NSObject[] { MyImage }; + case CustomerFilterType.NoOpColorWithParam: + return new NSObject[] { MyImage, new NSNumber(5) }; + case CustomerFilterType.ColorPositionKernel: + RectangleF dod = MyImage.Extent; + double radius = 0.5 * Math.Sqrt (Math.Pow (dod.Width, 2) + Math.Pow (dod.Height, 2)); + CIVector centerOffset = new CIVector ((float)(dod.Size.Width * .5), (float)(dod.Size.Height * .5)); + return new NSObject[] { MyImage, centerOffset, new NSNumber (radius) }; + case CustomerFilterType.NoOpWarpKernel: + return new NSObject[] { }; + } + throw new InvalidOperationException(); + } + + CustomerFilterType Type { get; set; } + public CIImage MyImage { get; set; } + public bool CallbackHit { get; private set; } + + public CIKernel kernel; + + public override CIImage OutputImage { + get { + if (IsColorKernel) { + return kernel.ApplyWithExtent (MyImage.Extent, (index, rect) => { + CallbackHit = true; + return rect; + }, GetParms ()); + } + else { + CIWarpKernel warp = (CIWarpKernel)kernel; + return warp.ApplyWithExtent (MyImage.Extent, (index, rect) => { + CallbackHit = true; + return rect; + }, MyImage, GetParms ()); + } + } + } + } + + [Test] + public void CIKernel_BasicTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Custom filters require iOS8+"); + + Exception ex = null; + var t = new Thread (() => { + // This code will crash if an MKMapView has been created previously on + // the same thread, so just run it on a different thread (MKMapViews can + // only be created on the main thread). This is obviously an Apple bug, + // and a radar has been filed: 19249153. ObjC test case: https://github.com/rolfbjarne/CIKernelMKMapViewCrash + try { + UIImage uiImg = new UIImage ("CoreImage/Xam.png"); + CIImage ciImg = new CIImage (uiImg); + + CIContext context = CIContext.FromOptions (null); + + foreach (CustomerFilterType type in Enum.GetValues(typeof(CustomerFilterType))) { + MyCustomFilter filter = new MyCustomFilter (type); + filter.MyImage = ciImg; + + CIImage outputImage = filter.OutputImage; + + CGImage cgImage = context.CreateCGImage (outputImage, outputImage.Extent); + UIImage finalImg = new UIImage (cgImage); + Assert.IsNotNull (finalImg, "CIKernel_BasicTest should not be null"); + Assert.IsTrue (filter.CallbackHit, "CIKernel_BasicTest callback must be hit"); + if (filter.IsColorKernel) + Assert.IsTrue (filter.kernel is CIColorKernel, "CIKernel_BasicTest we disagree that it is a color kernel"); + else + Assert.IsTrue (filter.kernel is CIWarpKernel, "CIKernel_BasicTest we disagree that it is a warp kernel"); + } + } catch (Exception ex2) { + ex = ex2; + } + }); + t.Start (); + t.Join (); + if (ex != null) + throw ex; + } + + [Test] + public void CIKernel_TestFromPrograms () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Custom filters require iOS8+"); + + CIKernel[] kernels = +#if XAMCORE_2_0 + CIKernel.FromProgramMultiple ( +#else + CIKernel.FromPrograms ( +#endif + NoOpColorKernel + "\n" + NoOpWithParamColorKernel + "\n" + PositionColorKernel + "\n" + NoOpWarpKernel); + Assert.AreEqual (4, kernels.Length, "CIKernel_TestFromPrograms did not get back the right number of programs"); + foreach (CIKernel kernel in kernels) + { + Assert.IsTrue (kernel is CIColorKernel || kernel is CIWarpKernel, "CIKernel_TestFromPrograms is neither type of kernel?"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/CoreContextTest.cs b/tests/monotouch-test/CoreImage/CoreContextTest.cs new file mode 100644 index 000000000000..836b18645806 --- /dev/null +++ b/tests/monotouch-test/CoreImage/CoreContextTest.cs @@ -0,0 +1,102 @@ +// +// Unit tests for CIContext +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; + +#if XAMCORE_2_0 +using Foundation; +using CoreImage; +using CoreGraphics; +using CoreVideo; +using ObjCRuntime; +using OpenGLES; +using UIKit; +#else +using MonoTouch.CoreImage; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreVideo; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.OpenGLES; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CIContextTest { + + [Test] + public void CreateRefCount () + { + // Bug #7117 + + CIImage img = new CIImage (CIColor.FromRgb (0.5f, 0.5f, 0.5f)); + Selector retainCount = new Selector ("retainCount"); + + using (var ctx = CIContext.Create ()) { + using (var v = ctx.CreateCGImage (img, new RectangleF (0, 0, 5, 5))) { + int rc = Messaging.int_objc_msgSend (v.Handle, retainCount.Handle); + Assert.AreEqual (1, rc, "CreateCGImage #a1"); + } + + using (var v = ctx.CreateCGImage (img, new RectangleF (0, 0, 32, 32), CIImage.FormatARGB8, null)) { + int rc = Messaging.int_objc_msgSend (v.Handle, retainCount.Handle); + Assert.AreEqual (1, rc, "CreateCGImage #b1"); + } + + using (var v = ctx.CreateCGImage (img, new RectangleF (0, 0, 5, 5), CIFormat.ARGB8, null)) { + int rc = Messaging.int_objc_msgSend (v.Handle, retainCount.Handle); + Assert.AreEqual (1, rc, "CreateCGImage #c1"); + } + } + } + + [Test] + public void FromContext_13983 () + { + using (var ctx = new EAGLContext (EAGLRenderingAPI.OpenGLES2)) + using (var ci = CIContext.FromContext (ctx)) { + Assert.NotNull (ci); + if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.That (ci.WorkingColorSpace.Model, Is.EqualTo (CGColorSpaceModel.RGB), "WorkingColorSpace"); + } + } + + [Test] + public void Render_Colorspace () + { + using (var ctx = new EAGLContext (EAGLRenderingAPI.OpenGLES2)) + using (var ci = CIContext.FromContext (ctx)) + using (var cv = new CVPixelBuffer (1, 1, CVPixelFormatType.CV24RGB)) + using (CIImage img = new CIImage (CIColor.FromRgb (0.5f, 0.5f, 0.5f))) { + // that one "null allowed" was undocumented + ci.Render (img, cv, RectangleF.Empty, null); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/CoreVectorTest.cs b/tests/monotouch-test/CoreImage/CoreVectorTest.cs new file mode 100644 index 000000000000..e1540dffb16a --- /dev/null +++ b/tests/monotouch-test/CoreImage/CoreVectorTest.cs @@ -0,0 +1,65 @@ +// +// Unit tests for CIVector +// +// Authors: +// Miguel de Icaza +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using CoreImage; +#else +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CIVectorTest { + + [Test] + public void Constructors () + { + // Make sure these do not crash + Assert.That (new CIVector (new nfloat [0]).Count, Is.EqualTo ((nint) 0)); + Assert.That (new CIVector (new nfloat [] {1}).Count, Is.EqualTo ((nint) 1)); + Assert.That (new CIVector (new nfloat [] {1,2}).Count, Is.EqualTo ((nint) 2)); + Assert.That (new CIVector (new nfloat [] {1,2,3}).Count, Is.EqualTo ((nint) 3)); + Assert.That (new CIVector (new nfloat [] {1,2,3,4}).Count, Is.EqualTo ((nint) 4)); + Assert.That (new CIVector (1).Count, Is.EqualTo ((nint) 1)); + Assert.That (new CIVector (1,2).Count, Is.EqualTo ((nint) 2)); + Assert.That (new CIVector (1,2,3).Count, Is.EqualTo ((nint) 3)); + Assert.That (new CIVector (1,2,3,4).Count, Is.EqualTo ((nint) 4)); + } + + [Test] + public void FromValues () + { + Assert.Throws (() => CIVector.FromValues (null), "null"); + using (var v = CIVector.FromValues (new nfloat [0])) { + Assert.That (v.Count, Is.EqualTo (0), "Count/empty"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/DetectorTest.cs b/tests/monotouch-test/CoreImage/DetectorTest.cs new file mode 100644 index 000000000000..3d718c02e119 --- /dev/null +++ b/tests/monotouch-test/CoreImage/DetectorTest.cs @@ -0,0 +1,64 @@ +// +// Unit tests for CIDetector +// +// Authors: +// Rolf Bjarne Kvinge (rolf@xamarin.com) +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; + +#if XAMCORE_2_0 +using Foundation; +using CoreImage; +using CoreGraphics; +using UIKit; +#else +using MonoTouch.CoreImage; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DetectorTest { + + [Test] + public void NullContext () + { + using (var dtor = CIDetector.CreateFaceDetector (null, true)) { + } + + using (var dtor = CIDetector.CreateFaceDetector (null, false)) { + } + + if (TestRuntime.CheckSystemAndSDKVersion (6, 0)) { + using (var dtor = CIDetector.CreateFaceDetector (null, false, 2.0f)) { + } + } + + using (var dtor = CIDetector.CreateFaceDetector (null, null, null, null)) { + } + } + + [Test] + public void EmptyOptions () + { + CIDetectorOptions options = new CIDetectorOptions (); + using (var dtor = CIDetector.CreateFaceDetector (null, options)) { + Assert.That (dtor.Description, Is.StringContaining ("CIFaceCoreDetector"), "Description"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/FilterTest.cs b/tests/monotouch-test/CoreImage/FilterTest.cs new file mode 100644 index 000000000000..84d305d6fe55 --- /dev/null +++ b/tests/monotouch-test/CoreImage/FilterTest.cs @@ -0,0 +1,115 @@ +// +// Unit tests for CIFilter +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using CoreGraphics; +using CoreImage; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FilterTest { + + [Test] + public void HighlightShadowAdjust () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var url = NSUrl.FromFilename (file)) + using (var input = CIImage.FromUrl (url)) + using (var filter = new CIHighlightShadowAdjust ()) { + filter.Image = input; + filter.HighlightAmount = 0.75f; + filter.ShadowAmount = 1.5f; + // https://bugzilla.xamarin.com/show_bug.cgi?id=15465 + Assert.NotNull (filter.OutputImage, "OutputImage"); + } + } + + class MyFilter : CIFilter + { + public int Input { get; set; } + } + + [Test] + public void CustomFilterTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Custom filters require iOS8+"); + + MyFilter filter = new MyFilter (); + Assert.NotNull (filter); + filter.Input = 10; + Assert.AreEqual(10, filter.Input); + } + + [Test] + public void UnsupportedInputImage () + { + // some filters do not support inputImage (which we bound to the Image property) + using (var filter = new CICheckerboardGenerator ()) { + // but if we call ObjC then we get a native exception and crash on devices + Assert.False (filter.RespondsToSelector (new Selector ("inputImage")), "inputImage"); + // so we return null in those cases + Assert.Null (filter.Image, "Image"); + } + } + + [DllImport (Constants.CoreFoundationLibrary)] + extern static nint CFGetRetainCount (IntPtr handle); + + [Test] + public void ColorSpace () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Ignoring ColorSpace test: CIColorCubeWithColorSpace requires iOS7+"); + + using (var f = new CIColorCubeWithColorSpace ()) { + Assert.Null (f.ColorSpace, "ColorSpace/default"); + using (var cs = CGColorSpace.CreateDeviceGray ()) { + f.ColorSpace = cs; + var rc = CFGetRetainCount (cs.Handle); + for (int i = 0; i < 5; i++) + Assert.NotNull (f.ColorSpace, i.ToString ()); + Assert.That (CFGetRetainCount (cs.Handle), Is.EqualTo (rc), "RetainCount"); + f.ColorSpace = null; + } + Assert.Null (f.ColorSpace, "ColorSpace/reset-null"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/ImageInitializationOptionsTest.cs b/tests/monotouch-test/CoreImage/ImageInitializationOptionsTest.cs new file mode 100644 index 000000000000..71658725abdf --- /dev/null +++ b/tests/monotouch-test/CoreImage/ImageInitializationOptionsTest.cs @@ -0,0 +1,74 @@ +// +// Unit tests for CIImageInitializationOptions +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreGraphics; +using CoreImage; +using Foundation; +using UIKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageInitializationOptionsTest { + + [Test] + public void Defaults () + { + var options = new CIImageInitializationOptions (); + Assert.That (options.Dictionary.Count, Is.EqualTo (0), "Count"); + Assert.Null (options.ColorSpace, "ColorSpace"); + } + + [Test] + public void ColorSpace () + { + var options = new CIImageInitializationOptions () { + ColorSpace = CGColorSpace.CreateDeviceRGB () + }; + Assert.That (options.Dictionary.Count, Is.EqualTo (1), "Count"); + Assert.NotNull (options.ColorSpace, "ColorSpace"); + } + + [Test] + public void WithMetadataDefaults () + { + var options = new CIImageInitializationOptionsWithMetadata (); + Assert.That (options.Dictionary.Count, Is.EqualTo (0), "Count"); + Assert.Null (options.Properties, "Properties"); + } + + [Test] + public void WithMetadataProperties () + { + var suboptions = new CGImageProperties () { + ProfileName = "Xamarin" + }; + var options = new CIImageInitializationOptionsWithMetadata () { + Properties = suboptions + }; + Assert.That (options.Dictionary.Count, Is.EqualTo (1), "Count"); + Assert.That (options.Properties.ProfileName, Is.EqualTo ("Xamarin"), "Properties"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/ImageTest.cs b/tests/monotouch-test/CoreImage/ImageTest.cs new file mode 100644 index 000000000000..67c58279d77d --- /dev/null +++ b/tests/monotouch-test/CoreImage/ImageTest.cs @@ -0,0 +1,99 @@ +// +// Unit tests for CIImage +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreImage; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch.CoreImage; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageTest { + + [Test] + public void EmptyImage () + { + Assert.IsNull (CIImage.EmptyImage.Properties); + } + + [Test] + public void InitializationWithCustomMetadata () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var dp = new CGDataProvider (file)) { + using (var img = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) { + + var opt = new CIImageInitializationOptionsWithMetadata () { + Properties = new CGImageProperties () { + ProfileName = "test profile name" + } + }; + + using (var ci = new CIImage (img, opt)) { + Assert.AreEqual ("test profile name", ci.Properties.ProfileName); + } + } + } + } + + [Test] + public void UIImageInterop () + { + // to validate http://stackoverflow.com/q/14464154/220643 + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var url = NSUrl.FromFilename (file)) + using (var ci = CIImage.FromUrl (url)) + using (var ui = new UIImage (ci, 1.0f, UIImageOrientation.Up)) { + Assert.IsNotNull (ui.CIImage, "CIImage"); + } + } + + [Test] + public void AreaHistogram () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("requires iOS8+"); + + // validate that a null NSDictionary is correct (i.e. uses filter defaults) + using (var h = CIImage.EmptyImage.CreateByFiltering ("CIAreaHistogram", null)) { + // broken on simulator/64 bits on iOS9 beta 2 - radar 21564256 -> fixed in beta 4 + Assert.That (h.Extent.Height, Is.EqualTo ((nfloat) 1), "Height"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreImage/Xam.png b/tests/monotouch-test/CoreImage/Xam.png new file mode 100644 index 000000000000..a88ad5857fec Binary files /dev/null and b/tests/monotouch-test/CoreImage/Xam.png differ diff --git a/tests/monotouch-test/CoreLocation/BeaconRegionTest.cs b/tests/monotouch-test/CoreLocation/BeaconRegionTest.cs new file mode 100644 index 000000000000..fa49bfbb9f20 --- /dev/null +++ b/tests/monotouch-test/CoreLocation/BeaconRegionTest.cs @@ -0,0 +1,92 @@ +// +// Unit tests for CLBeaconRegion +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreLocation; +using ObjCRuntime; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreLocation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BeaconRegionTest { + + [Test] + public void Ctor2 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var uuid = new NSUuid ("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")) + using (var br = new CLBeaconRegion (uuid, "identifier")) { + Assert.Null (br.Major, "Major"); + Assert.Null (br.Minor, "Minor"); + Assert.False (br.NotifyEntryStateOnDisplay, "NotifyEntryStateOnDisplay"); + Assert.AreSame (uuid, br.ProximityUuid, "ProximityUuid"); + // CLRegion + Assert.That (br.Identifier, Is.EqualTo ("identifier"), "identifier"); + Assert.True (br.NotifyOnEntry, "NotifyOnEntry"); + Assert.True (br.NotifyOnExit, "NotifyOnExit"); + Assert.False (br.NotifyEntryStateOnDisplay, "NotifyEntryStateOnDisplay"); + } + } + + [Test] + public void Ctor3 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var uuid = new NSUuid ("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")) + using (var br = new CLBeaconRegion (uuid, 0, "identifier")) { + Assert.That (br.Major.Int32Value, Is.EqualTo (0), "Major"); + Assert.Null (br.Minor, "Minor"); + Assert.False (br.NotifyEntryStateOnDisplay, "NotifyEntryStateOnDisplay"); + Assert.AreSame (uuid, br.ProximityUuid, "ProximityUuid"); + // CLRegion + Assert.That (br.Identifier, Is.EqualTo ("identifier"), "identifier"); + Assert.True (br.NotifyOnEntry, "NotifyOnEntry"); + Assert.True (br.NotifyOnExit, "NotifyOnExit"); + } + } + + [Test] + public void Ctor4 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var uuid = new NSUuid ("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")) + using (var br = new CLBeaconRegion (uuid, 2, 3, "identifier")) { + Assert.That (br.Major.Int32Value, Is.EqualTo (2), "Major"); + Assert.That (br.Minor.Int32Value, Is.EqualTo (3), "Minor"); + Assert.False (br.NotifyEntryStateOnDisplay, "NotifyEntryStateOnDisplay"); + Assert.AreSame (uuid, br.ProximityUuid, "ProximityUuid"); + // CLRegion + Assert.That (br.Identifier, Is.EqualTo ("identifier"), "identifier"); + Assert.True (br.NotifyOnEntry, "NotifyOnEntry"); + Assert.True (br.NotifyOnExit, "NotifyOnExit"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/CoreLocation/LocationTest.cs b/tests/monotouch-test/CoreLocation/LocationTest.cs new file mode 100644 index 000000000000..ee8ce79bd147 --- /dev/null +++ b/tests/monotouch-test/CoreLocation/LocationTest.cs @@ -0,0 +1,51 @@ +// +// Unit tests for CLLocation +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreLocation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreLocation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LocationTest { + + [Test] + public void Fields () + { + // documented as new in iOS 5.0 - https://developer.apple.com/library/ios/DOCUMENTATION/CoreLocation/Reference/CoreLocationConstantsRef/CoreLocationConstantsRef.pdf + // in PDF only, not in the HTML documentation - but it's also inside CLError.h + // this test will fail if Apple decide to include them in the future + IntPtr lib = Dlfcn.dlopen (Constants.CoreLocationLibrary, 0); + try { + string field = "kCLErrorUserInfoAlternateRegionKey"; + var p = Dlfcn.dlsym (lib, field); + if (TestRuntime.CheckiOSSystemVersion (7,1)) + Assert.That (p, Is.Not.EqualTo (IntPtr.Zero), field); + else + Assert.That (p, Is.EqualTo (IntPtr.Zero), field); + } + finally { + Dlfcn.dlclose (lib); + } + } + } +} diff --git a/tests/monotouch-test/CoreMedia/BlockBufferTest.cs b/tests/monotouch-test/CoreMedia/BlockBufferTest.cs new file mode 100644 index 000000000000..183c65edb576 --- /dev/null +++ b/tests/monotouch-test/CoreMedia/BlockBufferTest.cs @@ -0,0 +1,348 @@ +// +// Unit tests for CMBlockBuffer +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using CoreMedia; +using UIKit; +#else +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BlockBufferTest { + + [Test] + public void CreateEmpty () + { + CMBlockBufferError err; + using (var bb = CMBlockBuffer.CreateEmpty (16, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), "error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 0), "DataLength"); + } + } + +#if XAMCORE_2_0 + [Test] + public void CMBlockBufferCustomBlockSource () + { + var type = Type.GetType ("CoreMedia.CMCustomBlockAllocator/CMBlockBufferCustomBlockSource, " + typeof (NSObject).Assembly.GetName ().Name); + Assert.NotNull (type, "CMBlockBufferCustomBlockSource"); + // it's 28 (not 32) bytes when executed on 64bits iOS, which implies it's packed to 4 bytes + Assert.That (Marshal.SizeOf (type), Is.EqualTo (4 + 3 * IntPtr.Size), "Size"); + } +#endif + + [Test] + public void AppendMemoryBlockTest() + { + CMBlockBufferError err1; + CMBlockBufferError err2; + using (var bb = CMBlockBuffer.FromMemoryBlock (IntPtr.Zero, 16, null, 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err1)) { + Assert.That (err1, Is.EqualTo (CMBlockBufferError.None), "FromMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 5), "FromMemoryBlock DataLength"); + + var ptr = Marshal.AllocHGlobal (16); + err2 = bb.AppendMemoryBlock (ptr, 16, null, 0, 5, CMBlockBufferFlags.AssureMemoryNow); + Assert.That (err2, Is.EqualTo (CMBlockBufferError.None), "AppendMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 10), "AppendMemoryBlock DataLength"); + } + + using (var bb = CMBlockBuffer.FromMemoryBlock (IntPtr.Zero, 16, new CMCustomBlockAllocator (), 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err1)) { + Assert.That (err1, Is.EqualTo (CMBlockBufferError.None), "FromMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 5), "FromMemoryBlock DataLength"); + + var ptr = Marshal.AllocHGlobal (16); + err2 = bb.AppendMemoryBlock (ptr, 16, new CMCustomBlockAllocator (), 0, 5, CMBlockBufferFlags.AssureMemoryNow); + Assert.That (err2, Is.EqualTo (CMBlockBufferError.None), "AppendMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 10), "AppendMemoryBlock DataLength"); + } + + allocateCalled = false; + freeCalled = false; + using (var allocator = new CustomAllocator (this)) + using (var bb = CMBlockBuffer.FromMemoryBlock (IntPtr.Zero, 16, new CMCustomBlockAllocator (), 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err1)) { + Assert.That (err1, Is.EqualTo (CMBlockBufferError.None), "FromMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 5), "FromMemoryBlock DataLength"); + + var ptr = Marshal.AllocHGlobal (16); + err2 = bb.AppendMemoryBlock (ptr, 16, allocator, 0, 5, CMBlockBufferFlags.AssureMemoryNow); + Assert.That (err2, Is.EqualTo (CMBlockBufferError.None), "AppendMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 10), "FromMemoryBlock DataLength"); + } + Assert.IsTrue (freeCalled, "FromMemoryBlock FreeCalled"); + } + + public bool allocateCalled; + public bool freeCalled; + + [Test] + public void FromMemoryBlockAndContiguousTest () + { + CMBlockBufferError err1; + CMBlockBufferError err2; + using (var bb = CMBlockBuffer.FromMemoryBlock (IntPtr.Zero, 16, null, 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err1)) + using (var bc = CMBlockBuffer.CreateContiguous (bb, null, 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err2)) { + Assert.That (err1, Is.EqualTo (CMBlockBufferError.None), "FromMemoryBlock error"); + Assert.That (err2, Is.EqualTo (CMBlockBufferError.None), "CreateContiguous error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 5), "FromMemoryBlock DataLength"); + Assert.That (bc.DataLength, Is.EqualTo ((nuint) 5), "CreateContiguous DataLength"); + } + + using (var allocator = new CMCustomBlockAllocator ()) + using (var bb = CMBlockBuffer.FromMemoryBlock (IntPtr.Zero, 16, allocator, 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err1)) + using (var bc = CMBlockBuffer.CreateContiguous (bb, allocator, 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err2)) { + Assert.That (err1, Is.EqualTo (CMBlockBufferError.None), "FromMemoryBlock error"); + Assert.That (err2, Is.EqualTo (CMBlockBufferError.None), "CreateContiguous error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 5), "FromMemoryBlock DataLength"); + Assert.That (bc.DataLength, Is.EqualTo ((nuint) 5), "CreateContiguous DataLength"); + } + + using (var allocator = new CustomAllocator (this)) + using (var bb = CMBlockBuffer.FromMemoryBlock (IntPtr.Zero, 16, allocator, 0, 5, CMBlockBufferFlags.AssureMemoryNow, out err1)) { + Assert.That (err1, Is.EqualTo (CMBlockBufferError.None), "FromMemoryBlock error"); + Assert.That (bb.DataLength, Is.EqualTo ((nuint) 5), "FromMemoryBlock DataLength"); + Assert.IsTrue (allocateCalled, "FromMemoryBlock AllocateCalled"); + } + Assert.IsTrue (freeCalled, "FromMemoryBlock FreeCalled"); + } + + class CustomAllocator : CMCustomBlockAllocator + { + BlockBufferTest test; + + public CustomAllocator (BlockBufferTest bufferTest) + { + test = bufferTest; + } + + public override IntPtr Allocate (nuint sizeInBytes) + { + test.allocateCalled = true; + return base.Allocate (sizeInBytes); + } + + public override void Free (IntPtr doomedMemoryBlock, nuint sizeInBytes) + { + test.freeCalled = true; + base.Free (doomedMemoryBlock, sizeInBytes); + } + } + + [Test] + public void FromMemoryBlockWithManagedMemory () + { + byte [] data = new byte [32768]; + GCHandle pinned = GCHandle.Alloc (data, GCHandleType.Pinned); + IntPtr pointer = pinned.AddrOfPinnedObject (); + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (pointer, (uint)data.Length, null, 0, (uint)data.Length, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), "CMBlockBufferError"); + // dispose called before unpinning (ok) + } + pinned.Free (); + } + + [Test] + public void FromMemoryBlockWithByteArrayTest () + { + byte [] data = new byte [32768]; + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (data, 0, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), "CMBlockBufferError"); + // dispose called before unpinning (ok) + } + } + + [Test] + public void AppendMemoryBlockWithManagedMemory () + { + byte [] data = new byte [32768]; + byte [] data2 = new byte [32768]; + GCHandle pinned = GCHandle.Alloc (data, GCHandleType.Pinned); + GCHandle pinned2 = GCHandle.Alloc (data2, GCHandleType.Pinned); + IntPtr pointer = pinned.AddrOfPinnedObject (); + IntPtr pointer2 = pinned2.AddrOfPinnedObject (); + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (pointer, (uint) data.Length, null, 0, (uint) data.Length, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + + err = buf.AppendMemoryBlock (pointer2, (uint) data2.Length, null, 0, (uint) data2.Length, CMBlockBufferFlags.AssureMemoryNow); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + } + pinned2.Free (); + pinned.Free (); + } + + [Test] + public void AppendMemoryBlockWithByteArrayTest () + { + byte [] data = new byte [32768]; + byte [] data2 = new byte [32768]; + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (data, 0, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + + err = buf.AppendMemoryBlock (data2, 0, CMBlockBufferFlags.AssureMemoryNow); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + } + } + + [Test] + public void CopyDataBytesTest () + { + byte [] data = new byte []{ 0x0, 0x1, 0x2, 0x3, 0x4 }; + byte [] destData = new byte [data.Length]; + GCHandle pinned = GCHandle.Alloc (data, GCHandleType.Pinned); + GCHandle destPinned = GCHandle.Alloc (destData, GCHandleType.Pinned); + IntPtr pointer = pinned.AddrOfPinnedObject (); + IntPtr destPointer = destPinned.AddrOfPinnedObject (); + + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (pointer, (uint) data.Length, null, 0, (uint) data.Length, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + + err = buf.CopyDataBytes (0, (uint) data.Length, destPointer); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + for (int i = 0; i < data.Length; i++) + Assert.AreEqual (data [0], destData [0], $"CMBlockBuffer CopyDataBytesTest iteration: {i}"); + } + pinned.Free (); + destPinned.Free (); + } + + [Test] + public void CopyDataBytesUsingManagedArrayTest () + { + byte [] data = new byte [] { 0x0, 0x1, 0x2, 0x3, 0x4 }; + byte [] destData; + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (data, 0, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + + err = buf.CopyDataBytes (0, (uint) data.Length, out destData); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + for (int i = 0; i < data.Length; i++) + Assert.AreEqual (data [0], destData [0], $"CMBlockBuffer CopyDataBytesUsingManagedArrayTest iteration: {i}"); + } + } + + [Test] + public void ReplaceDataBytesTest () + { + byte [] data = new byte [] { 0x0, 0x1, 0x2, 0x3, 0x4 }; + byte [] replaceData = new byte [] { 0x5, 0x5, 0x5, 0x5, 0x5 }; + GCHandle pinned = GCHandle.Alloc (data, GCHandleType.Pinned); + GCHandle replacePinned = GCHandle.Alloc (replaceData, GCHandleType.Pinned); + IntPtr pointer = pinned.AddrOfPinnedObject (); + IntPtr replacePointer = replacePinned.AddrOfPinnedObject (); + + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (pointer, (uint) data.Length, null, 0, (uint) data.Length, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + + err = buf.ReplaceDataBytes (replacePointer, 0, (uint) replaceData.Length); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + for (int i = 0; i < data.Length; i++) + Assert.AreEqual (0x5, data [0], $"CMBlockBuffer ReplaceDataBytesTest iteration: {i}"); + } + pinned.Free (); + replacePinned.Free (); + } + + [Test] + public void ReplaceDataBytesManagedTest () + { + byte [] data = new byte [] { 0x0, 0x1, 0x2, 0x3, 0x4 }; + byte [] replaceData = new byte [] { 0x5, 0x5, 0x5, 0x5, 0x5 }; + + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (data, 0, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + + err = buf.ReplaceDataBytes (replaceData, 0); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + for (int i = 0; i < data.Length; i++) + Assert.AreEqual (0x5, data [0], $"CMBlockBuffer ReplaceDataBytesManagedTest iteration: {i}"); + } + } + + [Test] + public void AccessDataBytesTest () + { + byte [] data = new byte [] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9 }; + byte [] tempBuffer = new byte [5]; + GCHandle pinned = GCHandle.Alloc (data, GCHandleType.Pinned); + GCHandle tempBufferPinned = GCHandle.Alloc (tempBuffer, GCHandleType.Pinned); + IntPtr pointer = pinned.AddrOfPinnedObject (); + IntPtr tempBufferPtr = pinned.AddrOfPinnedObject (); + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (pointer, (uint) data.Length, null, 0, (uint) data.Length, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + IntPtr outPtr = IntPtr.Zero; + + err = buf.AccessDataBytes (5, 5, tempBufferPtr, ref outPtr); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + Marshal.Copy (outPtr, tempBuffer, 0, 5); + + for (int i = 0; i < tempBuffer.Length; i++) + Assert.AreEqual ((byte)(i + 5), tempBuffer [i], $"CMBlockBuffer AccessDataBytesTest iteration: {i}"); + } + pinned.Free (); + tempBufferPinned.Free (); + } + + [Test] + public void GetDataPointerTest () + { + byte [] data = new byte [] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9 }; + byte [] tempBuffer = new byte [5]; + GCHandle pinned = GCHandle.Alloc (data, GCHandleType.Pinned); + IntPtr pointer = pinned.AddrOfPinnedObject (); + CMBlockBufferError err; + using (var buf = CMBlockBuffer.FromMemoryBlock (pointer, (uint) data.Length, null, 0, (uint) data.Length, CMBlockBufferFlags.AssureMemoryNow, out err)) { + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 1: {err}"); + IntPtr outPtr = IntPtr.Zero; + nuint lengthAtOffset; + nuint totalLength; + + err = buf.GetDataPointer (5, out lengthAtOffset, out totalLength, ref outPtr); + Assert.That (err, Is.EqualTo (CMBlockBufferError.None), $"CMBlockBufferError 2: {err}"); + Marshal.Copy (outPtr, tempBuffer, 0, (int)lengthAtOffset); + + for (int i = 0; i < tempBuffer.Length; i++) + Assert.AreEqual ((byte) (i + 5), tempBuffer [i], $"CMBlockBuffer GetDataPointerTest iteration: {i}"); + } + pinned.Free (); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/CMClockTest.cs b/tests/monotouch-test/CoreMedia/CMClockTest.cs new file mode 100644 index 000000000000..14c68a9c592f --- /dev/null +++ b/tests/monotouch-test/CoreMedia/CMClockTest.cs @@ -0,0 +1,67 @@ +// +// Unit tests for CMClock +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using CoreMedia; +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.CoreMedia; +using MonoTouch.UIKit; +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CMClockTest { + + [DllImport (Constants.CoreFoundationLibrary)] + extern static nint CFGetRetainCount (IntPtr handle); + + [Test] + public void CreateAudioClock () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMClock is new in 6.0"); + + CMClockError ce; + using (var clock = CMClock.CreateAudioClock (out ce)) + { + Assert.AreEqual (CMClockError.None, ce); + } + } + + [Test] + public void HostTimeClock () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMClock is new in 6.0"); + + using (var clock = CMClock.HostTimeClock) { + Assert.That (clock.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (clock.Handle), Is.GreaterThanOrEqualTo ((nint) 1), "RetainCount"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/CMFormatDescriptionTest.cs b/tests/monotouch-test/CoreMedia/CMFormatDescriptionTest.cs new file mode 100644 index 000000000000..b3b8723920b4 --- /dev/null +++ b/tests/monotouch-test/CoreMedia/CMFormatDescriptionTest.cs @@ -0,0 +1,163 @@ +// +// Unit tests for CMFormatDescription +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012-2014 Xamarin Inc All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +#if XAMCORE_2_0 +using Foundation; +using CoreMedia; +using AVFoundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreMedia; +using MonoTouch.AVFoundation; +using MonoTouch.UIKit; +using nuint = global::System.UInt32; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CMFormatDescriptionTest + { + [Test] + public void ClosedCaption () + { + CMFormatDescriptionError fde; + using (var fd = CMFormatDescription.Create (CMMediaType.ClosedCaption, (uint) CMClosedCaptionFormatType.CEA608, out fde)) + { + Assert.AreEqual (CMFormatDescriptionError.None, fde, "#1"); + Assert.AreEqual ((CMMuxedStreamType) 0, fd.MuxedStreamType, "#2"); + Assert.AreEqual (CMMediaType.ClosedCaption, fd.MediaType, "#3"); + Assert.AreEqual (CMClosedCaptionFormatType.CEA608, fd.ClosedCaptionFormatType, "#4"); + } + } + + +#if !__TVOS__ + [Test] + public void Video () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("This test fails on iOS 6 (even though the API exists)."); + + CMFormatDescriptionError fde; + + var auth = AVCaptureDevice.GetAuthorizationStatus (AVMediaType.Video); + switch (auth) { + case AVAuthorizationStatus.Restricted: + case AVAuthorizationStatus.Denied: + case AVAuthorizationStatus.NotDetermined: + // We can't test the below, since the some other tests may have initialized whatever we need for the API to work correctly. +// Assert.Null (CMFormatDescription.Create (CMMediaType.Video, (uint) CMVideoCodecType.H264, out fde), "null ({0})", auth); +// Assert.That (fde, Is.EqualTo (CMFormatDescriptionError.InvalidParameter), "CMFormatDescriptionError"); + break; + case AVAuthorizationStatus.Authorized: + // We can't test the below, since the some other tests may have initialized whatever we need for the API to work correctly. +// Assert.Null (CMFormatDescription.Create (CMMediaType.Video, (uint) CMVideoCodecType.H264, out fde), "null (authorized)"); +// Assert.That (fde, Is.EqualTo (CMFormatDescriptionError.InvalidParameter), "CMFormatDescriptionError (authorized)"); + + using (var captureSession = new AVCaptureSession ()) { + using (var videoDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video)) { + NSError error; + using (var videoInput = new AVCaptureDeviceInput (videoDevice, out error)) { + // this seems to initialize something. + } + } + } + + Assert.IsNotNull (CMFormatDescription.Create (CMMediaType.Video, (uint) CMVideoCodecType.H264, out fde), "not null (authorized)"); + Assert.That (fde, Is.EqualTo (CMFormatDescriptionError.None), "CMFormatDescriptionError #2 (authorized)"); + break; + } + } + + [Test] + public void RefcountTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("This test uses iOS 7 API"); + + // Bug #27205 + + var auth = AVCaptureDevice.GetAuthorizationStatus (AVMediaType.Video); + switch (auth) { + case AVAuthorizationStatus.Restricted: + case AVAuthorizationStatus.Denied: + case AVAuthorizationStatus.NotDetermined: + Assert.Inconclusive ("This test requires video recording permissions."); + return; + } + + using (var captureSession = new AVCaptureSession ()) { + using (var videoDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video)) { + foreach (var format in videoDevice.Formats) { + for (int i = 0; i < 10; i++) { + using (var f = format.FormatDescription) { + } + } + } + } + } + } +#endif // !__TVOS__ + + [Test] + public void H264ParameterSetsTest () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) + Assert.Inconclusive ("CMVideoFormatDescription.FromH264ParameterSets is iOS7+"); + + var arr0 = new byte[] { 0x67, 0x64, 0x00, 0x29, 0xAC, 0x56, 0x80, 0x78, 0x02, 0x27, 0xE5, 0x9A, 0x80, 0x80, 0x80, 0x81 }; + var arr1 = new byte[] { 0x28, 0xEE, 0x04, 0xF2, 0xC0 }; + + var props = new List { arr0, arr1 }; + CMFormatDescriptionError error; + var desc = CMVideoFormatDescription.FromH264ParameterSets (props, 4, out error); + props = null; + Assert.That (error == CMFormatDescriptionError.None, "H264ParameterSetsTest"); + Assert.NotNull (desc, "H264ParameterSetsTest"); + Assert.That (desc.Dimensions.Height == 1080 && desc.Dimensions.Width == 1920, "H264ParameterSetsTest"); + + CMFormatDescriptionError err; + nuint paramCount; + int nalCount; + var bytes = desc.GetH264ParameterSet (0, out paramCount, out nalCount, out err); + Assert.That (err == CMFormatDescriptionError.None, "H264ParameterSetsTest"); + Assert.NotNull (bytes, "H264ParameterSetsTest"); + Assert.True (nalCount == 4 && paramCount == 2); + Assert.That (arr0, Is.EqualTo (bytes), "H264ParameterSetsTest roundtrip"); + + bytes = desc.GetH264ParameterSet (1, out paramCount, out nalCount, out err); + Assert.That (err == CMFormatDescriptionError.None, "H264ParameterSetsTest"); + Assert.NotNull (bytes, "H264ParameterSetsTest"); + Assert.True (nalCount == 4 && paramCount == 2); + Assert.That (arr1, Is.EqualTo (bytes), "H264ParameterSetsTest roundtrip"); + } + + [Test] + public void VideoFormatDescriptionConstructors () + { +#if __UNIFIED__ + using (var obj = new CMVideoFormatDescription (CMVideoCodecType.H264, new CMVideoDimensions (960, 540))) { + } +#else + using (var obj = new CMVideoFormatDescription (CMVideoCodecType.H264, new System.Drawing.Size (960, 540))) { + } +#endif + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/CMMemoryPoolTest.cs b/tests/monotouch-test/CoreMedia/CMMemoryPoolTest.cs new file mode 100644 index 000000000000..d7ebb9034e5d --- /dev/null +++ b/tests/monotouch-test/CoreMedia/CMMemoryPoolTest.cs @@ -0,0 +1,62 @@ +// +// Unit tests for CMMemoryPool +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreMedia; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreMedia; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CMMemoryPoolTest + { + [Test] + public void Ctor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("EntryPointNotFoundException : CMMemoryPoolCreate before 6.0"); + + using (var mp = new CMMemoryPool ()) + { + var allocator = mp.GetAllocator (); + var ptr = allocator.Allocate (55); + Assert.AreNotEqual (IntPtr.Zero, ptr); + allocator.Deallocate (ptr); + } + } + + [Test] + public void CtorAgeOutPeriod () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("EntryPointNotFoundException : CMMemoryPoolCreate before 6.0"); + + using (var mp = new CMMemoryPool (TimeSpan.FromSeconds (40))) + { + var allocator = mp.GetAllocator (); + var ptr = allocator.Allocate (2); + Assert.AreNotEqual (IntPtr.Zero, ptr); + allocator.Deallocate (ptr); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/CMTimeRangeTests.cs b/tests/monotouch-test/CoreMedia/CMTimeRangeTests.cs new file mode 100644 index 000000000000..8e29714030b5 --- /dev/null +++ b/tests/monotouch-test/CoreMedia/CMTimeRangeTests.cs @@ -0,0 +1,72 @@ +// +// Unit tests for CMTimeRange +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreMedia; +using UIKit; +#else +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class CMTimeRangeTests + { + [Test] + public void InvalidRangeFieldTest () + { + var invalid = CMTimeRange.InvalidRange; + Assert.NotNull (invalid, "CMTimeRange.InvalidRange Should Not be null"); + Assert.NotNull (invalid.Duration, "CMTimeRange.InvalidRange.Duration Should Not be null"); + Assert.NotNull (invalid.Start, "CMTimeRange.InvalidRange.Duration Should Not be null"); + Assert.That (invalid.Duration.IsInvalid, "CMTimeRange.InvalidRange.Duration.IsInvalid"); + Assert.That (invalid.Start.IsInvalid, "CMTimeRange.InvalidRange.Start.IsInvalid"); + Assert.That (invalid.Duration.Description, Is.EqualTo ("{INVALID}"), "Duration Description"); + Assert.That (invalid.Start.Description, Is.EqualTo ("{INVALID}"), "Start Description"); + } + + [Test] + public void InvalidMappingFieldTest () + { + var invalid = CMTimeRange.InvalidMapping; + Assert.NotNull (invalid, "CMTimeRange.InvalidMapping Should Not be null"); + Assert.NotNull (invalid.Duration, "CMTimeRange.InvalidMapping.Duration Should Not be null"); + Assert.NotNull (invalid.Start, "CMTimeRange.InvalidMapping.Duration Should Not be null"); + Assert.That (invalid.Duration.IsInvalid, "CMTimeRange.InvalidMapping.Duration.IsInvalid"); + Assert.That (invalid.Start.IsInvalid, "CMTimeRange.InvalidMapping.Start.IsInvalid"); + Assert.That (invalid.Duration.Description, Is.EqualTo ("{INVALID}"), "Duration Description"); + Assert.That (invalid.Start.Description, Is.EqualTo ("{INVALID}"), "Start Description"); + } + + [Test] + public void ZeroFieldTest () + { + var zero = CMTimeRange.Zero; + Assert.NotNull (zero, "CMTimeRange.Zero Should Not be null"); + Assert.NotNull (zero.Duration, "CMTimeRange.Zero.Duration Should Not be null"); + Assert.NotNull (zero.Start, "CMTimeRange.Zero.Duration Should Not be null"); + Assert.That (!zero.Duration.IsInvalid, "CMTimeRange.Zero.Duration.IsInvalid"); + Assert.That (!zero.Start.IsInvalid, "CMTimeRange.Zero.Start.IsInvalid"); + Assert.That (zero.Duration.Description, Is.EqualTo ("{0/1 = 0.000}"), "Duration Description"); + Assert.That (zero.Start.Description, Is.EqualTo ("{0/1 = 0.000}"), "Start Description"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/CMTimeTests.cs b/tests/monotouch-test/CoreMedia/CMTimeTests.cs new file mode 100644 index 000000000000..ff8b8c877698 --- /dev/null +++ b/tests/monotouch-test/CoreMedia/CMTimeTests.cs @@ -0,0 +1,171 @@ +// +// Unit tests for CMTime +// +// Authors: +// Rolf Bjarne Kvinge +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreMedia; +using UIKit; +#else +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CMTimeTests { + + [Test] + public void PropertiesTest () + { + CMTime v; + + v = new CMTime (1, 2); + Assert.That (v.Value, Is.EqualTo (1), "Value"); + Assert.That (v.TimeScale, Is.EqualTo (2), "TimeScale"); + Assert.That (!v.IsInvalid, "IsInvalid"); + Assert.That (v.AbsoluteValue.Description, Is.EqualTo ("{1/2 = 0.500}"), "AbsoluteValue"); +#if !XAMCORE_2_0 + Assert.That (v.AsDictionary != IntPtr.Zero, "AsDictionary"); +#endif + Assert.That (v.Description, Is.EqualTo ("{1/2 = 0.500}"), "Description"); + Assert.That (!v.IsIndefinite, "IsIndefinite"); + Assert.That (!v.IsNegativeInfinity, "IsNegativeInfinity"); + Assert.That (!v.IsPositiveInfinity, "IsPositiveInfinity"); + Assert.That (v.Seconds, Is.EqualTo (0.5), "Seconds"); + Assert.That (v.TimeEpoch, Is.EqualTo (0), "TimeEpoch"); + Assert.That (v.TimeFlags == CMTime.Flags.Valid, "TimeFlag"); + } + + [Test] + public void MethodsTest () + { + CMTime v, w, x, y; + v = new CMTime (1, 2); + w = new CMTime (1, 2); + x = new CMTime (2, 1); + y = new CMTime (2, 2); + + // equality operators + Assert.That (v == w, "Equality #1"); + Assert.That (!(v == x), "Equality #2"); + Assert.That (v != x, "Inequality #1"); + Assert.That (!(v != w), "Inequality #2"); + Assert.That (CMTime.Compare (v, w), Is.EqualTo (0), "Compare #1"); + Assert.That (CMTime.Compare (v, x) != 0, "Compare #2"); + Assert.That (v.Equals (w), "Equals #1"); + Assert.That (!x.Equals (v), "Equals #2"); + + // addition operator + Assert.That (v + w == new CMTime (2, 2), "Addition #1"); + Assert.That (CMTime.Add (v, w) == new CMTime (2, 2), "Addition #2"); + + // subtraction operator + Assert.That (v - w == new CMTime (0, 2), "Subtraction #1"); + Assert.That (CMTime.Subtract (v, w) == new CMTime (0, 2), "Subtraction #2"); + + // multiplication operators + Assert.That (v * 2 == new CMTime (2, 2), "Multiplication * int, #1"); + Assert.That (CMTime.Multiply (v, 3) == new CMTime (3, 2), "Multiplication * int, #2"); + Assert.That (v * 4.0 == new CMTime (4, 2), "Multiplication * double, #1"); + Assert.That (CMTime.Multiply (v, 5.0) == new CMTime (5, 2), "Multiplication * double, #2"); + + // ConvertScale + Assert.That (new CMTime (10, 2).ConvertScale (1, CMTimeRoundingMethod.Default) == new CMTime (5, 1), "ConvertScale #1"); + + // FromSeconds + Assert.That (CMTime.FromSeconds (20, 1) == new CMTime (20, 1), "FromSeconds #1"); + + // GetMaximum + Assert.That (CMTime.GetMaximum (v, y) == y, "GetMaximum #1"); + + // GetMinimum + Assert.That (CMTime.GetMinimum (v, y) == v, "GetMinimum #1"); + +#if XAMCORE_2_0 + using (var d = x.ToDictionary ()) { + Assert.That (d.RetainCount, Is.EqualTo ((nint) 1), "RetainCount"); + Assert.That (d.Count, Is.EqualTo ((nuint) 4), "Count"); + + var time = CMTime.FromDictionary (d); + Assert.That (time, Is.EqualTo (x), "FromDictionary"); + } +#endif + } + + [Test] + public void MultiplyByRatio () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 1)) + Assert.Inconclusive ("Requires 7.1+"); + + var t = new CMTime (1000, 1); + t = CMTime.Multiply (t, 20, 10); + Assert.That (t.Value, Is.EqualTo (2000), "Value"); + } + + [Test] + public void CMTimeRangeConstants () + { + // Just make sure accessing the constants doesn't hard crash us + Assert.DoesNotThrow (() => { var x = CMTimeRange.Zero; }, "CMTimeRangeConstants - Zero"); + Assert.DoesNotThrow (() => { var x = CMTimeRange.InvalidRange; }, "CMTimeRangeConstants - InvalidRange"); + Assert.DoesNotThrow (() => { var x = CMTimeRange.InvalidMapping; }, "CMTimeRangeConstants - InvalidMapping"); +#if !XAMCORE_3_0 + Assert.DoesNotThrow (() => { var x = CMTimeRange.Invalid; }, "CMTimeRangeConstants - Invalid"); +#endif + if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) { + Assert.DoesNotThrow (() => { var x = CMTimeRange.InvalidMapping; }, "CMTimeRangeConstants - InvalidMapping"); + Assert.DoesNotThrow (() => { var x = CMTimeRange.TimeMappingSourceKey; }, "CMTimeRangeConstants - TimeMappingSourceKey"); + Assert.DoesNotThrow (() => { var x = CMTimeRange.TimeMappingTargetKey; }, "CMTimeRangeConstants - TimeMappingTargetKey"); + } + } + + [Test] + public void CMTimeMappingFactoryMethods () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Inconclusive ("Requires 9.0+"); + + var first = new CMTimeRange () { Duration = new CMTime (12, 1), Start = new CMTime (1, 1) }; + var second = new CMTimeRange () { Duration = new CMTime (4, 1), Start = new CMTime (1, 1) }; + + CMTimeMapping map = CMTimeMapping.Create (first, second); + CompareCMTimeRange (map.Source, first, "CMTimeMapping.Create"); + CompareCMTimeRange (map.Target, second, "CMTimeMapping.Create"); + + map = CMTimeMapping.CreateEmpty (first); + CompareCMTimeRange (map.Source, CMTimeRange.InvalidRange, "CMTimeMapping.CreateEmpty"); + CompareCMTimeRange (map.Target, first, "CMTimeMapping.CreateEmpty"); + + map = CMTimeMapping.CreateFromDictionary (new NSDictionary ()); + CompareCMTimeRange (map.Source, CMTimeRange.InvalidRange, "CMTimeMapping.CreateFromDictionary"); + CompareCMTimeRange (map.Target, CMTimeRange.InvalidRange, "CMTimeMapping.CreateFromDictionary"); + + Assert.IsNotNull (map.AsDictionary (), "CMTimeMapping AsDictionary"); + + Assert.IsNotNull (map.Description, "CMTimeMapping Description"); + } + + void CompareCMTimeRange (CMTimeRange first, CMTimeRange second, string description) + { + Assert.AreEqual (first.Duration, second.Duration, "CompareCMTimeRange - duration - " + description); + Assert.AreEqual (first.Start, second.Start, "CompareCMTimeRange - start - " + description); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/CMTimebaseTest.cs b/tests/monotouch-test/CoreMedia/CMTimebaseTest.cs new file mode 100644 index 000000000000..2e146eaec8d6 --- /dev/null +++ b/tests/monotouch-test/CoreMedia/CMTimebaseTest.cs @@ -0,0 +1,132 @@ +// +// Unit tests for CMTimebase +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012-2014 Xamarin Inc All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreMedia; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreMedia; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CMTimebaseTest + { + [Test] + public void DefaultValues () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMTimebase is new in 6.0"); + + var htc = CMClock.HostTimeClock; + using (var tb = new CMTimebase (htc)) { + Assert.AreEqual (0, tb.EffectiveRate, "EffectiveRate"); + Assert.AreEqual (0, tb.Rate, "Rate"); + + using (var m = tb.GetMaster ()) { + Assert.That (m.Handle, Is.Not.EqualTo (IntPtr.Zero), "GetMaster"); + } + using (var m = tb.GetMasterClock ()) { + Assert.That (m.Handle, Is.Not.EqualTo (IntPtr.Zero), "GetMasterClock"); + } + Assert.Null (tb.GetMasterTimebase (), "GetMasterTimebase"); + } + } + + [Test] + public void SetAnchorTime () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMTimebase is new in 6.0"); + + using (var tb = new CMTimebase (CMClock.HostTimeClock)) { + Assert.AreEqual (CMTimebaseError.None, tb.SetAnchorTime (new CMTime (1000000, 200), new CMTime (-1, -2))); + var cmt = tb.GetTime (new CMTimeScale (int.MaxValue), CMTimeRoundingMethod.QuickTime); + Assert.AreEqual (5000, cmt.Seconds); + } + } + + [Test] + public void AddTimer () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMTimebase is new in 6.0"); + + using (var tb = new CMTimebase (CMClock.HostTimeClock)) { + var timer = NSTimer.CreateRepeatingTimer (CMTimebase.VeryLongTimeInterval, delegate { }); + + Assert.AreEqual (CMTimebaseError.None, tb.AddTimer (timer, NSRunLoop.Current), "#1"); + Assert.AreEqual (CMTimebaseError.None, tb.SetTimerNextFireTime (timer, new CMTime (100, 2)), "#2"); + + tb.RemoveTimer (timer); + } + } + + [Test] + public void GetMasterTests () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMTimebase is new in 6.0"); + + using (var tb = new CMTimebase (CMClock.HostTimeClock)) { + var masterTB = tb.GetMasterTimebase (); + AssertNullOrValidHandle (masterTB, "GetMasterTimebase"); + + var masterClock = tb.GetMasterClock (); + AssertNullOrValidHandle (masterClock, "GetMasterClock"); + + var master = tb.GetMaster (); + AssertNullOrValidHandle (master, "GetMaster"); + + var masterUlt = tb.GetUltimateMasterClock (); + AssertNullOrValidHandle (masterUlt, "GetUltimateMasterClock"); + } + } + + [Test] + public void CopyMasterTests () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("CMTimebase is new in 6.0"); + + using (var tb = new CMTimebase (CMClock.HostTimeClock)) { + var masterTB = tb.CopyMasterTimebase (); + AssertNullOrValidHandle (masterTB, "CopyMasterTimebase"); + + var masterClock = tb.CopyMasterClock (); + AssertNullOrValidHandle (masterClock, "CopyMasterClock"); + + var master = tb.CopyMaster (); + AssertNullOrValidHandle (master, "CopyMaster"); + + var masterUlt = tb.CopyUltimateMasterClock (); + AssertNullOrValidHandle (masterUlt, "CopyUltimateMasterClock"); + } + } + + // A returned item should be null if not valid in that context or have a valid handle + void AssertNullOrValidHandle (INativeObject o, string description) + { + if (o == null) + return; + Assert.AreNotEqual (IntPtr.Zero, o.Handle, "AssertNullOrValidHandle - " + description); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/EnumTest.cs b/tests/monotouch-test/CoreMedia/EnumTest.cs new file mode 100644 index 000000000000..e26001bd689b --- /dev/null +++ b/tests/monotouch-test/CoreMedia/EnumTest.cs @@ -0,0 +1,152 @@ +// +// Unit tests for 4cc-based enums +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreMedia; +using UIKit; +#else +using MonoTouch.CoreMedia; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EnumTest { + + string FourCC (int value) + { + return new string (new char [] { + (char) (byte) (value >> 24), + (char) (byte) (value >> 16), + (char) (byte) (value >> 8), + (char) (byte) value }); + } + + [Test] + public void MediaType () + { + Assert.That (FourCC ((int) CMMediaType.Audio), Is.EqualTo ("soun"), "Audio"); + Assert.That (FourCC ((int) CMMediaType.ClosedCaption), Is.EqualTo ("clcp"), "ClosedCaption"); + Assert.That (FourCC ((int) CMMediaType.Metadata), Is.EqualTo ("meta"), "Metadata"); + Assert.That (FourCC ((int) CMMediaType.Muxed), Is.EqualTo ("muxx"), "Muxed"); + Assert.That (FourCC ((int) CMMediaType.Subtitle), Is.EqualTo ("sbtl"), "Subtitle"); + Assert.That (FourCC ((int) CMMediaType.Text), Is.EqualTo ("text"), "Text"); + Assert.That (FourCC ((int) CMMediaType.TimeCode), Is.EqualTo ("tmcd"), "TimeCode"); +#if !XAMCORE_2_0 + Assert.That (FourCC ((int) CMMediaType.TimedMetadata), Is.EqualTo ("tmet"), "TimedMetadata"); +#endif + Assert.That (FourCC ((int) CMMediaType.Video), Is.EqualTo ("vide"), "Video"); + } + + [Test] + public void ClosedCaptionFormatType () + { + Assert.That (FourCC ((int) CMClosedCaptionFormatType.ATSC), Is.EqualTo ("atcc"), "ATSC"); + Assert.That (FourCC ((int) CMClosedCaptionFormatType.CEA608), Is.EqualTo ("c608"), "CEA608"); + Assert.That (FourCC ((int) CMClosedCaptionFormatType.CEA708), Is.EqualTo ("c708"), "CEA708"); + } + + [Test] + public void MuxedStreamType () + { + Assert.That (FourCC ((int) CMMuxedStreamType.DV), Is.EqualTo ("dv "), "DV"); + Assert.That (FourCC ((int) CMMuxedStreamType.MPEG1System), Is.EqualTo ("mp1s"), "MPEG1System"); + Assert.That (FourCC ((int) CMMuxedStreamType.MPEG2Program), Is.EqualTo ("mp2p"), "MPEG2Program"); + Assert.That (FourCC ((int) CMMuxedStreamType.MPEG2Transport), Is.EqualTo ("mp2t"), "MPEG2Transport"); + } + + [Test] + public void SubtitleFormatType () + { + Assert.That (FourCC ((int) CMSubtitleFormatType.Text3G), Is.EqualTo ("tx3g"), "Text3G"); + Assert.That (FourCC ((int) CMSubtitleFormatType.WebVTT), Is.EqualTo ("wvtt"), "WebVTT"); + } + + [Test] + public void MetadataFormatType () + { + Assert.That (FourCC ((int) CMMetadataFormatType.Boxed), Is.EqualTo ("mebx"), "Boxed"); + Assert.That (FourCC ((int) CMMetadataFormatType.ICY), Is.EqualTo ("icy "), "ICY"); + Assert.That (FourCC ((int) CMMetadataFormatType.ID3), Is.EqualTo ("id3 "), "ID3"); + } + + [Test] + public void TimeCodeFormatType () + { + Assert.That (FourCC ((int) CMTimeCodeFormatType.Counter32), Is.EqualTo ("cn32"), "Counter32"); + Assert.That (FourCC ((int) CMTimeCodeFormatType.Counter64), Is.EqualTo ("cn64"), "Counter64"); + Assert.That (FourCC ((int) CMTimeCodeFormatType.TimeCode32), Is.EqualTo ("tmcd"), "TimeCode32"); + Assert.That (FourCC ((int) CMTimeCodeFormatType.TimeCode64), Is.EqualTo ("tc64"), "TimeCode64"); + } + + [Test] + public void VideoCodecType () + { + Assert.That (FourCC ((int) CMVideoCodecType.Animation), Is.EqualTo ("rle "), "Animation"); + Assert.That (FourCC ((int) CMVideoCodecType.AppleProRes422), Is.EqualTo ("apcn"), "AppleProRes422"); + Assert.That (FourCC ((int) CMVideoCodecType.AppleProRes422HQ), Is.EqualTo ("apch"), "AppleProRes422HQ"); + Assert.That (FourCC ((int) CMVideoCodecType.AppleProRes422LT), Is.EqualTo ("apcs"), "AppleProRes422LT"); + Assert.That (FourCC ((int) CMVideoCodecType.AppleProRes422Proxy), Is.EqualTo ("apco"), "AppleProRes422Proxy"); + Assert.That (FourCC ((int) CMVideoCodecType.AppleProRes4444), Is.EqualTo ("ap4h"), "AppleProRes4444"); + Assert.That (FourCC ((int) CMVideoCodecType.Cinepak), Is.EqualTo ("cvid"), "Cinepak"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcNtsc), Is.EqualTo ("dvc "), "DvcNtsc"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcPal), Is.EqualTo ("dvcp"), "DvcPal"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcPro50NTSC), Is.EqualTo ("dv5n"), "DvcPro50NTSC"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcPro50PAL), Is.EqualTo ("dv5p"), "DvcPro50PAL"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProHD1080i50), Is.EqualTo ("dvh5"), "DvcProHD1080i50"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProHD1080i60), Is.EqualTo ("dvh6"), "DvcProHD1080i60"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProHD1080p25), Is.EqualTo ("dvh2"), "DvcProHD1080p25"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProHD1080p30), Is.EqualTo ("dvh3"), "DvcProHD1080p30"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProHD720p50), Is.EqualTo ("dvhq"), "DvcProHD720p50"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProHD720p60), Is.EqualTo ("dvhp"), "DvcProHD720p60"); + Assert.That (FourCC ((int) CMVideoCodecType.DvcProPal), Is.EqualTo ("dvpp"), "DvcProPal"); + Assert.That (FourCC ((int) CMVideoCodecType.H263), Is.EqualTo ("h263"), "H263"); + Assert.That (FourCC ((int) CMVideoCodecType.H264), Is.EqualTo ("avc1"), "H264"); + Assert.That (FourCC ((int) CMVideoCodecType.JPEG), Is.EqualTo ("jpeg"), "JPEG"); + Assert.That (FourCC ((int) CMVideoCodecType.JPEG_OpenDML), Is.EqualTo ("dmb1"), "JPEG_OpenDML"); + Assert.That (FourCC ((int) CMVideoCodecType.Mpeg1Video), Is.EqualTo ("mp1v"), "Mpeg1Video"); + Assert.That (FourCC ((int) CMVideoCodecType.Mpeg2Video), Is.EqualTo ("mp2v"), "Mpeg2Video"); + Assert.That (FourCC ((int) CMVideoCodecType.Mpeg4Video), Is.EqualTo ("mp4v"), "Mpeg4Video"); + Assert.That (FourCC ((int) CMVideoCodecType.SorensonVideo), Is.EqualTo ("SVQ1"), "SorensonVideo"); + Assert.That (FourCC ((int) CMVideoCodecType.SorensonVideo3), Is.EqualTo ("SVQ3"), "SorensonVideo3"); + Assert.That (FourCC ((int) CMVideoCodecType.YUV422YpCbCr8), Is.EqualTo ("2vuy"), "YUV422YpCbCr8"); + } + + [Test] + public void PixelFormat () + { + Assert.That ((int) CMPixelFormat.AlphaRedGreenBlue32bits, Is.EqualTo (32), "AlphaRedGreenBlue32bits"); + Assert.That (FourCC ((int) CMPixelFormat.BlueGreenRedAlpha32bits), Is.EqualTo ("BGRA"), "BlueGreenRedAlpha32bits"); + Assert.That ((int) CMPixelFormat.RedGreenBlue24bits, Is.EqualTo (24), "RedGreenBlue24bits"); + Assert.That ((int) CMPixelFormat.BigEndian555_16bits, Is.EqualTo (16), "BigEndian555_16bits"); + Assert.That (FourCC ((int) CMPixelFormat.BigEndian565_16bits), Is.EqualTo ("B565"), "BigEndian565_16bits"); + Assert.That (FourCC ((int) CMPixelFormat.LittleEndian555_16bits), Is.EqualTo ("L555"), "LittleEndian555_16bits"); + Assert.That (FourCC ((int) CMPixelFormat.LittleEndian565_16bits), Is.EqualTo ("L565"), "LittleEndian565_16bits"); + Assert.That (FourCC ((int) CMPixelFormat.LittleEndian5551_16bits), Is.EqualTo ("5551"), "LittleEndian5551_16bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCr422_8bits), Is.EqualTo ("2vuy"), "YpCbCr422_8bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCr422yuvs_8bits), Is.EqualTo ("yuvs"), "YpCbCr422yuvs_8bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCr444_8bits), Is.EqualTo ("v308"), "YpCbCr444_8bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCrA4444_8bits), Is.EqualTo ("v408"), "YpCbCrA4444_8bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCr422_16bits), Is.EqualTo ("v216"), "YpCbCr422_16bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCr422_10bits), Is.EqualTo ("v210"), "YpCbCr422_10bits"); + Assert.That (FourCC ((int) CMPixelFormat.YpCbCr444_10bits), Is.EqualTo ("v410"), "YpCbCr444_10bits"); + Assert.That ((int) CMPixelFormat.IndexedGrayWhiteIsZero_8bits, Is.EqualTo (40), "YpCbCr444_10bits"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMedia/SampleBufferTest.cs b/tests/monotouch-test/CoreMedia/SampleBufferTest.cs new file mode 100644 index 000000000000..42b6c4cb9f61 --- /dev/null +++ b/tests/monotouch-test/CoreMedia/SampleBufferTest.cs @@ -0,0 +1,220 @@ +// +// Unit tests for CMSampleBuffer +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +#if !__TVOS__ +using EventKit; +#endif +using ObjCRuntime; +using CoreVideo; +using CoreMedia; +#else +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreVideo; +using MonoTouch.CoreMedia; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMedia { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SampleBufferTest + { + [Test] + public void CreateForImageBuffer () + { + var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB); + + CMFormatDescriptionError fde; + var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde); + + var sampleTiming = new CMSampleTimingInfo (); + + CMSampleBufferError sbe; + var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe); + Assert.IsNotNull (sb, "#1"); + Assert.AreEqual (CMSampleBufferError.None, sbe, "#2"); + } + + [Test] + public void CreateReadyWithPacketDescriptions () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8"); + + CMBlockBufferError bbe; + using (var bb = CMBlockBuffer.CreateEmpty (0, CMBlockBufferFlags.AlwaysCopyData, out bbe)) { + CMFormatDescriptionError fde; + using (var fd = CMFormatDescription.Create (CMMediaType.ClosedCaption, (uint) CMClosedCaptionFormatType.CEA608, out fde)) { + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateReadyWithPacketDescriptions (bb, fd, 1, CMTime.Indefinite, null, out sbe)) { + Assert.Null (sb, "CMSampleBuffer"); + // the `null` does not match format description (but I lack a better test, at least it's callable) + Assert.That (sbe, Is.EqualTo (CMSampleBufferError.RequiredParameterMissing), "CMSampleBufferError"); + } + } + } + } + + [Test] + public void CreateReady () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8"); + + CMBlockBufferError bbe; + using (var bb = CMBlockBuffer.CreateEmpty (0, CMBlockBufferFlags.AlwaysCopyData, out bbe)) { + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateReady (bb, null, 0, null, null, out sbe)) { + Assert.That (sb.Handle, Is.Not.EqualTo (IntPtr.Zero), "CMSampleBuffer"); + Assert.That (sbe, Is.EqualTo (CMSampleBufferError.None), "CMSampleBufferError"); + } + } + } + + [Test] + public void CreateReadyWithImageBuffer () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8"); + + CMFormatDescriptionError fde; + using (var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB)) + using (var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde)) { + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateReadyWithImageBuffer (pixelBuffer, desc, new CMSampleTimingInfo [0], out sbe)) { + Assert.That (sb.Handle, Is.Not.EqualTo (IntPtr.Zero), "CMSampleBuffer"); + Assert.That (sbe, Is.EqualTo (CMSampleBufferError.None), "CMSampleBufferError"); + } + } + } + + [Test] + public void SetInvalidateCallback_Replace () + { + using (var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB)) { + CMFormatDescriptionError fde; + using (var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde)) { + var sampleTiming = new CMSampleTimingInfo (); + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe)) { + int i = 0; + var result = sb.SetInvalidateCallback (delegate (CMSampleBuffer buffer) { + i++; + }); + + // we cannot replace the (native) callback without getting an error (so we should not replace + // the managed one either, that would be confusing and make it hard to port code) + result = sb.SetInvalidateCallback (delegate (CMSampleBuffer buffer) { + i--; + Assert.AreSame (buffer, sb, "same"); + }); + Assert.That (result, Is.EqualTo (CMSampleBufferError.RequiredParameterMissing), "RequiredParameterMissing"); + + sb.Invalidate (); + Assert.That (i, Is.EqualTo (1), "1"); + } + } + } + } + + [Test] + public void SetInvalidateCallback () + { + using (var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB)) { + CMFormatDescriptionError fde; + using (var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde)) { + var sampleTiming = new CMSampleTimingInfo (); + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe)) { + int i = 0; + var result = sb.SetInvalidateCallback (delegate (CMSampleBuffer buffer) { + i++; + Assert.AreSame (buffer, sb, "same"); + }); + Assert.That (result, Is.EqualTo (CMSampleBufferError.None), "SetInvalidateCallback/None"); + + result = (CMSampleBufferError) sb.Invalidate (); + Assert.That (result, Is.EqualTo (CMSampleBufferError.None), "Invalidate/None"); + Assert.That (i, Is.EqualTo (1), "1"); + + // a second call to Invalidate returns Invalidated + result = (CMSampleBufferError) sb.Invalidate (); + Assert.That (result, Is.EqualTo (CMSampleBufferError.Invalidated), "Invalidated"); + } + } + } + } + + [Test] + public void SetInvalidateCallback_Null () + { + using (var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB)) { + CMFormatDescriptionError fde; + using (var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde)) { + var sampleTiming = new CMSampleTimingInfo (); + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe)) { + // ignore `null`, i.e. no crash + Assert.That (sb.SetInvalidateCallback (null), Is.EqualTo (CMSampleBufferError.None), "null"); + + int i = 0; + var result = sb.SetInvalidateCallback (delegate (CMSampleBuffer buffer) { + i++; + Assert.AreSame (buffer, sb, "same"); + }); + Assert.That (result, Is.EqualTo (CMSampleBufferError.None), "SetInvalidateCallback/None"); + + // we can reset (nullify) the callback + Assert.That (sb.SetInvalidateCallback (null), Is.EqualTo (CMSampleBufferError.None), "null-2"); + + result = (CMSampleBufferError) sb.Invalidate (); + Assert.That (result, Is.EqualTo (CMSampleBufferError.None), "Invalidate/None"); + Assert.That (i, Is.EqualTo (0), "0"); + } + } + } + } + + [Test] + public void CallForEachSample () + { + using (var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB)) { + CMFormatDescriptionError fde; + using (var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde)) { + var sampleTiming = new CMSampleTimingInfo (); + CMSampleBufferError sbe; + using (var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe)) { + int i = 0; + var result = sb.CallForEachSample (delegate (CMSampleBuffer buffer, int index) { + i++; + Assert.AreSame (buffer, sb, "same-1"); + return CMSampleBufferError.CannotSubdivide; + }); + Assert.That (result, Is.EqualTo (CMSampleBufferError.CannotSubdivide), "custom error"); + Assert.That (i, Is.EqualTo (1), "1"); + + Assert.Throws (delegate { + sb.CallForEachSample (null); + }, "null"); + } + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMidi/MidiThruConnectionTests.cs b/tests/monotouch-test/CoreMidi/MidiThruConnectionTests.cs new file mode 100644 index 000000000000..cb5df0c90a7f --- /dev/null +++ b/tests/monotouch-test/CoreMidi/MidiThruConnectionTests.cs @@ -0,0 +1,143 @@ +// +// Unit tests for MidiThruConnection +// +// Authors: +// Alex Soto +// +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ +using System; + +#if XAMCORE_2_0 +using Foundation; +using CoreMidi; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreMidi; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMidi { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MidiThruConnectionTests { + + [Test] + public void ConnectionCreateTest () + { + var cnnParams = new MidiThruConnectionParams { + Controls = new MidiControlTransform[] { + new MidiControlTransform (), + new MidiControlTransform (), + new MidiControlTransform () + }, + Maps = new MidiValueMap[] { + new MidiValueMap (), + new MidiValueMap () + }, + KeyPressure = new MidiTransform (MidiTransformType.Scale, 2), + FilterOutAllControls = true, + FilterOutBeatClock = true, + FilterOutMtc = true, + FilterOutSysEx = true, + FilterOutTuneRequest = true, + LowNote = 1, + HighNote = 8 + }; + + MidiError err; + using (var connection = MidiThruConnection.Create ("com.xamarin.midi", cnnParams, out err)) { + Assert.IsTrue (err == MidiError.Ok, "midi connection error"); + Assert.IsNotNull (connection, "midi connection should not be null"); + } + } + + [Test] + public void GetSetParamsTest () + { + var cnnParams = new MidiThruConnectionParams { + Controls = new MidiControlTransform[] { + new MidiControlTransform (), + new MidiControlTransform (), + new MidiControlTransform () + }, + Maps = new MidiValueMap[] { + new MidiValueMap (), + new MidiValueMap () + }, + KeyPressure = new MidiTransform (MidiTransformType.Scale, 2), + FilterOutAllControls = true, + FilterOutBeatClock = true, + FilterOutMtc = true, + FilterOutSysEx = true, + FilterOutTuneRequest = true, + LowNote = 1, + HighNote = 8 + }; + + MidiError err; + using (var connection = MidiThruConnection.Create ("com.xamarin.midi", cnnParams, out err)) { + Assert.IsTrue (err == MidiError.Ok, "midi connection error"); + Assert.IsNotNull (connection, "midi connection should not be null"); + + var gotParams = connection.GetParams (out err); + Assert.IsTrue (err == MidiError.Ok, "midi connection error"); + // Test dynamic part of the struct + Assert.IsTrue (gotParams.Controls.Length == cnnParams.Controls.Length, "midi params objects should be the same amount"); + Assert.IsTrue (gotParams.Maps.Length == cnnParams.Maps.Length, "midi params objects should be the same amount"); + + var newParams = new MidiThruConnectionParams { + FilterOutAllControls = false, + FilterOutBeatClock = true, + FilterOutMtc = true, + FilterOutSysEx = true, + FilterOutTuneRequest = true, + HighNote = 5 + }; + + err = connection.SetParams (newParams); + Assert.IsTrue (err == MidiError.Ok, "midi connection error"); + + gotParams = connection.GetParams (out err); + Assert.IsTrue (err == MidiError.Ok, "midi connection error"); + Assert.IsTrue (gotParams.FilterOutBeatClock, "FilterOutBeatClock should be true"); + Assert.IsFalse (gotParams.FilterOutAllControls, "FilterOutAllControls should be false"); + Assert.IsTrue (gotParams.HighNote == 5, "HighNote should be 5"); + } + } + + [Test] + public void FindTest() + { + var cnnParams1 = new MidiThruConnectionParams { + FilterOutAllControls = true, + FilterOutSysEx = true, + FilterOutTuneRequest = true, + LowNote = 1, + HighNote = 8 + }; + + var cnnParams2 = new MidiThruConnectionParams { + FilterOutAllControls = true, + FilterOutSysEx = false, + FilterOutTuneRequest = false, + LowNote = 1, + HighNote = 4 + }; + + using (var connection1 = MidiThruConnection.Create ("com.xamarin.midi", cnnParams1)) + using (var connection2 = MidiThruConnection.Create ("com.xamarin.midi", cnnParams2)) { + MidiError err; + var connections = MidiThruConnection.Find ("com.xamarin.midi", out err); + Assert.IsTrue (err == MidiError.Ok, "midi connection error"); + Assert.NotNull (connections, "connections should not be null"); + Assert.IsTrue (connections.Length == 2, "2 midi connections"); + } + } + } +} +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/CoreMotion/AccelerometerDataTest.cs b/tests/monotouch-test/CoreMotion/AccelerometerDataTest.cs new file mode 100644 index 000000000000..60fa3f7951bc --- /dev/null +++ b/tests/monotouch-test/CoreMotion/AccelerometerDataTest.cs @@ -0,0 +1,48 @@ +// +// Unit tests for CMAccelerometerData +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreMotion; +using ObjCRuntime; +#else +using MonoTouch.CoreMotion; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMotion { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AccelerometerDataTest { + +#if !XAMCORE_2_0 // the default ctor has been removed. + [Test] + public void Default () + { + // this would (and did) crash if we called 'init' + using (var ad = new CMAccelerometerData ()) { + Assert.That (ad.Acceleration.X, Is.EqualTo (0.0d), "X"); + Assert.That (ad.Acceleration.Y, Is.EqualTo (0.0d), "Y"); + Assert.That (ad.Acceleration.Z, Is.EqualTo (0.0d), "Z"); + // from CMLogItem + // NaN on the simulator, 0.0d on devices - but we just want to ensure we do not crash + Assert.That (ad.Timestamp, Is.Not.EqualTo (1.0d), "Timestamp"); + } + } +#endif + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/CoreMotion/LogItemTest.cs b/tests/monotouch-test/CoreMotion/LogItemTest.cs new file mode 100644 index 000000000000..9d7d285d4a6e --- /dev/null +++ b/tests/monotouch-test/CoreMotion/LogItemTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for CMLogItem +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +using CoreMotion; +#else +using MonoTouch.CoreMotion; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreMotion { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LogItemTest { + +#if !XAMCORE_2_0 // the default ctor has been removed. + [Test] + public void Default () + { + // this would (and did) crash if we called 'init' + using (var li = new CMLogItem ()) { + // NaN on the simulator, 0.0d on devices - but we just want to ensure we do not crash + Assert.That (li.Timestamp, Is.Not.EqualTo (1.0d), "Timestamp"); + } + } +#endif + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/CoreServices/HttpMessageTest.cs b/tests/monotouch-test/CoreServices/HttpMessageTest.cs new file mode 100644 index 000000000000..b4868b47f7a1 --- /dev/null +++ b/tests/monotouch-test/CoreServices/HttpMessageTest.cs @@ -0,0 +1,76 @@ +// +// Unit tests CFHTTPMessage +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Net; +#if XAMCORE_4_0 +using CFNetwork; +#elif XAMCORE_2_0 +using CoreServices; +#endif +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.CoreServices; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreServices { + + [TestFixture] + [Preserve (AllMembers = true)] + public class HttpMessageTest { + + [Test] + public void CreateEmptyTrue () + { + using (var m = CFHTTPMessage.CreateEmpty (true)) { + Assert.That (m.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.False (m.IsHeaderComplete, "IsHeaderComplete"); + Assert.True (m.IsRequest, "IsRequest"); + Assert.Throws (delegate { var x = m.ResponseStatusCode; }, "ResponseStatusCode"); + Assert.Throws (delegate { var x = m.ResponseStatusLine; }, "ResponseStatusLine"); + Assert.That (m.Version.ToString (), Is.EqualTo ("1.1"), "Version"); + } + } + + [Test] + public void CreateEmptyFalse () + { + using (var m = CFHTTPMessage.CreateEmpty (false)) { + Assert.That (m.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.False (m.IsHeaderComplete, "IsHeaderComplete"); + Assert.False (m.IsRequest, "IsRequest"); + Assert.That (m.ResponseStatusCode, Is.EqualTo (HttpStatusCode.OK), "ResponseStatusCode"); + Assert.That (m.ResponseStatusLine, Is.Empty, "ResponseStatusLine"); + Assert.That (m.Version.ToString (), Is.EqualTo ("1.1"), "Version"); + } + } + + [Test] + public void CreateRequest10 () + { + using (var m = CFHTTPMessage.CreateRequest (new Uri ("http://www.xamarin.com"), "GET", new Version (1, 0))) { + Assert.That (m.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.False (m.IsHeaderComplete, "IsHeaderComplete"); + Assert.True (m.IsRequest, "IsRequest"); + Assert.Throws (delegate { var x = m.ResponseStatusCode; }, "ResponseStatusCode"); + Assert.Throws (delegate { var x = m.ResponseStatusLine; }, "ResponseStatusLine"); + Assert.That (m.Version.ToString (), Is.EqualTo ("1.0"), "Version"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreText/CTFrameTests.cs b/tests/monotouch-test/CoreText/CTFrameTests.cs new file mode 100644 index 000000000000..cbc9b1b8697b --- /dev/null +++ b/tests/monotouch-test/CoreText/CTFrameTests.cs @@ -0,0 +1,46 @@ +// +// Unit tests for CTFrame +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreText; +using CoreGraphics; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.CoreText; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreText { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CTFrameTests { + + [Test] // #4677 + public void GetPathTest () + { + using (var framesetter = new CTFramesetter (new NSAttributedString ("Testing, testing, 1, 2, 3..."))) { + using (var frame = framesetter.GetFrame (new NSRange (0, 0), new CGPath (), null)) { + using (var f = frame.GetPath ()) { + } + using (var f = frame.GetPath ()) { + Console.WriteLine (f.BoundingBox); + } + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreText/CTLineTest.cs b/tests/monotouch-test/CoreText/CTLineTest.cs new file mode 100644 index 000000000000..6b5c8daca4a3 --- /dev/null +++ b/tests/monotouch-test/CoreText/CTLineTest.cs @@ -0,0 +1,81 @@ +// +// Unit tests for CTStringAttributes +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using CoreText; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.CoreText; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using System.Drawing; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreText +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class CTLineTests + { + [Test] + public void EnumerateCaretOffsets () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + var sa = new CTStringAttributes (); + sa.ForegroundColor = UIColor.Blue.CGColor; + sa.Font = new CTFont ("Georgia-BoldItalic", 24); + sa.UnderlineStyle = CTUnderlineStyle.Double; // It does not seem to do anything + sa.UnderlineColor = UIColor.Blue.CGColor; + sa.UnderlineStyleModifiers = CTUnderlineStyleModifiers.PatternDashDotDot; + + var attributedString = new NSAttributedString ("Hello world.\nWoohooo!\nThere", sa); + + var line = new CTLine (attributedString); + bool executed = false; +#if XAMCORE_2_0 + line.EnumerateCaretOffsets ((double o, nint charIndex, bool leadingEdge, ref bool stop) => { +#else + line.EnumerateCaretOffsets ((double o, int charIndex, bool leadingEdge, ref bool stop) => { +#endif + executed = true; + }); + Assert.IsTrue (executed); + } + + [Test] + public void GetImageBounds () + { + using (var a = new NSAttributedString ()) + using (var l = new CTLine (a)) { + Assert.True (l.GetImageBounds (null).IsEmpty, "GetImageBounds"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreText/FontDescriptorTest.cs b/tests/monotouch-test/CoreText/FontDescriptorTest.cs new file mode 100644 index 000000000000..308628c40e98 --- /dev/null +++ b/tests/monotouch-test/CoreText/FontDescriptorTest.cs @@ -0,0 +1,91 @@ +// +// Unit tests for CTFontDescriptor +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreText; +using UIKit; +#else +using MonoTouch.CoreText; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using System.Linq; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreText { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FontDescriptorTest { + + [Test] + // http://stackoverflow.com/questions/9007991/monotouch-custom-font-with-attributes/9009161#9009161 + public void FromAttributes () + { + CTFontDescriptorAttributes fda = new CTFontDescriptorAttributes () { + FamilyName = "Courier", + StyleName = "Bold", + Size = 16.0f + }; + using (CTFontDescriptor fd = new CTFontDescriptor (fda)) + using (CTFont font = new CTFont (fd, 0)) { + // check that the created font match the descriptor's attributes + Assert.That (font.FamilyName, Is.EqualTo ("Courier"), "FamilyName"); + Assert.That (font.FullName, Is.EqualTo ("Courier Bold"), "FullName"); + Assert.That (font.Size, Is.EqualTo ((nfloat)16), "Size"); + // that changed in iOS 8.3, there's an undocumented flag + MonoSpace (make sense) + bold + Assert.True ((font.SymbolicTraits & CTFontSymbolicTraits.Bold) != 0, "SymbolicTraits"); + } + } + + [Test] + public void WithFeature () + { +#if __TVOS__ + var fontName = "Gujarati Sangam MN"; +#else + var fontName = "HoeflerText-Regular"; +#endif + + using (var font = new CTFont (fontName, 10)) { + var f1 = font.GetFeatures (); + var ligatures = f1.Where (l => l.FeatureGroup == FontFeatureGroup.Ligatures).First (); + bool rare = ligatures.Selectors.Cast ().Any (l => l.Feature == CTFontFeatureLigatures.Selector.RareLigaturesOn); + Assert.That (rare, Is.True, "RareLigaturesOn available"); + Assert.That (font.GetFeatureSettings (), Is.Empty, "No custom settings"); + + } + + using (var fd = new CTFontDescriptor (fontName, 20)) + using (var rare_on_fd = fd.WithFeature (CTFontFeatureLigatures.Selector.RareLigaturesOn)) + using (var font = new CTFont (rare_on_fd, 13)) { + var set_feature = font.GetFeatureSettings ()[0]; + + Assert.That (set_feature.FeatureGroup, Is.EqualTo (FontFeatureGroup.Ligatures), "#1"); + Assert.That (set_feature.FeatureWeak, Is.EqualTo ((int)CTFontFeatureLigatures.Selector.RareLigaturesOn), "#2"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreText/FontManagerTest.cs b/tests/monotouch-test/CoreText/FontManagerTest.cs new file mode 100644 index 000000000000..668e0357cdb7 --- /dev/null +++ b/tests/monotouch-test/CoreText/FontManagerTest.cs @@ -0,0 +1,136 @@ +// +// Unit tests for CTFontManager +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using CoreText; +using UIKit; +#else +using MonoTouch.CoreText; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using System.Linq; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreText { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FontManagerTest { + + [Test] + public void RegisterTTF () + { + var ttf = Path.GetFullPath ("Pacifico.ttf"); + if (!File.Exists (ttf)) + Assert.Ignore ("Could not find the font file {0}", ttf); + + var url = NSUrl.FromFilename (ttf); + var err = CTFontManager.RegisterFontsForUrl (url, CTFontManagerScope.Process); + Assert.IsNull (err, "err 1"); + err = CTFontManager.UnregisterFontsForUrl (url, CTFontManagerScope.Process); + Assert.IsNull (err, "err 2"); + + url = NSUrl.FromFilename (Path.GetFullPath ("NonExistent.ttf")); + err = CTFontManager.RegisterFontsForUrl (url, CTFontManagerScope.Process); + Assert.IsNotNull (err, "err 3"); + err = CTFontManager.UnregisterFontsForUrl (url, CTFontManagerScope.Process); + Assert.IsNotNull (err, "err 4"); + } + + [Test] + public void RegisterTTFs () + { + var ttf = Path.GetFullPath ("Pacifico.ttf"); + if (!File.Exists (ttf)) + Assert.Ignore ("Could not find the font file {0}", ttf); + + var url = NSUrl.FromFilename (ttf); + var err = CTFontManager.RegisterFontsForUrl (new [] { url }, CTFontManagerScope.Process); + Assert.IsNull (err, "err 1"); + err = CTFontManager.UnregisterFontsForUrl (new [] { url }, CTFontManagerScope.Process); + Assert.IsNull (err, "err 2"); + + url = NSUrl.FromFilename (Path.GetFullPath ("NonExistent.ttf")); + err = CTFontManager.RegisterFontsForUrl (new [] { url }, CTFontManagerScope.Process); + Assert.IsNotNull (err, "err 3"); + Assert.AreEqual (1, err.Length, "err 3 l"); + Assert.IsNotNull (err [0], "err 3[0]"); + err = CTFontManager.UnregisterFontsForUrl (new [] { url }, CTFontManagerScope.Process); + Assert.IsNotNull (err, "err 4"); + Assert.AreEqual (1, err.Length, "err 4 l"); + Assert.IsNotNull (err [0], "err 4[0]"); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void GetFontsNullUrl () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7,0)) + Assert.Ignore ("Requires iOS 7.0+"); + var fonts = CTFontManager.GetFonts (null); + } + + [Test] + public void GetFontsPresent () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7,0)) + Assert.Ignore ("Requires iOS 7.0+"); + var ttf = Path.GetFullPath ("Pacifico.ttf"); + if (!File.Exists (ttf)) + Assert.Ignore ("Could not find the font file {0}", ttf); + + var url = NSUrl.FromFilename (ttf); + var err = CTFontManager.RegisterFontsForUrl (url, CTFontManagerScope.Process); + Assert.IsNull (err, "Register error"); + + // method under test + var fonts = CTFontManager.GetFonts (url); + Assert.AreEqual (1, fonts.Length); + Assert.AreEqual ("Pacifico", fonts[0].GetAttributes().Name?.ToString ()); + + err = CTFontManager.UnregisterFontsForUrl (url, CTFontManagerScope.Process); + Assert.IsNull (err, "Unregister error"); + } + + [Test] + public void GetFontsMissing () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7,0)) + Assert.Ignore ("Requires iOS 7.0+"); + var ttf = Path.GetFullPath ("NonExistent.ttf"); + if (!File.Exists (ttf)) + Assert.Ignore ("Could not find the font file {0}", ttf); + + var url = NSUrl.FromFilename (ttf); + + // method under test + var fonts = CTFontManager.GetFonts (url); + Assert.AreEqual (0, fonts.Length); + } + + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreText/FontTest.cs b/tests/monotouch-test/CoreText/FontTest.cs new file mode 100644 index 000000000000..a26e0211e68c --- /dev/null +++ b/tests/monotouch-test/CoreText/FontTest.cs @@ -0,0 +1,128 @@ +// +// Unit tests for CTFont +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreGraphics; +using CoreText; +using Foundation; +using UIKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.CoreText; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreText { + + [TestFixture] + [Preserve (AllMembers = true)] + public class A_FontTest { + + [Test] + public void CTFontCreateWithNameAndOptions () + { + // Apple documents CTFontCreateWithNameAndOptions as availble since 3.2 but it does not work before 7.0 (e.g. 6.1) + // it seems to be a known issue, http://stackoverflow.com/q/4419283 but I still left feedback to Apple to fix it + try { + using (var font = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default)) { + Assert.That (font.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + catch (EntryPointNotFoundException) { + Assert.True (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0), "< iOS 7.0"); + } + } + + [Test] + public void CTFontCreateWithFontDescriptorAndOptions () + { + // Apple documents CTFontCreateWithFontDescriptorAndOptions as availble since 3.2 but it does not work before 7.0 (e.g. 6.1) + // it seems to be a known issue, http://stackoverflow.com/q/4419283 but I still left feedback to Apple to fix it + try { + CTFontDescriptorAttributes fda = new CTFontDescriptorAttributes () { + FamilyName = "Courier", + StyleName = "Bold", + Size = 16.0f + }; + using (var fd = new CTFontDescriptor (fda)) + using (var font = new CTFont (fd, 10, CTFontOptions.Default)) { + Assert.That (font.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + catch (EntryPointNotFoundException) { + Assert.True (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0), "< iOS 7.0"); + } + } + + [Test] + public void GetCascadeList () + { + try { + using (var font = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default)) { + Assert.NotNull (font.GetDefaultCascadeList (null), "null"); + } + } + catch (EntryPointNotFoundException) { + Assert.True (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0), "< iOS 7.0"); + } + } + + [Test] + public void GetLocalizedName () + { + try { + using (var font = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default)) { + Assert.NotNull (font.GetLocalizedName (CTFontNameKey.Copyright), "1"); + + // We need to check if we are using english as our main language since this is the known case + // that the following code works. It fails with spanish for example but it is a false positive + // because the localized name for this font Full option does not have a spanish representation + var language = NSLocale.PreferredLanguages [0]; + if (language == "en") { + string str; + Assert.NotNull (font.GetLocalizedName (CTFontNameKey.Full, out str), "2"); + Assert.NotNull (str, "out str"); + } + } + } + catch (EntryPointNotFoundException) { + Assert.True (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0), "< iOS 7.0"); + } + } + + [Test] + public void GetGlyphsForCharacters_35048 () + { + using (var font = CGFont.CreateWithFontName ("AppleColorEmoji")) + using (var ctfont = font.ToCTFont ((nfloat) 10.0)) { + ushort[] gid = new ushort [2]; + Assert.True (ctfont.GetGlyphsForCharacters ("\ud83d\ude00".ToCharArray (), gid), "GetGlyphsForCharacters"); + Assert.That (gid [0], Is.Not.EqualTo (0), "0"); + Assert.That (gid [1], Is.EqualTo (0), "1"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreText/StringAttributes.cs b/tests/monotouch-test/CoreText/StringAttributes.cs new file mode 100644 index 000000000000..d202e9f364a8 --- /dev/null +++ b/tests/monotouch-test/CoreText/StringAttributes.cs @@ -0,0 +1,81 @@ +// +// Unit tests for CTStringAttributes +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using CoreText; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.CoreText; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using System.Drawing; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreText +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class StringAttributesTests + { + [Test] + public void SimpleValuesSet () + { + var sa = new CTStringAttributes (); + sa.ForegroundColor = UIColor.Blue.CGColor; + sa.Font = new CTFont ("Georgia-BoldItalic", 24); + sa.UnderlineStyle = CTUnderlineStyle.Double; // It does not seem to do anything + sa.UnderlineColor = UIColor.Blue.CGColor; + sa.UnderlineStyleModifiers = CTUnderlineStyleModifiers.PatternDashDotDot; + + // CTBaseline and CTWritingDirection support is new in iOS 6.0 and cause NRE before it + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + Assert.IsNull (sa.BaselineClass, "#0"); + sa.BaselineClass = CTBaselineClass.IdeographicHigh; + Assert.AreEqual (CTBaselineClass.IdeographicHigh, sa.BaselineClass, "#1"); + + sa.SetBaselineInfo (CTBaselineClass.Roman, 13); + sa.SetBaselineInfo (CTBaselineClass.IdeographicHigh, 3); + sa.SetWritingDirection (CTWritingDirection.LeftToRight); + } + + var size = new SizeF (300, 300); + UIGraphics.BeginImageContext (size); + var gctx = UIGraphics.GetCurrentContext (); + + gctx.SetFillColor (UIColor.Green.CGColor); + + var attributedString = new NSAttributedString ("Test_ME~`", sa); + + using (var textLine = new CTLine (attributedString)) { + textLine.Draw (gctx); + } + + UIGraphics.EndImageContext (); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreVideo/CoreVideoEnumsTest.cs b/tests/monotouch-test/CoreVideo/CoreVideoEnumsTest.cs new file mode 100644 index 000000000000..95d01c67eed8 --- /dev/null +++ b/tests/monotouch-test/CoreVideo/CoreVideoEnumsTest.cs @@ -0,0 +1,83 @@ +// +// Unit tests for 4cc-based enums +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreVideo; +using Foundation; +using UIKit; +#else +using MonoTouch.CoreVideo; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreVideo { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CoreVideoEnumTest { + + string FourCC (int value) + { + return new string (new char [] { + (char) (byte) (value >> 24), + (char) (byte) (value >> 16), + (char) (byte) (value >> 8), + (char) (byte) value }); + } + + [Test] + public void PixelFormatType () + { + Assert.That (FourCC ((int) CVPixelFormatType.CV16LE555), Is.EqualTo ("L555"), "CV16LE555"); + Assert.That (FourCC ((int) CVPixelFormatType.CV16LE5551), Is.EqualTo ("5551"), "CV16LE5551"); + Assert.That (FourCC ((int) CVPixelFormatType.CV16BE565), Is.EqualTo ("B565"), "CV16BE565"); + Assert.That (FourCC ((int) CVPixelFormatType.CV16LE565), Is.EqualTo ("L565"), "CV16LE565"); + Assert.That (FourCC ((int) CVPixelFormatType.CV24BGR), Is.EqualTo ("24BG"), "CV24BGR"); + Assert.That (FourCC ((int) CVPixelFormatType.CV32BGRA), Is.EqualTo ("BGRA"), "CV32BGRA"); + Assert.That (FourCC ((int) CVPixelFormatType.CV32ABGR), Is.EqualTo ("ABGR"), "CV32ABGR"); + Assert.That (FourCC ((int) CVPixelFormatType.CV32RGBA), Is.EqualTo ("RGBA"), "CV32RGBA"); + Assert.That (FourCC ((int) CVPixelFormatType.CV64ARGB), Is.EqualTo ("b64a"), "CV64ARGB"); + Assert.That (FourCC ((int) CVPixelFormatType.CV48RGB), Is.EqualTo ("b48r"), "CV48RGB"); + Assert.That (FourCC ((int) CVPixelFormatType.CV32AlphaGray), Is.EqualTo ("b32a"), "CV32AlphaGray"); + Assert.That (FourCC ((int) CVPixelFormatType.CV16Gray), Is.EqualTo ("b16g"), "CV16Gray"); + Assert.That (FourCC ((int) CVPixelFormatType.CV422YpCbCr8), Is.EqualTo ("2vuy"), "CV422YpCbCr8"); + Assert.That (FourCC ((int) CVPixelFormatType.CV4444YpCbCrA8), Is.EqualTo ("v408"), "CV4444YpCbCrA8"); + Assert.That (FourCC ((int) CVPixelFormatType.CV4444YpCbCrA8R), Is.EqualTo ("r408"), "CV4444YpCbCrA8R"); + Assert.That (FourCC ((int) CVPixelFormatType.CV444YpCbCr8), Is.EqualTo ("v308"), "CV444YpCbCr8"); + Assert.That (FourCC ((int) CVPixelFormatType.CV422YpCbCr16), Is.EqualTo ("v216"), "CV422YpCbCr16"); + Assert.That (FourCC ((int) CVPixelFormatType.CV422YpCbCr10), Is.EqualTo ("v210"), "CV422YpCbCr10"); + Assert.That (FourCC ((int) CVPixelFormatType.CV444YpCbCr10), Is.EqualTo ("v410"), "CV444YpCbCr10"); + Assert.That (FourCC ((int) CVPixelFormatType.CV420YpCbCr8Planar), Is.EqualTo ("y420"), "CV420YpCbCr8Planar"); + Assert.That (FourCC ((int) CVPixelFormatType.CV420YpCbCr8PlanarFullRange), Is.EqualTo ("f420"), "CV420YpCbCr8PlanarFullRange"); + Assert.That (FourCC ((int) CVPixelFormatType.CV422YpCbCr_4A_8BiPlanar), Is.EqualTo ("a2vy"), "CV422YpCbCr_4A_8BiPlanar"); + Assert.That (FourCC ((int) CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange), Is.EqualTo ("420v"), "CV420YpCbCr8BiPlanarVideoRange"); + Assert.That (FourCC ((int) CVPixelFormatType.CV420YpCbCr8BiPlanarFullRange), Is.EqualTo ("420f"), "CV420YpCbCr8BiPlanarFullRange"); + Assert.That (FourCC ((int) CVPixelFormatType.CV422YpCbCr8_yuvs), Is.EqualTo ("yuvs"), "CV422YpCbCr8_yuvs"); + Assert.That (FourCC ((int) CVPixelFormatType.CV422YpCbCr8FullRange), Is.EqualTo ("yuvf"), "CV422YpCbCr8FullRange"); + Assert.That (FourCC ((int) CVPixelFormatType.CV30RGB), Is.EqualTo ("R10k"), "CV30RGB"); + Assert.That (FourCC ((int) CVPixelFormatType.CV4444AYpCbCr8), Is.EqualTo ("y408"), "CV4444AYpCbCr8"); + Assert.That (FourCC ((int) CVPixelFormatType.CV4444AYpCbCr16), Is.EqualTo ("y416"), "CV4444AYpCbCr16"); + Assert.That (FourCC ((int) CVPixelFormatType.OneComponent8), Is.EqualTo ("L008"), "OneComponent8"); + Assert.That (FourCC ((int) CVPixelFormatType.TwoComponent8), Is.EqualTo ("2C08"), "TwoComponent8"); + Assert.That (FourCC ((int) CVPixelFormatType.OneComponent16Half), Is.EqualTo ("L00h"), "OneComponent16Half"); + Assert.That (FourCC ((int) CVPixelFormatType.OneComponent32Float), Is.EqualTo ("L00f"), "OneComponent32Float"); + Assert.That (FourCC ((int) CVPixelFormatType.TwoComponent16Half), Is.EqualTo ("2C0h"), "TwoComponent16Half"); + Assert.That (FourCC ((int) CVPixelFormatType.TwoComponent32Float), Is.EqualTo ("2C0f"), "TwoComponent32Float"); + Assert.That (FourCC ((int) CVPixelFormatType.CV64RGBAHalf), Is.EqualTo ("RGhA"), "CV64RGBAHalf"); + Assert.That (FourCC ((int) CVPixelFormatType.CV128RGBAFloat), Is.EqualTo ("RGfA"), "CV128RGBAFloat"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreVideo/PixelBufferAttributesTest.cs b/tests/monotouch-test/CoreVideo/PixelBufferAttributesTest.cs new file mode 100644 index 000000000000..0dfadbbf28ef --- /dev/null +++ b/tests/monotouch-test/CoreVideo/PixelBufferAttributesTest.cs @@ -0,0 +1,61 @@ +// Unit tests for CVPixelBufferAttributes +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreFoundation; +using Foundation; +using CoreVideo; +using ObjCRuntime; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreVideo; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreVideo { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PixelBufferAttributesTest { + + [Test] + public void Defaults () + { + var options = new CVPixelBufferAttributes (); + Assert.That (options.Dictionary.Count, Is.EqualTo (0), "Count"); + Assert.Null (options.MemoryAllocator, "MemoryAllocator"); + } + + [Test] + public void MemoryAllocator () + { + var options = new CVPixelBufferAttributes () { + MemoryAllocator = CFAllocator.MallocZone + }; + Assert.That (options.Dictionary.Count, Is.EqualTo (1), "Count"); + Assert.That (options.MemoryAllocator.Handle, Is.EqualTo (CFAllocator.MallocZone.Handle), "MemoryAllocator"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreVideo/PixelBufferPoolTest.cs b/tests/monotouch-test/CoreVideo/PixelBufferPoolTest.cs new file mode 100644 index 000000000000..a1ca3f892859 --- /dev/null +++ b/tests/monotouch-test/CoreVideo/PixelBufferPoolTest.cs @@ -0,0 +1,52 @@ +// +// Unit tests for CVPixelBufferPool +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using CoreVideo; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreVideo; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreVideo { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PixelBufferPoolTest + { + [Test] + public void AllocationSettings_Threshold () + { + var pbp = new CVPixelBufferPool ( + new CVPixelBufferPoolSettings (), + new CVPixelBufferAttributes (CVPixelFormatType.CV24RGB, 100, 50) + ); + + var a = new CVPixelBufferPoolAllocationSettings () { + Threshold = 2 + }; + + CVReturn error; + Assert.IsNotNull (pbp.CreatePixelBuffer (a, out error), "#1"); + Assert.IsNotNull (pbp.CreatePixelBuffer (a, out error), "#2"); + Assert.IsNull (pbp.CreatePixelBuffer (a, out error), "#3"); + Assert.AreEqual (CVReturn.WouldExceedAllocationThreshold, error, "#3a"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreVideo/PixelBufferTest.cs b/tests/monotouch-test/CoreVideo/PixelBufferTest.cs new file mode 100644 index 000000000000..c9e0b017d5bd --- /dev/null +++ b/tests/monotouch-test/CoreVideo/PixelBufferTest.cs @@ -0,0 +1,108 @@ +// +// Unit tests for CVPixelBuffer +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using CoreVideo; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreVideo; + +using nint = System.Int32; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreVideo { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PixelBufferTest + { + [Test] + public void CreateWithBytes () + { + nint width = 1280; + nint height = 720; + nint bytesPerRow = width * 4; + CVReturn status; + + var data = new byte [height * bytesPerRow]; + + using (var buf = CVPixelBuffer.Create (width, height, CVPixelFormatType.CV32RGBA, data, bytesPerRow, null, out status)) { + Assert.AreEqual (status, CVReturn.InvalidPixelFormat, "CV32RGBA"); + Assert.IsNull (buf, "CV32RGBA - null"); + } + + using (var buf = CVPixelBuffer.Create (width, height, CVPixelFormatType.CV32BGRA, data, bytesPerRow, null, out status)) { + Assert.AreEqual (status, CVReturn.Success, "CV32RGBA"); + Assert.IsNotNull (buf, "CV32BGRA - null"); + } + + var dict = new CVPixelBufferAttributes (); + using (var buf = CVPixelBuffer.Create (width, height, CVPixelFormatType.CV32BGRA, data, bytesPerRow, dict)) { + Assert.IsNotNull (buf); + } + + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV32BGRA, null, bytesPerRow, null), "null data"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV32BGRA, data, bytesPerRow + 1, null), "bytesPerRow+1"); + Assert.Throws (() => CVPixelBuffer.Create (width, height + 1, CVPixelFormatType.CV32BGRA, data, bytesPerRow + 1, null), "height+1"); + } + + [Test] + public void CreateWithPlanarBytes () + { + nint width = 1280; + nint height = 720; + nint[] planeWidths = new nint[] { width, width / 2 }; + nint[] planeHeights = new nint[] { height, height / 2 }; + nint[] planeBytesPerRow = new nint[] { width, width }; + CVReturn status; + + var data = new byte[][] { + new byte [planeHeights [0] * planeBytesPerRow [0]], + new byte [planeHeights [1] * planeBytesPerRow [1]], + }; + + using (var buf = CVPixelBuffer.Create (width, height, CVPixelFormatType.CV32RGBA, data, planeWidths, planeHeights, planeBytesPerRow, null, out status)) { + Assert.IsNull (buf); + Assert.AreEqual (CVReturn.InvalidPixelFormat, status, "invalid status"); + } + + using (var buf = CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, planeHeights, planeBytesPerRow, null)) { + Assert.IsNotNull (buf); + } + + var dict = new CVPixelBufferAttributes (); + using (var buf = CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, planeHeights, planeBytesPerRow, dict)) { + Assert.IsNotNull (buf); + } + + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, null, planeWidths, planeHeights, planeBytesPerRow, null), "null data"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, null, planeHeights, planeBytesPerRow, null), "null widths"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, null, planeBytesPerRow, null), "null heights"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, planeHeights, null, null), "null bytesPerRow"); + + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, new nint[] { width }, planeHeights, planeBytesPerRow, null), "invalid widths a"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, new nint[] { width, width, width }, planeHeights, planeBytesPerRow, null), "invalid widths b"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, new nint[] { height }, planeBytesPerRow, null), "invalid heights a"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, new nint[] { height, height, height }, planeBytesPerRow, null), "invalid heights b"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, planeHeights, new nint [] { width }, null), "invalid bytesPerRow"); + Assert.Throws (() => CVPixelBuffer.Create (width, height, CVPixelFormatType.CV420YpCbCr8BiPlanarVideoRange, data, planeWidths, planeHeights, new nint [] { width, width, width }, null), "invalid bytesPerRow"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs b/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs new file mode 100644 index 000000000000..bdea098749bc --- /dev/null +++ b/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs @@ -0,0 +1,82 @@ +// +// Unit tests for CVPixelFormatDescription +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreVideo; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreVideo; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.CoreVideo { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PixelFormatDescriptionTest { + + [Test] + public void AllTypes () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=13917 + Assert.NotNull (CVPixelFormatDescription.AllTypes); + } + + [Test] + public void Create () + { + // 0 is not defined + Assert.Null (CVPixelFormatDescription.Create (0), "0"); + + using (var dict = CVPixelFormatDescription.Create (CVPixelFormatType.CV16Gray)) { + Assert.NotNull (dict, "CV16Gray"); + } + + using (var dict = CVPixelFormatDescription.Create (CVPixelFormatType.CV32ARGB)) { + Assert.NotNull (dict, "CV32ARGB"); + } + } + + static bool registerDone; + [Test] + public void Register () + { + if (registerDone) + Assert.Ignore ("This test can only be executed once, it modifies global state."); + registerDone = true; + + Assert.Null (CVPixelFormatDescription.Create ((CVPixelFormatType) 3), "3a"); + + using (var dict = CVPixelFormatDescription.Create (CVPixelFormatType.CV24RGB)) { + Assert.NotNull (dict, "CV24RGB"); + CVPixelFormatDescription.Register (dict, (CVPixelFormatType) 3); + } + + Assert.NotNull (CVPixelFormatDescription.Create ((CVPixelFormatType) 3), "3b"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/CoreVideo/PixelFormatTypeTest.cs b/tests/monotouch-test/CoreVideo/PixelFormatTypeTest.cs new file mode 100644 index 000000000000..d60534266ea5 --- /dev/null +++ b/tests/monotouch-test/CoreVideo/PixelFormatTypeTest.cs @@ -0,0 +1,48 @@ +// +// Unit tests for PixelFormatType +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using CoreVideo; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.CoreVideo; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreVideo { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PixelFormatTypeTest { + + string FourCC (int value) + { + return new string (new char [] { + (char) (byte) (value >> 24), + (char) (byte) (value >> 16), + (char) (byte) (value >> 8), + (char) (byte) value }); + } + + [Test] + public void FourCC () + { + Assert.That (FourCC ((int) CVPixelFormatType.OneComponent8), Is.EqualTo ("L008"), "OneComponent8"); + Assert.That (FourCC ((int) CVPixelFormatType.TwoComponent8), Is.EqualTo ("2C08"), "TwoComponent8"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/EmptyNib.xib b/tests/monotouch-test/EmptyNib.xib new file mode 100644 index 000000000000..9c4e9c6d015c --- /dev/null +++ b/tests/monotouch-test/EmptyNib.xib @@ -0,0 +1,74 @@ + + + + 1280 + 11C25 + 1919 + 1138.11 + 566.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 916 + + + IBProxyObject + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + + + + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 1 + + + 0 + IBCocoaTouchFramework + YES + 3 + 916 + + diff --git a/tests/monotouch-test/Entitlements.plist b/tests/monotouch-test/Entitlements.plist new file mode 100644 index 000000000000..3745ea4f517a --- /dev/null +++ b/tests/monotouch-test/Entitlements.plist @@ -0,0 +1,16 @@ + + + + + com.apple.developer.ubiquity-kvstore-identifier + $(TeamIdentifierPrefix)com.xamarin.monotouch-test + keychain-access-groups + + $(AppIdentifierPrefix)com.xamarin.monotouch-test + + com.apple.developer.pass-type-identifiers + + A93A5CM278.tests/monotouch-test/Entitlements.plist + + + diff --git a/tests/monotouch-test/EventKit/AlarmTest.cs b/tests/monotouch-test/EventKit/AlarmTest.cs new file mode 100644 index 000000000000..ad1f883663f1 --- /dev/null +++ b/tests/monotouch-test/EventKit/AlarmTest.cs @@ -0,0 +1,45 @@ +// +// Unit tests for EKAlarm +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using EventKit; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AlarmTest { + + [Test] + public void NullAllowedTest () + { + using (var alarm = new EKAlarm ()) { + alarm.AbsoluteDate = null; + alarm.StructuredLocation = null; + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/EventKit/CalendarItemTest.cs b/tests/monotouch-test/EventKit/CalendarItemTest.cs new file mode 100644 index 000000000000..f4db7ef5584b --- /dev/null +++ b/tests/monotouch-test/EventKit/CalendarItemTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for EKCalendarItem +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using EventKit; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CalendarItemTest { + + [Test] + public void NullAllowedTest () + { + using (var item = new EKCalendarItem ()) { + item.Notes = null; + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/EventKit/CalendarTest.cs b/tests/monotouch-test/EventKit/CalendarTest.cs new file mode 100644 index 000000000000..1ac7797a6582 --- /dev/null +++ b/tests/monotouch-test/EventKit/CalendarTest.cs @@ -0,0 +1,102 @@ +// +// Unit tests for EKCalendar +// +// Authors: +// Sebastien Pouliot +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using ObjCRuntime; +using EventKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EventKitCalendarTest { + + // note: default .ctor disable since it would thrown an objective-c exception telling us to use 'calendarWithEventStore:' + [Test] + public void FromEventStore () + { + EKEventStore store = new EKEventStore (); + var c = EKCalendar.FromEventStore (store); + // defaults + Assert.True (c.AllowsContentModifications, "AllowsContentModifications"); + Assert.NotNull (c.CalendarIdentifier, "CalendarIdentifier"); + Assert.Null (c.CGColor, "CGColor"); + + if (TestRuntime.CheckSystemAndSDKVersion (6, 0)) { + // default value changed for iOS 6.0 beta 1 + Assert.False (c.Immutable, "Immutable"); + // new in 6.0 + Assert.AreEqual (EKEntityMask.Event, c.AllowedEntityTypes, "AllowedEntityTypes"); + } else { + Assert.True (c.Immutable, "Immutable"); + } + + Assert.Null (c.Source, "Source"); + Assert.False (c.Subscribed, "Subscribed"); + Assert.That (c.SupportedEventAvailabilities, Is.EqualTo (EKCalendarEventAvailability.None), "SupportedEventAvailabilities"); + Assert.Null (c.Title, "Title"); + Assert.That (c.Type, Is.EqualTo (EKCalendarType.Local), "Type"); + } + + [Test] + public void FromEventStoreWithReminder () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("+[EKCalendar calendarForEntityType:eventStore:]: unrecognized selector before 6.0"); + + var c = EKCalendar.Create (EKEntityType.Reminder, new EKEventStore ()); + // defaults + Assert.True (c.AllowsContentModifications, "AllowsContentModifications"); + Assert.NotNull (c.CalendarIdentifier, "CalendarIdentifier"); + Assert.Null (c.CGColor, "CGColor"); + + Assert.False (c.Immutable, "Immutable"); + Assert.Null (c.Source, "Source"); + Assert.False (c.Subscribed, "Subscribed"); + Assert.That (c.SupportedEventAvailabilities, Is.EqualTo (EKCalendarEventAvailability.None), "SupportedEventAvailabilities"); + Assert.Null (c.Title, "Title"); + Assert.That (c.Type, Is.EqualTo (EKCalendarType.Local), "Type"); + Assert.AreEqual (EKEntityMask.Reminder, c.AllowedEntityTypes, "AllowedEntityTypes"); + Assert.IsNotNull (c.CalendarIdentifier, "CalendarIdentifier"); + } + + [Test] + public void Title () + { + EKEventStore store = new EKEventStore (); + var c = EKCalendar.FromEventStore (store); + c.Title = "my title"; + Assert.That (c.Title, Is.EqualTo ("my title"), "Title"); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromEventStore_Null () + { + EKCalendar.FromEventStore (null); + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/EventKit/EventStoreTest.cs b/tests/monotouch-test/EventKit/EventStoreTest.cs new file mode 100644 index 000000000000..0bdb257f81a2 --- /dev/null +++ b/tests/monotouch-test/EventKit/EventStoreTest.cs @@ -0,0 +1,111 @@ +// +// Unit tests for EKEventStore +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using EventKit; +#else +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; +using System.Threading; +using System.Linq; + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EventStoreTest + { + [Test] + [Ignore ("fail on a cleaned iOS 6 simulator and (differently) on devices")] + public void DefaultCalendar () + { + var store = new EKEventStore (); + Assert.AreEqual ("Calendar", store.DefaultCalendarForNewEvents.Title, "DefaultCalendarForNewEvents"); + Assert.IsNull (store.DefaultCalendarForNewReminders, "DefaultCalendarForNewReminders"); + Assert.IsNotNull (store.Calendars, "Calendars"); + Assert.IsNotNull (store.Sources, "Sources"); + } + +#if false + // The EKEventStore constructor is no longer availble on iOS 6 Beta 4 + + [Test] + [Ignore ("fail on a cleaned iOS 6 simulator and (differently) on devices")] + public void DefaultReminder () + { + var store = new EKEventStore (EKEntityMask.Reminder); + Assert.AreEqual ("Reminders", store.DefaultCalendarForNewReminders.Title, "DefaultCalendarForNewReminders"); + Assert.IsNull (store.DefaultCalendarForNewEvents, "DefaultCalendarForNewEvents"); + Assert.IsNotNull (store.Calendars, "Calendars"); + Assert.IsNotNull (store.Sources, "Sources"); + } + + [Test] + [Ignore ("fail on a cleaned iOS 6 simulator and (differently) on devices")] + public void GetCalendars () + { + var store = new EKEventStore (EKEntityMask.Reminder); + var calendars = store.GetCalendars (EKEntityType.Reminder); + Assert.AreEqual ("Reminders", calendars[0].Title, "#1"); + + calendars = store.GetCalendars (EKEntityType.Event); + Assert.AreEqual (0, calendars.Length, "#2"); + } + + [Test] + public void Predicates() + { + if (Runtime.Arch == Arch.DEVICE) + Assert.Inconclusive ("defaults are different on devices"); + + var store = new EKEventStore (EKEntityMask.Reminder); + var rem = EKReminder.Create (store); + rem.Calendar = store.DefaultCalendarForNewReminders; + + NSError error; + Assert.IsTrue (store.SaveReminder (rem, true, out error), "SaveReminder"); + + var predicate = store.PredicateForIncompleteReminders (null, null, new [] { rem.Calendar }); + var mre = new ManualResetEvent (false); + bool found = false; + store.FetchReminders (predicate, l => { + found = l.Any (ll => ll.ClassHandle == rem.ClassHandle); + mre.Set (); + }); + + Assert.IsTrue (mre.WaitOne (3000), "#1"); + Assert.IsTrue (found, "#2"); + + mre.Reset (); + predicate = store.PredicateForReminders (null); + + store.FetchReminders (predicate, l => mre.Set ()); + Assert.IsTrue (mre.WaitOne (3000), "#10"); + + mre.Reset (); + predicate = store.PredicateForCompleteReminders (null, null, null); + + store.FetchReminders (predicate, l => mre.Set ()); + Assert.IsTrue (mre.WaitOne (3000), "#20"); + + Assert.IsTrue (store.RemoveReminder (rem, true, out error), "RemoveReminder"); + } +#endif + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/EventKit/RecurrenceRule.cs b/tests/monotouch-test/EventKit/RecurrenceRule.cs new file mode 100644 index 000000000000..d8e15b42b25c --- /dev/null +++ b/tests/monotouch-test/EventKit/RecurrenceRule.cs @@ -0,0 +1,59 @@ +// +// Unit tests for EKRecurrenceRule +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using EventKit; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class RecurrenceRuleTest + { + [Test] + public void DefaultProperties () + { + using (var rule = new EKRecurrenceRule ()) { + Assert.AreEqual ("gregorian", rule.CalendarIdentifier, "CalendarIdentifier"); + Assert.IsNull (rule.RecurrenceEnd, "RecurrenceEnd"); + Assert.AreEqual (EKRecurrenceFrequency.Weekly, rule.Frequency, "Frequency"); + Assert.AreEqual (1, rule.Interval, "Interval"); + Assert.AreEqual (EKDay.Monday, rule.FirstDayOfTheWeek, "FirstDayOfTheWeek"); + Assert.IsNull (rule.DaysOfTheWeek, "DaysOfTheWeek"); + Assert.IsNull (rule.DaysOfTheMonth, "DaysOfTheMonth"); + Assert.IsNull (rule.DaysOfTheYear, "DaysOfTheYear"); + Assert.IsNull (rule.WeeksOfTheYear, "WeeksOfTheYear"); + Assert.IsNull (rule.MonthsOfTheYear, "MonthsOfTheYear"); + Assert.IsNull (rule.SetPositions, "SetPositions"); + } + } + + [Test] + public void Constructors () + { + using (var rule = new EKRecurrenceRule (EKRecurrenceFrequency.Daily, 9, null)) { + } + using (var rule = new EKRecurrenceRule (EKRecurrenceFrequency.Yearly, 8, null, null, null, null, null, null, null)) { + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/EventKit/ReminderTest.cs b/tests/monotouch-test/EventKit/ReminderTest.cs new file mode 100644 index 000000000000..31bbe2b726db --- /dev/null +++ b/tests/monotouch-test/EventKit/ReminderTest.cs @@ -0,0 +1,88 @@ +// +// Unit tests for EKReminder +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using EventKit; +using ObjCRuntime; +#else +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ReminderTest + { + [Test] + public void DefaultProperties () + { + using (var rem = new EKReminder ()) { + Assert.AreEqual (0, rem.Priority, "Priority"); + Assert.IsFalse (rem.Completed, "Completed"); + Assert.IsNull (rem.CompletionDate, "CompletionDate"); + Assert.IsNull (rem.StartDateComponents, "StartDateComponents"); + Assert.IsNull (rem.DueDateComponents, "DueDateComponents"); + + rem.Completed = true; + Assert.IsTrue (rem.Completed, "Completed - Changed"); + } + } + + [Test] + public void NullableProperties () + { + using (var rem = new EKReminder ()) { + rem.StartDateComponents = null; + rem.DueDateComponents = null; + rem.CompletionDate = null; + } + } + + [Test] + public void Range () + { + using (var rem = new EKReminder ()) { + // priority is documented to have a range of 0-9 but there's no validation in ObjC + // this test is here to ensure Apple does not start throwing native exceptions at some points + rem.Priority = -1; + Assert.That (rem.Priority, Is.EqualTo ((nint) (-1)), "-1"); + rem.Priority = 10; + Assert.That (rem.Priority, Is.EqualTo ((nint) 10), "10"); + + // The following tests fail randomly. +// // at some point values are ?normalized? but no exception is thrown +// rem.Priority = nint.MinValue; +// Assert.That (rem.Priority, Is.EqualTo ((nint) 0), "MinValue"); +// // exposed as an NSInteger but internal storage looks different +// rem.Priority = nint.MaxValue; +// Assert.That (rem.Priority, Is.EqualTo ((nint) (-1)), "MaxValue"); + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/EventKit/StructuredLocationTest.cs b/tests/monotouch-test/EventKit/StructuredLocationTest.cs new file mode 100644 index 000000000000..b05199747efe --- /dev/null +++ b/tests/monotouch-test/EventKit/StructuredLocationTest.cs @@ -0,0 +1,58 @@ +// +// Unit tests for EKStructuredLocation +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using EventKit; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.EventKit; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.EventKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class StructureLocationTest + { + [Test] + public void DefaultValues () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("EKStructuredLocation is new in 6.0"); + + var sl = new EKStructuredLocation (); + Assert.IsNull (sl.GeoLocation, "GeoLocation"); + Assert.AreEqual (0, sl.Radius, "Radius"); + Assert.IsNull (sl.Title, "Title"); + } + + [Test] + public void FromTitle () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("EKStructuredLocation is new in 6.0"); + + var sl = EKStructuredLocation.FromTitle ("my title"); + Assert.IsNull (sl.GeoLocation, "GeoLocation"); + Assert.AreEqual (0, sl.Radius, "Radius"); + Assert.AreEqual ("my title", sl.Title, "Title"); + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/ExternalAccessory/AccessoryManagerTest.cs b/tests/monotouch-test/ExternalAccessory/AccessoryManagerTest.cs new file mode 100644 index 000000000000..509818daf96c --- /dev/null +++ b/tests/monotouch-test/ExternalAccessory/AccessoryManagerTest.cs @@ -0,0 +1,52 @@ +// +// EAAccessoryManager Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ExternalAccessory; +#else +using MonoTouch.ExternalAccessory; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ExternalAccessory { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + [TestFixture] + public class AccessoryManagerTest { + + [Test] + public void Shared () + { + // reported to throw an InvalidCastException on http://stackoverflow.com/q/18884195/220643 + var am = EAAccessoryManager.SharedAccessoryManager; + // IsEmpty most of the time... unless you docked something, like a keyboard + Assert.IsNotNull (am.ConnectedAccessories, "ConnectedAccessories"); + } + + [Test] + public void ShowBluetoothAccessoryPicker () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("Requires iOS6+"); + + EAAccessoryManager.SharedAccessoryManager.ShowBluetoothAccessoryPicker (null, null); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/Foundation/ArrayTest.cs b/tests/monotouch-test/Foundation/ArrayTest.cs new file mode 100644 index 000000000000..578ca3b95ae4 --- /dev/null +++ b/tests/monotouch-test/Foundation/ArrayTest.cs @@ -0,0 +1,135 @@ +// +// Unit tests for NSArray +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using Security; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.Security; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSArrayTest { + + [Test] + public void FromStrings_NullItem () + { + try { + NSArray.FromStrings (new string [1]); + } + catch (Exception e) { + Assert.Fail ("Unexpected exception {0}", e); + } + } + + int comparator_count; + + // the new NSObject are often, but not always, in ascending order + // (because of how we allocate them) so we sort the other way +#if XAMCORE_2_0 + NSComparisonResult +#else + int +#endif + Comparator (NSObject obj1, NSObject obj2) + { + comparator_count++; + return +#if XAMCORE_2_0 + (NSComparisonResult) +#endif + (int) ((nint) obj2.Handle - (nint) obj1.Handle); + } + + [Test] + public void Sort () + { + comparator_count = 0; + using (var obj1 = new NSObject ()) + using (var obj2 = new NSObject ()) + using (var a = new NSMutableArray ()) { + a.Add (obj1); + a.Add (a); + a.Add (obj2); + using (var s = a.Sort (Comparator)) { + Assert.That ((nuint) s.ValueAt (0), Is.GreaterThan ((nuint) s.ValueAt (1)), "0"); + Assert.That ((nuint) s.ValueAt (1), Is.GreaterThan ((nuint) s.ValueAt (2)), "1"); + } + } + Assert.That (comparator_count, Is.GreaterThanOrEqualTo (2), "2+"); + } + + int evaluator_count; + + bool Evaluator (NSObject evaluatedObject, NSDictionary bindings) + { + evaluator_count++; + return (evaluatedObject is NSMutableArray); + } + + [Test] + public void Filter () + { + evaluator_count = 0; + using (var obj1 = new NSObject ()) + using (var obj2 = new NSObject ()) + using (var a = new NSMutableArray ()) { + a.Add (obj1); + a.Add (a); + a.Add (obj2); + using (NSPredicate p = NSPredicate.FromExpression (Evaluator)) + using (var f = a.Filter (p)) { + Assert.That (f.ValueAt (0), Is.EqualTo (a.Handle), "0"); + Assert.That (f.Count, Is.EqualTo ((nuint) 1), "Count"); + } + } + Assert.That (evaluator_count, Is.EqualTo (3), "3"); + } + + [Test] + public void INativeObjects () + { + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.xamarin.com")) { + using (var a = NSArray.FromObjects (policy)) { + var b = NSArray.ArrayFromHandle (a.Handle); + Assert.AreNotSame (a, b); + } + } + } + + [Test] + public void FromNSObjects () + { + using (var a = NSArray.FromNSObjects (null)) { + // on the managed side we have an empty array + Assert.That (a.Count, Is.EqualTo ((nuint) 0), "Count"); + // if we provide the handle to the ObjC it will be `nil` + Assert.That (a.Handle, Is.EqualTo (IntPtr.Zero), "Handle"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/AttributedStringTest.cs b/tests/monotouch-test/Foundation/AttributedStringTest.cs new file mode 100644 index 000000000000..1a26fb335850 --- /dev/null +++ b/tests/monotouch-test/Foundation/AttributedStringTest.cs @@ -0,0 +1,179 @@ +using System; +using NUnit.Framework; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using ObjCRuntime; +#if !__WATCHOS__ +using CoreText; +#endif +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouch.CoreText; +#endif + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class AttributedStringTest { + + CGColor red, yellow; + bool failEnum, t1, t2, tFont1, tFont2; + +#if !__WATCHOS__ + [Test] + public void Attributes () + { + red = UIColor.Red.CGColor; + yellow = UIColor.Yellow.CGColor; + + var j = new NSMutableAttributedString ("Hello", new CTStringAttributes() { ForegroundColor = red }); + j.Append (new NSMutableAttributedString ("12345", new CTStringAttributes() { ForegroundColor = yellow })); + j.EnumerateAttributes (new NSRange (0, 10), NSAttributedStringEnumeration.None, cb); + Assert.True (t1); + Assert.True (t2); + Assert.False (failEnum); + Assert.True (tFont1); + Assert.True (tFont2); + } +#endif // !__WATCHOS__ + + void cb (NSDictionary attrs, NSRange range, ref bool stop) + { + stop = false; + if (range.Location == 0){ + if (range.Length == 5){ + t1 = true; + tFont1 = attrs.ContainsKey (new NSString ("CTForegroundColor")); + } + } else if (range.Location == 5){ + if (range.Length == 5){ + t2 = true; + tFont2 = attrs.ContainsKey (new NSString ("CTForegroundColor")); + } + } else + failEnum = true; + } + + [Test] + public void Fields () + { + // fields are not available in iOS (at least up to 5.1.1) + // this test will fail if this ever change in the future + IntPtr lib = Dlfcn.dlopen (Constants.FoundationLibrary, 0); + try { + Assert.That (Dlfcn.dlsym (lib, "NSFontAttributeName"), Is.EqualTo (IntPtr.Zero), "NSFontAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSLinkAttributeName"), Is.EqualTo (IntPtr.Zero), "NSLinkAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSUnderlineStyleAttributeName"), Is.EqualTo (IntPtr.Zero), "NSUnderlineStyleAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSStrikethroughStyleAttributeName"), Is.EqualTo (IntPtr.Zero), "NSStrikethroughStyleAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSStrokeWidthAttributeName"), Is.EqualTo (IntPtr.Zero), "NSStrokeWidthAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSParagraphStyleAttributeName"), Is.EqualTo (IntPtr.Zero), "NSParagraphStyleAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSForegroundColorAttributeName"), Is.EqualTo (IntPtr.Zero), "NSForegroundColorAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSBackgroundColorAttributeName"), Is.EqualTo (IntPtr.Zero), "NSBackgroundColorAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSLigatureAttributeName"), Is.EqualTo (IntPtr.Zero), "NSLigatureAttributeName"); + Assert.That (Dlfcn.dlsym (lib, "NSObliquenessAttributeName"), Is.EqualTo (IntPtr.Zero), "NSObliquenessAttributeName"); + } + finally { + Dlfcn.dlclose (lib); + } + } + +#if !XAMCORE_2_0 + [Test] + public void UIKitAttachmentConveniences_Old () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("requires iOS7+"); + + NSAttributedString as1 = null; + // it's weird looking to use an instance (even null) so you can call a *static* category method... + using (var ta = new NSTextAttachment (null, null)) + using (var as2 = as1.FromTextAttachment (ta)) { + Assert.That (as2.Length, Is.EqualTo ((nint) 1), "Length"); + Assert.That (as2.Value [0], Is.EqualTo ((char)0xFFFC), "NSAttachmentCharacter"); + } + } +#endif + +#if !__WATCHOS__ + [Test] + public void UIKitAttachmentConveniences_New () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("requires iOS7+"); + + // so we added custom code calling the (old) category helper - but we had to pick a different name + using (var ta = new NSTextAttachment (null, null)) + using (var as2 = NSAttributedString.FromAttachment (ta)) { + Assert.That (as2.Length, Is.EqualTo ((nint) 1), "Length"); + Assert.That (as2.Value [0], Is.EqualTo ((char)0xFFFC), "NSAttachmentCharacter"); + } + } +#endif // !__WATCHOS__ + + [Test] + public void InitWith () + { + using (var s1 = new NSAttributedString ("string")) { + // initWithString: does not respond (see dontlink.app) but it works + Assert.That (s1.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-1"); + + using (var d = new NSDictionary ()) + using (var s2 = new NSAttributedString ("string", d)) { + // initWithString:attributes: does not respond (see dontlink.app) but it works + Assert.That (s2.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-2"); + } + + using (var s3 = new NSAttributedString (s1)) { + // initWithAttributedString: does not respond (see dontlink.app) but it works + Assert.That (s3.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-3"); + } + } + } + + [Test] + public void MutableCopy () + { + using (var s1 = new NSAttributedString ("string")) { + using (var copy = s1.MutableCopy ()) + Assert.That (copy.RetainCount, Is.EqualTo ((nint) 1), "Copy retaincount 1"); + using (var copy = ((INSMutableCopying) s1).MutableCopy (NSZone.Default)) + Assert.That (copy.RetainCount, Is.EqualTo ((nint) 1), "Copy retaincount 2"); + } + } + + [Test] + public void NullDictionary () + { + using (var s = new NSAttributedString ("string", (NSDictionary) null)) { + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero)); + } + } + +#if !__WATCHOS__ + [Test] + public void IndirectNullDictionary () + { + // that will call NSAttributedString.ToDictionary which may return null (if empty) + using (var s = new NSAttributedString ("string", foregroundColor: null)) { + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero)); + } + } +#endif // !__WATCHOS__ + } +} diff --git a/tests/monotouch-test/Foundation/BlockOperationTest.cs b/tests/monotouch-test/Foundation/BlockOperationTest.cs new file mode 100644 index 000000000000..6acd6acc8a6a --- /dev/null +++ b/tests/monotouch-test/Foundation/BlockOperationTest.cs @@ -0,0 +1,53 @@ +// +// Unit tests for NSBlockOperation +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BlockOperationTest { + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Create_Null () + { + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: *** -[NSBlockOperation addExecutionBlock:]: block is nil + NSBlockOperation.Create (null); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Add_Null () + { + using (var bo = NSBlockOperation.Create (Create_Null)) { + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: *** -[NSBlockOperation addExecutionBlock:]: block is nil + bo.AddExecutionBlock (null); + } + } + + [Test] + public void ExecutionBlocks () + { + using (var bo = NSBlockOperation.Create (Create_Null)) { + bo.AddExecutionBlock (Add_Null); + Assert.That (bo.ExecutionBlocks.Length, Is.EqualTo (2), "ExecutionBlocks"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/BundleTest.cs b/tests/monotouch-test/Foundation/BundleTest.cs new file mode 100644 index 000000000000..1fcf567ec7f8 --- /dev/null +++ b/tests/monotouch-test/Foundation/BundleTest.cs @@ -0,0 +1,143 @@ +// +// Unit tests for NSBundle +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BundleTest { + + NSBundle main = NSBundle.MainBundle; + + [Test] + public void LocalizedString2 () + { + string s = main.LocalizedString (null, "comment"); + Assert.That (s, Is.Empty, "key"); + + s = main.LocalizedString ("key", null); + Assert.That (s, Is.EqualTo ("key"), "comment"); + + s = main.LocalizedString (null, null); + Assert.That (s, Is.Empty, "all-null"); + } + + [Test] + public void LocalizedString3 () + { + string s = main.LocalizedString (null, "value", "table"); + Assert.That (s, Is.EqualTo ("value"), "key"); + + s = NSBundle.MainBundle.LocalizedString ("key", null, "table"); + Assert.That (s, Is.EqualTo ("key"), "value"); + + s = NSBundle.MainBundle.LocalizedString (null, "value", null); + Assert.That (s, Is.EqualTo ("value"), "comment"); + + s = main.LocalizedString (null, null, null); + Assert.That (s, Is.Empty, "all-null"); + } + + [Test] + public void LocalizedString4 () + { + string s = main.LocalizedString (null, "value", "table", "comment"); + Assert.That (s, Is.EqualTo ("value"), "key"); + + s = NSBundle.MainBundle.LocalizedString ("key", null, "table", "comment"); + Assert.That (s, Is.EqualTo ("key"), "value"); + + s = NSBundle.MainBundle.LocalizedString ("key", "value", null, "comment"); + Assert.That (s, Is.EqualTo ("value"), "table"); + + s = NSBundle.MainBundle.LocalizedString ("key", "value", "table", null); + Assert.That (s, Is.EqualTo ("value"), "comment"); + + s = main.LocalizedString (null, null, null, null); + Assert.That (s, Is.Empty, "all-null"); + } + + // http://developer.apple.com/library/ios/#documentation/uikit/reference/NSBundle_UIKitAdditions/Introduction/Introduction.html + +#if !__WATCHOS__ + [Test] + public void LoadNibWithOptions () + { + Assert.NotNull (main.LoadNib ("EmptyNib", main, null)); + } +#endif // !__WATCHOS__ + +#if false + // some selectors are only in AppKit but we included them in MonoTouch (and this match Apple documentation) + // https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSBundle_AppKitAdditions/Reference/Reference.html + + // I guess no one ever used them since they don't work... + // commented (selectors removed from MT bindings) - can be re-enabled to test newer iOS releases + [Test] + [ExpectedException (typeof (MonoTouchException))] + public void PathForImageResource () + { + main.PathForImageResource ("basn3p08.png"); + } + + [Test] + [ExpectedException (typeof (MonoTouchException))] + public void PathForSoundResource () + { + main.PathForSoundResource ("basn3p08.png"); + } + + [Test] + [ExpectedException (typeof (MonoTouchException))] + public void LoadNib () + { + NSBundle.LoadNib (String.Empty, main); + } +#endif + [Test] + public void Localizations () + { + string [] locz = main.Localizations; + Assert.That (locz.Length, Is.GreaterThanOrEqualTo (1), "Length"); + Assert.That (locz, Contains.Item ("en"), "en"); + } + + [Test] + public void PreferredLocalizations () + { + string [] locz = main.PreferredLocalizations; + Assert.That (locz.Length, Is.GreaterThanOrEqualTo (1), "Length"); + Assert.That (locz, Contains.Item ("en"), "en"); + } + + [Test] + public void AppStoreReceiptURL () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + // on iOS8 device this now ends with "/StoreKit/sandboxReceipt" + // instead of "/StokeKit/receipt" + Assert.That (main.AppStoreReceiptUrl.AbsoluteString, Is.StringEnding ("eceipt"), "AppStoreReceiptUrl"); + } + } +} diff --git a/tests/monotouch-test/Foundation/CachedUrlResponseTest.cs b/tests/monotouch-test/Foundation/CachedUrlResponseTest.cs new file mode 100644 index 000000000000..4159335472a2 --- /dev/null +++ b/tests/monotouch-test/Foundation/CachedUrlResponseTest.cs @@ -0,0 +1,37 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CachedUrlResponseTest { + + [Test] + public void ConstructorTest () + { + // See https://bugzilla.xamarin.com/show_bug.cgi?id=3835 + using (var response = new NSUrlResponse ()) + using (var data = new NSData ()) { + + // Test that UserInfo is NullAllowed + using (var res1 = new NSCachedUrlResponse (response, data, null, NSUrlCacheStoragePolicy.Allowed)) { + Assert.That (res1.StoragePolicy, Is.EqualTo (NSUrlCacheStoragePolicy.Allowed), "StoragePolicy-1"); + Assert.Null (res1.UserInfo, "UserInfo-1"); + } + + using (var res2 = new NSCachedUrlResponse (response, data)) { + Assert.That (res2.StoragePolicy, Is.EqualTo (NSUrlCacheStoragePolicy.Allowed), "StoragePolicy-2"); + Assert.Null (res2.UserInfo, "UserInfo-2"); + } + } + } + } +} diff --git a/tests/monotouch-test/Foundation/CalendarTest.cs b/tests/monotouch-test/Foundation/CalendarTest.cs new file mode 100644 index 000000000000..c5e0cb036ec7 --- /dev/null +++ b/tests/monotouch-test/Foundation/CalendarTest.cs @@ -0,0 +1,448 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CalendarTest { + + [Test] + public void DateComponentsTest () + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var now = DateTime.Now; + NSDateComponents comps; + + comps = cal.Components (NSCalendarUnit.Year | NSCalendarUnit.Month | NSCalendarUnit.Day, NSDate.Now); + Assert.AreEqual (now.Year, comps.Year, "a year"); + Assert.AreEqual (now.Month, comps.Month, "a month"); + Assert.AreEqual (now.Day, comps.Day, "a day"); + + comps = cal.Components (NSCalendarUnit.Hour, (NSDate) now.AddHours (-1), (NSDate) now, NSDateComponentsWrappingBehavior.None); + Assert.AreEqual (1, comps.Hour, "b hour"); + } + + [Test] + public void DateByAddingComponentsTest () + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var now = (NSDate) DateTime.Now; + var comps = new NSDateComponents (); + NSDate date; + + comps.Day = 2; + comps.TimeZone = NSTimeZone.FromAbbreviation ("UTC"); + cal.TimeZone = comps.TimeZone; + date = cal.DateByAddingComponents (comps, now, NSDateComponentsWrappingBehavior.None); + Assert.AreEqual (now.SecondsSinceReferenceDate + 3600 * 24 * 2, date.SecondsSinceReferenceDate, "a"); + } + + [Test] + public void DateFromComponents () + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var comps = new NSDateComponents (); + comps.Year = 1965; + comps.Month = 1; + comps.Day = 6; + comps.Hour = 14; + comps.Minute = 10; + comps.Second = 0; + comps.TimeZone = new NSTimeZone ("Europe/Madrid"); + var date = cal.DateFromComponents (comps); + Assert.AreEqual (-1135594200d, date.SecondsSinceReferenceDate, "a"); + } + + static void RequiresIos8 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8+"); + } + + public NSDate Yesterday { get { return NSDate.FromTimeIntervalSinceNow (-60 * 60 * 24); } } + public NSDate Tomorrow { get { return NSDate.FromTimeIntervalSinceNow (60 * 60 * 24); } } + public NSDate NowPlusTenSeconds { get { return NSDate.FromTimeIntervalSinceNow (10); } } + public NSDate NowPlusOneHour { get { return NSDate.FromTimeIntervalSinceNow (60 * 60); } } + public NSDate NowMinusTenSeconds { get { return NSDate.FromTimeIntervalSinceNow (-10); } } + + + [Test] + public void GetAllCalendarIdentifiers () + { + RequiresIos8 (); + + foreach (NSCalendarType t in Enum.GetValues(typeof(NSCalendarType))) { + NSCalendar c = new NSCalendar (t); + Assert.IsNotNull (c.Identifier, "Can't find identifier: " + t.ToString()); + } + } + + [Test] + public void TestCalendarSymbols () + { + RequiresIos8 (); + + Assert.IsTrue (NSCalendar.CurrentCalendar.EraSymbols.Length > 0, "EraSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.LongEraSymbols.Length > 0, "LongEraSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.MonthSymbols.Length > 0, "MonthSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.ShortMonthSymbols.Length > 0, "ShortMonthSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.VeryShortMonthSymbols.Length > 0, "VeryShortMonthSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.StandaloneMonthSymbols.Length > 0, "StandaloneMonthSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.ShortStandaloneMonthSymbols.Length > 0, "ShortStandaloneMonthSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.VeryShortStandaloneMonthSymbols.Length > 0, "VeryShortStandaloneMonthSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.WeekdaySymbols.Length > 0, "WeekdaySymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.ShortWeekdaySymbols.Length > 0, "ShortWeekdaySymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.VeryShortWeekdaySymbols.Length > 0, "VeryShortWeekdaySymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.StandaloneWeekdaySymbols.Length > 0, "StandaloneWeekdaySymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.ShortStandaloneWeekdaySymbols.Length > 0, "ShortStandaloneWeekdaySymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.VeryShortStandaloneWeekdaySymbols.Length > 0, "VeryShortStandaloneWeekdaySymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.QuarterSymbols.Length > 0, "QuarterSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.ShortQuarterSymbols.Length > 0, "ShortQuarterSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.StandaloneQuarterSymbols.Length > 0, "StandaloneQuarterSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.ShortStandaloneQuarterSymbols.Length > 0, "ShortStandaloneQuarterSymbols not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.AMSymbol.Length > 0, "AMSymbol not found"); + Assert.IsTrue (NSCalendar.CurrentCalendar.PMSymbol.Length > 0, "PMSymbol not found"); + } + + [Test] + public void TestCalendarComparision () + { + RequiresIos8 (); + + NSDate today = NSDate.Now; + NSDate todayPlusSeconds = NowPlusTenSeconds; + if (NSCalendar.CurrentCalendar.CompareDate (today, todayPlusSeconds, NSCalendarUnit.Day) != NSComparisonResult.Same) + Assert.Inconclusive ("Now plus 10 seconds isn't the same day, either a bug or run < 10 seconds before midnight"); + Assert.IsFalse (NSCalendar.CurrentCalendar.CompareDate (today, todayPlusSeconds, NSCalendarUnit.Second) == NSComparisonResult.Same, "Now plus 10 seconds shouldn't be the same second"); + } + + [Test] + public void TestCalendarComponents () + { + RequiresIos8 (); + + nint era, year, month, day = -1; + NSCalendar.CurrentCalendar.GetComponentsFromDate (out era, out year, out month, out day, NSDate.Now); + Assert.IsTrue (era >= 0, "GetComponentsFromDate - era"); + Assert.IsTrue (year >= 0, "GetComponentsFromDate - year"); + Assert.IsTrue (month >= 0, "GetComponentsFromDate - month"); + Assert.IsTrue (day >= 0, "GetComponentsFromDate - day"); + + nint weekOfYear, weekday = -1; + era = year = -1; + NSCalendar.CurrentCalendar.GetComponentsFromDateForWeekOfYear (out era, out year, out weekOfYear, out weekday, NSDate.Now); + Assert.IsTrue (era >= 0, "GetComponentsFromDateForWeekOfYear - era"); + Assert.IsTrue (year >= 0, "GetComponentsFromDateForWeekOfYear - year"); + Assert.IsTrue (weekOfYear >= 0, "GetComponentsFromDateForWeekOfYear - weekOfYear"); + Assert.IsTrue (weekday >= 0, "GetComponentsFromDateForWeekOfYear - weekday"); + + nint hour, minute, second, nanosecond = -1; + NSCalendar.CurrentCalendar.GetHourComponentsFromDate (out hour, out minute, out second, out nanosecond, NSDate.Now); + Assert.IsTrue (hour >= 0, "GetHourComponentsFromDate - hour"); + Assert.IsTrue (minute >= 0, "GetHourComponentsFromDate - minute"); + Assert.IsTrue (second >= 0, "GetHourComponentsFromDate - second"); + Assert.IsTrue (nanosecond >= 0, "GetHourComponentsFromDate - nanosecond"); + + Assert.IsTrue (NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Day, NSDate.Now) > 0, "GetComponentFromDate - day"); + Assert.IsTrue (NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Week, NSDate.Now) > 0, "GetComponentFromDate - week"); + Assert.IsTrue (NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Month, NSDate.Now) > 0, "GetComponentFromDate - month"); + Assert.IsTrue (NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Year, NSDate.Now) > 0, "GetComponentFromDate - year"); + } + + [Test] + public void TestComponentsFromDateToDate () + { + RequiresIos8 (); + + NSDateComponents todayComponents = NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year, NSDate.Now); + NSDateComponents tomorrowComponents = NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year, Tomorrow); + + NSDateComponents components = NSCalendar.CurrentCalendar.ComponentsFromDateToDate (NSCalendarUnit.Day | NSCalendarUnit.Month, todayComponents, tomorrowComponents, NSCalendarOptions.None); + Assert.AreEqual (1, components.Day, "One day passed between today and tomorrow"); + } + + [Test] + public void TestComponentsInTimeZone () + { + RequiresIos8 (); + + NSTimeZone currentZone = NSTimeZone.LocalTimeZone; + NSTimeZone otherZone = new NSTimeZone ("Asia/Bangkok"); + + if (currentZone.SecondsFromGMT (NSDate.Now) == otherZone.SecondsFromGMT (NSDate.Now)) + Assert.Inconclusive ("Same time zone, change Asia/Bangkok"); + + NSDateComponents components = NSCalendar.CurrentCalendar.ComponentsInTimeZone (otherZone, NSDate.Now); + Assert.IsTrue (components.Hour != NSCalendar.CurrentCalendar.Components(NSCalendarUnit.Hour, NSDate.Now).Hour, "Different time zones should have different hours"); + } + + [Test] + public void TestMatchesComponents () + { + RequiresIos8 (); + + NSDateComponents todayComponent = NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Day, NSDate.Now); + bool futureMatch = NSCalendar.CurrentCalendar.Matches (NowPlusTenSeconds, todayComponent); + bool pastMatch = NSCalendar.CurrentCalendar.Matches (NowMinusTenSeconds, todayComponent); + if (futureMatch ^ pastMatch) // While unlikley, if you run it within 10 seconds of a day boundry, we can get inconclusive results. Better this than a random failure + Assert.Inconclusive ("Test was run with 10 seconds of a day switchover (unlikely) or malfunctioned."); + + Assert.IsTrue (futureMatch && pastMatch, "10 seconds on both side of us should both be on same day or Inconclusive"); + } + + [Test] + public void TestAddingByComponents () + { + RequiresIos8 (); + + NSDate now = NSDate.Now; + NSDate oneDayFromNow = NSCalendar.CurrentCalendar.DateByAddingUnit (NSCalendarUnit.Day, 1, now, NSCalendarOptions.None); + Assert.IsTrue (NSCalendar.CurrentCalendar.IsEqualToUnitGranularity (Tomorrow, oneDayFromNow, NSCalendarUnit.Day), "DateByAddingUnit - One day from now should be tomorrow"); + + var todayDayNumber = NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Day, NSDate.Now); + NSDate todayPlusADay = NSCalendar.CurrentCalendar.DateBySettingUnit (NSCalendarUnit.Day, todayDayNumber + 1, now, NSCalendarOptions.None); + if (todayPlusADay == null) { + var todayMonthNumber = NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Month, now); + todayPlusADay = NSCalendar.CurrentCalendar.DateBySettingUnit (NSCalendarUnit.Month, todayMonthNumber + 1, now, NSCalendarOptions.None); + } + Assert.IsTrue (NSCalendar.CurrentCalendar.IsEqualToUnitGranularity (Tomorrow, todayPlusADay, NSCalendarUnit.Day | NSCalendarUnit.Month), "DateBySettingUnit - One day from now should be tomorrow"); + } + + [Test] + public void TestSettingHourComponent () + { + RequiresIos8 (); + + var currentHour = NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Hour, NSDate.Now); + NSDate oneHourFromNow = NSCalendar.CurrentCalendar.DateBySettingsHour (currentHour + 1, 0, 0, NSDate.Now, NSCalendarOptions.None); + if (oneHourFromNow == null) + Assert.Inconclusive ("Test does not handle day change"); + Assert.IsTrue ((currentHour + 1) == NSCalendar.CurrentCalendar.GetComponentFromDate (NSCalendarUnit.Hour, oneHourFromNow), "DateBySettingsHour - One hour from now should be one hour"); + } + + [Test] + public void TestSignUpForDateNotification () + { + RequiresIos8 (); + + // Just make sure signing up and canceling for event doesn't crash + using (NSCalendar.Notifications.ObserveDayChanged ((o, e) => { + })) { + } + } + + [Test] + public void TestNSCalendarConstructors () + { + RequiresIos8 (); + + NSDate date1 = NSCalendar.CurrentCalendar.Date (1, 2, 3, 4, 5, 6, 7, 8); + Assert.IsNotNull (date1, "Date constructor 1"); + NSDate date2 = NSCalendar.CurrentCalendar.DateForWeekOfYear (1, 2, 3, 4, 5, 6, 7, 8); + Assert.IsNotNull (date2, "Date constructor 2"); + } + + [Test] + public void TestIsDateMethods () + { + RequiresIos8 (); + + Assert.IsTrue (NSCalendar.CurrentCalendar.IsDateInToday (NSDate.Now), "IsDateInToday positive"); + Assert.IsFalse (NSCalendar.CurrentCalendar.IsDateInToday (Tomorrow), "IsDateInToday negative"); + + Assert.IsFalse (NSCalendar.CurrentCalendar.IsDateInTomorrow (NSDate.Now), "IsDateInTomorrow negative"); + Assert.IsTrue (NSCalendar.CurrentCalendar.IsDateInTomorrow (Tomorrow), "IsDateInTomorrow positive"); + + Assert.IsFalse (NSCalendar.CurrentCalendar.IsDateInYesterday (NSDate.Now), "IsDateInYesterday negative"); + Assert.IsTrue (NSCalendar.CurrentCalendar.IsDateInYesterday (Yesterday), "IsDateInYesterday positive"); + + Assert.IsFalse (NSCalendar.CurrentCalendar.IsInSameDay (NSDate.Now, Tomorrow), "IsInSameDay negative"); + + NSDate weekend; + double length; + NSCalendar.CurrentCalendar.FindNextWeekend (out weekend, out length, NSCalendarOptions.None, NSDate.Now); + Assert.IsTrue (NSCalendar.CurrentCalendar.IsDateInWeekend (weekend), "IsDateInWeekend positive"); + } + + [Test] + public void TestRangeOfWeekendContainingDate () + { + RequiresIos8 (); + + NSDate weekend; + double length; + NSCalendar.CurrentCalendar.FindNextWeekend (out weekend, out length, NSCalendarOptions.None, NSDate.Now); + + NSDate weekend2; + double length2; + NSCalendar.CurrentCalendar.RangeOfWeekendContainingDate (out weekend2, out length2, weekend); + + Assert.IsTrue (NSCalendar.CurrentCalendar.CompareDate (weekend, weekend2, NSCalendarUnit.Day) == NSComparisonResult.Same, "Weekend test"); + } + + [Test] + public void TestStartOfDay () + { + RequiresIos8 (); + + NSDate firstMomentOfToday = NSCalendar.CurrentCalendar.StartOfDayForDate (NSDate.Now); + Assert.IsTrue (NSCalendar.CurrentCalendar.CompareDate (firstMomentOfToday, NSDate.Now, NSCalendarUnit.Day) == NSComparisonResult.Same, "StartOfDayForDate"); + } + + [Test] + public void TestFindNextDate () + { + RequiresIos8 (); + + NSDateComponents nextYearComponent = NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year, NSDate.Now); + nextYearComponent.Year++; + + NSDate nextYear = NSCalendar.CurrentCalendar.FindNextDateAfterDateMatching (NSDate.Now, nextYearComponent, NSCalendarOptions.MatchNextTime); + Assert.IsNotNull (nextYear, "FindNextDateAfterDateMatching"); + + NSDate nextNoon = NSCalendar.CurrentCalendar.FindNextDateAfterDateMatching (NSDate.Now, 12, 0, 0, NSCalendarOptions.MatchNextTime); + Assert.IsNotNull (nextNoon, "FindNextDateAfterDateMatching 2"); + + NSDate nextNoonAgain = NSCalendar.CurrentCalendar.FindNextDateAfterDateMatching (NSDate.Now, NSCalendarUnit.Hour, 12, NSCalendarOptions.MatchNextTime); + Assert.IsNotNull (nextNoonAgain, "FindNextDateAfterDateMatching 3"); + } + + [Test] + public void TestEnumerateDates () + { + RequiresIos8 (); + + NSDateComponents nextYearComponent = NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year, NSDate.Now); + nextYearComponent.Year++; + bool delegateHit = false; + NSCalendar.CurrentCalendar.EnumerateDatesStartingAfterDate(NSDate.Now, nextYearComponent, NSCalendarOptions.MatchNextTime, (NSDate d, bool exactMatch, ref bool s) => + { + delegateHit = true; + }); + Assert.IsTrue (delegateHit, "EnumerateDatesStartingAfterDate delegate called"); + } + + [Test] + public void TestNSDateComponentNewAPIs () + { + RequiresIos8 (); + + NSDateComponents todayComponents = NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year | NSCalendarUnit.Era | NSCalendarUnit.Calendar, NSDate.Now); + var nano = todayComponents.Nanosecond; + Assert.IsTrue (todayComponents.IsValidDate, "IsValidDate"); + Assert.IsTrue (todayComponents.IsValidDateInCalendar (NSCalendar.CurrentCalendar), "IsValidDateInCalendar"); + + todayComponents.SetValueForComponent (12, NSCalendarUnit.Day); + Assert.AreEqual (12, todayComponents.GetValueForComponent (NSCalendarUnit.Day), "GetValueForComponent\\SetValueForComponent"); + } + + [Test] + public void TestFindNextDateAfterDateMatching () + { + RequiresIos8 (); + + NSDateComponents nextYearComponent = new NSDateComponents (); + Assert.Throws (() => + NSCalendar.CurrentCalendar.FindNextDateAfterDateMatching (NSDate.Now, nextYearComponent, NSCalendarOptions.None)); + + Assert.Throws (() => + NSCalendar.CurrentCalendar.FindNextDateAfterDateMatching (NSDate.Now, NSCalendarUnit.Day, 8, NSCalendarOptions.None)); + + Assert.Throws (() => + NSCalendar.CurrentCalendar.FindNextDateAfterDateMatching (NSDate.Now, 1, 2, 3, NSCalendarOptions.None)); + } + + [TestCase (1, 12, NSCalendarUnit.Month)] + [TestCase (1, 28, NSCalendarUnit.Day)] + [TestCase (0, 24, NSCalendarUnit.Hour)] + public void TestMinimumRange (int location, int length, NSCalendarUnit unit) + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var range = cal.MinimumRange (unit); + Assert.AreEqual (location, range.Location); + Assert.AreEqual (length, range.Length); + } + + [TestCase (1, 12, NSCalendarUnit.Month)] + [TestCase (1, 31, NSCalendarUnit.Day)] + [TestCase (0, 24, NSCalendarUnit.Hour)] + public void TestMaximumRange (int location, int length, NSCalendarUnit unit) + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var range = cal.MaximumRange (unit); + Assert.AreEqual (length, range.Length); + Assert.AreEqual (location, range.Location); + } + + [TestCase (2010, 1, 11, 1, 31, NSCalendarUnit.Day, NSCalendarUnit.Month)] + [TestCase (2010, 2, 11, 1, 28, NSCalendarUnit.Day, NSCalendarUnit.Month)] + [TestCase (2010, 3, 11, 1, 31, NSCalendarUnit.Day, NSCalendarUnit.Month)] + [TestCase (1999, 1, 11, 0, 24, NSCalendarUnit.Hour, NSCalendarUnit.Day)] + public void TestRange (int year, int month, int day, int location, int length, NSCalendarUnit smaller, NSCalendarUnit larger) + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var date = new DateTime (year, month, day); + date = DateTime.SpecifyKind (date, DateTimeKind.Utc); + var range = cal.Range (smaller, larger, (NSDate) date); + Assert.AreEqual (location, range.Location); + Assert.AreEqual (length, range.Length); + } + + [TestCase (2010, 1, 11, NSCalendarUnit.Day, NSCalendarUnit.Month, 11)] + [TestCase (2010, 4, 15, NSCalendarUnit.Day, NSCalendarUnit.Month, 15)] + public void TestOrdinality (int year, int month, int day, NSCalendarUnit smaller, NSCalendarUnit larger, int expected) + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var date = new DateTime (year, month, day, 0, 0, 0, DateTimeKind.Local); + var ordinality = cal.Ordinality (smaller, larger, (NSDate) date); + Assert.AreEqual (ordinality, expected); + } + + [TestCase (2010, 1, 11, NSCalendarUnit.Day, 86400.0)] + [TestCase (2010, 2, 11, NSCalendarUnit.Hour, 3600.0)] + [TestCase (2015, 2, 11, NSCalendarUnit.Month, 2419200.0)] + public void TestRangeOrUnitInterval (int year, int month, int day, NSCalendarUnit unit, double expectedInterval) + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var date = new DateTime (year, month, day); + date = DateTime.SpecifyKind (date, DateTimeKind.Utc); + NSDate outDate = null; + double outInterval; + var success = cal.Range (unit, out outDate, out outInterval, (NSDate) date); + Assert.AreEqual (expectedInterval, outInterval); + } + + [TestCase (2010, 1, 11, NSCalendarUnit.Day, 86400.0)] + [TestCase (2010, 2, 11, NSCalendarUnit.Hour, 3600.0)] + [TestCase (2015, 2, 11, NSCalendarUnit.Month, 2419200.0)] + public void TestRangeOrUnitIntervalNotNull (int year, int month, int day, NSCalendarUnit unit, double expectedInterval) + { + var cal = new NSCalendar (NSCalendarType.Gregorian); + var date = new DateTime (year, month, day); + date = DateTime.SpecifyKind (date, DateTimeKind.Utc); + var outDate = (NSDate) DateTime.Now; + double outInterval; + var success = cal.Range (unit, out outDate, out outInterval, (NSDate) date); + Assert.AreEqual (expectedInterval, outInterval); + } + + } +} diff --git a/tests/monotouch-test/Foundation/CoderTest.cs b/tests/monotouch-test/Foundation/CoderTest.cs new file mode 100644 index 000000000000..23eed63f1aa6 --- /dev/null +++ b/tests/monotouch-test/Foundation/CoderTest.cs @@ -0,0 +1,85 @@ +// +// Unit tests for NSCoder +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Net; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CoderTest { + [Test] + public void EncodeDecodeTest () + { + var buffer = new byte[] { 3, 14, 15 }; + var obj = new NSString (); + byte[] data; + var ptr = Marshal.AllocHGlobal (buffer.Length); + + for (int i = 0; i < buffer.Length; i++) + Marshal.WriteByte (ptr, i, buffer [i]); + + using (var mutableData = new NSMutableData (1024)) { + using (var coder = new NSKeyedArchiver (mutableData)) { + coder.Encode (obj, "obj"); + coder.Encode (buffer, "buffer"); + coder.Encode (Int32.MaxValue, "int32"); + coder.Encode (float.MaxValue, "float"); + coder.Encode (double.MaxValue, "double"); + coder.Encode (true, "bool"); + coder.Encode (long.MaxValue, "long"); + coder.Encode (buffer, 2, 1, "buffer2"); +#if XAMCORE_2_0 + coder.Encode (nint.MaxValue, "nint"); +#endif + coder.EncodeBlock (ptr, buffer.Length, "block"); + coder.FinishEncoding (); + } + + using (var decoder = new NSKeyedUnarchiver (mutableData)) { + Assert.IsNotNull (decoder.DecodeObject ("obj")); + var buf = decoder.DecodeBytes ("buffer"); + Assert.AreEqual (buf.Length, buffer.Length, "buffer.length"); + for (int i = 0; i < buf.Length; i++) + Assert.AreEqual (buf [i], buffer [i], "buffer [" + i.ToString () + "]"); + Assert.AreEqual (Int32.MaxValue, decoder.DecodeInt ("int32")); + Assert.AreEqual (float.MaxValue, decoder.DecodeFloat ("float")); + Assert.AreEqual (true, decoder.DecodeBool ("bool")); + Assert.AreEqual (long.MaxValue, decoder.DecodeLong ("long")); + buf = decoder.DecodeBytes ("buffer2"); + Assert.AreEqual (buf.Length, buffer.Length, "buffer2.length"); + for (int i = 0; i < buf.Length; i++) + Assert.AreEqual (buf [i], buffer [i], "buffer2 [" + i.ToString () + "]"); +#if XAMCORE_2_0 + Assert.AreEqual (nint.MaxValue, decoder.DecodeNInt ("nint")); +#endif + + buf = decoder.DecodeBytes ("block"); + Assert.AreEqual (buf.Length, buffer.Length, "block.length"); + for (int i = 0; i < buf.Length; i++) + Assert.AreEqual (buf [i], buffer [i], "block [" + i.ToString () + "]"); + } + } + + Marshal.FreeHGlobal (ptr); + + } + } +} diff --git a/tests/monotouch-test/Foundation/CookieTest.cs b/tests/monotouch-test/Foundation/CookieTest.cs new file mode 100644 index 000000000000..7ef9017b38c8 --- /dev/null +++ b/tests/monotouch-test/Foundation/CookieTest.cs @@ -0,0 +1,253 @@ +// +// Unit tests for NSHttpCookie +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class HttpCookieTest { + + // https://bugzilla.xamarin.com/show_bug.cgi?id=3603 + [Test] + public void NSDictionaryCtor () + { + using (var props = new NSMutableDictionary ()) { +#if XAMCORE_2_0 + props.Add (NSHttpCookie.KeyOriginUrl, new NSString ("http://yodawg.com")); +#else + props.Add (NSHttpCookie.KeyOriginURL, new NSString ("http://yodawg.com")); +#endif + props.Add (NSHttpCookie.KeyName, new NSString ("iherd")); + props.Add (NSHttpCookie.KeyValue, new NSString ("ulikecookies")); + + // an invalid NSDictionary returns null from Objective-C but that + // results in an 'empty' instance inside MonoTouch + Assert.Throws (() => new NSHttpCookie (props), "ctor"); + + props.Add (NSHttpCookie.KeyPath, new NSString ("/")); + using (var cookie = new NSHttpCookie (props)) { + Assert.That (cookie.Handle, Is.Not.EqualTo (IntPtr.Zero), "ctor"); + + Assert.That (cookie.Domain, Is.EqualTo ("yodawg.com"), "Domain"); + Assert.That (cookie.Name, Is.EqualTo ("iherd"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("ulikecookies"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("/"), "Path"); + } + } + } + + [Test] + public void CookieFromProperties () + { + using (var props = new NSMutableDictionary ()) { +#if XAMCORE_2_0 + props.Add (NSHttpCookie.KeyOriginUrl, new NSString ("http://yodawg.com")); +#else + props.Add (NSHttpCookie.KeyOriginURL, new NSString ("http://yodawg.com")); +#endif + props.Add (NSHttpCookie.KeyName, new NSString ("iherd")); + props.Add (NSHttpCookie.KeyValue, new NSString ("ulikecookies")); + + var cookie = NSHttpCookie.CookieFromProperties (props); + Assert.Null (cookie, "missing path"); + + props.Add (NSHttpCookie.KeyPath, new NSString ("/")); + using (cookie = NSHttpCookie.CookieFromProperties (props)) { + Assert.NotNull (cookie, "w/path"); + + Assert.That (cookie.Domain, Is.EqualTo ("yodawg.com"), "Domain"); + Assert.That (cookie.Name, Is.EqualTo ("iherd"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("ulikecookies"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("/"), "Path"); + } + } + } + + [Test] + public void NiceTwoCtor () + { + using (NSHttpCookie cookie = new NSHttpCookie ("iherd", "ulikecookies")) { + Assert.That (cookie.Name, Is.EqualTo ("iherd"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("ulikecookies"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("/"), "Path"); + Assert.That (cookie.Domain, Is.EqualTo ("*"), "Domain"); + } + } + + [Test] + public void NiceThreeCtor () + { + using (NSHttpCookie cookie = new NSHttpCookie ("iherd", "ulikecookies", "/", null)) { + Assert.That (cookie.Name, Is.EqualTo ("iherd"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("ulikecookies"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("/"), "Path"); + Assert.That (cookie.Domain, Is.EqualTo ("*"), "Domain"); + } + } + + [Test] + public void NiceFourCtor () + { + using (NSHttpCookie cookie = new NSHttpCookie ("iherd", "ulikecookies", "/", "yodawg.com")) { + Assert.That (cookie.Name, Is.EqualTo ("iherd"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("ulikecookies"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("/"), "Path"); + Assert.That (cookie.Domain, Is.EqualTo ("yodawg.com"), "Domain"); + } + } + + [Test] + public void DotNetInteropMin () + { + // an invalid NSDictionary returns null from Objective-C but that + // results in an 'empty' instance inside MonoTouch + using (var cookie = new NSHttpCookie (new Cookie ())) { + Assert.That (cookie.Handle, Is.EqualTo (IntPtr.Zero), "ctor"); + } + } + + [Test] + public void DotNetInteropCommon () + { + var c = new Cookie ("name", "key", "path", "domain"); + using (NSHttpCookie cookie = new NSHttpCookie (c)) { + Assert.That (cookie.Name, Is.EqualTo ("name"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("key"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("path"), "Path"); + Assert.That (cookie.Domain, Is.EqualTo ("domain"), "Domain"); + // defaults + Assert.Null (cookie.Comment, "Comment"); + Assert.Null (cookie.CommentUrl, "CommentUrl"); + Assert.Null (cookie.ExpiresDate, "ExpiresDate"); + Assert.False (cookie.IsHttpOnly, "IsHttpOnly"); + Assert.False (cookie.IsSecure, "IsSecure"); + Assert.True (cookie.IsSessionOnly, "IsSessionOnly"); // discard + Assert.That (cookie.PortList.Length, Is.EqualTo (0), "PortList"); + Assert.NotNull (cookie.Properties, "Properties"); + Assert.That (cookie.Version, Is.EqualTo ((nuint) 0), "Version"); + } + } + + [Test] + public void DotNetInteropMax () + { + var c = new Cookie ("name", "key", "path", "domain"); + c.Comment = "comment"; + c.CommentUri = new Uri ("http://comment.uri"); + c.Discard = true; + c.Expires = DateTime.Now.AddDays (1); + c.HttpOnly = false; + c.Port = "\"80\""; + c.Secure = true; + c.Version = 1; + using (NSHttpCookie cookie = new NSHttpCookie (c)) { + Assert.That (cookie.Name, Is.EqualTo ("name"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("key"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("path"), "Path"); + Assert.That (cookie.Domain, Is.EqualTo ("domain"), "Domain"); + // custom values + Assert.That (cookie.Comment, Is.EqualTo ("comment"), "Comment"); + Assert.That (cookie.CommentUrl.ToString (), Is.EqualTo ("http://comment.uri/"), "CommentUrl"); + Assert.Null (cookie.ExpiresDate, "ExpiresDate"); // session-only always returns null + Assert.False (cookie.IsHttpOnly, "IsHttpOnly"); + Assert.True (cookie.IsSecure, "IsSecure"); + Assert.True (cookie.IsSessionOnly, "IsSessionOnly"); + Assert.That ((int) cookie.PortList [0], Is.EqualTo (80), "PortList"); + Assert.NotNull (cookie.Properties, "Properties"); + Assert.That (cookie.Version, Is.EqualTo ((nuint) 1), "Version"); + } + } + + [Test] + public void DotNetInterop_NonSession () + { + var c = new Cookie ("name", "key", "path", "domain"); + c.Comment = "comment"; + c.CommentUri = new Uri ("http://comment.uri"); + c.Discard = false; + c.Expires = DateTime.Now.AddDays (1); + c.HttpOnly = false; + c.Port = "\"80\""; + c.Secure = true; + c.Version = 1; + using (NSHttpCookie cookie = new NSHttpCookie (c)) { + Assert.That (cookie.Name, Is.EqualTo ("name"), "Name"); + Assert.That (cookie.Value, Is.EqualTo ("key"), "Value"); + Assert.That (cookie.Path, Is.EqualTo ("path"), "Path"); + Assert.That (cookie.Domain, Is.EqualTo ("domain"), "Domain"); + // custom values + Assert.That (cookie.Comment, Is.EqualTo ("comment"), "Comment"); + Assert.That (cookie.CommentUrl.ToString (), Is.EqualTo ("http://comment.uri/"), "CommentUrl"); + DateTime dt1 = (DateTime) cookie.ExpiresDate; // does not include milliseconds (so we do a string match) + DateTime dt2 = c.Expires.ToUniversalTime (); + Assert.That (dt1.ToString (), Is.EqualTo (dt2.ToString ()), "ExpiresDate"); + Assert.False (cookie.IsHttpOnly, "IsHttpOnly"); + Assert.True (cookie.IsSecure, "IsSecure"); + Assert.IsFalse (cookie.IsSessionOnly, "IsSessionOnly"); + Assert.That ((int) cookie.PortList [0], Is.EqualTo (80), "PortList"); + Assert.NotNull (cookie.Properties, "Properties"); + Assert.That (cookie.Version, Is.EqualTo ((nuint) 1), "Version"); + } + } + + [Test] + public void PortList_4990 () + { + Cookie c = new Cookie (); + c.Comment = String.Empty; + c.CommentUri = null; + c.Discard = true; + c.Domain = ".collectedit.com"; + c.Expired = false; + c.Expires = DateTime.Now.AddMonths (1); + c.HttpOnly = true; + c.Name = ".ASPXAUTH"; + c.Path = "/"; + c.Port = String.Empty; + c.Secure = false; + c.Value = "abc"; + using (NSHttpCookie c1 = new NSHttpCookie (c)) + using (NSHttpCookie c2 = new NSHttpCookie (".ASPXAUTH", "abc", "/", ".collectedit.com")) { + Assert.That (c1.Name, Is.EqualTo (c2.Name), "Name"); + Assert.That (c1.Value, Is.EqualTo (c2.Value), "Value"); + Assert.That (c1.Path, Is.EqualTo (c2.Path), "Path"); + Assert.That (c1.Domain, Is.EqualTo (c2.Domain), "Domain"); + Assert.That (c1.Comment, Is.EqualTo (c2.Comment), "Comment"); + Assert.That (c1.CommentUrl, Is.EqualTo (c2.CommentUrl), "CommentUrl"); + Assert.That (c1.ExpiresDate, Is.EqualTo (c2.ExpiresDate), "ExpiresDate"); + Assert.That (c1.IsHttpOnly, Is.EqualTo (c2.IsHttpOnly), "IsHttpOnly"); + Assert.That (c1.IsSecure, Is.EqualTo (c2.IsSecure), "IsSecure"); + Assert.That (c1.IsSessionOnly, Is.EqualTo (c2.IsSessionOnly), "IsSessionOnly"); + Assert.That (c1.PortList, Is.EqualTo (c2.PortList), "PortList"); + Assert.That (c1.Version, Is.EqualTo (c2.Version), "Version"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/DateFormatterTest.cs b/tests/monotouch-test/Foundation/DateFormatterTest.cs new file mode 100644 index 000000000000..df3088337e8e --- /dev/null +++ b/tests/monotouch-test/Foundation/DateFormatterTest.cs @@ -0,0 +1,48 @@ +// +// Unit tests for NSDateFormatter +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DateFormatterTest { + + [Test] + public void ToLocalizedStringTest () + { + var str = NSDateFormatter.ToLocalizedString (NSDate.Now, NSDateFormatterStyle.Full, NSDateFormatterStyle.Full); + Assert.IsNotNull (str); + } + + [Test] + public void GetDateFormatFromTemplateTest () + { + var us_locale = new NSLocale ("en_US"); + var gb_locale = new NSLocale ("en_GB"); + const string dateComponents = "yMMMMd"; + + var dateFormat = NSDateFormatter.GetDateFormatFromTemplate (dateComponents, 0, us_locale); + Assert.AreEqual ("MMMM d, y", dateFormat, "#US"); + + dateFormat = NSDateFormatter.GetDateFormatFromTemplate (dateComponents, 0, gb_locale); + Assert.AreEqual ("d MMMM y", dateFormat, "GB"); + } + } +} diff --git a/tests/monotouch-test/Foundation/DateTest.cs b/tests/monotouch-test/Foundation/DateTest.cs new file mode 100644 index 000000000000..ab16a3602df1 --- /dev/null +++ b/tests/monotouch-test/Foundation/DateTest.cs @@ -0,0 +1,70 @@ +// +// Unit tests for NSDate +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DateTest { + + [Test] + public void InLimits () + { + // .NET can represent this date just fine + Assert.AreEqual (new DateTime (4001, 01, 01), (DateTime)NSDate.DistantFuture, "distant future"); + + Assert.AreEqual (DateTime.MinValue.AddSeconds (1), (DateTime)NSDate.FromTimeIntervalSinceReferenceDate (-63113903999), "-63113903999"); + Assert.AreEqual (DateTime.MinValue, (DateTime)NSDate.FromTimeIntervalSinceReferenceDate (-63113904000), "-63113904000"); + + // NSDate doesn't seem to store the 'TimeIntervalSinceReferenceDate' as a double, causing a slight time warp. Round a bit to rewarp back. + Assert.AreEqual (new DateTime (9999, 12, 31, 23, 59, 58), new DateTime ((((DateTime)NSDate.FromTimeIntervalSinceReferenceDate (252423993598)).Ticks / 10000) * 10000, DateTimeKind.Utc), "252423993598"); + Assert.AreEqual (new DateTime (9999, 12, 31, 23, 59, 59), new DateTime ((((DateTime)NSDate.FromTimeIntervalSinceReferenceDate (252423993599)).Ticks / 10000) * 10000, DateTimeKind.Utc), "252423993599"); + } + + [Test] + public void OutLimits () + { +#if XAMCORE_2_0 + Assert.Throws (() => { var tmp = (DateTime) NSDate.DistantPast; }, "distant past"); + Assert.Throws (() => { var tmp = (DateTime) NSDate.FromTimeIntervalSinceReferenceDate (-63113904001); }, "-63113904001"); + + Assert.Throws (() => { var tmp = (DateTime) NSDate.FromTimeIntervalSinceReferenceDate (252423993600); }, "252423993600"); + + // [Min|Max]Value are DateTimeKind.Unspecified + Assert.Throws (() => { var tmp = (NSDate) DateTime.MinValue; }, "MinValue"); + Assert.Throws (() => { var tmp = (NSDate) DateTime.MaxValue; }, "MaxValue"); +#else + Assert.AreEqual (DateTime.MinValue, (DateTime)NSDate.DistantPast, "distant past"); + Assert.AreEqual (DateTime.MinValue, (DateTime)NSDate.FromTimeIntervalSinceReferenceDate (-63113904001), "-63113904001"); + + Assert.AreEqual (DateTime.MaxValue, (DateTime)NSDate.FromTimeIntervalSinceReferenceDate (252423993600), "252423993600"); + + Assert.DoesNotThrow (() => { var tmp = (NSDate) DateTime.MinValue; }, "MinValue"); + Assert.DoesNotThrow (() => { var tmp = (NSDate) DateTime.MaxValue; }, "MaxValue"); +#endif + } + + [Test] + public void DescriptionWithLocale () + { + Assert.IsNotNull (NSDate.Now.DescriptionWithLocale (NSLocale.CurrentLocale), "1"); + } + } +} diff --git a/tests/monotouch-test/Foundation/DecimalNumberTest.cs b/tests/monotouch-test/Foundation/DecimalNumberTest.cs new file mode 100644 index 000000000000..c4a6fff514e8 --- /dev/null +++ b/tests/monotouch-test/Foundation/DecimalNumberTest.cs @@ -0,0 +1,30 @@ +// +// Unit tests for NSDecimalNumber +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DecimalNumberTest { + + [Test] + public void One () + { + Assert.NotNull (NSDecimalNumber.One, "One"); + } + } +} diff --git a/tests/monotouch-test/Foundation/DecimalTest.cs b/tests/monotouch-test/Foundation/DecimalTest.cs new file mode 100644 index 000000000000..b0719c1d713b --- /dev/null +++ b/tests/monotouch-test/Foundation/DecimalTest.cs @@ -0,0 +1,83 @@ +// +// Unit tests for NSDecimal +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Globalization; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DecimalTest { + + [Test] + public void CastFloat () + { + float f = 0.7f; + NSDecimal nsd = (NSDecimal) f; + // We call NSNumberFormatter to adjust the test according to the iOS (not .NET) culture, + // since NSDecimal.ToString () takes culture into account. .NET CultureInfo does not handle cases + // like "en-HU" + if (TestRuntime.CheckSystemAndSDKVersion (6, 0) && (CultureInfo.CurrentCulture.Name != "ar-AE")) { + // interestingly the call to `NSDecimal.NSDecimalString (ref this, NSLocale.CurrentLocale.Handle);` does not consider the current locale on iOS 5.1 + var expected = NSNumberFormatter.LocalizedStringFromNumbernumberStyle ((NSNumber)f, NSNumberFormatterStyle.Decimal); + Assert.That (nsd.ToString (), Is.EqualTo (expected), "ToString"); + } + Assert.That (f, Is.EqualTo ((float) nsd), "float-rountrip"); + } + + [Test] + public void CastDecimal () + { + decimal m = 0.7m; + NSDecimal nsd = (NSDecimal) m; + // We call NSNumberFormatter to adjust the test according to the iOS (not .NET) culture, + // since NSDecimal.ToString () takes culture into account. .NET CultureInfo does not handle cases + // like "en-HU" + // note: there's no NSNumber / Decimal conversions + if (TestRuntime.CheckSystemAndSDKVersion (6, 0) && (CultureInfo.CurrentCulture.Name != "ar-AE")) { + // interestingly the call to `NSDecimal.NSDecimalString (ref this, NSLocale.CurrentLocale.Handle);` does not consider the current locale on iOS 5.1 + var expected = NSNumberFormatter.LocalizedStringFromNumbernumberStyle ((NSNumber)0.7d, NSNumberFormatterStyle.Decimal); + Assert.That (nsd.ToString (), Is.EqualTo (expected), "ToString"); + } + Assert.That (m, Is.EqualTo ((decimal) nsd), "decimal-rountrip"); + } + + [Test] + public void CastDouble () + { + double d = 0.7d; + NSDecimal nsd = (NSDecimal) d; + // We call NSNumberFormatter to adjust the test according to the iOS (not .NET) culture, + // since NSDecimal.ToString () takes culture into account. .NET CultureInfo does not handle cases + // like "en-HU" + if (TestRuntime.CheckSystemAndSDKVersion (6, 0) && (CultureInfo.CurrentCulture.Name != "ar-AE")) { + // interestingly the call to `NSDecimal.NSDecimalString (ref this, NSLocale.CurrentLocale.Handle);` does not consider the current locale on iOS 5.1 + var expected = NSNumberFormatter.LocalizedStringFromNumbernumberStyle ((NSNumber)d, NSNumberFormatterStyle.Decimal); + Assert.That (nsd.ToString (), Is.EqualTo (expected), "ToString"); + } + Assert.That (d, Is.EqualTo ((double) nsd), "double-rountrip"); + } + + [Test] + public void CastInt () + { + int i = 42; + NSDecimal nsd = (NSDecimal) i; + Assert.That (nsd.ToString (), Is.EqualTo ("42"), "ToString"); + Assert.That (i, Is.EqualTo ((int) nsd), "int-rountrip"); + } + } +} diff --git a/tests/monotouch-test/Foundation/DictionaryContainerTest.cs b/tests/monotouch-test/Foundation/DictionaryContainerTest.cs new file mode 100644 index 000000000000..dd940797e1af --- /dev/null +++ b/tests/monotouch-test/Foundation/DictionaryContainerTest.cs @@ -0,0 +1,237 @@ +// +// Unit tests for DictionaryContainer +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using CoreFoundation; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + public class DictionaryContainerPoker : DictionaryContainer { + + public DictionaryContainerPoker () + { + } + + + public void SetArrayValue_ (NSString key, NSNumber[] values) + { + SetArrayValue (key, values); + } + + public void SetArrayValue_ (NSString key, string[] values) + { + SetArrayValue (key, values); + } + + public void SetArrayValue_ (NSString key, T[] values) + { + SetArrayValue (key, values); + } + + public void SetArrayValue_ (NSString key, INativeObject[] values) + { + SetArrayValue (key, values); + } + + public void SetBooleanValue_ (NSString key, bool? value) + { + SetBooleanValue (key, value); + } + + public void SetNumberValue_ (NSString key, int? value) + { + SetNumberValue (key, value); + } + + public void SetNumberValue_ (NSString key, uint? value) + { + SetNumberValue (key, value); + } + +#if XAMCORE_2_0 + public void SetNumberValue_ (NSString key, nint? value) + { + SetNumberValue (key, value); + } + + public void SetNumberValue_ (NSString key, nuint? value) + { + SetNumberValue (key, value); + } +#endif + + public void SetStringValue_ (NSString key, string value) + { + SetStringValue (key, value); + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class DictionaryContainerTest { + + [Test] + public void Empty () + { + var dc = new DictionaryContainerPoker (); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "Count"); + } + + NSString key = new NSString ("key"); + + [Test] + public void SetArrayValue_NSNumber () + { + var numbers = new NSNumber [] { (NSNumber) 0, (NSNumber) 1 }; + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetArrayValue_ (null, numbers); + }, "null key"); + + dc.SetArrayValue_ (key, numbers); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + Assert.That ((int) (dc.Dictionary [key] as NSArray).Count, Is.EqualTo (2), "2"); + + numbers = null; + dc.SetArrayValue_ (key, numbers); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetArrayValue_String () + { + var strings = new String [] { "xamarin", "monkeys" }; + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetArrayValue_ (null, strings); + }, "null key"); + + dc.SetArrayValue_ (key, strings); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + Assert.That ((int) (dc.Dictionary [key] as NSArray).Count, Is.EqualTo (2), "2"); + + strings = null; + dc.SetArrayValue_ (key, strings); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetArrayValue_T_Enum () + { + var enums = new NSStringEncoding [] { NSStringEncoding.ISOLatin1, NSStringEncoding.ISOLatin2 }; + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetArrayValue_ (null, enums); + }, "null key"); + + dc.SetArrayValue_ (key, enums); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + Assert.That ((int) (dc.Dictionary [key] as NSArray).Count, Is.EqualTo (2), "2"); + + enums = null; + dc.SetArrayValue_ (key, enums); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetArrayValue_INativeObject () + { + var native = new INativeObject [] { new CFString ("xamarin"), CFRunLoop.Main }; + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetArrayValue_ (null, native); + }, "null key"); + + dc.SetArrayValue_ (key, native); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + Assert.That ((int) (dc.Dictionary [key] as NSArray).Count, Is.EqualTo (2), "2"); + + native = null; + dc.SetArrayValue_ (key, native); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetBooleanValue () + { + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetBooleanValue_ (null, true); + }, "null key"); + + dc.SetBooleanValue_ (key, true); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + + dc.SetBooleanValue_ (key, null); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetNumberValue_Int32 () + { + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetNumberValue_ (null, int.MinValue); + }, "null key"); + + dc.SetNumberValue_ (key, int.MinValue); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + + dc.SetNumberValue_ (key, (int?) null); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetNumberValue_UInt32 () + { + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetNumberValue_ (null, uint.MaxValue); + }, "null key"); + + dc.SetNumberValue_ (key, uint.MaxValue); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + + dc.SetNumberValue_ (key, (uint?) null); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + + [Test] + public void SetStringValue () + { + var dc = new DictionaryContainerPoker (); + + Assert.Throws (delegate { + dc.SetStringValue_ (null, String.Empty); + }, "null key"); + + dc.SetStringValue_ (key, (NSString) "monkey"); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (1), "1"); + + dc.SetStringValue_ (key, null); + Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); + } + } +} diff --git a/tests/monotouch-test/Foundation/EncodingDetectionOptionsTest.cs b/tests/monotouch-test/Foundation/EncodingDetectionOptionsTest.cs new file mode 100644 index 000000000000..147092cf663b --- /dev/null +++ b/tests/monotouch-test/Foundation/EncodingDetectionOptionsTest.cs @@ -0,0 +1,43 @@ +// +// Unit tests for EncodingDetectionOptions +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EncodingDetectionOptionsTest { + + [Test] + public void SetValueEnumArray () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Request iOS8+"); + + var encodings = new NSStringEncoding [] { NSStringEncoding.ISOLatin1, NSStringEncoding.ISOLatin2 }; + var edo = new EncodingDetectionOptions () { + EncodingDetectionDisallowedEncodings = encodings + }; + + using (var d = edo.Dictionary) { + Assert.That ((int) d.Count, Is.EqualTo (1), "Count"); + var values = d [d.Keys [0]] as NSArray; + Assert.That (values.GetItem (0), Is.EqualTo ((NSNumber) (int) NSStringEncoding.ISOLatin1), "0"); + Assert.That (values.GetItem (1), Is.EqualTo ((NSNumber) (int) NSStringEncoding.ISOLatin2), "1"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/FileCoordinatorTest.cs b/tests/monotouch-test/Foundation/FileCoordinatorTest.cs new file mode 100644 index 000000000000..ab1526c43c81 --- /dev/null +++ b/tests/monotouch-test/Foundation/FileCoordinatorTest.cs @@ -0,0 +1,179 @@ +// +// Unit tests for NSFileCoordinator +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FileCoordinatorTest { + + NSUrl GetUrl () + { + return new NSUrl (Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "FileCoordinatorTest.txt")); + } + + bool fileop; + + void FileOp (NSUrl url) + { + fileop = true; + } + + [Test] + public void CoordinateRead () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + fileop = false; + fc.CoordinateRead (url, NSFileCoordinatorReadingOptions.WithoutChanges, out err, FileOp); + Assert.True (fileop, "fileop/sync"); + Assert.Null (err, "NSError"); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void CoordinateRead_Null () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + // NULL is not documented by Apple but it crash the app with: + // NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid + fc.CoordinateRead (url, NSFileCoordinatorReadingOptions.WithoutChanges, out err, null); + } + } + + [Test] + public void CoordinateWrite () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + fileop = false; + fc.CoordinateWrite (url, NSFileCoordinatorWritingOptions.ForDeleting, out err, FileOp); + Assert.True (fileop, "fileop/sync"); + Assert.Null (err, "NSError"); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void CoordinateWrite_Null () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + // NULL is not documented by Apple but it crash the app with: + // NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid + fc.CoordinateWrite (url, NSFileCoordinatorWritingOptions.ForDeleting, out err, null); + } + } + + void FileOp (NSUrl url1, NSUrl url2) + { + fileop = true; + } + + [Test] + public void CoordinateReadWrite () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + fileop = false; + fc.CoordinateReadWrite (url, NSFileCoordinatorReadingOptions.WithoutChanges, url, NSFileCoordinatorWritingOptions.ForDeleting, out err, FileOp); + Assert.True (fileop, "fileop/sync"); + Assert.Null (err, "NSError"); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void CoordinateReadWrite_Null () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + // NULL is not documented by Apple but it crash the app with: + // NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid + fc.CoordinateReadWrite (url, NSFileCoordinatorReadingOptions.WithoutChanges, url, NSFileCoordinatorWritingOptions.ForDeleting, out err, null); + } + } + + [Test] + public void CoordinateWriteWrite () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + fileop = false; + fc.CoordinateWriteWrite (url, NSFileCoordinatorWritingOptions.ForMoving, url, NSFileCoordinatorWritingOptions.ForDeleting, out err, FileOp); + Assert.True (fileop, "fileop/sync"); + Assert.Null (err, "NSError"); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void CoordinateWriteWrite_Null () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + // NULL is not documented by Apple but it crash the app with: + // NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid + fc.CoordinateWriteWrite (url, NSFileCoordinatorWritingOptions.ForMoving, url, NSFileCoordinatorWritingOptions.ForDeleting, out err, null); + } + } + + void Action () + { + fileop = true; + } + + [Test] + public void CoordinateBatch_Action () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + fileop = false; + fc.CoordinateBatc (new NSUrl[] { url }, NSFileCoordinatorReadingOptions.WithoutChanges, new NSUrl[] { url }, NSFileCoordinatorWritingOptions.ForDeleting, out err, Action); + Assert.True (fileop, "fileop/sync"); + Assert.Null (err, "NSError"); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void CoordinateBatch_Action_Null () + { + using (var url = GetUrl ()) + using (var fc = new NSFileCoordinator ()) { + NSError err; + // NULL is not documented by Apple but it crash the app with: + // NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid + fc.CoordinateBatc (new NSUrl[] { url }, NSFileCoordinatorReadingOptions.WithoutChanges, new NSUrl[] { url }, NSFileCoordinatorWritingOptions.ForDeleting, out err, null); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/FileHandleTest.cs b/tests/monotouch-test/Foundation/FileHandleTest.cs new file mode 100644 index 000000000000..53fe3e7451ad --- /dev/null +++ b/tests/monotouch-test/Foundation/FileHandleTest.cs @@ -0,0 +1,41 @@ +// +// Unit tests for NSFileHandle +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class FileHandleTest { + + [Test] + public void Descriptor () + { + using (var s = new NSFileHandle (0)) { + // initWithFileDescriptor: does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void DescriptorClose () + { + using (var s = new NSFileHandle (0, false)) { + // initWithFileDescriptor:closeOnDealloc: does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/FileManagerTest.cs b/tests/monotouch-test/Foundation/FileManagerTest.cs new file mode 100644 index 000000000000..4d5ec193d45d --- /dev/null +++ b/tests/monotouch-test/Foundation/FileManagerTest.cs @@ -0,0 +1,158 @@ +// +// Unit tests for NSFileManager +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2011 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSFileManagerTest { + + static bool RunningOnSnowLeopard { + get { + return !File.Exists ("/usr/lib/system/libsystem_kernel.dylib"); + } + } + + [Test] + public void GetUrlForUbiquityContainer () + { + if ((Runtime.Arch == Arch.SIMULATOR) && RunningOnSnowLeopard) + Assert.Inconclusive ("sometimes crash under the iOS simulator (generally on the SL/iOS5 bots)"); + + NSFileManager fm = new NSFileManager (); + if (TestRuntime.CheckSystemAndSDKVersion (6, 0) && fm.UbiquityIdentityToken == null) { + // UbiquityIdentityToken is a fast way to check if iCloud is enabled + Assert.Pass ("not iCloud enabled"); + } + + NSUrl c = null; + Exception e = null; + ManualResetEvent evt = new ManualResetEvent (false); + + new Thread (() => + { + try { + // From Apple's documentaiton: + // Important: Do not call this method from your app’s main thread. Because this method might take a nontrivial amount of time to set up + // iCloud and return the requested URL, you should always call it from a secondary thread. + c = fm.GetUrlForUbiquityContainer (null); + } catch (Exception ex) { + e = ex; + } finally { + evt.Set (); + } + }) + { + IsBackground = true, + }.Start (); + + if (evt.WaitOne (TimeSpan.FromSeconds (15))) { + if (e != null) + throw e; + + if (c == null) + Assert.Pass ("not iCloud enabled"); // simulator or provisioning profile without iCloud enabled (old ones) + else { + Assert.That (c.ToString (), Is.StringStarting ("file://localhost/private/var/mobile/Library/Mobile%20Documents"). + Or.StringStarting ("file:///private/var/mobile/Library/Mobile%20Documents")); + } + } else { + Assert.Pass ("iCloud is probably not enabled"); + // aborting is evil, so don't bother aborting the thread, just let it run its course + } + } + + [Test] + public void GetSkipBackupAttribute () + { + if ((Runtime.Arch == Arch.SIMULATOR) && RunningOnSnowLeopard) + Assert.Inconclusive ("iOS simulator did not get libsystem_kernel.dylib before Lion"); + + Assert.False (NSFileManager.GetSkipBackupAttribute (NSBundle.MainBundle.ExecutableUrl.ToString ()), "MainBundle"); + + string filename = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), "DoNotBackupMe-NSFileManager"); + try { + File.WriteAllText (filename, "not worth a bit"); + + Assert.False (NSFileManager.GetSkipBackupAttribute (filename), "DoNotBackupMe-0"); + + NSFileManager.SetSkipBackupAttribute (filename, true); + + NSError error; + Assert.True (NSFileManager.GetSkipBackupAttribute (filename, out error), "DoNotBackupMe-1"); + Assert.Null (error, "error-1"); + + error = NSFileManager.SetSkipBackupAttribute (filename, false); + Assert.False (NSFileManager.GetSkipBackupAttribute (filename), "DoNotBackupMe-2"); + Assert.Null (error, "error-2"); + } + finally { + // otherwise the attribute won't reset even if the file is overwritten + File.Delete (filename); + } + } + + [Test] + public void DefaultManager () + { + // ICE on devices ? ref: http://forums.xamarin.com/discussion/6807/system-invalidcastexception-while-trying-to-get-nsfilemanager-defaultmanager + Assert.NotNull (NSFileManager.DefaultManager, "DefaultManager"); + } + + [Test] + public void DocumentDirectory () + { + var path = NSFileManager.DefaultManager.GetUrls (NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User) [0].Path; + var file = Path.Combine (path, "myfile.txt"); + try { + // because it's read-only MyDocuments != DocumentDirectory on tvOS as the former is required by a lot of code in the BCL + if (!TestRuntime.IsTVOS) { + File.WriteAllText (Path.Combine (path, "myfile.txt"), "woohoo"); + Assert.That (path, Is.EqualTo (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)), "GetFolderPath"); + } + } + finally { + File.Delete (file); + } + } + + [Test] + public void LibraryDirectory () + { + var path = NSFileManager.DefaultManager.GetUrls (NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomain.User) [0].Path; + var file = Path.Combine (path, "myfile.txt"); + try { + File.WriteAllText (Path.Combine (path, "myfile.txt"), "woohoo"); + Assert.That (path, Is.EqualTo (Environment.GetFolderPath (Environment.SpecialFolder.Resources)), "GetFolderPath"); + } + catch (UnauthorizedAccessException) { + // DocumentDirectory cannot be written to on tvOS + if (!TestRuntime.IsTVOS) + throw; + } + finally { + File.Delete (file); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/FormatterTests.cs b/tests/monotouch-test/Foundation/FormatterTests.cs new file mode 100644 index 000000000000..2818ae1ed56d --- /dev/null +++ b/tests/monotouch-test/Foundation/FormatterTests.cs @@ -0,0 +1,226 @@ +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class FormatterTests { + + NSDateComponentsFormatter dateComponentsFormatter; + NSEnergyFormatter energyFormatter; + + void RequiresIos8 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8+"); + + if (dateComponentsFormatter == null) + dateComponentsFormatter = new NSDateComponentsFormatter (); + if (energyFormatter == null) + energyFormatter = new NSEnergyFormatter (); + } + + static void TestFormattedString (string formattedString, string testName) + { + Assert.IsNotNull (formattedString, testName); + Assert.IsTrue (formattedString.Length > 0, testName + " length"); + } + + public NSDateComponents NowComponents + { + get + { + return NSCalendar.CurrentCalendar.Components (NSCalendarUnit.Era | NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year | NSCalendarUnit.WeekOfMonth, NSDate.Now); + } + } + + #region NSDateComponentsFormatter + + [Test] + public void DateTestProperties () + { + RequiresIos8 (); + + dateComponentsFormatter.UnitsStyle = NSDateComponentsFormatterUnitsStyle.Full; + Assert.AreEqual (NSDateComponentsFormatterUnitsStyle.Full, dateComponentsFormatter.UnitsStyle, "UnitsStyle"); + + dateComponentsFormatter.AllowedUnits = NSCalendarUnit.Month | NSCalendarUnit.Day; + Assert.AreEqual (NSCalendarUnit.Month | NSCalendarUnit.Day, dateComponentsFormatter.AllowedUnits, "AllowedUnits"); + + dateComponentsFormatter.ZeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehavior.Pad; + Assert.AreEqual (NSDateComponentsFormatterZeroFormattingBehavior.Pad, dateComponentsFormatter.ZeroFormattingBehavior, "ZeroFormattingBehavior"); + + NSCalendar c = new NSCalendar (NSCalendarType.Buddhist); + Assert.IsNotNull (dateComponentsFormatter.Calendar); + dateComponentsFormatter.Calendar = c; + Assert.AreEqual (c.Identifier, dateComponentsFormatter.Calendar.Identifier, "Calendar"); + + dateComponentsFormatter.AllowsFractionalUnits = true; + Assert.IsTrue (dateComponentsFormatter.AllowsFractionalUnits, "AllowsFractionalUnits"); + + dateComponentsFormatter.MaximumUnitCount = 50; + Assert.AreEqual (50, dateComponentsFormatter.MaximumUnitCount, "MaximumUnitCount"); + + dateComponentsFormatter.CollapsesLargestUnit = true; + Assert.IsTrue (dateComponentsFormatter.CollapsesLargestUnit, "CollapsesLargestUnit"); + + dateComponentsFormatter.IncludesApproximationPhrase = true; + Assert.IsTrue (dateComponentsFormatter.IncludesApproximationPhrase, "IncludesApproximationPhrase"); + + dateComponentsFormatter.IncludesTimeRemainingPhrase = true; + Assert.IsTrue (dateComponentsFormatter.IncludesTimeRemainingPhrase, "IncludesTimeRemainingPhrase"); + + Assert.IsNotNull (dateComponentsFormatter.FormattingContext); + dateComponentsFormatter.FormattingContext = new NSFormattingContext (); + } + + [Test] + public void DateStringForObjectValue () + { + RequiresIos8 (); + + string formattedString = dateComponentsFormatter.StringForObjectValue (NowComponents); + TestFormattedString (formattedString, "StringForObjectValue"); + } + + [Test] + public void DateStringFromDateComponents () + { + RequiresIos8 (); + + string formattedString = dateComponentsFormatter.StringFromDateComponents (NowComponents); + TestFormattedString (formattedString, "StringFromDateComponents"); + } + + [Test] + public void DateStringFromDate () + { + RequiresIos8 (); + + dateComponentsFormatter.AllowedUnits = NSCalendarUnit.Second; // New default allowed units won't give us second resolution + string formattedString = dateComponentsFormatter.StringFromDate (NSDate.Now, NSDate.Now.AddSeconds (60)); + TestFormattedString (formattedString, "StringFromDate"); + } + + [Test] + public void DateStringFromTimeInterval () + { + RequiresIos8 (); + + string formattedString = dateComponentsFormatter.StringFromTimeInterval (1.5); + TestFormattedString (formattedString, "StringFromTimeInterval"); + } + + [Test] + public void DateLocalizedStringFromDateComponents () + { + RequiresIos8 (); + + string formattedString = NSDateComponentsFormatter.LocalizedStringFromDateComponents (NowComponents, NSDateComponentsFormatterUnitsStyle.Full); + TestFormattedString (formattedString, "LocalizedStringFromDateComponents"); + } + + [Test] + public void DateGetObjectValueTest () + { + RequiresIos8 (); + + // NSDateComponentsFormatter currently only implements formatting, not parsing. Until it implements parsing, this will always return NO. + + NSObject o; + string e; + bool value = dateComponentsFormatter.GetObjectValue (out o, string.Empty, out e); + Assert.IsFalse (value, "DateGetObjectValueTest"); // If this ever returns true, we need to write a better test + } + + #endregion + + #region NSEnergyFormatter + + [Test] + public void EnergyEnergyStringFromValue () + { + RequiresIos8 (); + + string formattedString = energyFormatter.StringFromValue (2.0, NSEnergyFormatterUnit.Kilocalorie); + TestFormattedString (formattedString, "EnergyStringFromValue"); + } + + [Test] + public void EnergyEnergyStringFromJoules () + { + RequiresIos8 (); + + string formattedString = energyFormatter.StringFromJoules (2.0); + TestFormattedString (formattedString, "StringFromJoules"); + } + + [Test] + public void EnergyUnitStringFromValue () + { + RequiresIos8 (); + + string formattedString = energyFormatter.UnitStringFromValue (2.0, NSEnergyFormatterUnit.Kilojoule); + TestFormattedString (formattedString, "UnitStringFromValue"); + } + + [Test] + public void EnergyUnitStringFromJoules () + { + RequiresIos8 (); + + NSEnergyFormatterUnit unit; + string formattedString = energyFormatter.UnitStringFromJoules (2.0, out unit); + TestFormattedString (formattedString, "UnitStringFromJoules"); + Assert.IsTrue ((int)unit > 0); // We got some value from the API + } + + [Test] + public void EnergyGetObjectValue () + { + RequiresIos8 (); + // No parsing is supported. This method will return NO. + + NSObject o; + string e; + bool value = energyFormatter.GetObjectValue (out o, string.Empty, out e); + Assert.IsFalse (value, "EnergyGetObjectValue"); // If this ever returns true, we need to write a better test + } + + #endregion + + #region NSDateIntervalFormatter + + [Test] + public void DateIntervalStringFromDate () + { + RequiresIos8 (); + + using (var dateIntervalFormatter = new NSDateIntervalFormatter ()) { + string formattedString = dateIntervalFormatter.StringFromDate (NSDate.Now.AddSeconds (-60 * 60 * 24), NSDate.Now); + TestFormattedString (formattedString, "DateIntervalStringFromDate"); + } + } + + #endregion + } +} + \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/IndexPathTest.cs b/tests/monotouch-test/Foundation/IndexPathTest.cs new file mode 100644 index 000000000000..e587d744970e --- /dev/null +++ b/tests/monotouch-test/Foundation/IndexPathTest.cs @@ -0,0 +1,123 @@ +// +// Unit tests for NSIndexPath +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class IndexPathTest { + [Test] + public void FromIndex () + { + using (var ip = NSIndexPath.FromIndex (314159)) { + Assert.AreEqual ((nuint)1, ip.Length, "Length"); + var rv = ip.GetIndexes (); + Assert.AreEqual (1, rv.Length, "GetIndexes ().Length"); + Assert.AreEqual (314159, rv [0], "GetIndexes ()[0]"); + } + } + + [Test] + public void IndexPathByAddingIndexTest () + { + using (var ip1 = new NSIndexPath ()) { + using (var ip2 = ip1.IndexPathByAddingIndex (3141592)) { + Assert.AreEqual ((nuint)1, ip2.Length, "Length"); + var rv = ip2.GetIndexes (); + Assert.AreEqual (1, rv.Length, "GetIndexes ().Length"); + Assert.AreEqual (3141592, rv [0], "GetIndexes ()[0]"); + } + } + } + + [Test] + public void IndexPathByRemovingLastIndexTest () + { + using (var ip1 = NSIndexPath.FromIndex (3)) { + using (var ip2 = ip1.IndexPathByRemovingLastIndex ()) { + Assert.AreEqual ((nuint)0, ip2.Length, "Length"); + var rv = ip2.GetIndexes (); + Assert.AreEqual (0, rv.Length, "GetIndexes ().Length"); + } + } + } + + [Test] + public void IndexAtPositionTest () + { + using (var ip = NSIndexPath.Create (3, 14, 15)) { + Assert.AreEqual ((nuint) 3, ip.Length, "Length"); + Assert.AreEqual ((nuint)3, ip.IndexAtPosition (0), "[0]"); + Assert.AreEqual ((nuint)14, ip.IndexAtPosition (1), "[0]"); + Assert.AreEqual ((nuint)15, ip.IndexAtPosition (2), "[0]"); + } + } + + [Test] + public void CompareTest () + { + using (var ip1 = NSIndexPath.Create (3, 14, 15)) { + using (var ip2 = NSIndexPath.Create (3, 14, 15)) { + using (var ip3 = NSIndexPath.Create (3, 14)) { + Assert.AreEqual (0, ip1.Compare (ip2), "ip1.Compare (ip2)"); + Assert.True (ip1.Equals (ip2), "ip1.Equals (ip2)"); + // "Two objects that are equal return hash codes that are equal." + Assert.That (ip1.GetHashCode (), Is.EqualTo (ip2.GetHashCode ()), "GetHashCode"); + Assert.AreNotEqual (0, ip1.Compare (ip3), "ip1.Compare (ip3)"); + Assert.False (ip1.Equals (ip3), "ip1.Equals (ip3)"); + } + } + } + } + + [Test] + public void CreateTest () + { + Assert.Throws (() => NSIndexPath.Create ((int[])null), "ANE 1"); + Assert.Throws (() => NSIndexPath.Create ((uint[])null), "ANE 2"); + Assert.Throws (() => NSIndexPath.Create ((nint[])null), "ANE 3"); + Assert.Throws (() => NSIndexPath.Create ((nuint[])null), "ANE 4"); + + using (var ip = NSIndexPath.Create (1, 2, 3, 4)) { + Assert.AreEqual ((nuint)4, ip.Length, "Length"); + var rv = ip.GetIndexes (); + Assert.AreEqual ((nuint) 4, rv.Length, "GetIndexes ().Length"); + Assert.AreEqual ((nuint) 1, rv [0], "GetIndexes ()[0]"); + Assert.AreEqual ((nuint) 2, rv [1], "GetIndexes ()[1]"); + Assert.AreEqual ((nuint) 3, rv [2], "GetIndexes ()[2]"); + Assert.AreEqual ((nuint) 4, rv [3], "GetIndexes ()[3]"); + } + + using (var ip = NSIndexPath.Create ((uint) 1, (uint) 2)) { + Assert.AreEqual ((nuint) 2, ip.Length, "Length"); + var rv = ip.GetIndexes (); + Assert.AreEqual ((nuint) 2, rv.Length, "GetIndexes ().Length"); + Assert.AreEqual ((nuint) 1, rv [0], "GetIndexes ()[0]"); + Assert.AreEqual ((nuint) 2, rv [1], "GetIndexes ()[1]"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/KeyedUnarchiverTest.cs b/tests/monotouch-test/Foundation/KeyedUnarchiverTest.cs new file mode 100644 index 000000000000..ac70fae5ffba --- /dev/null +++ b/tests/monotouch-test/Foundation/KeyedUnarchiverTest.cs @@ -0,0 +1,48 @@ +// +// Unit tests for NSKeyedUnarchiver +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Net; +using System.IO; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +using MonoTouchException=Foundation.MonoTouchException; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouchException=MonoTouch.Foundation.MonoTouchException; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class KeyedUnarchiverTest { + + [Test] + public void Exceptions () + { + var data = NSData.FromString ("dummy string"); + if (TestRuntime.CheckiOSSystemVersion (9, 0)) { + // iOS9 does not throw if it cannot get correct data, it simply returns null (much better) + Assert.Null (NSKeyedUnarchiver.UnarchiveFile (Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png")), "UnarchiveFile"); + Assert.Null (NSKeyedUnarchiver.UnarchiveObject (data), "UnarchiveObject"); + } else { + Assert.Throws (() => NSKeyedUnarchiver.UnarchiveFile (Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png")), "UnarchiveFile"); + Assert.Throws (() => NSKeyedUnarchiver.UnarchiveObject (data), "UnarchiveObject"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/LocaleTest.cs b/tests/monotouch-test/Foundation/LocaleTest.cs new file mode 100644 index 000000000000..86dc2a60ad4c --- /dev/null +++ b/tests/monotouch-test/Foundation/LocaleTest.cs @@ -0,0 +1,113 @@ +// +// Unit tests for NSLocale +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Globalization; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LocaleTest { + + [Test] + public void CurrentLocale () + { + Assert.NotNull (NSLocale.CurrentLocale, "CurrentLocale"); + } + + [Test] + public void FromLocaleIdentifier () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + string ident = NSLocale.CurrentLocale.Identifier; + Assert.That (NSLocale.FromLocaleIdentifier (ident).Identifier, Is.EqualTo (ident), "FromLocaleIdentifier"); + } + + [Test] + public void InitRegionInfo () + { + string name = NSLocale.CurrentLocale.CountryCode; // two letter code + // Handle manually set locale (without country) in iOS Simulator (plist) - ref bug #18520 + if (name == null) + Assert.Inconclusive ("You can construct locale without countries"); + RegionInfo ri = new RegionInfo (name); + Assert.That (ri.Name, Is.EqualTo (name), "Name"); + } + + [Test] + public void CountryLessLocale () + { + string name = "zh-Hans"; // there's no country data from the supplied name - ref bug #18520 + using (NSLocale locale = new NSLocale (name)) { + Assert.Null (locale.CountryCode, "CountryCode"); + } + } + + [Test] + public void Properties () + { + using (NSLocale en = new NSLocale ("en-US")) { + Assert.That (en.AlternateQuotationBeginDelimiterKey, Is.EqualTo ("‘"), "AlternateQuotationBeginDelimiterKey"); + Assert.That (en.AlternateQuotationEndDelimiterKey, Is.EqualTo ("’"), "AlternateQuotationEndDelimiterKey"); + Assert.Null (en.CollationIdentifier, "CollationIdentifier"); + Assert.That (en.CollatorIdentifier, Is.EqualTo ("en-US"), "CollatorIdentifier"); + Assert.That (en.CountryCode, Is.EqualTo ("US"), "CountryCode"); + Assert.That (en.CurrencyCode, Is.EqualTo ("USD"), "CurrencyCode"); + Assert.That (en.CurrencySymbol, Is.EqualTo ("$"), "CurrencySymbol"); + Assert.That (en.DecimalSeparator, Is.EqualTo ("."), "DecimalSeparator"); + Assert.That (en.GroupingSeparator, Is.EqualTo (","), "GroupingSeparator"); + Assert.That (en.Identifier, Is.EqualTo ("en-US"), "Identifier"); + Assert.That (en.LanguageCode, Is.EqualTo ("en"), "LanguageCode"); + Assert.That (en.LocaleIdentifier, Is.EqualTo ("en-US"), "LocaleIdentifier"); + Assert.That (en.MeasurementSystem, Is.EqualTo ("U.S."), "MeasurementSystem"); + Assert.That (en.QuotationBeginDelimiterKey, Is.EqualTo ("“"), "QuotationBeginDelimiterKey"); + Assert.That (en.QuotationEndDelimiterKey, Is.EqualTo ("”"), "QuotationEndDelimiterKey"); + } + } + + [Test] + public void DisplayName_En () + { + using (NSLocale en = new NSLocale ("en-US")) { + Assert.That (en.GetIdentifierDisplayName (en.Identifier), Is.EqualTo ("English (United States)"), "Identifier"); + Assert.That (en.GetLanguageCodeDisplayName (en.LanguageCode), Is.EqualTo ("English"), "LanguageCode"); + Assert.That (en.GetCountryCodeDisplayName (en.CountryCode), Is.EqualTo ("United States"), "CountryCode"); + Assert.That (en.GetCurrencyCodeDisplayName (en.CurrencyCode), Is.EqualTo ("US Dollar"), "CurrencyCode"); + } + } + + [Test] + public void DisplayName_Fr () + { + using (NSLocale en = new NSLocale ("en-US")) + using (NSLocale fr = new NSLocale ("fr-CA")) { + Assert.That (fr.GetIdentifierDisplayName (en.Identifier), Is.EqualTo ("anglais (États-Unis)"), "Identifier"); + Assert.That (fr.GetLanguageCodeDisplayName (en.LanguageCode), Is.EqualTo ("anglais"), "LanguageCode"); + Assert.That (fr.GetCountryCodeDisplayName (en.CountryCode), Is.EqualTo ("États-Unis"), "CountryCode"); + Assert.That (fr.GetCurrencyCodeDisplayName (en.CurrencyCode), Is.EqualTo ("dollar des États-Unis"), "CurrencyCode"); + + Assert.That (en.GetIdentifierDisplayName (fr.Identifier), Is.EqualTo ("French (Canada)"), "Identifier"); + Assert.That (en.GetLanguageCodeDisplayName (fr.LanguageCode), Is.EqualTo ("French"), "LanguageCode"); + Assert.That (en.GetCountryCodeDisplayName (fr.CountryCode), Is.EqualTo ("Canada"), "CountryCode"); + Assert.That (en.GetCurrencyCodeDisplayName (fr.CurrencyCode), Is.EqualTo ("Canadian Dollar"), "CurrencyCode"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/MutableAttributedStringTest.cs b/tests/monotouch-test/Foundation/MutableAttributedStringTest.cs new file mode 100644 index 000000000000..fe76ae4efa03 --- /dev/null +++ b/tests/monotouch-test/Foundation/MutableAttributedStringTest.cs @@ -0,0 +1,62 @@ +// +// Unit tests for NSMutableSAttributedString +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2014 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class MutableSAttributedStringTest { + + [Test] + public void InitWith () + { + using (var s1 = new NSMutableAttributedString ("string")) { + // initWithString: does not respond (see dontlink.app) but it works + Assert.That (s1.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-1"); + + using (var d = new NSDictionary ()) + using (var s2 = new NSMutableAttributedString ("string", d)) { + // initWithString:attributes: does not respond (see dontlink.app) but it works + Assert.That (s2.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-2"); + } + + using (var s3 = new NSMutableAttributedString (s1)) { + // initWithAttributedString: does not respond (see dontlink.app) but it works + Assert.That (s3.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-3"); + } + } + } + + [Test] + public void NullDictionary () + { + using (var s = new NSMutableAttributedString ("string", (NSDictionary) null)) { + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero)); + } + } + +#if !__WATCHOS__ + [Test] + public void IndirectNullDictionary () + { + // that will call NSAttributedString.ToDictionary which may return null (if empty) + using (var s = new NSMutableAttributedString ("string", foregroundColor: null)) { + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero)); + } + } +#endif // !__WATCHOS__ + } +} diff --git a/tests/monotouch-test/Foundation/MutableDataTest.cs b/tests/monotouch-test/Foundation/MutableDataTest.cs new file mode 100644 index 000000000000..66e5a3ae1539 --- /dev/null +++ b/tests/monotouch-test/Foundation/MutableDataTest.cs @@ -0,0 +1,87 @@ +// +// Unit tests for NSMutableData +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MutableDataTest { + + [Test] + public void FromCapacity () + { + Assert.Throws (delegate { + NSMutableData.FromCapacity (-1); + }, "negative"); + using (var empty = NSMutableData.FromCapacity (0)) { + Assert.That (empty.Length, Is.EqualTo ((nuint) 0), "Length"); + } + } + + [Test] + public void FromLength () + { + Assert.Throws (delegate { + NSMutableData.FromLength (-1); + }, "negative"); + using (var empty = NSMutableData.FromLength (0)) { + Assert.That (empty.Length, Is.EqualTo ((nuint) 0), "Length"); + } + } + + [Test] + public void Constructor () + { + // the bound constructor is for capacity (not length) + TestDelegate check_capacity = delegate { + uint capacity = (uint)Int32.MaxValue + 2; + Console.WriteLine ("Trying to allocate {0} bytes, this may cause malloc errors", capacity); + new NSMutableData (capacity).Dispose (); + }; + + if (IntPtr.Size == 4) { + Assert.Throws (check_capacity, "negative"); + } else { + // this can either fail with an Exception due to not enough memory to allocate 2GB (typical on device), or it can succeed (usually in the sim). + try { + check_capacity (); + // It worked, that's fine. + } catch (Exception ex) { + // Verify that the exception is an OOM (i.e. native code failed to init the object). + Assert.AreSame (typeof (Exception), ex.GetType (), "exception type"); + Assert.That (ex.Message, Is.StringStarting ("Could not initialize an instance of the type 'Foundation.NSMutableData': the native 'initWithCapacity:' method returned nil."), "OOM"); + } + } + + using (var empty = new NSMutableData (0)) { + Assert.That (empty.Length, Is.EqualTo ((nuint) 0), "Length"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/MutableStringTest.cs b/tests/monotouch-test/Foundation/MutableStringTest.cs new file mode 100644 index 000000000000..5521f4cca351 --- /dev/null +++ b/tests/monotouch-test/Foundation/MutableStringTest.cs @@ -0,0 +1,99 @@ +// +// Unit tests for NSMutableString +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MutableStringTest { + + [Test] + public void Insert () + { + using (var s = new NSMutableString (-1)) { + s.SetString ((NSString)"Hello World"); + s.Insert ((NSString)"!", s.Length); + Assert.That (s.ToString (), Is.EqualTo ("Hello World!"), "end"); + + Assert.Throws (delegate { + s.Insert ((NSString)"@", -1); + }, "negative"); + Assert.Throws (delegate { + s.Insert ((NSString)"oops", s.Length + 1); + }, "out of range"); + } + } + + [Test] + public void Replace () + { + using (var s = new NSMutableString (0)) { + s.SetString ((NSString)"Hello World"); + + var number = s.ReplaceOcurrences ((NSString)"World", (NSString)"Xamarin", + NSStringCompareOptions.CaseInsensitiveSearch, new NSRange (0, s.Length)); +#if XAMCORE_2_0 + Assert.That (number, Is.EqualTo ((nuint) 1), "Number of replacements"); +#else + Assert.That (number, Is.EqualTo (1), "Number of replacements"); +#endif + Assert.That (s.ToString (), Is.EqualTo ("Hello Xamarin"), "replaced"); + + Assert.Throws (delegate { + s.ReplaceOcurrences ((NSString)"Xamarin", (NSString)"World!", + NSStringCompareOptions.CaseInsensitiveSearch, new NSRange (0, s.Length + 1)); + }, "bad 1"); + + Assert.Throws (delegate { + s.ReplaceOcurrences ((NSString)"Xamarin", (NSString)"World!", + NSStringCompareOptions.CaseInsensitiveSearch, new NSRange (1, s.Length)); + }, "bad 2"); + } + } + + [Test] + public void Delete () + { + using (var s = new NSMutableString (0)) { + s.SetString ((NSString)"Hello World"); + s.DeleteCharacters (new NSRange (5, 6)); + Assert.That (s.ToString (), Is.EqualTo ("Hello"), "deleetd"); + + Assert.Throws (delegate { + s.DeleteCharacters (new NSRange (0, s.Length + 1)); + }, "bad 1"); + + Assert.Throws (delegate { + s.DeleteCharacters (new NSRange (1, s.Length)); + }, "bad 2"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/NSArray1Test.cs b/tests/monotouch-test/Foundation/NSArray1Test.cs new file mode 100644 index 000000000000..d7703281607c --- /dev/null +++ b/tests/monotouch-test/Foundation/NSArray1Test.cs @@ -0,0 +1,99 @@ +// +// Unit tests for NSArray Generic support +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + [TestFixture] + public class NSArray1Test { + [Test] + public void Ctor () + { + var arr = new NSArray (); + + Assert.AreEqual (0, arr.Count, "NSArray Count"); + } + + [Test] + public void FromNSObjectsTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + + using (var arr = NSArray.FromNSObjects (str1, str2, str3)) { + Assert.AreEqual (3, arr.Count, "NSArray Count"); + Assert.AreSame (str1, arr [0], "NSArray indexer"); + Assert.AreSame (str2, arr [1], "NSArray indexer"); + Assert.AreSame (str3, arr [2], "NSArray indexer"); + } + } + + [Test] + public void FromNSObjectsCountTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + + using (var arr = NSArray.FromNSObjects (3, str1, str2, str3)) { + Assert.AreEqual (3, arr.Count, "NSArray Count"); + Assert.AreSame (str1, arr [0], "NSArray indexer"); + Assert.AreSame (str2, arr [1], "NSArray indexer"); + Assert.AreSame (str3, arr [2], "NSArray indexer"); + } + } + + [Test] + public void IEnumerableTest () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + var st = NSArray.FromNSObjects (values); + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (NSString a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + + [Test] + public void FromNSObjectsNullTest () + { + var str1 = (NSString) "1"; + NSString str2 = null; + var str3 = (NSString) "3"; + + using (var arr = NSArray.FromNSObjects (str1, str2, str3)) { + Assert.AreEqual (3, arr.Count, "NSArray Count"); + Assert.AreSame (str1, arr [0], "NSArray indexer"); + Assert.IsNull (arr [1], "NSArray null indexer"); + Assert.AreSame (str3, arr [2], "NSArray indexer"); + } + } + } +} +#endif // XAMCORE_2_0 \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/NSCharacterSetTest.cs b/tests/monotouch-test/Foundation/NSCharacterSetTest.cs new file mode 100644 index 000000000000..6c3702ab2158 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSCharacterSetTest.cs @@ -0,0 +1,65 @@ +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class NSCharacterSetTest + { + static void RequiresIos8 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8+"); + } + + [Test] + public void NSMutableCharacterSet_TestStaticSets () + { + RequiresIos8 (); + + TestSet (NSMutableCharacterSet.Alphanumerics, "Alphanumerics", 'a'); + TestSet (NSMutableCharacterSet.Capitalized, "Capitalized", '\u01C5'); + TestSet (NSMutableCharacterSet.Controls, "Controls", '\u0000'); + TestSet (NSMutableCharacterSet.DecimalDigits, "DecimalDigits", '1'); + TestSet (NSMutableCharacterSet.Decomposables, "Decomposables", '\u00e9'); + TestSet (NSMutableCharacterSet.Illegals, "Illegals", '\uFFFE'); + TestSet (NSMutableCharacterSet.Letters, "Letters", 'a'); + TestSet (NSMutableCharacterSet.LowercaseLetters, "LowercaseLetters", 'a'); + TestSet (NSMutableCharacterSet.Newlines, "Newlines", '\n'); + TestSet (NSMutableCharacterSet.Marks, "Marks", '\u20DD'); + TestSet (NSMutableCharacterSet.Punctuation, "Punctuation", '.'); + TestSet (NSMutableCharacterSet.Symbols, "Symbols", '~'); + TestSet (NSMutableCharacterSet.UppercaseLetters, "UppercaseLetters", 'A'); + TestSet (NSMutableCharacterSet.WhitespaceAndNewlines, "WhitespaceAndNewlines", ' '); + TestSet (NSMutableCharacterSet.Whitespaces, "Whitespaces", ' '); + } + + void TestSet (NSCharacterSet s, string setName, char characterThatShouldBeInSet) + { + RequiresIos8 (); + + Assert.IsNotNull (s, setName + " was null"); + Assert.IsTrue (s.Contains (characterThatShouldBeInSet), setName + " did not contain: " + characterThatShouldBeInSet); + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSDataTest.cs b/tests/monotouch-test/Foundation/NSDataTest.cs new file mode 100644 index 000000000000..857c0bf16587 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSDataTest.cs @@ -0,0 +1,329 @@ +// +// Unit tests for NSData +// +// Authors: +// Rolf Bjarne Kvinge +// Sebastien Pouliot +// +// Copyright 2011-2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSDataTest { + + [Test] + public void ConstructorTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("This test uses API introduced in iOS 7"); + + var bytes = Marshal.AllocHGlobal (1); + var deallocated = false; + + Marshal.WriteByte (bytes, 31); + + using (var data = new NSData (bytes, 1, (a, b) => + { + deallocated = true; + Marshal.FreeHGlobal (a); + Assert.AreEqual (1, (int) b, "length in deallocator"); + })) + { + NSError error; + var file = Path.GetTempFileName (); + var url = NSUrl.FromFilename (file + ".url"); + + Assert.IsTrue (data.Save (file, false, out error), "save 1"); + Assert.IsTrue (data.Save (file, true, out error), "save 2"); + Assert.IsTrue (data.Save (file, NSDataWritingOptions.Atomic, out error), "save 3"); + Assert.IsTrue (data.Save (url, false, out error), "save url 1"); + Assert.IsTrue (data.Save (url, true, out error), "save url 2"); + Assert.IsTrue (data.Save (url, NSDataWritingOptions.Atomic, out error), "save url 3"); + } + + Assert.IsTrue (deallocated, "deallocated"); + } + + [Test] + public void FromEmptyArrayTest () + { + Assert.That (NSData.FromArray (new byte [0] {}) != null, "#1"); + } + + [Test] + public void FromFile () + { + Assert.Null (NSData.FromFile ("does not exists"), "unexisting"); + Assert.NotNull (NSData.FromFile ("Info.plist"), "Info.plist"); + } + + [Test] + public void FromFile_Options () + { + NSError err; + var n = NSData.FromFile ("does not exists", NSDataReadingOptions.Uncached, out err); + Assert.Null (n, "unexisting"); + Assert.That (err.Code, Is.EqualTo ((nint) 260), "err"); + } + + [Test] + public void AsStream () + { + // suggested solution for http://stackoverflow.com/q/10623162/220643 + using (var data = NSData.FromArray (new byte [1] { 42 })) + using (MemoryStream ms = new MemoryStream ()) { + data.AsStream ().CopyTo (ms); + byte[] result = ms.ToArray (); + Assert.That (result.Length, Is.EqualTo (1), "Length"); + Assert.That (result [0], Is.EqualTo (42), "Content"); + } + } + + [Test] + public void ToArray () + { + using (var data = NSData.FromArray (new byte[] { 1, 2, 3 })) { + var arr = data.ToArray (); + Assert.AreEqual (3, arr.Length, "Length"); + for (int i = 0; i < arr.Length; i++) + Assert.AreEqual (i + 1, arr [i], "idx " + i.ToString ()); + } + } + + [Test] + public void BytesLength () + { + // suggested alternative for http://stackoverflow.com/q/10623162/220643 + using (var data = NSData.FromArray (new byte [1] { 42 })) { + byte[] result = new byte[data.Length]; + Marshal.Copy (data.Bytes, result, 0, (int) data.Length); + Assert.That (result.Length, Is.EqualTo (1), "Length"); + Assert.That (result [0], Is.EqualTo (42), "Content"); + } + } + + [Test] + public void Https () + { + using (var url = new NSUrl ("https://blog.xamarin.com/robots.txt")) + using (var x = NSData.FromUrl (url)) { + Assert.That ((x != null) && (x.Length > 0)); + } + } + + [Test] + public void Base64_Short () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + using (var data = NSData.FromArray (new byte [1] { 42 })) { + string s1 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithCarriageReturn); + Assert.That (s1, Is.EqualTo ("Kg=="), "EndLineWithCarriageReturn"); + string s2 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithLineFeed); + Assert.That (s2, Is.EqualTo ("Kg=="), "EndLineWithLineFeed"); + string s3 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithCarriageReturn | NSDataBase64EncodingOptions.EndLineWithCarriageReturn); + Assert.That (s3, Is.EqualTo ("Kg=="), "EndLineWithCarriageReturn/EndLineWithLineFeed"); + // '~' will be ignored + using (var base64a = new NSData ("~" + s3, NSDataBase64DecodingOptions.IgnoreUnknownCharacters)) { + Assert.That (base64a.GetBase64EncodedString (NSDataBase64EncodingOptions.None), Is.EqualTo ("Kg=="), "ctor(string)/None"); + Assert.Throws (() => new NSData (data, NSDataBase64DecodingOptions.None), "invalid data"); + } + } + } + + [Test] + public void Base64_Long () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + byte[] array = new byte [60]; + using (var data = NSData.FromArray (array)) { + string s0 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithCarriageReturn); + Assert.That (s0.Length, Is.EqualTo (80), "no line limit/break"); + string s1 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithCarriageReturn | NSDataBase64EncodingOptions.SixtyFourCharacterLineLength); + Assert.That (s1.Length, Is.EqualTo (81), "break 64 + CR"); + string s2 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithLineFeed | NSDataBase64EncodingOptions.SeventySixCharacterLineLength); + Assert.That (s2.Length, Is.EqualTo (81), "break 76 + LF"); + string s3 = data.GetBase64EncodedString (NSDataBase64EncodingOptions.EndLineWithLineFeed | NSDataBase64EncodingOptions.EndLineWithCarriageReturn | NSDataBase64EncodingOptions.SixtyFourCharacterLineLength); + Assert.That (s3.Length, Is.EqualTo (82), "break 76 + CR/LF"); + // '~' will be ignored + using (var base64a = new NSData ("~"+ s3, NSDataBase64DecodingOptions.IgnoreUnknownCharacters)) { + Assert.That (base64a.GetBase64EncodedString (NSDataBase64EncodingOptions.None).Length, Is.EqualTo (80), "ctor(string)/None"); + Assert.Throws (() => new NSData (data, NSDataBase64DecodingOptions.None), "invalid data"); + } + } + } + + [Test] + public void FromStream () + { + Assert.Throws (delegate { + NSData.FromStream (null); + }, "null"); + using (var d = NSData.FromStream (Stream.Null)) { + Assert.That (d.Length, Is.EqualTo ((nuint) 0), "Length"); + } + } + + class CanNotReadStream : MemoryStream { + public override bool CanRead { + get { return false; } + } + } + + [Test] + public void FromStream_CanNotRead () + { + using (var s = new CanNotReadStream ()) { + Assert.Null (NSData.FromStream (s), "!CanRead"); + } + } + + class CanNotSeekStream : MemoryStream { + + public CanNotSeekStream () : base (new byte [8]) + { + } + + public override bool CanSeek { + get { return false; } + } + } + + [Test] + public void FromStream_CanNotSeek () + { + using (var s = new CanNotSeekStream ()) + using (var d = NSData.FromStream (s)) { + Assert.That (d.Length, Is.EqualTo ((nuint) 8), "Length"); + } + } + + class NegativeLengthStream : MemoryStream { + + bool can_seek; + + public NegativeLengthStream (bool canSeek) : base (new byte [12]) + { + can_seek = canSeek; + } + + public override bool CanSeek { + get { return can_seek; } + } + + public override long Length { + get { return -1; } + } + } + + [Test] + public void FromStream_Negative () + { + using (var s = new NegativeLengthStream (false)) + using (var d = NSData.FromStream (s)) { + Assert.That (d.Length, Is.EqualTo ((nuint) 12), "Length"); + } + + // that would be a very buggy stream implementation + using (var s = new NegativeLengthStream (true)) { + Assert.Throws (delegate { + NSData.FromStream (s); + }, "negative"); + } + } + + class NoLengthStream : MemoryStream { + + public NoLengthStream () : base (new byte [16]) + { + } + + public override long Length { + get { throw new NotSupportedException (); } + } + } + + [Test] + public void FromStream_NoLength () + { + using (var s = new NoLengthStream ()) + using (var d = NSData.FromStream (s)) { + Assert.That (d.Length, Is.EqualTo ((nuint) 16), "Length"); + } + } + + [Test] + public void FromStream_Position () + { + using (var s = new MemoryStream (new byte [20])) { + s.Position = 10; + using (var d = NSData.FromStream (s)) { + Assert.That (d.Length, Is.EqualTo ((nuint) 10), "Length"); + } + } + } + + [Test] + public void Base64String () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + using (var d = new NSData ("WGFtYXJpbg==", NSDataBase64DecodingOptions.IgnoreUnknownCharacters)) { + Assert.That (d.ToString (), Is.EqualTo ("Xamarin")); + } + } + + [Test] + public void Base64Data () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + using (var b = NSData.FromString ("WGFtYXJpbg==")) + using (var d = new NSData (b, NSDataBase64DecodingOptions.IgnoreUnknownCharacters)) { + Assert.That (d.ToString (), Is.EqualTo ("Xamarin")); + } + } + + [Test] + public void ToString_17693 () + { + byte[] data = { 0x10, 0x02, 0x0A, 0x42, 0xC0, 0xA8, 0x02, 0x1E }; + using (var ms = new MemoryStream (data)) + using (var d = NSData.FromStream (ms)) { + // This cannot be converted to an UTF8 string and ToString should not throw + // so we go back to showing the result of the `descruption` selector + Assert.That (d.ToString (), Is.EqualTo (d.Description), "ToString"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/NSDictionary2Test.cs b/tests/monotouch-test/Foundation/NSDictionary2Test.cs new file mode 100644 index 000000000000..47740246fc19 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSDictionary2Test.cs @@ -0,0 +1,560 @@ + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using NUnit.Framework; + +using Foundation; +using ObjCRuntime; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSDictionary2Test { + + [Test] + public void Ctor () + { + var dict = new NSDictionary (); + Assert.AreEqual (0, dict.Count, "Count"); + } + + // + // Tests for the new NSDictionary from parameters constructors + // + [Test] + public void DictionaryCtorKeyValues () + { + var key = new NSString ("key"); + var value = new NSString ("value"); + + var j = new NSDictionary (key, value); + Assert.AreEqual (j.Count, 1, "count"); + Assert.AreEqual (j [key], value, "key lookup"); + } + + [Test] + public void Ctor_Arrays () + { + var j = new NSDictionary ( + new NSString[] { new NSString ("first-k"), new NSString ("second-k") }, + new NSString[] { new NSString ("first"), new NSString ("second") } + ); + Assert.AreEqual (j.Count, 2, "count"); + Assert.AreEqual ((string)(j [(NSString) "first-k"]), "first", "lookup1"); + Assert.AreEqual ((string)(j [(NSString) "second-k"]), "second", "lookup2"); + } + + [Test] + public void Ctor_NSDictionary () + { + var other = new NSDictionary ((NSString) "key", (NSString) "value"); + var j = new NSDictionary (other); + + Assert.AreEqual (j.Count, 1, "count"); + Assert.AreEqual ((string)(NSString)(j ["key"]), "value", "key lookup"); + } + + [Test] + public void InbalancedCtor() + { + Assert.Throws (() => { + new NSDictionary ( + new NSString[] { new NSString ("key") }, + new NSString[] { new NSString ("value"), new NSString ("other") }); + }); + } + + [Test] + public void KeyValue_Autorelease () + { + using (var k = new NSString ("keyz")) + using (var v = new NSString ("valuez")) { + var k1 = k.RetainCount; + if (k1 >= int.MaxValue) + Assert.Ignore ("RetainCount unusable for testing"); + var k2 = k1; + Assert.That (k.RetainCount, Is.EqualTo ((nint) 1), "Key.RetainCount-a"); + var v1 = v.RetainCount; + var v2 = v1; + Assert.That (v.RetainCount, Is.EqualTo ((nint) 1), "Value.RetainCount-a"); + using (var d = new NSDictionary (k, v)) { + k2 = k.RetainCount; + Assert.That (k2, Is.GreaterThan (k1), "Key.RetainCount-b"); + v2 = v.RetainCount; + Assert.That (v2, Is.GreaterThan (v1), "Value.RetainCount-b"); + + Assert.NotNull (d.Keys, "Keys"); + // accessing `allKeys` should *NOT* change the retainCount + // that would happen without an [Autorelease] and can lead to memory exhaustion + // https://bugzilla.xamarin.com/show_bug.cgi?id=7723 + Assert.That (k.RetainCount, Is.EqualTo (k2), "Key.RetainCount-c"); + + Assert.NotNull (d.Values, "Values"); + Assert.That (v.RetainCount, Is.EqualTo (v2), "Value.RetainCount-c"); + } + Assert.That (k.RetainCount, Is.LessThan (k2), "Key.RetainCount-d"); + Assert.That (v.RetainCount, Is.LessThan (v2), "Value.RetainCount-d"); + } + } + + [Test] + public void XForY_Autorelease () + { + using (var k = new NSString ("keyz")) + using (var v = new NSString ("valuez")) { + var k1 = k.RetainCount; + if (k1 >= int.MaxValue) + Assert.Ignore ("RetainCount unusable for testing"); + var k2 = k1; + Assert.That (k.RetainCount, Is.EqualTo ((nint) 1), "Key.RetainCount-a"); + var v1 = v.RetainCount; + var v2 = v1; + Assert.That (v.RetainCount, Is.EqualTo ((nint) 1), "Value.RetainCount-a"); + using (var d = new NSDictionary (k, v)) { + k2 = k.RetainCount; + Assert.That (k2, Is.GreaterThan (k1), "Key.RetainCount-b"); + v2 = v.RetainCount; + Assert.That (v2, Is.GreaterThan (v1), "Value.RetainCount-b"); + + var x = d.KeysForObject (v); + Assert.That (x [0], Is.SameAs (k), "KeysForObject"); + + var y = d.ObjectForKey (k); + Assert.NotNull (y, "ObjectForKey"); + + using (var a = new NSMutableArray ()) { + a.Add (k); + var z = d.ObjectsForKeys (a, k); + Assert.That (z [0], Is.SameAs (v), "ObjectsForKeys"); + } + + Assert.That (k.RetainCount, Is.EqualTo (k2), "Key.RetainCount-c"); + Assert.That (v.RetainCount, Is.EqualTo (v2), "Value.RetainCount-c"); + } + Assert.That (k.RetainCount, Is.LessThan (k2), "Key.RetainCount-d"); + Assert.That (v.RetainCount, Is.LessThan (v2), "Value.RetainCount-d"); + } + } + + [Test] + public void Copy () + { + using (var k = new NSString ("key")) + using (var v = new NSString ("value")) + using (var d = new NSDictionary (k, v)) { + // NSObject.Copy works because NSDictionary conforms to NSCopying + // note: we do not Dispose the "copies" because it's the same instance being returned + var copy1 = (NSDictionary) d.Copy (); + Assert.AreSame (d, copy1, "1"); + Assert.That (copy1, Is.Not.TypeOf (), "NSDictionary-1"); + Assert.That (copy1.Count, Is.EqualTo ((nuint) 1), "Count-1"); + + var copy2 = (NSDictionary) d.Copy (null); + Assert.AreSame (d, copy2, "2"); + Assert.That (copy2, Is.Not.TypeOf (), "NSDictionary-2"); + Assert.That (copy2.Count, Is.EqualTo ((nuint) 1), "Count-2"); + + var copy3 = (NSDictionary) d.Copy (NSZone.Default); + Assert.AreSame (d, copy3, "3"); + Assert.That (copy3, Is.Not.TypeOf (), "NSDictionary-3"); + Assert.That (copy3.Count, Is.EqualTo ((nuint) 1), "Count-3"); + } + } + + [Test] + public void MutableCopy () + { + using (var k = new NSString ("key")) + using (var v = new NSString ("value")) + using (var d = new NSDictionary (k, v)) { + // NSObject.Copy works because NSDictionary conforms to NSMutableCopying + using (var copy = (NSDictionary) d.MutableCopy ()) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count"); + } + + using (var copy = (NSDictionary) d.MutableCopy (null)) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary-2"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count-2"); + } + + using (var copy = (NSDictionary) d.MutableCopy (NSZone.Default)) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary-3"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count-3"); + } + } + } + + [Test] + public void ObjectForKeyTest () + { + var value = NSDate.FromTimeIntervalSinceNow (23); + var key = new NSString ("right key"); + var dict = new NSDictionary (key, value); + + Assert.Throws (() => dict.ObjectForKey ((NSString) null), "ANE"); + Assert.AreSame (value, dict.ObjectForKey (key), "right"); + Assert.IsNull (dict.ObjectForKey ((NSString) "wrong key"), "wrong"); + } + + [Test] + public void KeysTest () + { + var value = NSDate.FromTimeIntervalSinceNow (23); + var key = new NSString ("right key"); + var dict = new NSDictionary (key, value); + + var keys = dict.Keys; + Assert.AreEqual (1, keys.Length, "Length"); + Assert.AreSame (key, keys [0], "1"); + } + + [Test] + public void KeysForObjectTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSDictionary ( + new NSString [] { key1, key2, key3 }, + new NSDate[] { value1, value1, value2 } + ); + + var rv = dict.KeysForObject (value1); + Assert.AreEqual (2, rv.Length, "v1"); + + rv = dict.KeysForObject (value2); + Assert.AreEqual (1, rv.Length, "v2"); + Assert.AreSame (key3, rv [0], "v2 key"); + + rv = dict.KeysForObject (value3); + Assert.AreEqual (0, rv.Length, "v3"); + + Assert.Throws (() => dict.KeysForObject (null), "ANE"); + } + + [Test] + public void ValuesTest () + { + var value = NSDate.FromTimeIntervalSinceNow (23); + var key = new NSString ("right key"); + var dict = new NSDictionary (key, value); + + var keys = dict.Values; + Assert.AreEqual (1, dict.Values.Length, "Length"); + Assert.AreSame (value, dict [key], "1"); + } + + [Test] + public void ObjectsForKeysTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + var key4 = new NSString ("key4"); + + var dict = new NSDictionary ( + new NSString [] { key1, key2, key3 }, + new NSDate[] { value1, value1, value2 } + ); + + var rv = dict.ObjectsForKeys (new NSString [] { key1, key4 }, value3); + Assert.AreEqual (2, rv.Length, "a"); + Assert.AreSame (value1, rv [0], "a 0"); + Assert.AreSame (value3, rv [1], "a 1"); + + rv = dict.ObjectsForKeys (new NSString [] { }, value3); + Assert.AreEqual (0, rv.Length, "b length"); + + Assert.Throws (() => dict.ObjectsForKeys ((NSString []) null, value3), "c"); + Assert.Throws (() => dict.ObjectsForKeys (new NSString [] { }, null), "d"); + } + + [Test] + public void ContainsKeyTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + Assert.True (dict.ContainsKey (key1), "a"); + Assert.False (dict.ContainsKey (key3), "b"); + Assert.Throws (() => dict.ContainsKey ((NSString) null), "ANE"); + } + + [Test] + public void TryGetValueTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + NSDate value; + + Assert.True (dict.TryGetValue (key1, out value), "a"); + Assert.AreSame (value1, value, "a same"); + + Assert.False (dict.TryGetValue (key3, out value), "b"); + Assert.IsNull (value, "b null"); + } + + [Test] + public void IndexerTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + Assert.AreSame (value1, dict [key1], "a"); + Assert.IsNull (dict [key3], "b"); + Assert.Throws (() => GC.KeepAlive (dict [(NSString) null]), "c"); + } + + [Test] + public void IDictionary2Test () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (IDictionary) dictobj; + + // Add + Assert.Throws (() => dict.Add (new KeyValuePair (null, null)), "Add"); + + // Clear + Assert.Throws (() => dict.Clear (), "Clear"); + + // Contains + Assert.IsTrue (dict.Contains (new KeyValuePair (key1, value1)), "Contains 1"); // both key and value matches + Assert.IsFalse (dict.Contains (new KeyValuePair (key1, value2)), "Contains 2"); // found key, wrong value + Assert.IsFalse (dict.Contains (new KeyValuePair (key3, value2)), "Contains 3"); // wrong key + + // ContainsKey + Assert.IsTrue (dict.ContainsKey (key1), "ContainsKey 1"); + Assert.IsFalse (dict.ContainsKey (key3), "ContainsKey 2"); + + // CopyTo + var kvp_array = new KeyValuePair [1]; + Assert.Throws (() => dict.CopyTo (null, 0), "CopyTo ANE"); + Assert.Throws (() => dict.CopyTo (kvp_array, -1), "CopyTo AOORE"); + Assert.Throws (() => dict.CopyTo (kvp_array, kvp_array.Length), "CopyTo AE 2"); + Assert.Throws (() => dict.CopyTo (kvp_array, 0), "CopyTo AE 3"); + + kvp_array = new KeyValuePair [dictobj.Count]; + + Assert.Throws (() => dict.CopyTo (kvp_array, 1), "CopyTo AE 4"); + dict.CopyTo (kvp_array, 0); + Assert.That (key1, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K1"); + Assert.AreSame (value1, kvp_array [0].Value, "CopyTo V1"); + Assert.That (key2, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K2"); + Assert.AreSame (value1, kvp_array [1].Value, "CopyTo V2"); + + // Count + Assert.AreEqual (2, dict.Count, "Count"); + + // GetEnumerator + var enumerated = Enumerable.ToArray (dict); + Assert.AreEqual (2, enumerated.Length, "Enumerator Count"); + + // IsReadOnly + Assert.IsTrue (dict.IsReadOnly, "IsReadOnly"); + + // Keys + Assert.AreEqual (2, dict.Keys.Count, "Keys Count"); + + // Remove + Assert.Throws (() => dict.Remove (null), "Remove NSE"); + + // TryGetValue + NSDate value; + Assert.Throws (() => dict.TryGetValue (null, out value), "TryGetValue ANE"); + Assert.IsTrue (dict.TryGetValue (key1, out value), "TryGetValue K1"); + Assert.AreSame (value1, value, "TryGetValue V1"); + Assert.IsFalse (dict.TryGetValue (key3, out value), "TryGetValue K2"); + + // Values + Assert.AreEqual (2, dict.Values.Count, "Values Count"); + + // Indexer + Assert.AreSame (value1, dict [key1], "this [1]"); + Assert.IsNull (dict [key3], "this [2]"); + Assert.Throws (() => GC.KeepAlive (dict [null]), "this [null]"); + + Assert.Throws (() => dict [key3] = value3, "this [1] = 1"); + } + + [Test] + public void ICollection2Test () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (ICollection>) dictobj; + + // Add + Assert.Throws (() => dict.Add (new KeyValuePair (null, null)), "Add"); + + // Clear + Assert.Throws (() => dict.Clear (), "Clear"); + + // Contains + Assert.IsTrue (dict.Contains (new KeyValuePair (key1, value1)), "Contains 1"); // both key and value matches + Assert.IsFalse (dict.Contains (new KeyValuePair (key1, value2)), "Contains 2"); // found key, wrong value + Assert.IsFalse (dict.Contains (new KeyValuePair (key3, value2)), "Contains 3"); // wrong key + + + // CopyTo + var kvp_array = new KeyValuePair [1]; + Assert.Throws (() => dict.CopyTo (null, 0), "CopyTo ANE"); + Assert.Throws (() => dict.CopyTo (kvp_array, -1), "CopyTo AOORE"); + Assert.Throws (() => dict.CopyTo (kvp_array, kvp_array.Length), "CopyTo AE 2"); + Assert.Throws (() => dict.CopyTo (kvp_array, 0), "CopyTo AE 3"); + + kvp_array = new KeyValuePair [dictobj.Count]; + + Assert.Throws (() => dict.CopyTo (kvp_array, 1), "CopyTo AE 4"); + dict.CopyTo (kvp_array, 0); + Assert.That (key1, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K1"); + Assert.AreSame (value1, kvp_array [0].Value, "CopyTo V1"); + Assert.That (key2, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K2"); + Assert.AreSame (value1, kvp_array [1].Value, "CopyTo V2"); + + // Count + Assert.AreEqual (2, dict.Count, "Count"); + + // GetEnumerator + var enumerated = Enumerable.ToArray (dict); + Assert.AreEqual (2, enumerated.Length, "Enumerator Count"); + + // IsReadOnly + Assert.IsTrue (dict.IsReadOnly, "IsReadOnly"); + + // Remove + Assert.Throws (() => dict.Remove (new KeyValuePair (null, null)), "Remove NSE"); + } + + [Test] + public void IEnumerable_KVP2Test () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (IEnumerable>) dictobj; + + // GetEnumerator + var enumerated = Enumerable.ToArray (dict); + Assert.AreEqual (2, enumerated.Length, "Enumerator Count"); + } + + [Test] + public void IEnumerableTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (IEnumerable) dictobj; + + // GetEnumerator + var c = 0; + foreach (var obj in dict) + c++; + Assert.AreEqual (2, c, "Enumerator Count"); + } + + [Test] + public void InvalidType () + { + var kv = (NSString) "a"; + var dt = NSDate.FromTimeIntervalSinceNow (1); + var obj = new NSDictionary (kv, kv); + NSDate value = NSDate.FromTimeIntervalSinceNow (3); + + // dict where TValue is wrong + var dict = Runtime.GetNSObject> (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), kv.Handle, kv.Handle)); + Assert.Throws (() => GC.KeepAlive (dict [kv]), "idx 1"); + Assert.Throws (() => dict.ObjectForKey (kv), "ObjectForKey"); + Assert.Throws (() => dict.ObjectsForKeys (new NSString [] { kv }, value), "ObjectsForKeys"); + Assert.Throws (() => dict.TryGetValue (kv, out value), "TryGetValue"); + Assert.Throws (() => GC.KeepAlive (dict.Values), "Values"); + + // dict where TKey is wrong + var dictK = Runtime.GetNSObject> (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), kv.Handle, kv.Handle)); + Assert.Throws (() => GC.KeepAlive (dictK.Keys), "K Keys"); + Assert.Throws (() => dictK.KeysForObject (kv), "K KeysForObject"); + } + } +} + +#endif // XAMCORE_2_0 diff --git a/tests/monotouch-test/Foundation/NSDictionaryTest.cs b/tests/monotouch-test/Foundation/NSDictionaryTest.cs new file mode 100644 index 000000000000..cbea2dd8cd1e --- /dev/null +++ b/tests/monotouch-test/Foundation/NSDictionaryTest.cs @@ -0,0 +1,276 @@ +using System; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSDictionaryTest { + + // + // Tests for the new NSDictionary from parameters constructors + // + [Test] + public void DictionaryCtorKeyValues () + { + var key = new NSString ("key"); + var value = new NSString ("value"); + var j = new NSDictionary (key, value); + + Assert.AreEqual (j.Count, 1, "count"); + Assert.AreEqual (j [key], value, "key lookup"); + + j = new NSDictionary (new NSString ("first"), new NSString ("first-k"), + new NSString ("second"), new NSString ("second-k")); + Assert.AreEqual (j.Count, 2, "count"); + Assert.AreEqual ((string)(NSString)(j ["first"]), "first-k", "lookup1"); + Assert.AreEqual ((string)(NSString)(j ["second"]), "second-k", "lookup2"); + } + + [Test] + public void DictionaryCtorKeyValuesObjects () + { + var j = new NSDictionary ("key", "value"); + + Assert.AreEqual (j.Count, 1, "count"); + Assert.AreEqual ((string)(NSString)(j ["key"]), "value", "key lookup"); + + j = new NSDictionary (1, 2, 3, 4); + + Assert.AreEqual (j.Count, 2, "count"); + Assert.AreEqual (((NSNumber) j [new NSNumber (1)]).Int32Value, 2, "lookup1"); + Assert.AreEqual (((NSNumber) j [new NSNumber (3)]).Int32Value, 4, "lookup2"); + } + + [Test] + public void InbalancedCtor() + { + try { + var j = new NSDictionary (new NSString ("key"), new NSString ("value"), new NSString ("other")); + } catch (ArgumentException) { + return; + } + Assert.Fail ("Should have thrown an exception"); + } + + [Test] + public void InbalancedCtor2() + { + try { + var j = new NSDictionary (1, 2, 3); + } catch (ArgumentException) { + return; + } + Assert.Fail ("Should have thrown an exception"); + } + + [Test] + public void KeyValue_Autorelease () + { + using (var k = new NSString ("keyz")) + using (var v = new NSString ("valuez")) { + var k1 = k.RetainCount; + if (k1 >= int.MaxValue) + Assert.Ignore ("RetainCount unusable for testing"); + var k2 = k1; + Assert.That (k.RetainCount, Is.EqualTo ((nint) 1), "Key.RetainCount-a"); + var v1 = v.RetainCount; + var v2 = v1; + Assert.That (v.RetainCount, Is.EqualTo ((nint) 1), "Value.RetainCount-a"); + using (var d = new NSDictionary (k, v)) { + k2 = k.RetainCount; + Assert.That (k2, Is.GreaterThan (k1), "Key.RetainCount-b"); + v2 = v.RetainCount; + Assert.That (v2, Is.GreaterThan (v1), "Value.RetainCount-b"); + + Assert.NotNull (d.Keys, "Keys"); + // accessing `allKeys` should *NOT* change the retainCount + // that would happen without an [Autorelease] and can lead to memory exhaustion + // https://bugzilla.xamarin.com/show_bug.cgi?id=7723 + Assert.That (k.RetainCount, Is.EqualTo (k2), "Key.RetainCount-c"); + + Assert.NotNull (d.Values, "Values"); + Assert.That (v.RetainCount, Is.EqualTo (v2), "Value.RetainCount-c"); + } + Assert.That (k.RetainCount, Is.LessThan (k2), "Key.RetainCount-d"); + Assert.That (v.RetainCount, Is.LessThan (v2), "Value.RetainCount-d"); + } + } + + [Test] + public void XForY_Autorelease () + { + using (var k = new NSString ("keyz")) + using (var v = new NSString ("valuez")) { + var k1 = k.RetainCount; + if (k1 >= int.MaxValue) + Assert.Ignore ("RetainCount unusable for testing"); + var k2 = k1; + Assert.That (k.RetainCount, Is.EqualTo ((nint) 1), "Key.RetainCount-a"); + var v1 = v.RetainCount; + var v2 = v1; + Assert.That (v.RetainCount, Is.EqualTo ((nint) 1), "Value.RetainCount-a"); + using (var d = new NSDictionary (k, v)) { + k2 = k.RetainCount; + Assert.That (k2, Is.GreaterThan (k1), "Key.RetainCount-b"); + v2 = v.RetainCount; + Assert.That (v2, Is.GreaterThan (v1), "Value.RetainCount-b"); + + var x = d.KeysForObject (v); + Assert.That (x [0], Is.SameAs (k), "KeysForObject"); + + var y = d.ObjectForKey (k); + Assert.NotNull (y, "ObjectForKey"); + + using (var a = new NSMutableArray ()) { + a.Add (k); + var z = d.ObjectsForKeys (a, k); + Assert.That (z [0], Is.SameAs (v), "ObjectsForKeys"); + } + + Assert.That (k.RetainCount, Is.EqualTo (k2), "Key.RetainCount-c"); + Assert.That (v.RetainCount, Is.EqualTo (v2), "Value.RetainCount-c"); + } + Assert.That (k.RetainCount, Is.LessThan (k2), "Key.RetainCount-d"); + Assert.That (v.RetainCount, Is.LessThan (v2), "Value.RetainCount-d"); + } + } + + [Test] + public void FromObjectsAndKeysTest () + { + { + var keys = new NSObject[] { new NSNumber(1), new NSNumber(2) }; + var objs = new NSObject[] { new NSNumber(1), new NSNumber(4) }; + NSDictionary ns = NSDictionary.FromObjectsAndKeys (objs, keys, 1); + Console.WriteLine (ns.Count); + Assert.AreEqual (1, ns.Count, "#1"); + } + { + var keys = new object[] { 1, 2 }; + var objs = new object[] { 3, 4 }; + NSDictionary ns = NSDictionary.FromObjectsAndKeys (objs, keys, 1); + Assert.AreEqual (1, ns.Count, "#2"); + } + } + + [Test] + public void Copy () + { + using (var k = new NSString ("key")) + using (var v = new NSString ("value")) + using (var d = new NSDictionary (k, v)) { + // NSObject.Copy works because NSDictionary conforms to NSCopying + // note: we do not Dispose the "copies" because it's the same instance being returned + var copy1 = (NSDictionary) d.Copy (); + Assert.AreSame (d, copy1, "1"); + Assert.That (copy1, Is.Not.TypeOf (), "NSDictionary-1"); + Assert.That (copy1.Count, Is.EqualTo ((nuint) 1), "Count-1"); + + var copy2 = (NSDictionary) d.Copy (null); + Assert.AreSame (d, copy2, "2"); + Assert.That (copy2, Is.Not.TypeOf (), "NSDictionary-2"); + Assert.That (copy2.Count, Is.EqualTo ((nuint) 1), "Count-2"); + + var copy3 = (NSDictionary) d.Copy (NSZone.Default); + Assert.AreSame (d, copy3, "3"); + Assert.That (copy3, Is.Not.TypeOf (), "NSDictionary-3"); + Assert.That (copy3.Count, Is.EqualTo ((nuint) 1), "Count-3"); + } + } + + [Test] + public void MutableCopy () + { + using (var k = new NSString ("key")) + using (var v = new NSString ("value")) + using (var d = new NSDictionary (k, v)) { + // NSObject.Copy works because NSDictionary conforms to NSMutableCopying + using (var copy = (NSDictionary) d.MutableCopy ()) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count"); + } + + using (var copy = (NSDictionary) d.MutableCopy (null)) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary-2"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count-2"); + } + + using (var copy = (NSDictionary) d.MutableCopy (NSZone.Default)) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary-3"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count-3"); + } + } + } + + [Test] + public void IndexerTest () + { + IntPtr strkeyptr = IntPtr.Zero; + IntPtr strobjptr = IntPtr.Zero; + IntPtr objptr; + IntPtr keyptr; + + NSString obj, key; + NSString v; + + try { + strkeyptr = Marshal.StringToHGlobalAuto ("key"); + strobjptr = Marshal.StringToHGlobalAuto ("obj"); + + // this[string] + keyptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strkeyptr); + objptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strobjptr); + using (var dict = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), objptr, keyptr))) { + v = (NSString) dict ["key"]; + Assert.AreEqual ("obj", (string) v, "a"); + + Assert.Throws (() => dict ["key"] = (NSString) "value", "a ex"); + } + + // this[NSObject] + keyptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strkeyptr); + objptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strobjptr); + using (var dict = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), objptr, keyptr))) { + v = (NSString) dict [(NSObject) (NSString) "key"]; + Assert.AreEqual ("obj", (string) v, "b"); + + Assert.Throws (() => dict [(NSObject) (NSString) "key"] = (NSString) "value", "a ex"); + } + + // this[NSString] + keyptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strkeyptr); + objptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strobjptr); + using (var dict = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), objptr, keyptr))) { + v = (NSString) dict [(NSString) "key"]; + Assert.AreEqual ("obj", (string) v, "c"); + + Assert.Throws (() => dict [(NSString) "key"] = (NSString) "value", "a ex"); + } + + } finally { + Marshal.FreeHGlobal (strkeyptr); + Marshal.FreeHGlobal (strobjptr); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/NSExpressionTest.cs b/tests/monotouch-test/Foundation/NSExpressionTest.cs new file mode 100644 index 000000000000..65417f21742f --- /dev/null +++ b/tests/monotouch-test/Foundation/NSExpressionTest.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation +{ + [TestFixture] + [Preserve (AllMembers = true)] + [assembly: Preserve (typeof (NSExpression))] + public class NSExpressionTest + { + List properties = new List { "Block", "ConstantValue", "KeyPath", "Function", + "Variable", "Operand", "Arguments", "Collection", "Predicate", "LeftExpression", + "RightExpression", "TrueExpression", "FalseExpression"}; + + void TestProperties (NSExpression expression, List availableProperties) + { + foreach (var pName in properties) { + var type = typeof (NSExpression); + var pInfo = type.GetProperty (pName); + if (!availableProperties.Contains (pName)) { + Assert.Throws (() => { + // we want to make sure that is an invalid operation exception and not + // a reflection one + try { + pInfo.GetValue (expression); + } catch (TargetInvocationException e) { + throw e.GetBaseException (); + } + }, $"Expressions of type '{expression.ExpressionType}' does not support the property '{pName}'"); + } else { + Assert.DoesNotThrow (() => { + pInfo.GetValue (expression); + }, $"Expressions of type '{expression.ExpressionType}' do support the property '{pName}'"); + } + } + } + + + [Test] + public void FromConstant () + { + using (var expression = NSExpression.FromConstant (new NSString ("Foo"))) + using (var result = expression.EvaluateWith (null, null) as NSString) + Assert.AreEqual ("Foo", result.ToString ()); + } + + [Test] + public void FromKeyPath () + { + using (var expression = NSExpression.FromKeyPath ("value")) + using (var result = expression.EvaluateWith (null, null) as NSString) + Assert.IsNull (result); + } + + [Test] + public void FromFunctionTest () + { + using (var expression = NSExpression.FromFunction ((o, e, c) => { return new NSString ("Foo"); }, new NSExpression [] { })) + using (var result = expression.EvaluateWith (null, null) as NSString) + Assert.AreEqual ("Foo", result.ToString ()); + } + + [Test] + public void FromFormatWithArgsTest () + { + using (var expression = NSExpression.FromFormat ("%f*%f", new NSObject [] { new NSNumber (2.0), new NSNumber (2.0) })) + using (var result = expression.EvaluateWith (null, null) as NSNumber) + Assert.AreEqual (4.0, result.DoubleValue); + } + + [Test] + public void FromFormatWithNoArgsTest () + { + using (var expression = NSExpression.FromFormat ("2*2")) + using (var result = expression.EvaluateWith (null, null) as NSNumber) + Assert.AreEqual (4.0, result.DoubleValue); + } + + [Test] + public void FromFormatConstant () + { + using (var expression = NSExpression.FromFormat ("2")) + using (var result = expression.EvaluateWith (null, null) as NSNumber) + Assert.AreEqual (2, result.DoubleValue); + } + + [Test] + public void AggregatePropertiesTest () + { + var availableProperties = new List { "Collection" }; + using (var lower = NSExpression.FromConstant (new NSNumber (0))) + using (var upper = NSExpression.FromConstant (new NSNumber (5))) + using (var expression = NSExpression.FromAggregate (new NSExpression [] { lower, upper })) { + Assert.AreEqual (NSExpressionType.NSAggregate, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void UnionSetPropertiesTest () + { + var availableProperties = new List { "LeftExpression", "RightExpression"}; + + using (var llower = NSExpression.FromConstant (new NSNumber (0))) + using (var lupper = NSExpression.FromConstant (new NSNumber (5))) + using (var lh = NSExpression.FromAggregate (new NSExpression [] { llower, lupper })) + using (var rlower = NSExpression.FromConstant (new NSNumber (10))) + using (var rupper = NSExpression.FromConstant (new NSNumber (50))) + using (var rh = NSExpression.FromAggregate (new NSExpression [] { rlower, rupper })) + using (var expression = NSExpression.FromUnionSet (lh, rh)) { + Assert.AreEqual (NSExpressionType.UnionSet, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void IntersectSetPropertiesTest () + { + var availableProperties = new List { "LeftExpression", "RightExpression" }; + + using (var llower = NSExpression.FromConstant (new NSNumber (0))) + using (var lupper = NSExpression.FromConstant (new NSNumber (5))) + using (var lh = NSExpression.FromAggregate (new NSExpression [] { llower, lupper })) + using (var rlower = NSExpression.FromConstant (new NSNumber (10))) + using (var rupper = NSExpression.FromConstant (new NSNumber (50))) + using (var rh = NSExpression.FromAggregate (new NSExpression [] { rlower, rupper })) + using (var expression = NSExpression.FromIntersectSet (lh, rh)) { + Assert.AreEqual (NSExpressionType.IntersectSet, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void MinusSetPropertiesTest () + { + var availableProperties = new List { "LeftExpression", "RightExpression" }; + + using (var llower = NSExpression.FromConstant (new NSNumber (0))) + using (var lupper = NSExpression.FromConstant (new NSNumber (5))) + using (var lh = NSExpression.FromAggregate (new NSExpression [] { llower, lupper })) + using (var rlower = NSExpression.FromConstant (new NSNumber (10))) + using (var rupper = NSExpression.FromConstant (new NSNumber (50))) + using (var rh = NSExpression.FromAggregate (new NSExpression [] { rlower, rupper })) + using (var expression = NSExpression.FromMinusSet (lh, rh)) { + Assert.AreEqual (NSExpressionType.MinusSet, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void ConstantPropertiesTest () + { + var availableProperties = new List { "ConstantValue"}; + using (var expression = NSExpression.FromFormat ("2")) { + Assert.AreEqual (NSExpressionType.ConstantValue, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void VariablePropertiesTest () + { + var availableProperties = new List { "Variable" }; + using (var expression = NSExpression.FromVariable ("Variable")) { + Assert.AreEqual (NSExpressionType.Variable, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void KeyPathPropertiesTest () + { + var availableProperties = new List { "KeyPath", "Operand", "Arguments" }; + using (var expression = NSExpression.FromKeyPath ("value")) { + Assert.AreEqual (NSExpressionType.KeyPath, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void FunctionPropertiesTest () + { + var availableProperties = new List { "Function", "Operand", "Arguments"}; + using (var expression = NSExpression.FromFormat ("2*2")) { + Assert.AreEqual (NSExpressionType.Function, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void BlockPropertiesTest () + { + var availableProperties = new List { "Block", "Arguments"}; + using (var expression = NSExpression.FromFunction ((o, e, c) => { return new NSString ("Foo"); }, new NSExpression [] { })) { + Assert.AreEqual (NSExpressionType.Block, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void EvaluatedObjectPropertiesTest () + { + var availableProperties = new List { }; + var mySearchKey = new NSString ("James"); + using (var predicate = NSPredicate.FromFormat ("ANY employees.firstName like 'Matthew'") as NSComparisonPredicate) + using (var expression = predicate.LeftExpression.Operand) { // NSExpressionType.EvaluatedObject; + Assert.AreEqual (NSExpressionType.EvaluatedObject, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + + [Test] + public void AnyKeyPropertiesTest () + { + var availableProperties = new List { }; + using (var expression = NSExpression.FromAnyKey ()) { + Assert.AreEqual (NSExpressionType.AnyKey, expression.ExpressionType); + TestProperties (expression, availableProperties); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/NSInputStreamTest.cs b/tests/monotouch-test/Foundation/NSInputStreamTest.cs new file mode 100644 index 000000000000..a392af9752e5 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSInputStreamTest.cs @@ -0,0 +1,92 @@ +using System; +using NUnit.Framework; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSInputStreamTest + { + [Test] + public void SubclassedCtor () + { + using (var s = new SubStream ()) { + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + class SubStream : NSInputStream { + } + + [Test] + public void Path () + { + using (var s = new NSInputStream ("Info.plist")) { + // initWithFileAtPath: does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void Data () + { + using (var d = NSData.FromFile ("Info.plist")) + using (var s = new NSInputStream (d)) { + // initWithData: does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void Url () + { + using (var u = NSUrl.FromFilename ("Info.plist")) + using (var s = new NSInputStream (u)) { + // initWithURL: does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public unsafe void Read () + { + using (var data = NSData.FromArray (new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })) { + using (var s = NSInputStream.FromData (data)) { + byte[] arr = new byte[10]; + s.Open (); + Assert.IsTrue (s.HasBytesAvailable ()); + Assert.AreEqual (2, s.Read (arr, 2), "#a 1"); + Assert.AreEqual (0, arr [0], "#a[0]"); + Assert.AreEqual (1, arr [1], "#a[1]"); + } + + using (var s = new NSInputStream (data)) { + byte[] arr = new byte[10]; + s.Open (); + Assert.IsTrue (s.HasBytesAvailable ()); + Assert.AreEqual (2, s.Read (arr, 1, 2), "#b 1"); + Assert.AreEqual (0, arr [0], "#b[0]"); + Assert.AreEqual (0, arr [1], "#b[1]"); + Assert.AreEqual (1, arr [2], "#b[2]"); + } + + using (var s = new NSInputStream (data)) { + byte[] arr = new byte[10]; + s.Open (); + Assert.IsTrue (s.HasBytesAvailable ()); + fixed (byte* ptr = &arr[2]) + Assert.AreEqual (2, s.Read ((IntPtr) ptr, 2), "#c 1"); + Assert.AreEqual (0, arr [0], "#c[0]"); + Assert.AreEqual (0, arr [1], "#c[1]"); + Assert.AreEqual (0, arr [2], "#c[2]"); + Assert.AreEqual (1, arr [3], "#c[3]"); + } + } + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSLayoutConstraintTest.cs b/tests/monotouch-test/Foundation/NSLayoutConstraintTest.cs new file mode 100644 index 000000000000..cde21e7623a0 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSLayoutConstraintTest.cs @@ -0,0 +1,93 @@ +// +// Unit tests for NSLayoutConstraint +// +// Authors: +// Oleg Demchenko +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 +using UIKit; +#else +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSLayoutConstraintTest { + +#if !__WATCHOS__ // FIXME: it looks like this test can be rewritten to not use UIViewController, so that it can run on WatchOS as well. + [Test] + public void FromVisualFormat () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Ignoring FromVisualFormat tests: Requires iOS7+"); + + using (var testViewController = new TestViewController ()) { + var constraints = NSLayoutConstraint.FromVisualFormat ("V:|[topLayoutGuide]-[firstLabel]-[secondLabel]", + NSLayoutFormatOptions.DirectionLeadingToTrailing, + "topLayoutGuide", testViewController.TopLayoutGuide, + "firstLabel", testViewController.FirstLabel, + "secondLabel", testViewController.SecondLabel + ); + + const int expectedNumberOfConstraints = 3; + + Assert.That (constraints != null, + "'NSLayoutConstraint.FromVisualFormat' method returned no constraints"); + + Assert.That (constraints.Length, Is.EqualTo (expectedNumberOfConstraints), + string.Format ("Expected number of constraints is {0}. Actual number is {1}", expectedNumberOfConstraints, constraints.Length)); + + Assert.That (constraints [0].FirstItem.Handle == testViewController.TopLayoutGuide.Handle, + "First item of constraints[0] is not testViewController.TopLayoutGuide"); + Assert.That (constraints [0].SecondItem == testViewController.View, + "Second item of constraints[0] is not testViewController.View"); + Assert.That (constraints [0].Relation == NSLayoutRelation.Equal, + string.Format ("Relation between views of constraints[0] must be `NSLayoutRelation.Equal`. Actual realtion is {0}", constraints [0].Relation)); + + Assert.That (constraints [1].FirstItem == testViewController.FirstLabel, + "First item of constraints[1] is not testViewController.FirstLabel"); + Assert.That (constraints [1].SecondItem.Handle == testViewController.TopLayoutGuide.Handle, + "Second item of constraints[1] is not testViewController.TopLayoutGuide"); + Assert.That (constraints [1].Relation == NSLayoutRelation.Equal, + string.Format ("Relation between views of constraints[1] must be `NSLayoutRelation.Equal`. Actual realtion is {0}", constraints [1].Relation)); + + Assert.That (constraints [2].FirstItem == testViewController.SecondLabel, + "First item of constraints[2] is not testViewController.SecondLabel"); + Assert.That (constraints [2].SecondItem == testViewController.FirstLabel, + "Second item of constraints[2] is not testViewController.FirstLabel"); + Assert.That (constraints [2].Relation == NSLayoutRelation.Equal, + string.Format ("Relation between views of constraints[2] must be `NSLayoutRelation.Equal`. Actual realtion is {0}", constraints [2].Relation)); + } + } + + public class TestViewController : UIViewController { + public UILabel FirstLabel { get; private set; } + + public UILabel SecondLabel { get; private set; } + + public TestViewController () + { + FirstLabel = new UILabel { + Font = UIFont.PreferredBody, + TranslatesAutoresizingMaskIntoConstraints = false + }; + + View.Add (FirstLabel); + + SecondLabel = new UILabel { + Font = UIFont.PreferredBody, + TranslatesAutoresizingMaskIntoConstraints = false + }; + + View.Add (SecondLabel); + } + } +#endif // !__WATCHOS__ + } +} + diff --git a/tests/monotouch-test/Foundation/NSLocaleTest.cs b/tests/monotouch-test/Foundation/NSLocaleTest.cs new file mode 100644 index 000000000000..7810aa8dc490 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSLocaleTest.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSLocaleTest { + + public void DisplayCountryCodeNames (NSString s) + { + Console.WriteLine (s); + NSLocale current = NSLocale.CurrentLocale; + IntPtr handle = current.Handle; + IntPtr selDisplayNameForKeyValue = new Selector ("displayNameForKey:value:").Handle; + foreach (var countryCode in NSLocale.ISOCountryCodes) { + using (var nsvalue = new NSString (countryCode)) { + string ret = NSString.FromHandle (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (handle, selDisplayNameForKeyValue, s.Handle, nsvalue.Handle)); + if (!String.IsNullOrWhiteSpace (ret)) + Console.WriteLine ("{0} -> {1}", countryCode, ret); + } + } + } + + [Test] + public void GetNSObject_IntPtrZero () + { +#if false + DisplayCountryCodeNames (NSLocale._AlternateQuotationBeginDelimiterKey); + DisplayCountryCodeNames (NSLocale._AlternateQuotationEndDelimiterKey); + DisplayCountryCodeNames (NSLocale._Calendar); + DisplayCountryCodeNames (NSLocale._CollationIdentifier); + DisplayCountryCodeNames (NSLocale._CollatorIdentifier); + DisplayCountryCodeNames (NSLocale._CurrencyCode); + DisplayCountryCodeNames (NSLocale._CountryCode); + DisplayCountryCodeNames (NSLocale._CurrencySymbol); + DisplayCountryCodeNames (NSLocale._DecimalSeparator); + DisplayCountryCodeNames (NSLocale._ExemplarCharacterSet); + DisplayCountryCodeNames (NSLocale._GroupingSeparator); + DisplayCountryCodeNames (NSLocale._Identifier); + DisplayCountryCodeNames (NSLocale._LanguageCode); + DisplayCountryCodeNames (NSLocale._MeasurementSystem); + DisplayCountryCodeNames (NSLocale._QuotationBeginDelimiterKey); + DisplayCountryCodeNames (NSLocale._QuotationEndDelimiterKey); + DisplayCountryCodeNames (NSLocale._ScriptCode); + DisplayCountryCodeNames (NSLocale._UsesMetricSystem); + DisplayCountryCodeNames (NSLocale._VariantCode); +#endif + } + } +} diff --git a/tests/monotouch-test/Foundation/NSMutableArray1Test.cs b/tests/monotouch-test/Foundation/NSMutableArray1Test.cs new file mode 100644 index 000000000000..321d82156ca5 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableArray1Test.cs @@ -0,0 +1,237 @@ + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSMutableArray1Test { + + [Test] + public void Ctor () + { + using (var arr = new NSMutableArray ()) { + Assert.AreEqual (0, arr.Count, "Count"); + } + } + + [Test] + public void Ctor_Capacity () + { + using (var arr = new NSMutableArray (1)) { + Assert.AreEqual (0, arr.Count, "Count"); + } + } + + [Test] + public void ContainsTest () + { + var v = (NSString) "value"; + var v2 = (NSString) "value 2"; + using (var arr = new NSMutableArray (v, v)) { + Assert.Throws (() => arr.Contains (null), "Contains ANE"); + Assert.IsTrue (arr.Contains (v), "Contains 1"); + Assert.IsFalse (arr.Contains (v2), "Contains 2"); + } + } + + [Test] + public void IndexOfTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var arr = new NSMutableArray (v1)) { + Assert.Throws (() => arr.IndexOf (null), "IndexOf ANE"); + Assert.AreEqual (0, arr.IndexOf (v1), "IndexOf 1"); + Assert.AreEqual (nint.MaxValue, arr.IndexOf (v2), "IndxOf 2"); // [NSArray indexOfObject:] returns NSNotFound = NSIntegerMax when object isn't found in the array + } + } + + [Test] + public void AddTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var arr = new NSMutableArray (v1)) { + Assert.AreEqual (1, arr.Count, "Count 1"); + Assert.Throws (() => arr.Add (null), "Add ANE"); + arr.Add (v2); + Assert.AreEqual (2, arr.Count, "Count 2"); + Assert.AreSame (v2, arr [1], "idx[1]"); + } + } + + [Test] + public void InsertTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + var v3 = (NSString) "3"; + + using (var arr = new NSMutableArray (v1, v3)) { + Assert.AreEqual (2, arr.Count, "Insert 1"); + Assert.Throws (() => arr.Insert (null, 0), "Insert ANE"); + Assert.Throws (() => arr.Insert (v2, -1), "Insert AOORE 1"); + Assert.Throws (() => arr.Insert (v2, 3), "Insert AOORE 2"); + arr.Insert (v2, 1); + Assert.AreEqual (3, arr.Count, "Insert 2"); + Assert.AreSame (v1, arr [0], "[0]"); + Assert.AreSame (v2, arr [1], "[1]"); + Assert.AreSame (v3, arr [2], "[2]"); + } + } + + [Test] + public void ReplaceObjectTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + var v3 = (NSString) "3"; + + using (var arr = new NSMutableArray (v1, v3)) { + Assert.AreEqual (2, arr.Count, "ReplaceObject 1"); + Assert.AreSame (v1, arr [0], "a [0]"); + Assert.AreSame (v3, arr [1], "a [1]"); + Assert.Throws (() => arr.ReplaceObject (0, null), "Insert ANE"); + Assert.Throws (() => arr.ReplaceObject (-1, v2), "Insert AOORE 1"); + Assert.Throws (() => arr.ReplaceObject (3, v2), "Insert AOORE 2"); + arr.ReplaceObject (1, v2); + Assert.AreEqual (2, arr.Count, "ReplaceObject 2"); + Assert.AreSame (v1, arr [0], "b [0]"); + Assert.AreSame (v2, arr [1], "b [1]"); + } + } + + [Test] + public void AddObjectsTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + var v3 = (NSString) "3"; + + using (var arr = new NSMutableArray ()) { + Assert.Throws (() => arr.AddObjects ((NSString[]) null), "AddObjects ANE 1"); + Assert.AreEqual (0, arr.Count, "Count 1"); + + Assert.Throws (() => arr.AddObjects (new NSString [] { null }), "AddObjects ANE 2"); + Assert.AreEqual (0, arr.Count, "Count 2"); + + Assert.Throws (() => arr.AddObjects (new NSString [] { v1, null, v3 }), "AddObjects ANE 3"); + Assert.AreEqual (0, arr.Count, "Count 3"); + + arr.AddObjects (v1, v2); + Assert.AreEqual (2, arr.Count, "AddObjects 1"); + Assert.AreSame (v1, arr [0], "a [0]"); + Assert.AreSame (v2, arr [1], "a [1]"); + } + } + + [Test] + public void InsertObjectsTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + var v3 = (NSString) "3"; + var v4 = (NSString) "4"; + + using (var arr = new NSMutableArray (v1, v2)) { + var iset = new NSMutableIndexSet (); + iset.Add (1); + iset.Add (2); + + Assert.Throws (() => arr.InsertObjects ((NSString[]) null, iset), "InsertObjects ANE 1"); + Assert.AreEqual (2, arr.Count, "Count 1"); + + Assert.Throws (() => arr.InsertObjects (new NSString [] { null, null }, iset), "InsertObjects ANE 2"); + Assert.AreEqual (2, arr.Count, "Count 2"); + + Assert.Throws (() => arr.InsertObjects (new NSString [] { v1, null }, iset), "InsertObjects ANE 3"); + Assert.AreEqual (2, arr.Count, "Count 3"); + + Assert.Throws (() => arr.InsertObjects (new NSString [] { v1 }, null), "InsertObjects ANE 4"); + Assert.AreEqual (2, arr.Count, "Count 4"); + + arr.InsertObjects (new NSString [] { v3, v4 }, iset); + + Assert.AreEqual (4, arr.Count, "InsertObjects 1"); + Assert.AreSame (v1, arr [0], "a [0]"); + Assert.AreSame (v3, arr [1], "a [1]"); + Assert.AreSame (v4, arr [2], "a [2]"); + Assert.AreSame (v2, arr [3], "a [3]"); + + iset.Clear (); + iset.Add (9); + Assert.Throws (() => arr.InsertObjects (new NSString [] { v1 }, iset), "InsertObjects ANE 5"); + } + } + + [Test] + public void IndexerTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + var v3 = (NSString) "3"; + + using (var arr = new NSMutableArray (v1, v2)) { + arr [1] = v3; + Assert.AreEqual (2, arr.Count, "a 1"); + Assert.AreSame (v1, arr [0], "a [0]"); + Assert.AreSame (v3, arr [1], "a [1]"); + + Assert.Throws (() => arr [0] = null, "ANE 1"); + Assert.Throws (() => arr [2] = v3, "IOORE 1"); + } + } + + [Test] + public void IEnumerableTest () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + using (var arr = new NSMutableArray ()) { + for (int i = 0; i < C; i++) + arr.Add ((NSString) i.ToString ()); + Assert.AreEqual (C, arr.Count, "Count 1"); + + var lst = new List (); + foreach (NSString a in (IEnumerable) arr) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + Assert.AreEqual (lst.Count.ToString (), (string) a, "#" + lst.Count.ToString ()); + lst.Add (a); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + } + + [Test] + public void IEnumerable1Test () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + using (var arr = new NSMutableArray ()) { + for (int i = 0; i < C; i++) + arr.Add ((NSString) i.ToString ()); + Assert.AreEqual (C, arr.Count, "Count 1"); + + var lst = new List (); + foreach (var a in (IEnumerable) arr) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + Assert.AreEqual (lst.Count.ToString (), (string) a, "#" + lst.Count.ToString ()); + lst.Add (a); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + } + } +} + +#endif // XAMCORE_2_0 diff --git a/tests/monotouch-test/Foundation/NSMutableDictionary2Test.cs b/tests/monotouch-test/Foundation/NSMutableDictionary2Test.cs new file mode 100644 index 000000000000..43b1d3c6b027 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableDictionary2Test.cs @@ -0,0 +1,627 @@ + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSMutableDictionary2Test { + + [Test] + public void Ctor () + { + var dict = new NSMutableDictionary (); + Assert.AreEqual (0, dict.Count, "Count"); + } + + [Test] + public void Ctor_NSDictionary () + { + var other = new NSDictionary ((NSString) "key", (NSString) "value"); + var j = new NSMutableDictionary (other); + + Assert.AreEqual (j.Count, 1, "count"); + Assert.AreEqual ((string)(NSString)(j [(NSString) "key"]), "value", "key lookup"); + } + + [Test] + public void Ctor_NSMutableDictionary () + { + var other = new NSMutableDictionary (); + other.Add ((NSString) "key", (NSString) "value"); + var j = new NSMutableDictionary (other); + + Assert.AreEqual (j.Count, 1, "count"); + Assert.AreEqual ((string)(NSString)(j [(NSString) "key"]), "value", "key lookup"); + } + + [Test] + public void KeyValue_Autorelease () + { + using (var k = new NSString ("keyz")) + using (var v = new NSString ("valuez")) { + var k1 = k.RetainCount; + if (k1 >= int.MaxValue) + Assert.Ignore ("RetainCount unusable for testing"); + var k2 = k1; + Assert.That (k.RetainCount, Is.EqualTo ((nint) 1), "Key.RetainCount-a"); + var v1 = v.RetainCount; + var v2 = v1; + Assert.That (v.RetainCount, Is.EqualTo ((nint) 1), "Value.RetainCount-a"); + using (var d = new NSMutableDictionary (k, v)) { + k2 = k.RetainCount; + Assert.That (k2, Is.GreaterThan (k1), "Key.RetainCount-b"); + v2 = v.RetainCount; + Assert.That (v2, Is.GreaterThan (v1), "Value.RetainCount-b"); + + Assert.NotNull (d.Keys, "Keys"); + // accessing `allKeys` should *NOT* change the retainCount + // that would happen without an [Autorelease] and can lead to memory exhaustion + // https://bugzilla.xamarin.com/show_bug.cgi?id=7723 + Assert.That (k.RetainCount, Is.EqualTo (k2), "Key.RetainCount-c"); + + Assert.NotNull (d.Values, "Values"); + Assert.That (v.RetainCount, Is.EqualTo (v2), "Value.RetainCount-c"); + } + Assert.That (k.RetainCount, Is.LessThan (k2), "Key.RetainCount-d"); + Assert.That (v.RetainCount, Is.LessThan (v2), "Value.RetainCount-d"); + } + } + + [Test] + public void XForY_Autorelease () + { + using (var k = new NSString ("keyz")) + using (var v = new NSString ("valuez")) { + var k1 = k.RetainCount; + if (k1 >= int.MaxValue) + Assert.Ignore ("RetainCount unusable for testing"); + var k2 = k1; + Assert.That (k.RetainCount, Is.EqualTo ((nint) 1), "Key.RetainCount-a"); + var v1 = v.RetainCount; + var v2 = v1; + Assert.That (v.RetainCount, Is.EqualTo ((nint) 1), "Value.RetainCount-a"); + using (var d = new NSMutableDictionary (k, v)) { + k2 = k.RetainCount; + Assert.That (k2, Is.GreaterThan (k1), "Key.RetainCount-b"); + v2 = v.RetainCount; + Assert.That (v2, Is.GreaterThan (v1), "Value.RetainCount-b"); + + var x = d.KeysForObject (v); + Assert.That (x [0], Is.SameAs (k), "KeysForObject"); + + var y = d.ObjectForKey (k); + Assert.NotNull (y, "ObjectForKey"); + + using (var a = new NSMutableArray ()) { + a.Add (k); + var z = d.ObjectsForKeys (a, k); + Assert.That (z [0], Is.SameAs (v), "ObjectsForKeys"); + } + + Assert.That (k.RetainCount, Is.EqualTo (k2), "Key.RetainCount-c"); + Assert.That (v.RetainCount, Is.EqualTo (v2), "Value.RetainCount-c"); + } + Assert.That (k.RetainCount, Is.LessThan (k2), "Key.RetainCount-d"); + Assert.That (v.RetainCount, Is.LessThan (v2), "Value.RetainCount-d"); + } + } + + [Test] + public void Copy () + { + using (var k = new NSString ("key")) + using (var v = new NSString ("value")) + using (var d = new NSMutableDictionary (k, v)) { + // NSObject.Copy works because NSDictionary conforms to NSCopying + using (var copy1 = (NSDictionary) d.Copy ()) { + Assert.AreNotSame (d, copy1, "1"); + Assert.That (copy1, Is.Not.TypeOf (), "NSDictionary-1"); + Assert.That (copy1.Count, Is.EqualTo ((nuint) 1), "Count-1"); + } + + using (var copy2 = (NSDictionary) d.Copy (null)) { + Assert.AreNotSame (d, copy2, "2"); + Assert.That (copy2, Is.Not.TypeOf (), "NSDictionary-2"); + Assert.That (copy2.Count, Is.EqualTo ((nuint) 1), "Count-2"); + } + + using (var copy3 = (NSDictionary) d.Copy (NSZone.Default)) { + Assert.AreNotSame (d, copy3, "3"); + Assert.That (copy3, Is.Not.TypeOf (), "NSDictionary-3"); + Assert.That (copy3.Count, Is.EqualTo ((nuint) 1), "Count-3"); + } + } + } + + [Test] + public void MutableCopy () + { + using (var k = new NSString ("key")) + using (var v = new NSString ("value")) + using (var d = new NSMutableDictionary (k, v)) { + // NSObject.Copy works because NSDictionary conforms to NSMutableCopying + using (var copy = (NSDictionary) d.MutableCopy ()) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count"); + } + + using (var copy = (NSDictionary) d.MutableCopy (null)) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary-2"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count-2"); + } + + using (var copy = (NSDictionary) d.MutableCopy (NSZone.Default)) { + Assert.That (copy, Is.TypeOf (), "NSMutableDictionary-3"); + Assert.That (copy.Count, Is.EqualTo ((nuint) 1), "Count-3"); + } + } + } + + [Test] + public void ObjectForKeyTest () + { + var value = NSDate.FromTimeIntervalSinceNow (23); + var key = new NSString ("right key"); + var dict = new NSMutableDictionary (key, value); + + Assert.Throws (() => dict.ObjectForKey ((NSString) null), "ANE"); + Assert.AreSame (value, dict.ObjectForKey (key), "right"); + Assert.IsNull (dict.ObjectForKey ((NSString) "wrong key"), "wrong"); + } + + [Test] + public void KeysTest () + { + var value = NSDate.FromTimeIntervalSinceNow (23); + var key = new NSString ("right key"); + var dict = new NSMutableDictionary (key, value); + + var keys = dict.Keys; + Assert.AreEqual (1, keys.Length, "Length"); + Assert.AreSame (key, keys [0], "1"); + } + + [Test] + public void KeysForObjectTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSMutableDictionary ( + new NSString [] { key1, key2, key3 }, + new NSDate[] { value1, value1, value2 } + ); + + var rv = dict.KeysForObject (value1); + Assert.AreEqual (2, rv.Length, "v1"); + + rv = dict.KeysForObject (value2); + Assert.AreEqual (1, rv.Length, "v2"); + Assert.AreSame (key3, rv [0], "v2 key"); + + rv = dict.KeysForObject (value3); + Assert.AreEqual (0, rv.Length, "v3"); + + Assert.Throws (() => dict.KeysForObject (null), "ANE"); + } + + [Test] + public void ValuesTest () + { + var value = NSDate.FromTimeIntervalSinceNow (23); + var key = new NSString ("right key"); + var dict = new NSMutableDictionary (key, value); + + var keys = dict.Values; + Assert.AreEqual (1, dict.Values.Length, "Length"); + Assert.AreSame (value, dict [key], "1"); + } + + [Test] + public void ObjectsForKeysTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + var key4 = new NSString ("key4"); + + var dict = new NSMutableDictionary ( + new NSString [] { key1, key2, key3 }, + new NSDate[] { value1, value1, value2 } + ); + + var rv = dict.ObjectsForKeys (new NSString [] { key1, key4 }, value3); + Assert.AreEqual (2, rv.Length, "a"); + Assert.AreSame (value1, rv [0], "a 0"); + Assert.AreSame (value3, rv [1], "a 1"); + + rv = dict.ObjectsForKeys (new NSString [] { }, value3); + Assert.AreEqual (0, rv.Length, "b length"); + + Assert.Throws (() => dict.ObjectsForKeys ((NSString []) null, value3), "c"); + Assert.Throws (() => dict.ObjectsForKeys (new NSString [] { }, null), "d"); + } + + [Test] + public void ContainsKeyTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + Assert.True (dict.ContainsKey (key1), "a"); + Assert.False (dict.ContainsKey (key3), "b"); + Assert.Throws (() => dict.ContainsKey ((NSString) null), "ANE"); + } + + [Test] + public void TryGetValueTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + NSDate value; + + Assert.True (dict.TryGetValue (key1, out value), "a"); + Assert.AreSame (value1, value, "a same"); + + Assert.False (dict.TryGetValue (key3, out value), "b"); + Assert.IsNull (value, "b null"); + } + + [Test] + public void IndexerTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dict = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + Assert.AreSame (value1, dict [key1], "a"); + Assert.IsNull (dict [key3], "b"); + Assert.Throws (() => GC.KeepAlive (dict [(NSString) null]), "c"); + } + + [Test] + public void IDictionary2Test () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (IDictionary) dictobj; + + // Add + Assert.Throws (() => dict.Add (new KeyValuePair (null, value1)), "Add ANE 1"); + Assert.Throws (() => dict.Add (new KeyValuePair (key1, null)), "Add ANE 2"); + dict.Add (new KeyValuePair (key3, value3)); + Assert.AreSame (value3, dictobj [key3], "Add 1"); + Assert.AreEqual (3, dict.Count, "Add Count"); + dictobj.Remove (key3); // restore state. + + // Clear + dict.Clear (); + Assert.AreEqual (0, dict.Count, "Clear Count"); + dictobj.Add (key1, value1); // restore state + dictobj.Add (key2, value1); // restore state + + // Contains + Assert.IsTrue (dict.Contains (new KeyValuePair (key1, value1)), "Contains 1"); // both key and value matches + Assert.IsFalse (dict.Contains (new KeyValuePair (key1, value2)), "Contains 2"); // found key, wrong value + Assert.IsFalse (dict.Contains (new KeyValuePair (key3, value2)), "Contains 3"); // wrong key + + // ContainsKey + Assert.IsTrue (dict.ContainsKey (key1), "ContainsKey 1"); + Assert.IsFalse (dict.ContainsKey (key3), "ContainsKey 2"); + + // CopyTo + var kvp_array = new KeyValuePair [1]; + Assert.Throws (() => dict.CopyTo (null, 0), "CopyTo ANE"); + Assert.Throws (() => dict.CopyTo (kvp_array, -1), "CopyTo AOORE"); + Assert.Throws (() => dict.CopyTo (kvp_array, kvp_array.Length), "CopyTo AE 2"); + Assert.Throws (() => dict.CopyTo (kvp_array, 0), "CopyTo AE 3"); + + kvp_array = new KeyValuePair [dictobj.Count]; + + Assert.Throws (() => dict.CopyTo (kvp_array, 1), "CopyTo AE 4"); + dict.CopyTo (kvp_array, 0); + Assert.That (key1, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K1"); + Assert.AreSame (value1, kvp_array [0].Value, "CopyTo V1"); + Assert.That (key2, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K2"); + Assert.AreSame (value1, kvp_array [1].Value, "CopyTo V2"); + + // Count + Assert.AreEqual (2, dict.Count, "Count"); + + // GetEnumerator + var enumerated = Enumerable.ToArray (dict); + Assert.AreEqual (2, enumerated.Length, "Enumerator Count"); + + // IsReadOnly + Assert.IsFalse (dict.IsReadOnly, "IsReadOnly"); + + // Keys + Assert.AreEqual (2, dict.Keys.Count, "Keys Count"); + + // Remove + Assert.Throws (() => dict.Remove (new KeyValuePair (null, value3)), "Remove ANE 1"); + Assert.Throws (() => dict.Remove (new KeyValuePair (key3, null)), "Remove ANE 2"); + Assert.IsFalse (dict.Remove (new KeyValuePair (key3, value3)), "Remove 1"); // inexistent key + Assert.AreEqual (2, dict.Count, "Remove 1 Count"); + + Assert.IsFalse (dict.Remove (new KeyValuePair (key1, value2)), "Remove 2"); // existing key, wrong value + Assert.AreEqual (2, dict.Count, "Remove 2 Count"); + + Assert.IsTrue (dict.Remove (new KeyValuePair (key1, value1)), "Remove 3"); // existing key,value pair + Assert.AreEqual (1, dict.Count, "Remove 3 Count"); + dictobj.Add (key1, value1); // restore state + + // TryGetValue + NSDate value; + Assert.Throws (() => dict.TryGetValue (null, out value), "TryGetValue ANE"); + Assert.IsTrue (dict.TryGetValue (key1, out value), "TryGetValue K1"); + Assert.AreSame (value1, value, "TryGetValue V1"); + Assert.IsFalse (dict.TryGetValue (key3, out value), "TryGetValue K2"); + + // Values + Assert.AreEqual (2, dict.Values.Count, "Values Count"); + + // Indexer + Assert.AreSame (value1, dict [key1], "this [1]"); + Assert.IsNull (dict [key3], "this [2]"); + Assert.Throws (() => GC.KeepAlive (dict [null]), "this [null]"); + + dict [key3] = value3; + Assert.AreEqual (3, dict.Count, "this [3] Count"); + Assert.AreSame (value3, dict [key3], "this [3] = 3"); + dictobj.Remove (key3); // restore state + + Assert.Throws (() => dict [key3] = null, "this [4] = null"); + } + + [Test] + public void ICollection2Test () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (ICollection>) dictobj; + + // Add + Assert.Throws (() => dict.Add (new KeyValuePair (null, value1)), "Add ANE 1"); + Assert.Throws (() => dict.Add (new KeyValuePair (key1, null)), "Add ANE 2"); + dict.Add (new KeyValuePair (key3, value3)); + Assert.AreSame (value3, dictobj [key3], "Add 1"); + Assert.AreEqual (3, dict.Count, "Add Count"); + dictobj.Remove (key3); // restore state. + + // Clear + dict.Clear (); + Assert.AreEqual (0, dict.Count, "Clear Count"); + dictobj.Add (key1, value1); // restore state + dictobj.Add (key2, value1); // restore state + + // Contains + Assert.IsTrue (dict.Contains (new KeyValuePair (key1, value1)), "Contains 1"); // both key and value matches + Assert.IsFalse (dict.Contains (new KeyValuePair (key1, value2)), "Contains 2"); // found key, wrong value + Assert.IsFalse (dict.Contains (new KeyValuePair (key3, value2)), "Contains 3"); // wrong key + + + // CopyTo + var kvp_array = new KeyValuePair [1]; + Assert.Throws (() => dict.CopyTo (null, 0), "CopyTo ANE"); + Assert.Throws (() => dict.CopyTo (kvp_array, -1), "CopyTo AOORE"); + Assert.Throws (() => dict.CopyTo (kvp_array, kvp_array.Length), "CopyTo AE 2"); + Assert.Throws (() => dict.CopyTo (kvp_array, 0), "CopyTo AE 3"); + + kvp_array = new KeyValuePair [dictobj.Count]; + + Assert.Throws (() => dict.CopyTo (kvp_array, 1), "CopyTo AE 4"); + dict.CopyTo (kvp_array, 0); + Assert.That (key1, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K1"); + Assert.AreSame (value1, kvp_array [0].Value, "CopyTo V1"); + Assert.That (key2, Is.SameAs (kvp_array [0].Key).Or.SameAs (kvp_array [1].Key), "CopyTo K2"); + Assert.AreSame (value1, kvp_array [1].Value, "CopyTo V2"); + + // Count + Assert.AreEqual (2, dict.Count, "Count"); + + // GetEnumerator + var enumerated = Enumerable.ToArray (dict); + Assert.AreEqual (2, enumerated.Length, "Enumerator Count"); + + // IsReadOnly + Assert.IsFalse (dict.IsReadOnly, "IsReadOnly"); + + // Remove + Assert.Throws (() => dict.Remove (new KeyValuePair (null, value3)), "Remove ANE 1"); + Assert.Throws (() => dict.Remove (new KeyValuePair (key3, null)), "Remove ANE 2"); + Assert.IsFalse (dict.Remove (new KeyValuePair (key3, value3)), "Remove 1"); // inexistent key + Assert.AreEqual (2, dict.Count, "Remove 1 Count"); + + Assert.IsFalse (dict.Remove (new KeyValuePair (key1, value2)), "Remove 2"); // existing key, wrong value + Assert.AreEqual (2, dict.Count, "Remove 2 Count"); + + Assert.IsTrue (dict.Remove (new KeyValuePair (key1, value1)), "Remove 3"); // existing key,value pair + Assert.AreEqual (1, dict.Count, "Remove 3 Count"); + dictobj.Add (key1, value1); // restore state + } + + [Test] + public void IEnumerable_KVP2Test () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (IEnumerable>) dictobj; + + // GetEnumerator + var enumerated = Enumerable.ToArray (dict); + Assert.AreEqual (2, enumerated.Length, "Enumerator Count"); + } + + [Test] + public void IEnumerableTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var value3 = NSDate.FromTimeIntervalSinceNow (3); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + var key3 = new NSString ("key3"); + + var dictobj = new NSMutableDictionary ( + new NSString [] { key1, key2 }, + new NSDate[] { value1, value1 } + ); + + var dict = (IEnumerable) dictobj; + + // GetEnumerator + var c = 0; + foreach (var obj in dict) + c++; + Assert.AreEqual (2, c, "Enumerator Count"); + } + + [Test] + public void AddTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + + var dict = new NSMutableDictionary (); + + Assert.Throws (() => dict.Add (null, value1), "ANE 1"); + Assert.Throws (() => dict.Add (key1, null), "ANE 2"); + + dict.Add (key1, value1); + Assert.AreEqual (1, dict.Count, "a Count"); + Assert.AreSame (value1, dict [key1], "a idx"); + + dict.Add (key1, value1); + Assert.AreEqual (1, dict.Count, "b Count"); + Assert.AreSame (value1, dict [key1], "b idx"); + + dict.Add (key2, value1); + Assert.AreEqual (2, dict.Count, "c Count"); + Assert.AreSame (value1, dict [key2], "c idx"); + } + + [Test] + public void RemoveTest () + { + var value1 = NSDate.FromTimeIntervalSinceNow (1); + var value2 = NSDate.FromTimeIntervalSinceNow (2); + var key1 = new NSString ("key1"); + var key2 = new NSString ("key2"); + + var dict = new NSMutableDictionary (); + + Assert.Throws (() => dict.Remove ((NSString) null), "ANE 1"); + + dict.Add (key1, value1); + + dict.Remove (key2); + Assert.AreEqual (1, dict.Count, "a Count"); + Assert.AreSame (value1, dict [key1], "a idx"); + + dict.Remove (key1); + Assert.AreEqual (0, dict.Count, "b Count"); + } + + [Test] + public void InvalidType () + { + var kv = (NSString) "a"; + var dt = NSDate.FromTimeIntervalSinceNow (1); + var obj = new NSDictionary (kv, kv); + NSDate value = NSDate.FromTimeIntervalSinceNow (3); + + // dict where TValue is wrong + var dict = new NSMutableDictionary (); + dict.Add (kv, kv); + Assert.Throws (() => GC.KeepAlive (dict [kv]), "idx 1"); + Assert.Throws (() => dict.ObjectForKey (kv), "ObjectForKey"); + Assert.Throws (() => dict.ObjectsForKeys (new NSString [] { kv }, value), "ObjectsForKeys"); + Assert.Throws (() => dict.TryGetValue (kv, out value), "TryGetValue"); + Assert.Throws (() => GC.KeepAlive (dict.Values), "Values"); + + // dict where TKey is wrong + var dictK = new NSMutableDictionary (); + dictK.Add (kv, kv); + Assert.Throws (() => GC.KeepAlive (dictK.Keys), "K Keys"); + Assert.Throws (() => dictK.KeysForObject (kv), "K KeysForObject"); + } + } +} + +#endif // XAMCORE_2_0 diff --git a/tests/monotouch-test/Foundation/NSMutableDictionaryTest.cs b/tests/monotouch-test/Foundation/NSMutableDictionaryTest.cs new file mode 100644 index 000000000000..0ed0c960f010 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableDictionaryTest.cs @@ -0,0 +1,97 @@ +using System; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace monotouchtest +{ + [TestFixture] + public class NSMutableDictionaryTest { + + [Test] + public void IndexerTest () + { + IntPtr strkeyptr = IntPtr.Zero; + IntPtr strobjptr = IntPtr.Zero; + IntPtr objptr; + IntPtr keyptr; + + NSString obj, key; + NSString v; + + try { + strkeyptr = Marshal.StringToHGlobalAuto ("key"); + strobjptr = Marshal.StringToHGlobalAuto ("obj"); + + // this[string] + keyptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strkeyptr); + objptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strobjptr); + using (var dict = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSMutableDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), objptr, keyptr))) { + v = (NSString) dict ["key"]; + Assert.AreEqual ("obj", (string) v, "a"); + + dict ["key"] = (NSString) "value"; + v = (NSString) dict ["key"]; + Assert.AreEqual ("value", (string) v, "a"); + } + + // this[NSObject] + keyptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strkeyptr); + objptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strobjptr); + using (var dict = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSMutableDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), objptr, keyptr))) { + v = (NSString) dict [(NSObject) (NSString) "key"]; + Assert.AreEqual ("obj", (string) v, "b"); + + dict [(NSObject) (NSString) "key"] = (NSString) "value"; + v = (NSString) dict ["key"]; + Assert.AreEqual ("value", (string) v, "a"); + } + + // this[NSString] + keyptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strkeyptr); + objptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strobjptr); + using (var dict = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (NSMutableDictionary)), Selector.GetHandle ("dictionaryWithObject:forKey:"), objptr, keyptr))) { + v = (NSString) dict [(NSString) "key"]; + Assert.AreEqual ("obj", (string) v, "c"); + + dict [(NSString) "key"] = (NSString) "value"; + v = (NSString) dict ["key"]; + Assert.AreEqual ("value", (string) v, "a"); + } + + } finally { + Marshal.FreeHGlobal (strkeyptr); + Marshal.FreeHGlobal (strobjptr); + } + } + + [Test] + public void Bug39993 () + { + using (NSMutableDictionary testDict = new NSMutableDictionary ()) { + testDict.Add ((NSString) "Key1", (NSString) "Key1"); + testDict.Add ((NSString) "Key2", (NSString) "KeyTest2"); + Assert.NotNull (testDict ["Key1"], "Key1"); + Assert.NotNull (testDict ["Key2"], "Key2"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/NSMutableOrderedSet1Test.cs b/tests/monotouch-test/Foundation/NSMutableOrderedSet1Test.cs new file mode 100644 index 000000000000..c5f5f5b36a86 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableOrderedSet1Test.cs @@ -0,0 +1,419 @@ +// +// Unit tests for NSMutableOrderedSet Generic support +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSMutableOrderedSet1Test { + + [Test] + public void Ctor () + { + var oset = new NSMutableOrderedSet (); + + Assert.AreEqual (0, oset.Count, "NSMutableOrderedSet Count"); + } + + [Test] + public void Ctor_Capacity () + { + var oset = new NSMutableOrderedSet (10); + + Assert.AreEqual (0, oset.Count, "NSMutableOrderedSet Count"); + } + + [Test] + public void Ctor_Start () + { + var oSet = new NSMutableOrderedSet (start: (NSString) "foo"); + + Assert.AreEqual (1, oSet.Count, "NSMutableOrderedSet Count"); + } + + [Test] + public void Ctor_Params () + { + var oSet = new NSMutableOrderedSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + + Assert.AreEqual (3, oSet.Count, "NSMutableOrderedSet Count"); + } + + [Test] + public void Ctor_NSSet () + { + var set = new NSSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + var oSet = new NSMutableOrderedSet (set); + + Assert.AreEqual (set.Count, oSet.Count, "NSMutableOrderedSet Count"); + } + + [Test] + public void Ctor_NSOrderedSet () + { + var oSetSource = new NSOrderedSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + var oSet = new NSMutableOrderedSet (oSetSource); + + Assert.AreEqual (oSetSource.Count, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void Ctor_NSMutableOrderedSet () + { + var oMutableSet = new NSMutableOrderedSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + var oSet = new NSMutableOrderedSet (oMutableSet); + + Assert.AreEqual (oMutableSet.Count, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void IndexerTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet (str1, str2, str3); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreSame (str2, oSet[1], "NSOrderedSet1Test IndexOf"); + Assert.Throws (()=> oSet[1] = null); + } + + [Test] + public void AsSetTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet (str1, str2, str3); + NSSet set = oSet.AsSet (); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreEqual (3, set.Count, "NSOrderedSet1Test Count"); + Assert.AreSame (str3, set.LookupMember (str3), "NSOrderedSet1Test IndexOf"); + } + + [Test] + public void InsertTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet (); + Assert.AreEqual (0, oSet.Count, "InsertTest Count"); + + oSet.Insert (str1, 0); + oSet.Insert (str2, 1); + oSet.Insert (str3, 2); + Assert.AreEqual (3, oSet.Count, "InsertTest Count"); + } + + [Test] + public void ReplaceTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + var oSet = new NSMutableOrderedSet (str1, str2, str3); + + oSet.Replace (0, str4); + + Assert.IsTrue (oSet.Contains (str4), "ReplaceTesr Contains 4"); + Assert.IsFalse (oSet.Contains (str1), "ReplaceTesr Contains 4"); + } + + [Test] + public void AddTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet { + str1, str2, str3 + }; + + Assert.AreEqual (3, oSet.Count, "AddTest Count"); + Assert.IsTrue (oSet.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (oSet.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (oSet.Contains (str3), "AddTest Contains 3"); + } + + [Test] + public void AddObjectsTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet (); + oSet.AddObjects (str1, str2, str3); + + Assert.AreEqual (3, oSet.Count, "AddObjectsTest Count"); + Assert.IsTrue (oSet.Contains (str1), "AddObjectsTest Contains 1"); + Assert.IsTrue (oSet.Contains (str2), "AddObjectsTest Contains 2"); + Assert.IsTrue (oSet.Contains (str3), "AddObjectsTest Contains 3"); + } + + [Test] + public void InsertObjectsTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + var oSet = new NSMutableOrderedSet (str4); + oSet.InsertObjects (new[] {str1, str2, str3}, NSIndexSet.FromNSRange (new NSRange (0, 3))); + + Assert.AreEqual (4, oSet.Count, "InsertObjectsTest Count"); + Assert.IsTrue (oSet.Contains (str1), "InsertObjectsTest Contains 1"); + Assert.IsTrue (oSet.Contains (str2), "InsertObjectsTest Contains 2"); + Assert.IsTrue (oSet.Contains (str3), "InsertObjectsTest Contains 3"); + Assert.IsTrue (oSet.Contains (str4), "InsertObjectsTest Contains 4"); + Assert.AreSame (str1, oSet[0], "InsertObjectsTest 1 == 1"); + Assert.AreSame (str4, oSet[3], "InsertObjectsTest 4 == 4"); + } + + [Test] + public void ReplaceObjectsTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var oSet = new NSMutableOrderedSet (str1, str2); + Assert.AreEqual (2, oSet.Count, "ReplaceObjectsTest Count"); + Assert.AreSame (str1, oSet[0], "ReplaceObjectsTest 1 == 1"); + Assert.AreSame (str2, oSet[1], "ReplaceObjectsTest 2 == 2"); + + oSet.ReplaceObjects (NSIndexSet.FromNSRange (new NSRange (0, 2)), str3, str4); + Assert.AreSame (str3, oSet[0], "ReplaceObjectsTest 3 == 3"); + Assert.AreSame (str4, oSet[1], "ReplaceObjectsTest 4 == 4"); + } + + [Test] + public void RemoveObjectTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet (str1, str2, str3); + Assert.AreEqual (3, oSet.Count, "RemoveObjectTest Count"); + + oSet.RemoveObject (str2); + Assert.AreEqual (2, oSet.Count, "RemoveObjectTest Count"); + Assert.IsFalse (oSet.Contains (str2), "RemoveObjectTest must not contain 2"); + Assert.IsTrue (oSet.Contains (str1), "RemoveObjectTest Contains 1"); + Assert.IsTrue (oSet.Contains (str3), "RemoveObjectTest Contains 3"); + } + + [Test] + public void RemoveObjectsTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSMutableOrderedSet (str1, str2, str3); + Assert.AreEqual (3, oSet.Count, "RemoveObjectsTest Count"); + + oSet.RemoveObjects (str1, str2); + Assert.AreEqual (1, oSet.Count, "RemoveObjectsTest Count"); + Assert.IsFalse (oSet.Contains (str1), "RemoveObjectsTest must not contain 1"); + Assert.IsFalse (oSet.Contains (str2), "RemoveObjectsTest must not contain 2"); + Assert.IsTrue (oSet.Contains (str3), "RemoveObjectsTest Contains 3"); + } + + [Test] + public void IEnumerable1Test () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + var st = new NSMutableOrderedSet (values); + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (var a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + + [Test] + public void IEnumerableTest () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + var st = new NSMutableOrderedSet (values); + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (NSString a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + + [Test] + public void OperatorAddTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSMutableOrderedSet (str1, str2); + var second = new NSMutableOrderedSet (str3, str4); + var third = first + second; + Assert.AreEqual (4, third.Count, "OperatorAdd Count"); + Assert.IsTrue (third.Contains (str1), "OperatorAdd 1"); + Assert.IsTrue (third.Contains (str2), "OperatorAdd 2"); + Assert.IsTrue (third.Contains (str3), "OperatorAdd 3"); + Assert.IsTrue (third.Contains (str4), "OperatorAdd 4"); + } + + [Test] + public void OperatorAddTest2 () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSMutableOrderedSet (str1, str2); + var second = new NSSet (str3, str4); + var third = first + second; + Assert.AreEqual (4, third.Count, "OperatorAdd Count"); + Assert.IsTrue (third.Contains (str1), "OperatorAdd 1"); + Assert.IsTrue (third.Contains (str2), "OperatorAdd 2"); + Assert.IsTrue (third.Contains (str3), "OperatorAdd 3"); + Assert.IsTrue (third.Contains (str4), "OperatorAdd 4"); + } + + [Test] + public void OperatorAddTest3 () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSMutableOrderedSet (str1, str2); + var second = new NSOrderedSet (str3, str4); + var third = first + second; + Assert.AreEqual (4, third.Count, "OperatorAdd Count"); + Assert.IsTrue (third.Contains (str1), "OperatorAdd 1"); + Assert.IsTrue (third.Contains (str2), "OperatorAdd 2"); + Assert.IsTrue (third.Contains (str3), "OperatorAdd 3"); + Assert.IsTrue (third.Contains (str4), "OperatorAdd 4"); + } + + [Test] + public void OperatorSubtractTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSMutableOrderedSet (str1, str2, str3, str4); + var second = new NSMutableOrderedSet (str3, str4); + var third = first - second; + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + + [Test] + public void OperatorSubtractTest2 () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSMutableOrderedSet (str1, str2, str3, str4); + var second = new NSSet (str3, str4); + var third = first - second; + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + + [Test] + public void OperatorSubtractTest3 () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSMutableOrderedSet (str1, str2, str3, str4); + var second = new NSOrderedSet (str3, str4); + var third = first - second; + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + + [Test] + public void OperatorPlusReferenceTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + var str5 = (NSString) "5"; + var str6 = (NSString) "6"; + + var one = new NSMutableOrderedSet (str1, str2, str3); + var two = new NSMutableOrderedSet (str4, str5, str6); + NSMutableOrderedSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + } +} + +#endif // XAMCORE_2_0 \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/NSMutableOrderedSetTest.cs b/tests/monotouch-test/Foundation/NSMutableOrderedSetTest.cs new file mode 100644 index 000000000000..21d5d40a88e5 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableOrderedSetTest.cs @@ -0,0 +1,106 @@ +// +// Unit tests for NSMutableOrderedSet +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSMutableOrderedSetTest { + + [Test] + public void OperatorAddTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSMutableOrderedSet (str1)) + using (var set2 = new NSMutableOrderedSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorSubtractTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + using (var first = new NSMutableOrderedSet (str1, str2, str3, str4)) + using (var second = new NSMutableOrderedSet (str3, str4)) + using (var third = first - second) { + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + } + + [Test] + public void OperatorPlusReferenceTest () + { + var one = new NSMutableOrderedSet ("1", "2", "3"); + var two = new NSMutableOrderedSet ("4", "5", "6"); + NSMutableOrderedSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + + [Test] + public void OperatorEqualTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var oSet = new NSMutableOrderedSet (str1, str2, str3)) + using (var oSet2 = new NSMutableOrderedSet (str1, str2, str3)) { + Assert.IsTrue (oSet == oSet2, "NSMutableOrderedSetTest == must be true"); + Assert.IsTrue (oSet.Equals (oSet2), "NSMutableOrderedSetTest Equals must be true"); + } + } + + [Test] + public void OperatorDifferentTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var oSet = new NSMutableOrderedSet (str1, str2, str3)) + using (var oSet2 = new NSMutableOrderedSet (str3, str2, str1)) { + Assert.IsTrue (oSet != oSet2, "NSMutableOrderedSetTest != must be true"); + Assert.IsFalse (oSet.Equals (oSet2), "NSMutableOrderedSetTest Equals must be false"); + } + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSMutableSet1Test.cs b/tests/monotouch-test/Foundation/NSMutableSet1Test.cs new file mode 100644 index 000000000000..6de9972ce936 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableSet1Test.cs @@ -0,0 +1,269 @@ + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSMutableSet1Test { + + [Test] + public void Ctor () + { + using (var arr = new NSMutableSet ()) { + Assert.AreEqual (0, arr.Count, "Count"); + } + } + + [Test] + public void Ctor_Params () + { + using (var arr = new NSMutableSet ((NSString) "foo")) { + Assert.AreEqual (1, arr.Count, "Count"); + } + using (var arr = new NSMutableSet ((NSString) "foo", (NSString) "bar")) { + Assert.AreEqual (2, arr.Count, "Count"); + } + } + + [Test] + public void Ctor_OtherSet () + { + var v1 = (NSString) "1"; + + using (var first = new NSSet (v1)) { + using (var second = new NSMutableSet (first)) { + Assert.AreEqual (1, first.Count, "1 count"); + Assert.AreEqual (1, second.Count, "2 count"); + } + } + } + + [Test] + public void Ctor_OtherMutableSet () + { + var v1 = (NSString) "1"; + + using (var first = new NSMutableSet (v1)) { + using (var second = new NSMutableSet (first)) { + Assert.AreEqual (1, first.Count, "1 count"); + Assert.AreEqual (1, second.Count, "2 count"); + } + } + } + + [Test] + public void LookupMemberTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSMutableSet (v1)) { + Assert.Throws (() => st.LookupMember ((NSString) null), "LookupMember ANE 1"); + Assert.AreSame (v1, st.LookupMember (v1), "LookupMember 1"); + Assert.IsNull (st.LookupMember (v2), "LookupMember 2"); + } + } + + [Test] + public void AnyObjectTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSMutableSet ()) { + Assert.IsNull (st.AnyObject, "AnyObject 1"); + } + + using (var st = new NSMutableSet (v1)) { + Assert.AreSame (v1, st.AnyObject, "AnyObject 2"); + } + } + + [Test] + public void ContainsTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSMutableSet (v1)) { + Assert.Throws (() => st.Contains ((NSString) null), "Contains ANE 1"); + Assert.IsTrue (st.Contains (v1), "Contains 1"); + Assert.IsFalse (st.Contains (v2), "Contains 2"); + } + } + + [Test] + public void ToArrayTest () + { + var v1 = (NSString) "1"; + + using (var st = new NSMutableSet (v1)) { + var arr = st.ToArray (); + Assert.AreEqual (1, arr.Length, "ToArray Length"); + Assert.AreSame (v1, arr [0], "ToArray () [0]"); + } + } + + [Test] + public void OperatorAddTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var first = new NSMutableSet (v1)) { + using (var second = new NSMutableSet (v2)) { + using (var third = first + second) { + Assert.AreEqual (2, third.Count, "+ Count"); + Assert.IsTrue (third.Contains (v1), "+ 1"); + Assert.IsTrue (third.Contains (v2), "+ 2"); + } + } + } + } + + [Test] + public void OperatorSubtractTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var first = new NSMutableSet (v1, v2)) { + using (var second = new NSMutableSet (v2)) { + using (var third = first - second) { + Assert.AreEqual (1, third.Count, "- Count"); + Assert.IsTrue (third.Contains (v1), "- 1"); + } + } + } + } + + [Test] + public void AddTest () + { + var v1 = (NSString) "1"; + + using (var st = new NSMutableSet ()) { + Assert.Throws (() => st.Add ((NSString) null), "Add ANE 1"); + + st.Add (v1); + Assert.IsTrue (st.Contains (v1), "Add 1"); + Assert.AreSame (v1, st.AnyObject, "Add 2"); + } + } + + [Test] + public void RemoveTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSMutableSet (v1)) { + Assert.Throws (() => st.Remove ((NSString) null), "Remove ANE 1"); + + st.Remove (v2); + Assert.AreEqual (1, st.Count, "Remove 1 Count"); + Assert.IsTrue (st.Contains (v1), "Remove 1 Contains"); + Assert.AreSame (v1, st.AnyObject, "Remove 1 AnyObject"); + + st.Remove (v1); + Assert.AreEqual (0, st.Count, "Remove 2 Count"); + } + } + + [Test] + public void AddObjectsTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSMutableSet ()) { + Assert.Throws (() => st.AddObjects ((NSString) null), "AddObjects ANE 1"); + Assert.Throws (() => st.AddObjects ((NSString[]) null), "AddObjects ANE 2"); + + st.AddObjects (v1); + Assert.AreEqual (1, st.Count, "AddObjects 1 Count"); + Assert.IsTrue (st.Contains (v1), "AddObjects 1 Contains"); + + st.RemoveAll (); + st.AddObjects (v1, v1); + Assert.AreEqual (1, st.Count, "AddObjects 2 Count"); + Assert.IsTrue (st.Contains (v1), "AddObjects 2 Contains"); + + st.RemoveAll (); + st.AddObjects (v2, v1); + Assert.AreEqual (2, st.Count, "AddObjects 3 Count"); + Assert.IsTrue (st.Contains (v1), "AddObjects 3 Contains a"); + Assert.IsTrue (st.Contains (v2), "AddObjects 3 Contains b"); + } + } + + [Test] + public void IEnumerable1Test () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + using (var st = new NSMutableSet (values)) { + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (var a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + } + + [Test] + public void IEnumerableTest () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + using (var st = new NSMutableSet (values)) { + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (NSString a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + } + + [Test] + public void OperatorPlusReferenceTest () + { + var one = new NSMutableSet ((NSString)"1", (NSString)"2", (NSString)"3"); + var two = new NSMutableSet ((NSString)"4", (NSString)"5", (NSString)"6"); + NSMutableSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + } +} + +#endif // XAMCORE_2_0 diff --git a/tests/monotouch-test/Foundation/NSMutableSetTest.cs b/tests/monotouch-test/Foundation/NSMutableSetTest.cs new file mode 100644 index 000000000000..88bb8bc57ac0 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSMutableSetTest.cs @@ -0,0 +1,77 @@ +// +// Unit tests for NSMutableSet +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSMutableSetTest { + + [Test] + public void OperatorAddTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSMutableSet (str1)) + using (var set2 = new NSMutableSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorSubtractTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + var first = new NSMutableSet (str1, str2, str3, str4); + var second = new NSMutableSet (str3, str4); + var third = first - second; + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + + [Test] + public void OperatorPlusReferenceTest () + { + var one = new NSMutableSet ("1", "2", "3"); + var two = new NSMutableSet ("4", "5", "6"); + NSMutableSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSOrderedSet1Test.cs b/tests/monotouch-test/Foundation/NSOrderedSet1Test.cs new file mode 100644 index 000000000000..0dd235c16d4e --- /dev/null +++ b/tests/monotouch-test/Foundation/NSOrderedSet1Test.cs @@ -0,0 +1,328 @@ +// +// Unit tests for NSOrderedSet Generic support +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSOrderedSet1Test { + + [Test] + public void Ctor () + { + var oset = new NSOrderedSet (); + + Assert.AreEqual (0, oset.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void Ctor_Start () + { + var oSet = new NSOrderedSet (start: (NSString) "foo"); + + Assert.AreEqual (1, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void Ctor_Params () + { + var oSet = new NSOrderedSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void Ctor_NSSet () + { + var set = new NSSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + var oSet = new NSOrderedSet (set); + + Assert.AreEqual (set.Count, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void Ctor_NSOrderedSet () + { + var oSetSource = new NSOrderedSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + var oSet = new NSOrderedSet (oSetSource); + + Assert.AreEqual (oSetSource.Count, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void Ctor_NSMutableOrderedSet () + { + var oMutableSet = new NSMutableOrderedSet ((NSString) "foo", (NSString) "bar", (NSString) "xyz"); + var oSet = new NSOrderedSet (oMutableSet); + + Assert.AreEqual (oMutableSet.Count, oSet.Count, "NSOrderedSet1Test Count"); + } + + [Test] + public void IndexerTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreSame (str2, oSet[1], "NSOrderedSet1Test IndexOf"); + } + + [Test] + public void ToArrayTest () + { + var str = (NSString)"Test"; + var oSet = new NSOrderedSet (str); + var arr = oSet.ToArray (); + + Assert.AreEqual (1, arr.Length, "NSOrderedSet1Test ToArray Length"); + Assert.AreSame (str, arr [0], "NSOrderedSet1Test ToArray () [0]"); + } + + [Test] + public void ContainsTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var oSet = new NSOrderedSet (str1); + + Assert.Throws (() => oSet.Contains ((NSString) null), "NSOrderedSet1Test Contains str1"); + Assert.IsTrue (oSet.Contains (str1), "NSOrderedSet1Test Contains str1"); + Assert.IsFalse (oSet.Contains (str2), "NSOrderedSet1Test Does not Contains str2"); + } + + [Test] + public void IndexOfTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreEqual (1, oSet.IndexOf (str2), "NSOrderedSet1Test IndexOf"); + } + + [Test] + public void FirstObjectTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreSame (str1, oSet.FirstObject (), "NSOrderedSet1Test IndexOf"); + } + + [Test] + public void LastObjectTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreSame (str3, oSet.LastObject (), "NSOrderedSet1Test IndexOf"); + } + + [Test] + public void AsSetTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + NSSet set = oSet.AsSet (); + + Assert.AreEqual (3, oSet.Count, "NSOrderedSet1Test Count"); + Assert.AreEqual (3, set.Count, "NSOrderedSet1Test Count"); + Assert.AreSame (str3, set.LookupMember (str3), "NSOrderedSet1Test IndexOf"); + } + + [Test] + public void IEnumerable1Test () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + var st = new NSOrderedSet (values); + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (var a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + + [Test] + public void IEnumerableTest () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + var st = new NSOrderedSet (values); + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (NSString a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + + [Test] + public void OperatorEqualTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + var oSet2 = new NSOrderedSet (str1, str2, str3); + + Assert.IsTrue (oSet == oSet2, "NSOrderedSet1Test == must be true"); + Assert.IsTrue (oSet.Equals (oSet2), "NSOrderedSet1Test Equals must be true"); + } + + [Test] + public void OperatorDifferentTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var oSet = new NSOrderedSet (str1, str2, str3); + var oSet2 = new NSOrderedSet (str3, str2, str1); + + Assert.IsTrue (oSet != oSet2, "NSOrderedSet1Test != must be true"); + Assert.IsFalse (oSet.Equals (oSet2), "NSOrderedSet1Test Equals must be false"); + } + + [Test] + public void OperatorAddTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSOrderedSet (str1, str2); + var second = new NSOrderedSet (str3, str4); + var third = first + second; + Assert.AreEqual (4, third.Count, "OperatorAdd Count"); + Assert.IsTrue (third.Contains (str1), "OperatorAdd 1"); + Assert.IsTrue (third.Contains (str2), "OperatorAdd 2"); + Assert.IsTrue (third.Contains (str3), "OperatorAdd 3"); + Assert.IsTrue (third.Contains (str4), "OperatorAdd 4"); + } + + [Test] + public void OperatorAddTest2 () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSOrderedSet (str1, str2); + var second = new NSSet (str3, str4); + var third = first + second; + Assert.AreEqual (4, third.Count, "OperatorAdd Count"); + Assert.IsTrue (third.Contains (str1), "OperatorAdd 1"); + Assert.IsTrue (third.Contains (str2), "OperatorAdd 2"); + Assert.IsTrue (third.Contains (str3), "OperatorAdd 3"); + Assert.IsTrue (third.Contains (str4), "OperatorAdd 4"); + } + + [Test] + public void OperatorSubtractTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSOrderedSet (str1, str2, str3, str4); + var second = new NSOrderedSet (str3, str4); + var third = first - second; + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + + [Test] + public void OperatorSubtractTest2 () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + + var first = new NSOrderedSet (str1, str2, str3, str4); + var second = new NSSet (str3, str4); + var third = first - second; + + Assert.AreEqual (2, third.Count, "OperatorSubtract2 Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract2 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract2 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract2 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract2 4"); + } + + [Test] + public void OperatorPlusReferenceTest () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + var str4 = (NSString) "4"; + var str5 = (NSString) "5"; + var str6 = (NSString) "6"; + + var one = new NSOrderedSet (str1, str2, str3); + var two = new NSOrderedSet (str4, str5, str6); + NSOrderedSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + } +} + +#endif // XAMCORE_2_0 \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/NSOrderedSetTest.cs b/tests/monotouch-test/Foundation/NSOrderedSetTest.cs new file mode 100644 index 000000000000..88bd1d4ff651 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSOrderedSetTest.cs @@ -0,0 +1,180 @@ +// +// Unit tests for NSOrderedSet +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSOrderedSetTest { + + [Test] + public void OperatorAddTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSOrderedSet (str1)) + using (var set2 = new NSOrderedSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorAddTest2 () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSOrderedSet (str1)) + using (var set2 = new NSSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorAddTest3 () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSOrderedSet (str1)) + using (var set2 = new NSMutableSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorSubtractTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + using (var first = new NSOrderedSet (str1, str2, str3, str4)) + using (var second = new NSOrderedSet (str3, str4)) + using (var third = first - second) { + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + } + + [Test] + public void OperatorSubtractTest2 () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + using (var first = new NSOrderedSet (str1, str2, str3, str4)) + using (var second = new NSSet (str3, str4)) + using (var third = first - second) { + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + } + + [Test] + public void OperatorSubtractTest3 () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + using (var first = new NSOrderedSet (str1, str2, str3, str4)) + using (var second = new NSMutableSet (str3, str4)) + using (var third = first - second) { + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + } + + [Test] + public void OperatorPlusReferenceTest () + { + var one = new NSOrderedSet ("1", "2", "3"); + var two = new NSOrderedSet ("4", "5", "6"); + NSOrderedSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + + [Test] + public void OperatorEqualTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var oSet = new NSOrderedSet (str1, str2, str3)) + using (var oSet2 = new NSOrderedSet (str1, str2, str3)) { + Assert.IsTrue (oSet == oSet2, "NSOrderedSetTest == must be true"); + Assert.IsTrue (oSet.Equals (oSet2), "NSOrderedSetTest Equals must be true"); + } + } + + [Test] + public void OperatorDifferentTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var oSet = new NSOrderedSet (str1, str2, str3)) + using (var oSet2 = new NSOrderedSet (str3, str2, str1)) { + Assert.IsTrue (oSet != oSet2, "NSOrderedSetTest != must be true"); + Assert.IsFalse (oSet.Equals (oSet2), "NSOrderedSetTest Equals must be false"); + } + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSSet1Test.cs b/tests/monotouch-test/Foundation/NSSet1Test.cs new file mode 100644 index 000000000000..afdeff84dc4e --- /dev/null +++ b/tests/monotouch-test/Foundation/NSSet1Test.cs @@ -0,0 +1,209 @@ + +#if XAMCORE_2_0 + +using System; +using System.Collections; +using System.Collections.Generic; + +using NUnit.Framework; + +using Foundation; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSSet1Test { + + [Test] + public void Ctor () + { + using (var arr = new NSSet ()) { + Assert.AreEqual (0, arr.Count, "Count"); + } + } + + [Test] + public void Ctor_Params () + { + using (var arr = new NSSet ((NSString) "foo")) { + Assert.AreEqual (1, arr.Count, "Count"); + } + using (var arr = new NSSet ((NSString) "foo", (NSString) "bar")) { + Assert.AreEqual (2, arr.Count, "Count"); + } + } + + [Test] + public void Ctor_OtherSet () + { + var v1 = (NSString) "1"; + + using (var first = new NSSet (v1)) { + using (var second = new NSSet (first)) { + Assert.AreEqual (1, first.Count, "1 count"); + Assert.AreEqual (1, second.Count, "2 count"); + } + } + } + + [Test] + public void Ctor_OtherMutableSet () + { + var v1 = (NSString) "1"; + + using (var first = new NSMutableSet (v1)) { + using (var second = new NSSet (first)) { + Assert.AreEqual (1, first.Count, "1 count"); + Assert.AreEqual (1, second.Count, "2 count"); + } + } + } + + [Test] + public void LookupMemberTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSSet (v1)) { + Assert.Throws (() => st.LookupMember ((NSString) null), "LookupMember ANE 1"); + Assert.AreSame (v1, st.LookupMember (v1), "LookupMember 1"); + Assert.IsNull (st.LookupMember (v2), "LookupMember 2"); + } + } + + [Test] + public void AnyObjectTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSSet ()) { + Assert.IsNull (st.AnyObject, "AnyObject 1"); + } + + using (var st = new NSSet (v1)) { + Assert.AreSame (v1, st.AnyObject, "AnyObject 2"); + } + } + + [Test] + public void ContainsTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var st = new NSSet (v1)) { + Assert.Throws (() => st.Contains ((NSString) null), "Contains ANE 1"); + Assert.IsTrue (st.Contains (v1), "Contains 1"); + Assert.IsFalse (st.Contains (v2), "Contains 2"); + } + } + + [Test] + public void ToArrayTest () + { + var v1 = (NSString) "1"; + + using (var st = new NSSet (v1)) { + var arr = st.ToArray (); + Assert.AreEqual (1, arr.Length, "ToArray Length"); + Assert.AreSame (v1, arr [0], "ToArray () [0]"); + } + } + + [Test] + public void OperatorAddTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var first = new NSSet (v1)) { + using (var second = new NSSet (v2)) { + using (var third = first + second) { + Assert.AreEqual (2, third.Count, "+ Count"); + Assert.IsTrue (third.Contains (v1), "+ 1"); + Assert.IsTrue (third.Contains (v2), "+ 2"); + } + } + } + } + + [Test] + public void OperatorSubtractTest () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var first = new NSSet (v1, v2)) { + using (var second = new NSSet (v2)) { + using (var third = first - second) { + Assert.AreEqual (1, third.Count, "- Count"); + Assert.IsTrue (third.Contains (v1), "- 1"); + } + } + } + } + + [Test] + public void IEnumerable1Test () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + using (var st = new NSSet (values)) { + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (var a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + } + + [Test] + public void IEnumerableTest () + { + const int C = 16 * 2 + 3; // NSFastEnumerator has a array of size 16, use more than that, and not an exact multiple. + var values = new NSString [C]; + for (int i = 0; i < C; i++) + values [i] = (NSString) i.ToString (); + + using (var st = new NSSet (values)) { + Assert.AreEqual (C, st.Count, "Count 1"); + + var lst = new List (); + foreach (NSString a in (IEnumerable) st) { + Assert.IsNotNull (a, "null item iterator"); + Assert.IsFalse (lst.Contains (a), "duplicated item iterator"); + lst.Add (a); + Assert.IsTrue (Array.IndexOf (values, a) >= 0, "different object"); + } + Assert.AreEqual (C, lst.Count, "iterator count"); + } + } + + [Test] + public void OperatorPlusReferenceTest () + { + var one = new NSSet ((NSString)"1", (NSString)"2", (NSString)"3"); + var two = new NSSet ((NSString)"4", (NSString)"5", (NSString)"6"); + NSSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + } +} + +#endif // XAMCORE_2_0 diff --git a/tests/monotouch-test/Foundation/NSSetTest.cs b/tests/monotouch-test/Foundation/NSSetTest.cs new file mode 100644 index 000000000000..5f7aa47c67fd --- /dev/null +++ b/tests/monotouch-test/Foundation/NSSetTest.cs @@ -0,0 +1,162 @@ + +using System; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class NSSetTest + { + [Test] + public void SetCtors() + { + // The NSSet (params object [] args) + var s = new NSSet (1); + Assert.AreEqual (s.Count, 1); + s = new NSSet (1, 2, 3); + Assert.AreEqual (s.Count, 3); + + // The NSSet (params [] NSObject args) + var objs = new NSObject [5]; + for (int i = 0; i < objs.Length; i++) + objs [i] = new NSNumber (i); + + s = new NSSet (objs [0], objs [1], objs [2], objs [3], objs [4]); + Assert.AreEqual (s.Count, 5); + + // Repeat the values + s = new NSSet (objs [0], objs [1], objs [2], objs [0], objs [1]); + Assert.AreEqual (s.Count, 3); + } + + [Test] + public void OperatorPlus () + { + var one = new NSSet (1, 2, 3); + var two = new NSSet (4, 5, 6); + var sum = one + two; + Assert.AreEqual (sum.Count, 6); + + var objs = new NSObject [5]; + for (int i = 0; i < objs.Length; i++) + objs [i] = new NSNumber (i*100); + + sum = new NSSet (objs) + one + two; + Assert.AreEqual (sum.Count, 11); + sum = new NSSet (objs) + new NSSet (objs); + Assert.AreEqual (sum.Count, 5); + + Assert.AreEqual ((one + one).Count, 3); + var sub = one - one; + Assert.AreEqual (sub.Count, 0); + + var three = new NSSet (1, 2, 3, 4, 5, 6); + var subt = three - two; + Assert.AreEqual (subt.Count, 3); + Assert.True (three.Contains (1)); + Assert.True (three.Contains (2)); + Assert.True (three.Contains (3)); + subt = three - one; + Assert.AreEqual (subt.Count, 3); + Assert.True (three.Contains (4)); + Assert.True (three.Contains (5)); + Assert.True (three.Contains (6)); + + } + + [Test] + public void OperatorPlusReferenceTest () + { + var one = new NSSet (1, 2, 3); + var two = new NSSet (4, 5, 6); + NSSet nil = null; + using (var sum = one + nil) + using (var sum2 = two + one) + using (var sum3 = one + two) { + + } + Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); + Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); + } + + [Test] + public void OperatorAddTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSSet (str1)) + using (var set2 = new NSOrderedSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorAddTest2 () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + + using (var set1 = new NSSet (str1)) + using (var set2 = new NSMutableOrderedSet (str2, str3)) + using (var result = set1 + set2) { + Assert.AreEqual (3, result.Count, "AddTest Count"); + Assert.IsTrue (result.Contains (str1), "AddTest Contains 1"); + Assert.IsTrue (result.Contains (str2), "AddTest Contains 2"); + Assert.IsTrue (result.Contains (str3), "AddTest Contains 3"); + } + } + + [Test] + public void OperatorSubtractTest () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + using (var first = new NSSet (str1, str2, str3, str4)) + using (var second = new NSOrderedSet (str3, str4)) + using (var third = first - second) { + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + } + + [Test] + public void OperatorSubtractTest2 () + { + var str1 = "1"; + var str2 = "2"; + var str3 = "3"; + var str4 = "4"; + + using (var first = new NSSet (str1, str2, str3, str4)) + using (var second = new NSMutableOrderedSet (str3, str4)) + using (var third = first - second) { + + Assert.AreEqual (2, third.Count, "OperatorSubtract Count"); + Assert.IsTrue (third.Contains (str1), "OperatorSubtract 1"); + Assert.IsTrue (third.Contains (str2), "OperatorSubtract 2"); + Assert.IsFalse (third.Contains (str3), "OperatorSubtract 3"); + Assert.IsFalse (third.Contains (str4), "OperatorSubtract 4"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/NSStreamTest.cs b/tests/monotouch-test/Foundation/NSStreamTest.cs new file mode 100644 index 000000000000..6908cbd416b6 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSStreamTest.cs @@ -0,0 +1,133 @@ +using System; +using NUnit.Framework; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +#if XAMCORE_2_0 +using CoreFoundation; +using Foundation; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class AA_NSStreamTest + { + [Test] + public void BoundPairTest () + { + NSInputStream read; + NSOutputStream write; + + NSStream.CreateBoundPair (out read, out write, 1024); + read.Open (); + write.Open (); + + var send = Encoding.ASCII.GetBytes ("hello, world"); + var n = send.Length; + + Assert.AreEqual (n, write.Write (send)); + var result = new byte [n+10]; + + Assert.AreEqual (n, read.Read (result, (uint)n)); + for (int i = 0; i < n; i++) + Assert.AreEqual (send [i], result [i], "Item " + i); + + } + + TcpListener FindPort (out int port) + { + for (port = 3000; port < 6000; port++) { + var listener = new TcpListener (IPAddress.Any, port); + try { + listener.Start (); + return listener; + } catch { + } + } + return null; + } + +#if !__WATCHOS__ + [Test] + public void ConnectToHost () + { + NSInputStream read; + NSOutputStream write; + + int port; + var listener = FindPort (out port); + if (listener == null) { + Assert.Inconclusive ("Not possible to bind a port"); + return; + } + + var listenThread = new Thread (new ParameterizedThreadStart (DebugListener)); + listenThread.Start (listener); + NSStream.CreatePairWithSocketToHost (new IPEndPoint (IPAddress.Loopback, port), out read, out write); + read.Open (); + write.Open (); + var send = new byte[] { 1, 2, 3, 4, 5 }; + Assert.AreEqual (5, write.Write (send)); + var result = new byte [5]; + Assert.AreEqual (5, read.Read (result,5)); + for (int i = 0; i < 5; i++) + Assert.AreEqual (send [i] * 10, result [i]); + listenThread.Join (); + listener.Stop (); + read.Close (); + write.Close (); + } +#endif // !__WATCHOS__ + + [Test] + public void ConnectToPeer () + { + NSInputStream read; + NSOutputStream write; + + int port; + var listener = FindPort (out port); + if (listener == null) { + Assert.Inconclusive ("Not possible to bind a port"); + return; + } + + var listenThread = new Thread (new ParameterizedThreadStart (DebugListener)); + listenThread.Start (listener); + NSStream.CreatePairWithPeerSocketSignature (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, new IPEndPoint (IPAddress.Loopback, port), out read, out write); + read.Open (); + write.Open (); + var send = new byte[] { 1, 2, 3, 4, 5 }; + Assert.AreEqual (5, write.Write (send)); + var result = new byte [5]; + Assert.AreEqual (5, read.Read (result,5)); + for (int i = 0; i < 5; i++) + Assert.AreEqual (send [i] * 10, result [i]); + listenThread.Join (); + listener.Stop (); + read.Close (); + write.Close (); + } + + void DebugListener (object data) + { + var listener = data as TcpListener; + var client = listener.AcceptTcpClient(); + var stream = client.GetStream(); + + byte [] buffer = new byte [512]; + if (stream.Read (buffer, 0, 5) == 5){ + stream.Write (new byte[] {10,20,30,40,50}, 0, 5); + stream.Flush (); + } + client.Close (); + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSStringTest.cs b/tests/monotouch-test/Foundation/NSStringTest.cs new file mode 100644 index 000000000000..1b7a211d52a2 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSStringTest.cs @@ -0,0 +1,40 @@ +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using Security; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.Security; +#endif +using NUnit.Framework; + +namespace monotouchtest +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class NSStringTest + { + [Test] + public void LocalizedFormatTest () + { + // Strings and NSstring + Assert.AreEqual ("hello", NSString.LocalizedFormat ("hello").ToString ()); + Assert.AreEqual ("hello", NSString.LocalizedFormat (new NSString ("hello")).ToString ()); + + // Test the overloads with numbers + Assert.AreEqual ("hello", NSString.LocalizedFormat ("hello").ToString ()); + Assert.AreEqual ("hello0", NSString.LocalizedFormat ("hello%@", 0).ToString ()); + Assert.AreEqual ("hello01", NSString.LocalizedFormat ("hello%@%@", 0, 1).ToString ()); + Assert.AreEqual ("hello012", NSString.LocalizedFormat ("hello%@%@%@", 0, 1, 2).ToString ()); + Assert.AreEqual ("hello0123", NSString.LocalizedFormat ("hello%@%@%@%@", 0, 1, 2, 3).ToString ()); + Assert.AreEqual ("hello01234", NSString.LocalizedFormat ("hello%@%@%@%@%@", 0, 1, 2, 3, 4).ToString ()); + Assert.AreEqual ("hello012345", NSString.LocalizedFormat ("hello%@%@%@%@%@%@", 0, 1, 2, 3, 4, 5).ToString ()); + Assert.AreEqual ("hello0123456", NSString.LocalizedFormat ("hello%@%@%@%@%@%@%@", 0, 1, 2, 3, 4, 5, 6).ToString ()); + Assert.AreEqual ("hello01234567", NSString.LocalizedFormat ("hello%@%@%@%@%@%@%@%@", 0, 1, 2, 3, 4, 5, 6, 7).ToString ()); + Assert.AreEqual ("hello012345678", NSString.LocalizedFormat ("hello%@%@%@%@%@%@%@%@%@", 0, 1, 2, 3, 4, 5, 6, 7, 8).ToString ()); + } + } +} + diff --git a/tests/monotouch-test/Foundation/NSTimeZoneTest.cs b/tests/monotouch-test/Foundation/NSTimeZoneTest.cs new file mode 100644 index 000000000000..448f3e8d0802 --- /dev/null +++ b/tests/monotouch-test/Foundation/NSTimeZoneTest.cs @@ -0,0 +1,63 @@ +// +// Unit tests for NSTimeZone +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2011 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSTimeZoneTest { + + [Test] + public void KnownTimeZoneNames () + { + Assert.That (NSTimeZone.KnownTimeZoneNames.Count, Is.GreaterThan (400), "KnownTimeZoneNames"); // 416 on iOS5 + } + + [Test] + public void AbbreviationsTest () + { + Assert.That (NSTimeZone.Abbreviations.ContainsKey (new NSString ("CST"))); + } + + [Test] + public void AbbreviationTest () + { + var timezone = NSTimeZone.LocalTimeZone; + Assert.NotNull (timezone.Abbreviation ()); + } + + [Test] + public void All_28300 () + { + foreach (var name in NSTimeZone.KnownTimeZoneNames) { + // simulator uses OSX to get timezones which might have some holes, + // e.g. @"Pacific/Bougainville" does not seems to be available in Mavericks + if (Runtime.Arch == Arch.SIMULATOR) { + if (!File.Exists (Path.Combine ("/usr/share/zoneinfo/", name))) + continue; + } + TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (name); + Assert.NotNull (tzi.GetUtcOffset (DateTime.Now), name); + } + + Assert.NotNull (TimeZoneInfo.Local.GetUtcOffset (DateTime.Now), "Local"); + } + } +} diff --git a/tests/monotouch-test/Foundation/NetServiceTest.cs b/tests/monotouch-test/Foundation/NetServiceTest.cs new file mode 100644 index 000000000000..f8f2eb93ed48 --- /dev/null +++ b/tests/monotouch-test/Foundation/NetServiceTest.cs @@ -0,0 +1,45 @@ +// +// Unit tests for NSNetService +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NetServiceTest { + + [Test] + public void DefaultCtor () + { + using (var ns = new NSNetService ("d", "_test._tcp", UIDevice.CurrentDevice.Name, 1234)) { + Assert.That (ns.Domain, Is.EqualTo ("d"), "Domain"); + Assert.That (ns.Type, Is.EqualTo ("_test._tcp"), "Type"); + Assert.That (ns.Port, Is.EqualTo (1234), "Port"); + NSInputStream input; + NSOutputStream output; + Assert.True (ns.GetStreams (out input, out output), "GetStreams"); + Assert.NotNull (input, "input"); + Assert.NotNull (output, "output"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/Foundation/NotificationCenter.cs b/tests/monotouch-test/Foundation/NotificationCenter.cs new file mode 100644 index 000000000000..f679dd73c320 --- /dev/null +++ b/tests/monotouch-test/Foundation/NotificationCenter.cs @@ -0,0 +1,102 @@ +// +// Unit tests for NotificationCenter +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Diagnostics; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NotificationCenterTest { + + [Test] + [Ignore ("This test is 'randomly' failing the first time it's executed with debugging disabled (if executed with the rest of the tests) - CWLS show that the TestNotification instance is freed at the end of the test run.")] + public void Free () + { + bool freed = false; + bool a = false, b = false; + Action destroyedCallback = delegate (TestNotification n) { freed = true; a = n.A; b = n.B; }; + FreeLeaf (destroyedCallback); + Stopwatch watch = new Stopwatch (); + watch.Start (); + while (!freed && watch.ElapsedMilliseconds < 1000) { + GC.Collect (GC.MaxGeneration); + Thread.Sleep (10); + } + Assert.True (a, "a"); + Assert.True (b, "b"); + Assert.True (freed, "freed"); + } + + void FreeLeaf (Action destroyedCallback) + { + var testNotification = new TestNotification (destroyedCallback); + + NSNotificationCenter.DefaultCenter.PostNotificationName ("notifyA", null); + NSNotificationCenter.DefaultCenter.PostNotificationName ("notifyB", null); + + testNotification.StopObserving (); + } + + public class TestNotification : NSObject + { + public bool A; + public bool B; + Action destroyed_callback; + + public TestNotification (Action destroyedCallback) + { + destroyed_callback = destroyedCallback; + + NSNotificationCenter.DefaultCenter.AddObserver(this, + new Selector("a:"), + new NSString("notifyA"), + null); + + NSNotificationCenter.DefaultCenter.AddObserver(this, + new Selector("b:"), + new NSString("notifyB"), + null); + } + + [Export ("a:")] + public void a (NSNotification notification) + { + A = true; + } + + [Export ("b:")] + public void b (NSNotification notification) + { + B = true; + } + + public void StopObserving () + { + NSNotificationCenter.DefaultCenter.RemoveObserver (this); + } + + ~TestNotification() + { + destroyed_callback (this); + } + + } + } +} diff --git a/tests/monotouch-test/Foundation/NotificationQueueTest.cs b/tests/monotouch-test/Foundation/NotificationQueueTest.cs new file mode 100644 index 000000000000..1e07ded332bc --- /dev/null +++ b/tests/monotouch-test/Foundation/NotificationQueueTest.cs @@ -0,0 +1,29 @@ +// +// Unit tests for NotificationQueue +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NotificationQueueTest { + + [Test] + public void DefaultQueue () + { + Assert.That (NSNotificationQueue.DefaultQueue, Is.TypeOf (), "DefaultQueue"); + } + } +} diff --git a/tests/monotouch-test/Foundation/NumberTest.cs b/tests/monotouch-test/Foundation/NumberTest.cs new file mode 100644 index 000000000000..22d16164c345 --- /dev/null +++ b/tests/monotouch-test/Foundation/NumberTest.cs @@ -0,0 +1,99 @@ +// +// Unit tests for NSNumber +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NumberTest { + + [Test] + public void CompareTo () + { + NSNumber n0 = (NSNumber) 0; + NSNumber n1 = (NSNumber) 1; + NSNumber n1f = (NSNumber) 1.0f; + NSNumber n2 = (NSNumber) 2.0f; + + Assert.That (n1.Compare (n1f), Is.EqualTo ((nint) 0), "Compare-a"); + Assert.That (n0.Compare (n1f), Is.LessThan ((nint) 0), "Compare-b"); + Assert.That (n2.Compare (n0), Is.GreaterThan ((nint) 0), "Compare-c"); + + // IComparable + Assert.That (n1.CompareTo ((object) n1f), Is.EqualTo (0), "CompareTo-a"); + Assert.That (n0.CompareTo ((object) n1f), Is.LessThan (0), "CompareTo-b"); + Assert.That (n2.CompareTo ((object) n0), Is.GreaterThan (0), "CompareTo-c"); + + // IComparable + Assert.That (n1.CompareTo (n1f), Is.EqualTo (0), "CompareTo-a"); + Assert.That (n0.CompareTo (n1f), Is.LessThan (0), "CompareTo-b"); + Assert.That (n2.CompareTo (n0), Is.GreaterThan (0), "CompareTo-c"); + } + + [Test] + public void CtorNSCoder () + { + // NSNumber conforms to NSCoding - so it's .ctor(NSCoder) is usable + using (var n = new NSNumber (-1)) + using (var d = new NSMutableData ()) { + using (var a = new NSKeyedArchiver (d)) { + n.EncodeTo (a); + a.FinishEncoding (); + } + using (var u = new NSKeyedUnarchiver (d)) + using (var n2 = new NSNumber (u)) { + // so we can re-create an instance from it + Assert.That (n.Int32Value, Is.EqualTo (-1), "Value"); + } + } + } + + [Test] + public void Singleton () + { + var a = new NSNumber (true); + var b = new NSNumber (true); + a.Dispose (); + Assert.That (b.Handle, Is.Not.EqualTo (IntPtr.Zero)); + } + + [Test] + public void Equals () + { + using (var a = new NSNumber (1)) + using (var b = new NSNumber (1d)) { +#if !XAMCORE_2_0 + Assert.True (a.IsEqualToNumber (b), "IsEqualToNumber"); +#endif + // Two objects that are equal return hash codes that are equal. + Assert.True (a.Equals (b), "Equals(NSNumber)"); + Assert.True (b.Equals ((object) a), "Equals(Object)"); + Assert.That (a.GetHashCode (), Is.EqualTo (b.GetHashCode ()), "GetHashCode"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/ObjectTest.cs b/tests/monotouch-test/Foundation/ObjectTest.cs new file mode 100644 index 000000000000..54268b50ccea --- /dev/null +++ b/tests/monotouch-test/Foundation/ObjectTest.cs @@ -0,0 +1,329 @@ +// +// Unit tests for NSObject +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012, 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +using System.Reflection; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +using MonoTouchException=Foundation.MonoTouchException; +using Security; +using UIKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouchException=MonoTouch.Foundation.MonoTouchException; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSObjectTest { + + bool GetIsDirectBinding (NSObject obj) + { +#if XAMCORE_2_0 + int flags = (byte) typeof (NSObject).GetField ("flags", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); + return (flags & 4) == 4; +#else + return (bool) typeof (NSObject).GetField ("IsDirectBinding", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); +#endif + } + + class MyObject : NSObject { + + public bool GetIsDirectBinding () + { + return this.IsDirectBinding; + } + } + + [Test] + public void IsDirectBinding () + { + using (var o1 = new NSObject ()) { + Assert.True (GetIsDirectBinding (o1), "inside monotouch.dll"); + } + using (var o2 = new MyObject ()) { + Assert.False (o2.GetIsDirectBinding (), "outside monotouch.dll"); + } + } + + [Test] + public void SuperClass () + { + Class c = new Class ("NSObject"); + Assert.That (c.Name, Is.EqualTo ("NSObject"), "Name"); + Assert.That (c.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (c.SuperClass, Is.EqualTo (IntPtr.Zero), "SuperClass"); + } + + [Test] + public void FromObject_INativeObject () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=8458 + using (CGPath p = CGPath.FromRect (new RectangleF (1, 2, 3, 4))) { + Assert.IsNotNull (NSObject.FromObject (p), "CGPath"); + } + using (CGColor c = new CGColor (CGColorSpace.CreateDeviceRGB (), new nfloat [] { 0.1f, 0.2f, 0.3f, 1.0f })) { + Assert.IsNotNull (NSObject.FromObject (c), "CGColor"); + } + if (TestRuntime.CheckSystemAndSDKVersion (8,0)) { + using (var sac = new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly)) { + Assert.IsNotNull (NSObject.FromObject (sac), "SecAccessControl"); + } + } + } + + [Test] + public void FromObject_Handle () + { + using (CGPath p = CGPath.FromRect (new RectangleF (1, 2, 3, 4))) { + Assert.IsNotNull (NSObject.FromObject (p.Handle), "CGPath"); + } + using (CGColor c = new CGColor (CGColorSpace.CreateDeviceRGB (), new nfloat [] { 0.1f, 0.2f, 0.3f, 1.0f })) { + Assert.IsNotNull (NSObject.FromObject (c.Handle), "CGColor"); + } + } + + [Test] + public void FromObject_NativeTypes () + { + // to avoid issues like https://github.com/mono/xwt/commit/9b110e848030d5f6a0319212fd21bac02efad2c1 + using (var nativeint = (NSNumber) NSObject.FromObject ((nint)(-42))) { + Assert.That (nativeint.Int32Value, Is.EqualTo (-42), "nint"); + } + using (var nativeuint = (NSNumber) NSObject.FromObject ((nuint)42)) { + Assert.That (nativeuint.UInt32Value, Is.EqualTo (42), "nuint"); + } + using (var nativefloat = (NSNumber) NSObject.FromObject ((nfloat)3.14)) { + Assert.That (nativefloat.FloatValue, Is.EqualTo (3.14f), "nfloat"); + } + } + + [Test] + public void ValueForInvalidKeyTest () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=13243 + Assert.Throws (() => + { + using (var str = new NSString ("test")) { + str.ValueForKey(str); + } + }); + } + + [Test] + public void Copy () + { + IntPtr nscopying = Runtime.GetProtocol ("NSCopying"); + Assert.That (nscopying, Is.Not.EqualTo (IntPtr.Zero), "NSCopying"); + + IntPtr nsmutablecopying = Runtime.GetProtocol ("NSMutableCopying"); + Assert.That (nsmutablecopying, Is.Not.EqualTo (IntPtr.Zero), "NSMutableCopying"); + + // NSObject does not conform to NSCopying + using (var o = new NSObject ()) { + Assert.False (o.ConformsToProtocol (nscopying), "NSObject/NSCopying"); + Assert.False (o.ConformsToProtocol (nsmutablecopying), "NSObject/NSMutableCopying"); + } + + // NSNumber conforms to NSCopying - but not NSMutableCopying + using (var n = new NSNumber (-1)) { + Assert.True (n.ConformsToProtocol (nscopying), "NSNumber/NSCopying"); + using (var xn = n.Copy ()) { + Assert.NotNull (xn, "NSNumber/Copy/NotNull"); + Assert.AreSame (n, xn, "NSNumber/Copy/NotSame"); + } + Assert.False (n.ConformsToProtocol (nsmutablecopying), "NSNumber/NSMutableCopying"); + } + + // NSMutableString conforms to NSCopying - but not NSMutableCopying + using (var s = new NSMutableString (1)) { + Assert.True (s.ConformsToProtocol (nscopying), "NSMutableString/NSCopying"); + using (var xs = s.Copy ()) { + Assert.NotNull (xs, "NSMutableString/Copy/NotNull"); + Assert.AreNotSame (s, xs, "NSMutableString/Copy/NotSame"); + } + Assert.True (s.ConformsToProtocol (nsmutablecopying), "NSMutableString/NSMutableCopying"); + using (var xs = s.MutableCopy ()) { + Assert.NotNull (xs, "NSMutableString/MutableCopy/NotNull"); + Assert.AreNotSame (s, xs, "NSMutableString/MutableCopy/NotSame"); + } + } + } + + [Test] + public void Encode () + { + IntPtr nscoding = Runtime.GetProtocol ("NSCoding"); + Assert.That (nscoding, Is.Not.EqualTo (IntPtr.Zero), "NSCoding"); + +#if !XAMCORE_2_0 + // NSObject does not conform to NSCoding + using (var o = new NSObject ()) { + Assert.False (o.ConformsToProtocol (nscoding), "NSObject/NSCoding"); + using (var c = new NSCoder ()) { + Assert.Throws (delegate { + o.EncodeTo (c); + }, "NSObject/!NSCoding"); + } + } +#endif + + // NSNumber conforms to NSCoding + using (var n = new NSNumber (-1)) { + Assert.True (n.ConformsToProtocol (nscoding), "NSNumber/NSCoding"); + using (var d = new NSMutableData ()) + using (var a = new NSKeyedArchiver (d)) { + n.EncodeTo (a); + a.FinishEncoding (); + } + } + } + +#if !XAMCORE_2_0 + [Test] + public void CtorNSCoder () + { + // NSObject does NOT conform but (funnily enough) does not have a .ctor(NSCoder) like every other + // type that subclass it. We'll use NSKeyedUnarchiver as it also does not conform to NSCoding + using (var c = new NSCoder ()) { + Assert.Throws (delegate { + new NSKeyedUnarchiver (c); + }, "NSObject/!NSCoding"); + } + } +#endif + + [Test] + public void Equality () + { + using (var o1 = new NSObject ()) + using (var o2 = new NSObject ()) { + Assert.False (o1.Equals ((object)null), "Equals(object) null"); + Assert.False (o1.Equals ((object)o2), "Equals(object) 1-2"); + Assert.False (o2.Equals ((object)o1), "Equals(object) 2-1"); + + Assert.False (o1.Equals (3), "Equals(object) 1-3"); + + Assert.False (o1.Equals ((NSObject)null), "Equals(NSObject) null"); + Assert.False (o1.Equals ((NSObject)o2), "Equals(NSObject) 1-2"); + Assert.False (o2.Equals ((NSObject)o1), "Equals(NSObject) 2-1"); + + // on a more positive note... + Assert.True (o1.Equals ((object)o1), "Equals(object) 1-1"); + Assert.True (o2.Equals ((NSObject)o2), "Equals(NSObject) 2-2"); + } + } + + class NSOverrideEqualObject : NSObject { + + public NSOverrideEqualObject (bool throwEquals) + { + Throw = throwEquals; + } + + bool Throw { get; set; } + + public bool Direct { + get { return IsDirectBinding; } + } + + public override bool Equals (object obj) + { + if (Throw) + throw new NotFiniteNumberException (); + return base.Equals (obj); + } + + public override int GetHashCode () + { + return 42; + } + } + + [Test] + public void SubclassEquality () + { + using (var o1 = new NSObject ()) + using (var o2 = new NSOverrideEqualObject (true)) + using (var o3 = new NSOverrideEqualObject (false)) { + // true, same object + Assert.True (o1.Equals (o1), "direct - direct / same"); + Assert.True (o3.Equals (o3), "indirect - indirect / same"); + + // false, good since there's state in o2 and o3 that does not exists in o1 (direct / native only) + Assert.False (o1.Equals (o2), "direct - indirect"); + Assert.False (o3.Equals (o1), "indirect - direct"); + + // default is false, which is good since the managed state (Throw) differs between o2 and o3 + Assert.False (o3.Equals (o2), "indirect - indirect"); + + // throws (as implemented above) + Assert.Throws (() => { o2.Equals ((object) o1); }, "Equals(object) 2-1"); + + // throws (as IEquatable.Equals calls _overriden_ Equals + Assert.Throws (() => { o2.Equals ((NSObject) o1); }, "Equals(NSObject) 2-1"); + } + } + +#if !__WATCHOS__ // FIXME: this test can probably be fixed to run on WatchOS by testing something other than UIView + [Test] + public void ObserverTest () + { + bool observed = false; + using (var o = new UIView ()) { + using (var observer = o.AddObserver ("frame", NSKeyValueObservingOptions.OldNew, change => { + var old = ((NSValue) change.OldValue).CGRectValue; + var @new = ((NSValue) change.NewValue).CGRectValue; + Assert.AreEqual ("{X=0,Y=0,Width=0,Height=0}", old.ToString (), "#old"); + Assert.AreEqual ("{X=0,Y=0,Width=123,Height=234}", @new.ToString (), "#new"); + observed = true; + })) { + o.Frame = new RectangleF (0, 0, 123, 234); + } + } + Assert.IsTrue (observed, "observed"); + } +#endif // !__WATCHOS__ + + [Test] + [Timeout (5000)] + public void InvokeTest () + { + var evt = new ManualResetEvent (false); + using (var obj = new NSObject ()) + obj.Invoke (() => evt.Set (), .2); + while (!evt.WaitOne (1)) + NSRunLoop.Current.RunUntil (NSRunLoopMode.Default, NSDate.Now.AddSeconds (1)); + + Assert.True (evt.WaitOne (1), "Our invoke was not fired?"); + } + } +} diff --git a/tests/monotouch-test/Foundation/OperationQueueTest.cs b/tests/monotouch-test/Foundation/OperationQueueTest.cs new file mode 100644 index 000000000000..85a4ad8aa5cc --- /dev/null +++ b/tests/monotouch-test/Foundation/OperationQueueTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for NSOperationQueue +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class OperationQueueTest { + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Add_NSAction_Null () + { + using (var q = new NSOperationQueue ()) { + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: *** -[NSBlockOperation addExecutionBlock:]: block is nil +#if XAMCORE_2_0 + q.AddOperation ((Action) null); +#else + q.AddOperation ((NSAction) null); +#endif + } + } + + [Test] + public void Add_NSOperation_Null () + { + using (var q = new NSOperationQueue ()) { + q.AddOperation ((NSOperation) null); + Assert.That (q.OperationCount, Is.EqualTo (0), "OperationCount"); + Assert.That (q.Operations.Length, Is.EqualTo (0), "Operations"); + } + } + + [Test] + public void Add_NSOperations_Null () + { + using (var q = new NSOperationQueue ()) { + q.AddOperations (null, true); + Assert.That (q.OperationCount, Is.EqualTo (0), "OperationCount"); + Assert.That (q.Operations.Length, Is.EqualTo (0), "Operations"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/OutputStreamTest.cs b/tests/monotouch-test/Foundation/OutputStreamTest.cs new file mode 100644 index 000000000000..db5ecc579580 --- /dev/null +++ b/tests/monotouch-test/Foundation/OutputStreamTest.cs @@ -0,0 +1,79 @@ +// +// Unit tests for NSOutputStream +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + public class OutputStreamTest { + + [Test] + public void Path () + { + using (var s = new NSOutputStream ("Info.plist", false)) { + // initToFileAtPath:append: does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void Memory () + { + using (var s = new NSOutputStream ()) { + // initToMemory does not respond (see dontlink.app) but it works + Assert.That (s.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public unsafe void Write () + { + using (var s = (NSOutputStream) NSOutputStream.OutputStreamToMemory ()) { + s.Open (); + s.Write (new byte[] { 1, 2, 3 }, 3); + using (var obj = s [NSStream.DataWrittenToMemoryStreamKey] as NSData) { + Assert.IsNotNull (obj, "a"); + Assert.AreEqual (1, Marshal.ReadByte (obj.Bytes, 0), "a[0]"); + Assert.AreEqual (2, Marshal.ReadByte (obj.Bytes, 1), "a[1]"); + Assert.AreEqual (3, Marshal.ReadByte (obj.Bytes, 2), "a[2]"); + } + } + + using (var s = new NSOutputStream ()) { + s.Open (); + s.Write (new byte[] { 1, 2, 3 }); + using (var obj = s [NSStream.DataWrittenToMemoryStreamKey] as NSData) { + Assert.IsNotNull (obj, "a"); + Assert.AreEqual (1, Marshal.ReadByte (obj.Bytes, 0), "b[0]"); + Assert.AreEqual (2, Marshal.ReadByte (obj.Bytes, 1), "b[1]"); + Assert.AreEqual (3, Marshal.ReadByte (obj.Bytes, 2), "b[2]"); + } + } + + using (var s = (NSOutputStream) NSOutputStream.OutputStreamToMemory ()) { + s.Open (); + s.Write (new byte[] { 1, 2, 3 }, 2, 1); + using (var obj = s [NSStream.DataWrittenToMemoryStreamKey] as NSData) { + Assert.IsNotNull (obj, "a"); + Assert.AreEqual (3, Marshal.ReadByte (obj.Bytes, 0), "c[0]"); + } + } + } + } +} diff --git a/tests/monotouch-test/Foundation/ProtocolAttributeTest.cs b/tests/monotouch-test/Foundation/ProtocolAttributeTest.cs new file mode 100644 index 000000000000..e0c2bcfb7a0a --- /dev/null +++ b/tests/monotouch-test/Foundation/ProtocolAttributeTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for ProtocolAttribute (yeah, really!) +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ProtocolAttributeTest { + + [Test] + public void ModelMustBeProtocol () + { + int count = 0; + + // + // Note that [Model], but no [Protocol] is not a universal truth (so it's + // not enforced in the generator), but it should be true for monotouch.dll. + // + + foreach (var type in typeof (NSObject).Assembly.GetTypes ()) { + if (!type.IsSubclassOf (typeof (NSObject))) + continue; + + var register = (RegisterAttribute)Attribute.GetCustomAttribute (type, typeof(RegisterAttribute), false); + if (register != null && !register.IsWrapper) + continue; + + if (Attribute.GetCustomAttribute (type, typeof(ModelAttribute), false) == null) + continue; + + if (Attribute.GetCustomAttribute (type, typeof(ProtocolAttribute), false) == null) { + Console.WriteLine ("{0} must have a [Protocol] attribute if it has a [Model] attribute", type.FullName); + count++; + } + } + + if (count > 0) + Assert.Fail ("Found {0} types with a [Model] attribute (and no [Register(false)] attribute signalling that they're not wrapper types), but without a [Protocol] attribute.", count); + } + } +} diff --git a/tests/monotouch-test/Foundation/StringTest.cs b/tests/monotouch-test/Foundation/StringTest.cs new file mode 100644 index 000000000000..7840d8d3f718 --- /dev/null +++ b/tests/monotouch-test/Foundation/StringTest.cs @@ -0,0 +1,247 @@ +// +// Unit tests for NSString +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2011-2012 Xamarin Inc. All rights reserved. +// + +using System; +#if !__WATCHOS__ +using System.Drawing; +#endif +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class StringTest { + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Compare_Null () + { + using (NSString s = new NSString ("s")) { + s.Compare (null); + } + } + + [Test] + public void Compare () + { + using (NSString s1 = new NSString ("Sebastien")) + using (NSString s2 = new NSString ("Sébastien")) + { + Assert.That (s1.Compare (s1), Is.EqualTo (NSComparisonResult.Same), "Same"); + Assert.That (s1.Compare (s2), Is.EqualTo (NSComparisonResult.Ascending), "Ascending"); + Assert.That (s2.Compare (s1), Is.EqualTo (NSComparisonResult.Descending), "Descending"); + } + } + + [Test] + public void Compare_Options () + { + using (NSString s1 = new NSString ("Sebastien")) + using (NSString s2 = new NSString ("Sébastien")) + { + Assert.That (s1.Compare (s2, NSStringCompareOptions.DiacriticInsensitiveSearch), + Is.EqualTo (NSComparisonResult.Same), "DiacriticInsensitiveSearch"); + } + } + + [Test] + public void Compare_Range () + { + using (NSString s1 = new NSString ("Bastien")) + using (NSString s2 = new NSString ("Sébastien")) + { + NSRange r = new NSRange (2, s2.Length - 2); + Assert.That (s2.Compare (s1, NSStringCompareOptions.CaseInsensitiveSearch, r), + Is.EqualTo (NSComparisonResult.Same), "skip accent"); + } + } + + [Test] + public void Compare_Locale () + { + using (NSString s1 = new NSString ("sebastien")) + using (NSString s2 = new NSString ("Sébastien")) + { + NSStringCompareOptions options = NSStringCompareOptions.DiacriticInsensitiveSearch | NSStringCompareOptions.CaseInsensitiveSearch; + NSRange r = new NSRange (0, s2.Length); + Assert.That (s1.Compare (s2, options, r, null), + Is.EqualTo (NSComparisonResult.Same), "null"); + Assert.That (s1.Compare (s2, options, r, NSLocale.SystemLocale), + Is.EqualTo (NSComparisonResult.Same), "SystemLocale"); + } + } + + [Test] + // requested in http://bugzilla.xamarin.com/show_bug.cgi?id=1870 + public void Replace_Range () + { + using (NSString s1 = new NSString ("Sebastien")) + using (NSString s2 = new NSString ("é")) + using (NSString s3 = new NSString ("sébastien")) + using (NSString result = s1.Replace (new NSRange (1, 1), s2)) + { + NSStringCompareOptions options = NSStringCompareOptions.CaseInsensitiveSearch; + Assert.That (result.Compare (s3, options), + Is.EqualTo (NSComparisonResult.Same), "Replace"); + } + } + +#if !__TVOS__ && !__WATCHOS__ + [Test] + [Culture ("en")] // fails for some cultures, e.g. ar-AE + public void DrawString_7 () + { + nfloat actualFontSize = 12; + var f = UIFont.BoldSystemFontOfSize (actualFontSize); + try { + using (NSString s = new NSString ("s")) { + SizeF size = s.DrawString (PointF.Empty, 20, f, 6, ref actualFontSize, UILineBreakMode.MiddleTruncation, UIBaselineAdjustment.None); + Assert.That (actualFontSize, Is.EqualTo ((nfloat) 12), "actualFontSize"); + Assert.That (size.Width, Is.InRange ((nfloat) 6f, (nfloat) 7f), "Width"); + Assert.That (size.Height, Is.InRange ((nfloat) 14f, (nfloat) 15f), "Height"); + } + using (NSString s = new NSString ("saterlipopette")) { + SizeF size = s.DrawString (PointF.Empty, 20, f, 6, ref actualFontSize, UILineBreakMode.MiddleTruncation, UIBaselineAdjustment.None); + Assert.That (actualFontSize, Is.EqualTo ((nfloat) 6), "actualFontSize-2"); + Assert.That (size.Width, Is.InRange ((nfloat) 17f, (nfloat) 19f), "Width-2"); + Assert.That (size.Height, Is.InRange ((nfloat) 7f, (nfloat) 8f), "Height-2"); + } + } catch { + Console.WriteLine ("DrawString_7: actualFontSize: {0} font: {1}", actualFontSize, f); + throw; + } + } + + [Test] + [Culture ("en")] // fails for some cultures, e.g. ar-AE + public void StringSize_5 () + { + nfloat actualFontSize = 12; + var f = UIFont.BoldSystemFontOfSize (actualFontSize); + try { + using (NSString s = new NSString ("s")) { + SizeF size = s.StringSize (f, 6, ref actualFontSize, 10, UILineBreakMode.MiddleTruncation); + Assert.That (actualFontSize, Is.EqualTo ((nfloat) 12), "actualFontSize"); + Assert.That (size.Width, Is.InRange ((nfloat) 6f, (nfloat) 7f), "Width"); + Assert.That (size.Height, Is.InRange ((nfloat) 14f, (nfloat) 15f), "Height"); + } + using (NSString s = new NSString ("saterlipopette")) { + SizeF size = s.StringSize (f, 6, ref actualFontSize, 10, UILineBreakMode.MiddleTruncation); + Assert.That (actualFontSize, Is.EqualTo ((nfloat) 6), "actualFontSize-2"); + Assert.That (size.Width, Is.InRange ((nfloat) 5f, (nfloat) 10f), "Width-2"); + Assert.That (size.Height, Is.InRange ((nfloat) 14f, (nfloat) 15f), "Height-2"); + } + } catch { + Console.WriteLine ("StringSize_5: actualFontSize: {0} font: {1}", actualFontSize, f); + throw; + } + } +#endif // !__TVOS__ && !__WATCHOS__ + + [Test] + public void PathExtensions () + { + using (NSString s = new NSString ("/dir/file.ext")) { + Assert.That (s.PathExtension.ToString (), Is.EqualTo ("ext"), "PathExtension"); + var components = s.PathComponents; + Assert.That (components.Length, Is.EqualTo (3), "PathComponents"); + Assert.That (components [0], Is.EqualTo ("/"), "PathComponents-0"); + Assert.That (components [1], Is.EqualTo ("dir"), "PathComponents-1"); + Assert.That (components [2], Is.EqualTo ("file.ext"), "PathComponents-2"); + Assert.That (s.LastPathComponent.ToString (), Is.EqualTo (components [2]), "LastPathComponent"); + } + } + + [Test] + public void DrawingExtensions () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("requires iOS7+"); + + using (var s = new NSString ("foo")) { + NSStringDrawingOptions options = NSStringDrawingOptions.OneShot; + var attrib = new UIStringAttributes (); + using (var dict = new NSDictionary ()) { + Assert.DoesNotThrow (() => s.GetBoundingRect (new SizeF (5, 5), options, attrib, null), "GetBoundingRect 1"); + Assert.DoesNotThrow (() => s.WeakGetBoundingRect (new SizeF (5, 5), options, dict, null), "WeakGetBoundingRect 1"); + Assert.DoesNotThrow (() => s.DrawString (new RectangleF (0, 0, 10, 10), options, attrib, null), "DrawString 1"); + Assert.DoesNotThrow (() => s.WeakDrawString (new RectangleF (0, 0, 10, 10), options, dict, null), "WeakDrawString 1"); + Assert.DoesNotThrow (() => s.WeakDrawString (new RectangleF (0, 0, 10, 10), dict), "WeakDrawString 2"); + Assert.DoesNotThrow (() => s.WeakDrawString (new PointF (0, 0), dict), "WeakDrawString 3"); + } + } + } + + [Test] + public void ReleaseEmptyString () + { + NSString.Empty.DangerousRelease (); + NSString.Empty.DangerousRelease (); + NSString.Empty.DangerousRelease (); + NSString.Empty.DangerousRelease (); + NSString.Empty.DangerousRelease (); + +#if XAMCORE_2_0 + Assert.That (NSString.Empty.RetainCount, Is.EqualTo (nuint.MaxValue), "RetainCount"); +#else + Assert.That (NSString.Empty.RetainCount, Is.EqualTo (-1), "RetainCount"); +#endif + Assert.That (NSString.Empty.Compare (new NSString (string.Empty)), Is.EqualTo (NSComparisonResult.Same), "Same"); + } + + [Test] + public void Equality () + { + using (var s1 = new NSString ("\u00f6")) // o-umlaut + using (var s2 = new NSString ("o\u0308")) { // o + combining diaeresis + // since ObjC thinks it's different + Assert.That (s1.GetHashCode (), Is.Not.EqualTo (s2.GetHashCode ()), "GetHashCode"); + // then it's "correct" to return false for equality + Assert.False (s1.Equals ((object) s2), "Equal(object)"); + Assert.False (s1.Equals ((NSObject) s2), "Equal(NSObject)"); + Assert.False (s1.Equals ((NSString) s2), "Equal(NSString)"); + Assert.False (NSString.Equals (s1, s2), "static"); + // and people need to call compare + Assert.That (s1.Compare (s2), Is.EqualTo (NSComparisonResult.Same), "Same"); + } + } + + [Test] + public void FromData () + { + UIImage img = UIImage.FromFile ("basn3p08.png"); + using (NSData imageData = img.AsPNG ()) { + using (var str = NSString.FromData (imageData, NSStringEncoding.UTF8)) { + Assert.IsNull (str, "NSDataFromImage"); + } + } + Assert.Throws (() => { + NSString.FromData (null, NSStringEncoding.UTF8); + }, "NSDataNull"); + } + } +} diff --git a/tests/monotouch-test/Foundation/ThreadTest.cs b/tests/monotouch-test/Foundation/ThreadTest.cs new file mode 100644 index 000000000000..9d4aabfe4925 --- /dev/null +++ b/tests/monotouch-test/Foundation/ThreadTest.cs @@ -0,0 +1,77 @@ +// +// Unit tests for NSThread +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; +using System.Threading; +using System.Threading.Tasks; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ThreadTest { + + [Test] + public void MainThread () + { + Assert.True (NSThread.IsMain, "IsMain"); + Assert.True (NSThread.MainThread.IsMainThread, "IsMainThread"); + } + + [Test] + public void GetEntryAssemblyReturnsOk () + { + Assert.IsNotNull (Assembly.GetEntryAssembly ()); + Assert.IsTrue (NSThread.IsMain); + int rv = -1; + var t = new Thread (() => { + if (NSThread.IsMain) + rv = 1; + else if (Assembly.GetEntryAssembly () == null) + rv = 2; + else + rv = 0; + }) { + IsBackground = true, + }; + t.Start (); + t.Join (); + Assert.AreEqual (0, rv); + } + + [Test] + public void InitWithDataTest () + { + var obj = new InitWithDataObject (); + var thread = new NSThread (obj, new Selector ("start:"), null); + thread.Start (); + Assert.IsTrue (obj.StartedEvent.WaitOne (TimeSpan.FromSeconds (5)), "thread start"); + GC.Collect (); + } + + class InitWithDataObject : NSObject { + public ManualResetEvent StartedEvent = new ManualResetEvent (false); + + [Export ("start:")] + public void Start (NSObject obj) + { + StartedEvent.Set (); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/TimerTest.cs b/tests/monotouch-test/Foundation/TimerTest.cs new file mode 100644 index 000000000000..747d1d763e47 --- /dev/null +++ b/tests/monotouch-test/Foundation/TimerTest.cs @@ -0,0 +1,91 @@ +// +// Unit tests for NSTimer +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; +using System.Threading; +using System.Threading.Tasks; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TimerTest { + [Test] + public void Bug17793 () + { + var evt = new CountdownEvent (2); + + NSTimer timer = null; + + using (timer = NSTimer.CreateRepeatingTimer (0.1f, delegate { + // This is the real test - not a timer test, but properly preserving VFP registers. + // When bug #17793 manifests, this method is only called once instead of repeatedly. + Func (0, 0, 0, 0, 0, 0, 0); + if (evt.Signal ()) + timer.Invalidate (); + })) { + + var thread = new Thread (() => { + NSRunLoop.Current.AddTimer (timer, NSRunLoopMode.Default); + NSRunLoop.Current.RunUntil (NSRunLoopMode.Default, NSDate.Now.AddSeconds (5)); + }) + { + IsBackground = true, + }; + thread.Start (); + + Assert.IsTrue (evt.Wait (TimeSpan.FromSeconds (5)), "Not signalled twice in 5s"); + thread.Join (); + } + } + + void Func (double m00, double m01, double m02, double m03, double m10, double m11, double m12) + { + } + +#if XAMCORE_2_0 + [Test] + public void CreateTimer_NewSignature () + { + bool result = false; + var evt = new ManualResetEvent (false); + + NSTimer timer = null; + + using (timer = NSTimer.CreateTimer (0.1f, (NSTimer t) => { + result = t != null && t.Handle == timer.Handle; + evt.Set (); + })) { + + var thread = new Thread (() => { + NSRunLoop.Current.AddTimer (timer, NSRunLoopMode.Default); + NSRunLoop.Current.RunUntil (NSRunLoopMode.Default, NSDate.Now.AddSeconds (5)); + }) + { + IsBackground = true, + }; + thread.Start (); + + Assert.IsTrue (evt.WaitOne (TimeSpan.FromSeconds (5)), "WaitOne"); + Assert.IsTrue (result, "result"); + thread.Join (); + } + } +#endif + } +} diff --git a/tests/monotouch-test/Foundation/UbiquitousKeyValueStoreTest.cs b/tests/monotouch-test/Foundation/UbiquitousKeyValueStoreTest.cs new file mode 100644 index 000000000000..daaf43ce5e85 --- /dev/null +++ b/tests/monotouch-test/Foundation/UbiquitousKeyValueStoreTest.cs @@ -0,0 +1,45 @@ +// +// Unit tests for NSTimer +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; +using System.Threading; +using System.Threading.Tasks; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NSUbiquitousKeyValueStoreTest { + [Test] + public void Indexer () + { + using (var store = new NSUbiquitousKeyValueStore ()) { + using (var key = new NSString ("key")) { + using (var value = new NSString ("value")) { + store [key] = value; + Assert.AreEqual (value, store [key], "key 1"); + + store [(string) key] = value; + Assert.AreEqual (value, store [(string) key], "key 2"); + } + + } + } + } + } +} diff --git a/tests/monotouch-test/Foundation/UrlConnectionTest.cs b/tests/monotouch-test/Foundation/UrlConnectionTest.cs new file mode 100644 index 000000000000..a255871d07f8 --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlConnectionTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for UrlConnection +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlConnectionTest { + + class MyDelegate : NSUrlConnectionDelegate { + + } + + [Test] + public void StartCancel () + { + using (var url = new NSUrl ("http://www.google.com")) + using (var r = new NSUrlRequest (url)) + using (var d = new MyDelegate ()) + using (var c = new NSUrlConnection (r, d)) { + c.Start (); + c.Cancel (); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/UrlCredentialTest.cs b/tests/monotouch-test/Foundation/UrlCredentialTest.cs new file mode 100644 index 000000000000..c048a861056a --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlCredentialTest.cs @@ -0,0 +1,66 @@ +// +// Unit tests for NSUrlCredential +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Security.Cryptography.X509Certificates; +#if XAMCORE_2_0 +using Foundation; +using Security; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +using MonoTouchFixtures.Security; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlCredentialTest { + + SecTrust GetTrust () + { + X509Certificate x = new X509Certificate (CertificateTest.mail_google_com); + using (var policy = SecPolicy.CreateBasicX509Policy ()) + return new SecTrust (x, policy); + } + + [Test] + public void Ctor_Trust () + { + using (var trust = GetTrust ()) + using (var creds = new NSUrlCredential (trust)) { + Assert.Null (creds.Certificates, "Certificates"); + Assert.False (creds.HasPassword, "HasPassword"); + Assert.Null (creds.SecIdentity, "SecIdentity"); + Assert.Null (creds.Password, "Password"); + Assert.That (creds.Persistence, Is.EqualTo (NSUrlCredentialPersistence.ForSession), "Persistence"); + Assert.Null (creds.User, "User"); + } + } + + [Test] + public void FromTrust () + { + using (var trust = GetTrust ()) + using (var creds = NSUrlCredential.FromTrust (trust)) { + Assert.Null (creds.Certificates, "Certificates"); + Assert.False (creds.HasPassword, "HasPassword"); + Assert.Null (creds.SecIdentity, "SecIdentity"); + Assert.Null (creds.Password, "Password"); + Assert.That (creds.Persistence, Is.EqualTo (NSUrlCredentialPersistence.ForSession), "Persistence"); + Assert.Null (creds.User, "User"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/UrlProtectionSpaceTest.cs b/tests/monotouch-test/Foundation/UrlProtectionSpaceTest.cs new file mode 100644 index 000000000000..65118ce4be3e --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlProtectionSpaceTest.cs @@ -0,0 +1,113 @@ +// +// Unit tests for NSUrlProtectionSpace +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Security.Cryptography.X509Certificates; +#if XAMCORE_2_0 +using Foundation; +using Security; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +using MonoTouchFixtures.Security; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlProtectionSpaceTest { + + [Test] + public void Http () + { + using (var ps = new NSUrlProtectionSpace ("www.xamarin.com", 80, NSUrlProtectionSpace.HTTP, null, null)) { + Assert.That (ps.AuthenticationMethod, Is.EqualTo ("NSURLAuthenticationMethodDefault"), "AuthenticationMethod"); + Assert.Null (ps.DistinguishedNames, "DistinguishedNames"); + Assert.That (ps.Host, Is.EqualTo ("www.xamarin.com"), "Host"); + Assert.False (ps.IsProxy, "IsProxy"); + Assert.That (ps.Port, Is.EqualTo ((nint) 80), "Port"); + Assert.That (ps.Protocol, Is.EqualTo ("http"), "Protocol"); + Assert.Null (ps.ProxyType, "ProxyType"); + Assert.Null (ps.Realm, "Realm"); + Assert.False (ps.ReceivesCredentialSecurely, "ReceivesCredentialSecurely"); + Assert.Null (ps.ServerSecTrust, "ServerSecTrust"); + } + } + + [Test] + public void Https () + { + using (var ps = new NSUrlProtectionSpace ("mail.google.com", 443, NSUrlProtectionSpace.HTTPS, null, NSUrlProtectionSpace.AuthenticationMethodHTTPBasic)) { + if (TestRuntime.CheckiOSSystemVersion (9, 0)) { + Assert.That (ps.AuthenticationMethod, Is.EqualTo ("NSURLAuthenticationMethodHTTPBasic"), "AuthenticationMethod"); + } else { + Assert.That (ps.AuthenticationMethod, Is.EqualTo ("NSURLAuthenticationMethodDefault"), "AuthenticationMethod"); + } + Assert.Null (ps.DistinguishedNames, "DistinguishedNames"); + Assert.That (ps.Host, Is.EqualTo ("mail.google.com"), "Host"); + Assert.False (ps.IsProxy, "IsProxy"); + Assert.That (ps.Port, Is.EqualTo ((nint) 443), "Port"); + Assert.That (ps.Protocol, Is.EqualTo ("https"), "Protocol"); + Assert.Null (ps.ProxyType, "ProxyType"); + Assert.Null (ps.Realm, "Realm"); + Assert.True (ps.ReceivesCredentialSecurely, "ReceivesCredentialSecurely"); + Assert.Null (ps.ServerSecTrust, "ServerSecTrust"); + } + } + + [Test] + public void HttpProxy () + { + using (var ps = new NSUrlProtectionSpace ("www.xamarin.com", 80, NSUrlProtectionSpace.HTTPProxy, "default", NSUrlProtectionSpace.AuthenticationMethodHTTPDigest, false)) { + Assert.That (ps.AuthenticationMethod, Is.EqualTo ("NSURLAuthenticationMethodHTTPDigest"), "AuthenticationMethod"); + Assert.Null (ps.DistinguishedNames, "DistinguishedNames"); + Assert.That (ps.Host, Is.EqualTo ("www.xamarin.com"), "Host"); + Assert.False (ps.IsProxy, "IsProxy"); + Assert.That (ps.Port, Is.EqualTo ((nint) 80), "Port"); + Assert.That (ps.Protocol, Is.EqualTo ("http"), "Protocol"); + Assert.Null (ps.ProxyType, "ProxyType"); + Assert.That (ps.Realm, Is.EqualTo ("default"), "Realm"); + Assert.True (ps.ReceivesCredentialSecurely, "ReceivesCredentialSecurely"); + Assert.Null (ps.ServerSecTrust, "ServerSecTrust"); + } + } + + [Test] + public void HttpProxy_Proxy () + { + using (var ps = new NSUrlProtectionSpace ("www.xamarin.com", 80, NSUrlProtectionSpace.HTTPProxy, "default", NSUrlProtectionSpace.AuthenticationMethodHTTPDigest, true)) { + Assert.That (ps.AuthenticationMethod, Is.EqualTo ("NSURLAuthenticationMethodHTTPDigest"), "AuthenticationMethod"); + Assert.Null (ps.DistinguishedNames, "DistinguishedNames"); + Assert.That (ps.Host, Is.EqualTo ("www.xamarin.com"), "Host"); + Assert.True (ps.IsProxy, "IsProxy"); + Assert.That (ps.Port, Is.EqualTo ((nint) 80), "Port"); + Assert.That (ps.Protocol, Is.EqualTo ("http"), "Protocol"); + Assert.That (ps.ProxyType, Is.EqualTo ("http"), "ProxyType"); + Assert.Null (ps.Realm, "Realm"); + Assert.True (ps.ReceivesCredentialSecurely, "ReceivesCredentialSecurely"); + Assert.Null (ps.ServerSecTrust, "ServerSecTrust"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/UrlProtocolTest.cs b/tests/monotouch-test/Foundation/UrlProtocolTest.cs new file mode 100644 index 000000000000..7b496a481a3d --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlProtocolTest.cs @@ -0,0 +1,66 @@ +// +// Unit tests for NSUrlProtocol +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlProtocolTest { + [Test] + public void Registration () + { + Class c = new Class (typeof (CustomProtocol)); + bool res; + + res = NSUrlProtocol.RegisterClass (c); + + Assert.That (res, "#1"); + + NSUrlProtocol.UnregisterClass (c); + } + + class CustomProtocol : NSUrlProtocol + { + } + + // API disabled - see comments in src/foundation.cs +#if false + [Test] + public void CanInitWithTask () + { + // NSInvalidArgumentException Reason: *** -canInitWithRequest: cannot be sent to an abstract object of class NSURLProtocol: Create a concrete instance! + using (var t = new NSUrlSessionTask ()) { + Assert.False (NSUrlProtocol.CanInitWithTask (t), "CanInitWithTask"); + } + } + + [Test] + public void Task () + { + // NSInvalidArgumentException -[MonoTouchFixtures_Foundation_UrlProtocolTest_CustomProtocol task]: unrecognized selector sent to instance 0x7ff4c910 + using (var p = new CustomProtocol ()) { + Assert.Null (p.Task, "Task"); + } + } +#endif + } +} diff --git a/tests/monotouch-test/Foundation/UrlRequestTest.cs b/tests/monotouch-test/Foundation/UrlRequestTest.cs new file mode 100644 index 000000000000..e063584cc73a --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlRequestTest.cs @@ -0,0 +1,70 @@ +// +// Unit tests for NSUrlRequest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlRequestTest { + + [Test] + public void Mutability_30744 () + { + using (var s1 = new NSString ("Authorization")) + using (var s2 = new NSString ("ok")) + using (var s3 = new NSString ("fail")) + using (var md = NSMutableDictionary.FromObjectAndKey (s2, s1)) + using (var ur = new NSUrlRequest ()) + using (var mur = (NSMutableUrlRequest)ur.MutableCopy ()) { + Assert.Null (ur.Headers, "NSUrlRequest / Headers / null"); + Assert.Null (mur.Headers, "NSMutableUrlRequest / Headers / null"); + + mur.Headers = md; + + // that a bit like lying, we still consider it an NSMutableDictionary but it't not mutable + Assert.That (mur.Headers, Is.TypeOf (typeof (NSMutableDictionary)), "NSMutableDictionary"); + + // that would crash on devices + // NSInternalInconsistencyException -[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object + if (Runtime.Arch == Arch.SIMULATOR) { + bool native_exception = false; + try { + mur.Headers.SetValueForKey (s3, s1); + Assert.Fail ("exception immutability"); + } catch { + native_exception = true; + } + Assert.True (native_exception, "non-mutable NSDictionary"); + + // the original NSMutableDictionary is fine - but it's not what's being used, i.e. property is "copy" + md.Remove (s1); + Assert.That (md.Count, Is.EqualTo (0), "1"); + Assert.That (mur.Headers.Count, Is.EqualTo (1), "2"); + md.SetValueForKey (s3, s1); + Assert.That (md.Count, Is.EqualTo (1), "3"); + Assert.That (mur.Headers.Count, Is.EqualTo (1), "40"); + + Assert.AreNotSame (md, mur.Headers, "!same"); + } + + // https://www.bignerdranch.com/blog/about-mutability/ + Assert.That (mur.Headers.Class.Name, Is.EqualTo ("__NSCFDictionary"), "__NSCFDictionary"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/UrlSessionConfigurationTest.cs b/tests/monotouch-test/Foundation/UrlSessionConfigurationTest.cs new file mode 100644 index 000000000000..624ffb1f29f5 --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlSessionConfigurationTest.cs @@ -0,0 +1,122 @@ +// +// Unit tests for NSUrlSessionConfiguration +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2015 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using Security; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlSessionConfigurationTest { + + [Test] + public void BackgroundSessionConfiguration () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + // https://trello.com/c/F6cyUBFU/70-simple-background-transfer-bo-pang-block-by-an-system-invalidcastexception-in-nsurlsessionconfiguration-backgroundsessionconfigu + using (var session = NSUrlSessionConfiguration.BackgroundSessionConfiguration ("id")) { + Assert.That (session.Identifier, Is.EqualTo ("id"), "Identifier"); + } + } + + [Test] + public void Default_Properties () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + var config = NSUrlSessionConfiguration.DefaultSessionConfiguration; + + // in iOS9 those selectors do not respond - but they do work (forwarded to __NSCFURLSessionConfiguration type ?) + + Assert.True (config.AllowsCellularAccess, "allowsCellularAccess"); + config.AllowsCellularAccess = config.AllowsCellularAccess; // setAllowsCellularAccess: + + Assert.Null (config.ConnectionProxyDictionary, "connectionProxyDictionary"); + config.ConnectionProxyDictionary = null; // setConnectionProxyDictionary: + + Assert.False (config.Discretionary, "isDiscretionary"); + config.Discretionary = config.Discretionary; // setDiscretionary: + + Assert.Null (config.HttpAdditionalHeaders, "HTTPAdditionalHeaders"); + config.HttpAdditionalHeaders = config.HttpAdditionalHeaders; // setHTTPAdditionalHeaders: + + Assert.That (config.HttpCookieAcceptPolicy, Is.EqualTo (NSHttpCookieAcceptPolicy.OnlyFromMainDocumentDomain), "HTTPCookieAcceptPolicy"); + config.HttpCookieAcceptPolicy = config.HttpCookieAcceptPolicy; // setHTTPCookieAcceptPolicy: + + Assert.NotNull (config.HttpCookieStorage, "HTTPCookieStorage"); + config.HttpCookieStorage = config.HttpCookieStorage; // setHTTPCookieStorage: + + // iOS 7.x returned 6 (instead of 4) + Assert.That (config.HttpMaximumConnectionsPerHost, Is.GreaterThanOrEqualTo (4), "HTTPMaximumConnectionsPerHost"); + config.HttpMaximumConnectionsPerHost = config.HttpMaximumConnectionsPerHost; // setHTTPMaximumConnectionsPerHost: + + Assert.True (config.HttpShouldSetCookies, "HTTPShouldSetCookies"); + config.HttpShouldSetCookies = config.HttpShouldSetCookies; // setHTTPShouldSetCookies: + + Assert.False (config.HttpShouldUsePipelining, "HTTPShouldUsePipelining"); + config.HttpShouldUsePipelining = config.HttpShouldUsePipelining; // setHTTPShouldUsePipelining: + + Assert.Null (config.Identifier, "identifier"); + + Assert.That (config.NetworkServiceType, Is.EqualTo (NSUrlRequestNetworkServiceType.Default), "networkServiceType"); + config.NetworkServiceType = config.NetworkServiceType; // setNetworkServiceType: + + Assert.That (config.RequestCachePolicy, Is.EqualTo (NSUrlRequestCachePolicy.UseProtocolCachePolicy), "requestCachePolicy"); + config.RequestCachePolicy = config.RequestCachePolicy; // setRequestCachePolicy: + + Assert.False (config.SessionSendsLaunchEvents, "sessionSendsLaunchEvents"); + config.SessionSendsLaunchEvents = config.SessionSendsLaunchEvents; // setSessionSendsLaunchEvents: + + if (TestRuntime.CheckiOSSystemVersion (8,0)) { + Assert.Null (config.SharedContainerIdentifier, "sharedContainerIdentifier"); + config.SharedContainerIdentifier = config.SharedContainerIdentifier; // setSharedContainerIdentifier: + } + + Assert.That (config.TimeoutIntervalForRequest, Is.GreaterThan (0), "timeoutIntervalForRequest"); + config.TimeoutIntervalForRequest = config.TimeoutIntervalForRequest; // setTimeoutIntervalForRequest: + + Assert.That (config.TimeoutIntervalForResource, Is.GreaterThan (0), "timeoutIntervalForResource"); + config.TimeoutIntervalForResource = config.TimeoutIntervalForResource; // setTimeoutIntervalForResource: + + Assert.That (config.TLSMaximumSupportedProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "TLSMaximumSupportedProtocol"); + config.TLSMaximumSupportedProtocol = config.TLSMaximumSupportedProtocol; // setTLSMaximumSupportedProtocol: + + Assert.That (config.TLSMinimumSupportedProtocol, Is.GreaterThanOrEqualTo (SslProtocol.Ssl_3_0), "TLSMinimumSupportedProtocol"); + config.TLSMinimumSupportedProtocol = config.TLSMinimumSupportedProtocol; // setTLSMinimumSupportedProtocol: + + Assert.NotNull (config.URLCache, "URLCache"); + config.URLCache = config.URLCache; // setURLCache: + + Assert.NotNull (config.URLCredentialStorage, "URLCredentialStorage"); + config.URLCredentialStorage = config.URLCredentialStorage; // setURLCredentialStorage: + + if (TestRuntime.CheckiOSSystemVersion (8,0)) { + Assert.NotNull (config.WeakProtocolClasses, "protocolClasses"); + } else { + Assert.Null (config.WeakProtocolClasses, "protocolClasses"); + } + config.WeakProtocolClasses = config.WeakProtocolClasses; // setProtocolClasses: + } + } +} diff --git a/tests/monotouch-test/Foundation/UrlSessionTaskTest.cs b/tests/monotouch-test/Foundation/UrlSessionTaskTest.cs new file mode 100644 index 000000000000..918754146d16 --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlSessionTaskTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for NSUrlSessionTask +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlSessionTaskTest { + + [Test] + public void Properties () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + using (var ur = new NSUrlRequest ()) + using (var task = NSUrlSession.SharedSession.CreateDownloadTask (ur)) { + // in iOS9 those selectors do not respond - but they do work (forwarded to __NSCFLocalDownloadTask type ?) + // * countOfBytesExpectedToReceive, countOfBytesExpectedToSend, countOfBytesReceived, countOfBytesSent, + // currentRequest, originalRequest, response, state, taskDescription, setTaskDescription:, taskIdentifier + Assert.That (task.BytesExpectedToReceive, Is.EqualTo (0), "countOfBytesExpectedToReceive"); + Assert.That (task.BytesExpectedToSend, Is.EqualTo (0), "countOfBytesExpectedToSend"); + Assert.That (task.BytesReceived, Is.EqualTo (0), "countOfBytesReceived"); + Assert.That (task.BytesSent, Is.EqualTo (0), "countOfBytesSent"); + Assert.NotNull (task.CurrentRequest, "currentRequest"); + Assert.Null (task.Error, "error"); + Assert.NotNull (task.OriginalRequest, "originalRequest"); + Assert.Null (task.Response, "response"); + Assert.That (task.State, Is.EqualTo (NSUrlSessionTaskState.Suspended), "state"); + Assert.Null (task.TaskDescription, "taskDescription"); + task.TaskDescription = "descriptive label"; + Assert.That ((string)task.TaskDescription, Is.EqualTo ("descriptive label"), "setTaskDescription:"); + Assert.That (task.TaskIdentifier, Is.GreaterThanOrEqualTo (0), "taskIdentifier"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/Foundation/UrlSessionTest.cs b/tests/monotouch-test/Foundation/UrlSessionTest.cs new file mode 100644 index 000000000000..8685293e1dd2 --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlSessionTest.cs @@ -0,0 +1,145 @@ +// +// Unit tests for NSUrlSession +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlSessionTest { + [Test] + public void CreateDataTaskAsync () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + NSUrlSession session = NSUrlSession.SharedSession; + + var url = new NSUrl ("http://www.xamarin.com"); + var tmpfile = Path.GetTempFileName (); + File.WriteAllText (tmpfile, "TMPFILE"); + var file_url = NSUrl.FromFilename (tmpfile); + var file_data = NSData.FromFile (tmpfile); + var request = new NSUrlRequest (url); + + var completed = false; + var timeout = 30; + + /* CreateDataTask */ + completed = false; + Assert.IsTrue (TestRuntime.RunAsync (DateTime.Now.AddSeconds (timeout), async () => { + await session.CreateDataTaskAsync (request); + completed = true; + }, () => completed), "CreateDataTask a"); + + completed = false; + Assert.IsTrue (TestRuntime.RunAsync (DateTime.Now.AddSeconds (timeout), async () => { + await session.CreateDataTaskAsync (url); + completed = true; + }, () => completed), "CreateDataTask b"); + + /* CreateDownloadTask */ + completed = false; + Assert.IsTrue (TestRuntime.RunAsync (DateTime.Now.AddSeconds (timeout), async () => { + await session.CreateDownloadTaskAsync (request); + completed = true; + }, () => completed), "CreateDownloadTask a"); + + + completed = false; + Assert.IsTrue (TestRuntime.RunAsync (DateTime.Now.AddSeconds (timeout), async () => { + await session.CreateDownloadTaskAsync (url); + completed = true; + }, () => completed), "CreateDownloadTask b"); + + /* CreateUploadTask */ + completed = false; + Assert.IsTrue (TestRuntime.RunAsync (DateTime.Now.AddSeconds (timeout), async () => { + try { + await session.CreateUploadTaskAsync (request, file_url); + } catch /* (Exception ex) */ { +// Console.WriteLine ("Ex: {0}", ex); + } finally { + completed = true; + } + }, () => completed), "CreateUploadTask a"); + + completed = false; + Assert.IsTrue (TestRuntime.RunAsync (DateTime.Now.AddSeconds (timeout), async () => { + try { + await session.CreateUploadTaskAsync (request, file_data); + } catch /* (Exception ex) */ { +// Console.WriteLine ("Ex: {0}", ex); + } finally { + completed = true; + } + }, () => completed), "CreateUploadTask b"); + } + + [Test] + public void DownloadDataAsync () + { + if (!TestRuntime.CheckiOSSystemVersion (7, 0)) + Assert.Inconclusive ("NSUrlSession is iOS7+"); + + bool completed = false; + int failed_iteration = -1; + + TestRuntime.RunAsync (DateTime.Now.AddSeconds (30), async () => { + for (int i = 0; i < 5; i++) { + // Use the default configuration so we can make use of the shared cookie storage. + var session = NSUrlSession.FromConfiguration (NSUrlSessionConfiguration.DefaultSessionConfiguration); + + var downloadUri = new Uri ("https://google.com"); + var downloadResponse = await session.CreateDownloadTaskAsync (downloadUri); + + var tempLocation = downloadResponse.Location; + if (!File.Exists (tempLocation.Path)) { + Console.WriteLine ("#{1} {0} does not exists", tempLocation, i); + failed_iteration = i; + break; + } + } + completed = true; + }, () => completed); + + Assert.AreEqual (-1, failed_iteration, "Failed"); + } + + [Test] + public void SharedSession () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + // in iOS9 those selectors do not respond - but they do work (forwarded to __NSURLSessionLocal type ?) + // * delegateQueue, sessionDescription, setSessionDescription:, delegate + var session = NSUrlSession.SharedSession; + Assert.Null (session.Delegate, "delegate"); + Assert.NotNull (session.DelegateQueue, "delegateQueue"); + Assert.Null (session.SessionDescription, "sessionDescription"); + session.SessionDescription = "descriptive label"; + Assert.That ((string)session.SessionDescription, Is.EqualTo ("descriptive label"), "setSessionDescription:"); + session.SessionDescription = null; // the session instance is global, so revert value to to make sure the test can be re-run successfully. + } + } +} diff --git a/tests/monotouch-test/Foundation/UrlTest.cs b/tests/monotouch-test/Foundation/UrlTest.cs new file mode 100644 index 000000000000..fc739f009d44 --- /dev/null +++ b/tests/monotouch-test/Foundation/UrlTest.cs @@ -0,0 +1,355 @@ +// +// Unit tests for NSUrl +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UrlTest { + + [Test] + public void Fields () + { + // new in 5.1 + if (!TestRuntime.CheckSystemAndSDKVersion (5, 1)) + return; + + Assert.That (NSUrl.IsExcludedFromBackupKey.ToString (), Is.EqualTo ("NSURLIsExcludedFromBackupKey"), "IsExcludedFromBackupKey"); + } + + [Test] + public void IsExcludedFromBackupKey () + { + // new in 5.1 + if (!TestRuntime.CheckSystemAndSDKVersion (5, 1)) + return; + + // NOTE: this test was failing with either NullReferenceException or InvalidCastException + // when we used CFBoolean as a NSObject (i.e. CFBoolean.TrueObject). The test order execution + // was important to track this down + + NSObject value; + Assert.True (NSBundle.MainBundle.ExecutableUrl.TryGetResource (NSUrl.IsExcludedFromBackupKey, out value), "MainBundle"); + Assert.That (value, Is.TypeOf (typeof (NSNumber)), "NSNumber"); + Assert.That ((int) (value as NSNumber), Is.EqualTo (0), "0"); + + string filename = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), "DoNotBackupMe-NSUrl"); + try { + File.WriteAllText (filename, "not worth a bit"); + using (NSUrl url = NSUrl.FromFilename (filename)) { + Assert.True (url.TryGetResource (NSUrl.IsExcludedFromBackupKey, out value)); + Assert.That ((int) (value as NSNumber), Is.EqualTo (0), "DoNotBackupMe-0"); + + url.SetResource (NSUrl.IsExcludedFromBackupKey, (NSNumber) 1); + + Assert.True (url.TryGetResource (NSUrl.IsExcludedFromBackupKey, out value)); + Assert.That ((int) (value as NSNumber), Is.EqualTo (1), "DoNotBackupMe-1"); + + NSError error; + NSDictionary dict = url.GetResourceValues (new NSString [] { NSUrl.IsExcludedFromBackupKey }, out error); + Assert.Null (error, "error"); + Assert.That (dict.Keys [0], Is.EqualTo (NSUrl.IsExcludedFromBackupKey), "Key"); + Assert.That ((int) (dict.Values [0] as NSNumber), Is.EqualTo (1), "Value"); + } + } + finally { + // otherwise the attribute won't reset even if the file is overwritten + File.Delete (filename); + } + } + + const string bad_uri = "http://localhost/page?query={bad}"; + const string good_uri = "http://localhost/page?query=%7Bgood%7D"; + + [Test] + public void FromString () + { + Assert.Null (NSUrl.FromString (bad_uri), "invalid"); + + using (var url = NSUrl.FromString (good_uri)) { + Assert.That (url.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + + Assert.That (url.PathExtension, Is.EqualTo (String.Empty), "PathExtension-1"); + + Assert.NotNull (url.ToString (), "ToString"); // see #4763 + } + + using (var url = NSUrl.FromString ("file.extension")) { + Assert.That (url.PathExtension, Is.EqualTo ("extension"), "PathExtension-2"); + } + } + + [Test] + public void Ctor_string () + { + Assert.Throws (() => new NSUrl (bad_uri), "exception"); + + using (var url = new NSUrl (good_uri)) { + Assert.That (url.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + + [Test] + public void Unicode_6597 () + { + const string bug6597 = "http://www.bing.com/images/search?q=雅詩蘭黛"; + + // does not work - From* static methods returns null for invalid URL + Assert.Null (NSUrl.FromString (bug6597), "1"); + + // does not work - handle is null (as a .NET .ctor can't return null like ObjC init can do) + Assert.Throws (() => new NSUrl (bug6597), "exception"); + + // works + using (var s = new NSString (bug6597)) + using (var url3 = NSUrl.FromObject (s)) { + Assert.That (url3.Handle, Is.Not.EqualTo (IntPtr.Zero), "3"); + Assert.That (url3.ToString (), Is.EqualTo (bug6597), "ToString"); + } + } + + [Test] + public void Bug13069 () + { + string url = "http://username:password@google.com:8080/path?query=value.ext"; + var uri = new Uri (url); + Assert.That (url.ToString (), Is.EqualTo (url), "Uri.ToString"); + var ns1 = (NSUrl) uri; + Assert.That (ns1.ToString (), Is.EqualTo (url), "implicit NSUrl.ToString"); + var ns2 = new NSUrl (uri.ToString ()); + Assert.That (ns2.ToString (), Is.EqualTo (url), "created NSUrl.ToString"); + } + + [Test] + public void InitWithSpaces () + { + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=14307 + // note: add space in file name - otherwise there was no space in the file on devices + // device: /var/mobile/Applications/2042876B-F875-4A67-94EE-286B6A81FDCF/monotouchtest.app/Hand.wav + // simulator: /Users/poupou/Library/Application Support/iPhone Simulator/6.0/Applications/DCFB542F-1D37-4ADC-9046-BB0D26ABB3A3/monotouchtest.app + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "Hand Left.wav"); + + // initWithString: will fail with spaces + Assert.Throws (() => new NSUrl (file), "1"); + + using (var url2 = new NSUrl (file, false)) { + // initFileURLWithPath:isDirectory: will always works (both sim or devices) + Assert.That (url2.Handle, Is.Not.EqualTo (IntPtr.Zero), "2"); + } + } + + [Test] + public void Copy () + { + using (var url = NSUrl.FromString ("http://www.xamarin.com")) { + // NSObject.Copy works because NSUrl conforms to NSCopying + using (var copy = (NSUrl)url.Copy ()) { + Assert.That (copy.AbsoluteString, Is.EqualTo ("http://www.xamarin.com"), "AbsoluteString"); + } + } + } + + [Test] + public void MutableCopy () + { + using (var url = NSUrl.FromString ("http://www.xamarin.com")) { + // NSObject.MutableCopy does NOT works because NSUrl does NOT conforms to NSMutableCopying + Assert.Throws (delegate { + url.MutableCopy (); + }, "MutableCopy"); + } + } + + [Test] + public void Equals () + { + using (var url1 = NSUrl.FromString ("http://www.xamarin.com/ios")) + using (var url2 = NSUrl.FromString ("http://www.xamarin.com")) + using (var url3 = new NSUrl ("http://www.xamarin.com")) { + Assert.That (url1.GetHashCode (), Is.Not.EqualTo (url2.GetHashCode ()), "GetHashCode 1-2"); + // created differently but still identical + Assert.That (url2.GetHashCode (), Is.EqualTo (url3.GetHashCode ()), "GetHashCode 2-3"); + + // NSObject + Assert.False (url1.Equals ((NSObject) url2), "Equals(NSObject) 1-2"); + Assert.True (url2.Equals ((NSObject) url3), "Equals(NSObject) 2-3"); + Assert.False (url1.Equals ((NSObject) null), "Equals(NSObject) null"); + + // NSUrl / IEquatable + Assert.False (url1.Equals (url2), "Equals(NSUrl) 1-2"); + Assert.True (url2.Equals (url3), "Equals(NSUrl) 2-3"); + Assert.False (url1.Equals ((NSUrl) null), "Equals(NSUrl) null"); + } + } + + class BadCustomUrl : NSUrl { + + public BadCustomUrl (string url) : base (url) + { + Comment = "Bad"; + } + + public string Comment { get; set; } + + public bool DirectBinding { + get { return IsDirectBinding; } + } + } + + class GoodCustomUrl : NSUrl { + + public GoodCustomUrl (string url) : base (url) + { + Comment = "Good"; + } + + public string Comment { get; set; } + + public bool DirectBinding { + get { return IsDirectBinding; } + } + + public override int GetHashCode () + { + return base.GetHashCode () ^ Comment.GetHashCode (); + } + + public override bool Equals (object t) + { + var url = (t as GoodCustomUrl); + if (url == null) + return false; + return base.Equals (t) && Comment == url.Comment; + } + } + + [Test] + public void SubclassEquality () + { + using (var url1 = NSUrl.FromString ("http://www.xamarin.com")) + using (var url2 = new BadCustomUrl ("http://www.xamarin.com")) + using (var url3 = new GoodCustomUrl ("http://www.xamarin.com")) { +#if XAMCORE_2_0 + // for compatibility only unified has the correct behavior + Assert.That (url1.GetHashCode (), Is.Not.EqualTo (url2.GetHashCode ()), "GetHashCode 1-2"); +#else + // state is ignored in classic + Assert.That (url1.GetHashCode (), Is.EqualTo (url2.GetHashCode ()), "GetHashCode 1-2"); +#endif + Assert.That (url2.GetHashCode (), Is.Not.EqualTo (url3.GetHashCode ()), "GetHashCode 2-3"); + + Assert.False (url2.DirectBinding, "DirectBinding 2"); + Assert.False (url3.DirectBinding, "DirectBinding 3"); + Assert.That (url2.GetHashCode (), Is.Not.EqualTo (url3.GetHashCode ()), "GetHashCode 2-3"); + + // NSObject +#if XAMCORE_2_0 + // for compatibility only unified has the correct behavior + Assert.False (url1.Equals ((NSObject) url2), "Equals(NSObject) 1-2"); + Assert.False (url2.Equals ((NSObject) url3), "Equals(NSObject) 2-3"); +#else + // state is ignored in classic + Assert.True (url1.Equals ((NSObject) url2), "Equals(NSObject) 1-2"); + Assert.True (url2.Equals ((NSObject) url3), "Equals(NSObject) 2-3"); +#endif + + // NSUrl / IEquatable +#if XAMCORE_2_0 + // for compatibility only unified has the correct behavior + Assert.False (url1.Equals (url2), "Equals(NSUrl) 1-2"); + Assert.False (url2.Equals (url3), "Equals(NSUrl) 2-3"); +#else + // otherwise it's ObjC comparing the URL string + Assert.True (url1.Equals (url2), "Equals(NSUrl) 1-2"); + Assert.True (url2.Equals (url3), "Equals(NSUrl) 2-3"); +#endif + + // System.Object +#if XAMCORE_2_0 + // for compatibility only unified has the correct behavior + Assert.False (url1.Equals ((object) url2), "Equals(object) 1-2"); + Assert.False (url2.Equals ((object) url3), "Equals(object) 2-3"); +#else + // state is ignored in classic + Assert.True (url1.Equals ((object) url2), "Equals(object) 1-2"); + Assert.True (url2.Equals ((object) url3), "Equals(object) 2-3"); +#endif + } + } + + [Test] + public void Invalid_29510 () + { + string bad = "Server 1/Custom View/Analog Schedule!@#$%^&&%$#@"; + + string bad_url = Uri.EscapeUriString (bad); + Assert.Null (NSUrl.FromString (bad_url), "bad"); + + string converted = ((NSString) bad).CreateStringByAddingPercentEscapes (NSStringEncoding.UTF8); + using (var url = NSUrl.FromString (converted)) { + Assert.That (url.AbsoluteString, Is.EqualTo ("Server%201/Custom%20View/Analog%20Schedule!@%23$%25%5E&&%25$%23@"), "good"); + } + } + + [Test] + public void TestEqualOperatorSameInstace () + { + using (var url = NSUrl.FromString ("http://www.xamarin.com")) + Assert.IsTrue (url == url); + + } + + [Test] + public void TestEqualOperatorNull () + { + using (var url = NSUrl.FromString ("http://www.xamarin.com")) { + Assert.IsFalse (url == null, "url == null"); + Assert.IsFalse (null == true, "null == url"); + } + } + + [Test] + public void TestEqualOperator () + { + using (var url1 = NSUrl.FromString ("http://www.xamarin.com")) + using (var url2 = NSUrl.FromString ("http://www.xamarin.com/foo")) + Assert.AreEqual (url1 == url2, url1.IsEqual (url2)); + } + + [Test] + public void TestNotEqualOperatorNull () + { + using (var url = NSUrl.FromString ("http://www.xamarin.com")) { + Assert.IsTrue (url != null, "url != null"); + Assert.IsTrue (null != url, "null != url"); + } + } + + [Test] + public void TestNotEqualOperator () + { + using (var url1 = NSUrl.FromString ("http://www.xamarin.com")) + using (var url2 = NSUrl.FromString ("http://www.xamarin.com/foo")) + Assert.AreEqual (url1 != url2, !url1.IsEqual (url2)); + } + } +} diff --git a/tests/monotouch-test/Foundation/UserDefaultsTest.cs b/tests/monotouch-test/Foundation/UserDefaultsTest.cs new file mode 100644 index 000000000000..caaf79c0121d --- /dev/null +++ b/tests/monotouch-test/Foundation/UserDefaultsTest.cs @@ -0,0 +1,82 @@ +// +// Unit tests for NSUserDefaults +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UserDefaultsTest { + + [Test] + public void SetString () + { + // confusing API for .NET developers since the parameters are 'value', 'key' + // http://stackoverflow.com/q/12415054/220643 + NSUserDefaults defaults = NSUserDefaults.StandardUserDefaults; + defaults.RemoveObject ("spid"); + Assert.Null (defaults.StringForKey ("spid"), "StringForKey-1"); + defaults.SetString ("coucou", "spid"); + defaults.Synchronize (); + Assert.That (defaults.StringForKey ("spid"), Is.EqualTo ("coucou"), "StringForKey-2"); + } + + [Test] + public void Ctor_UserName () + { + // initWithUser: + using (var ud = new NSUserDefaults ("username")) { + Assert.That (ud.RetainCount, Is.EqualTo ((nint) 1), "RetainCount"); + ud.SetString ("value", "key"); + ud.Synchronize (); + } + + using (var ud = new NSUserDefaults ("username", NSUserDefaultsType.UserName)) { + Assert.That (ud.RetainCount, Is.EqualTo ((nint) 1), "RetainCount"); + Assert.That (ud ["key"].ToString (), Is.EqualTo ("value"), "[key]-1"); + ud.RemoveObject ("key"); + ud.Synchronize (); + Assert.Null (ud ["key"], "[key]-2"); + } + } + + [Test] + public void Ctor_SuiteName () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS7"); + + // initWithSuiteName: + using (var ud = new NSUserDefaults ("suitename", NSUserDefaultsType.SuiteName)) { + Assert.That (ud.RetainCount, Is.EqualTo ((nint) 1), "RetainCount"); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/UuidTest.cs b/tests/monotouch-test/Foundation/UuidTest.cs new file mode 100644 index 000000000000..21d04be6ee33 --- /dev/null +++ b/tests/monotouch-test/Foundation/UuidTest.cs @@ -0,0 +1,70 @@ +// +// Unit tests for NSUuid +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UuidTest { + + [Test] + public void Constructors () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("NSUUID is new in 6.0"); + + var uuid = new NSUuid (new byte [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }); + Assert.That (uuid, Is.Not.EqualTo (null), "constructed"); + + var bytes = uuid.GetBytes (); + Assert.That (bytes.Length, Is.EqualTo (16), "lenght"); + + for (int i = 0; i < 16; i++) + Assert.That (bytes [i], Is.EqualTo (i), "value " + i); + } + + [Test] + public void ConstructorFailures () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("NSUUID is new in 6.0"); + + try { + var uuid = new NSUuid ((byte[]) null); + Assert.Fail ("Should have t;hrown an exception"); + } catch (ArgumentNullException) { + // good + } catch (Exception e){ + Assert.Fail ("Unexpected exception {0}", e); + } + + try { + var uuid = new NSUuid (new byte [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }); + Assert.Fail ("Should have thrown an ArgumentException"); + } catch (ArgumentException){ + // ok + } catch (Exception e){ + Assert.Fail ("Expected an ArgumentException {0}", e); + } + } + } +} diff --git a/tests/monotouch-test/Foundation/ZoneTest.cs b/tests/monotouch-test/Foundation/ZoneTest.cs new file mode 100644 index 000000000000..53b310f7c651 --- /dev/null +++ b/tests/monotouch-test/Foundation/ZoneTest.cs @@ -0,0 +1,39 @@ +// +// Unit tests for NSZone +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Foundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ZoneTest { + + [Test] + public void Default () + { + var z = NSZone.Default; + Assert.That (z.Handle, Is.Not.EqualTo (IntPtr.Zero), "Default"); + Assert.That (z.Name, Is.EqualTo ("DefaultMallocZone"), "Name"); + + z.Name = "default"; + Assert.That (z.Name, Is.EqualTo ("default"), "Name-modified"); + + // in case the test is executed more than once + z.Name = "DefaultMallocZone"; + } + } +} diff --git a/tests/monotouch-test/GLKit/BaseEffectTest.cs b/tests/monotouch-test/GLKit/BaseEffectTest.cs new file mode 100644 index 000000000000..bb9a5f97ef47 --- /dev/null +++ b/tests/monotouch-test/GLKit/BaseEffectTest.cs @@ -0,0 +1,43 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using GLKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GLKit; +#endif +using OpenTK; +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.GLKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BaseEffectTest { + + [Test] + [Culture ("en")] + public void Properties () + { + var effect = new GLKBaseEffect (); + Assert.That (effect.LightModelAmbientColor.ToString (), Is.EqualTo ("(0.2, 0.2, 0.2, 1)"), "LightModelAmbientColor"); + Assert.That (effect.ConstantColor.ToString (), Is.EqualTo ("(1, 1, 1, 1)"), "ConstantColor"); + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GLKit/EffectPropertyFog.cs b/tests/monotouch-test/GLKit/EffectPropertyFog.cs new file mode 100644 index 000000000000..bd48624d7b62 --- /dev/null +++ b/tests/monotouch-test/GLKit/EffectPropertyFog.cs @@ -0,0 +1,35 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using GLKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GLKit; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.GLKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EffectPropertyFogTest { + + [Test] + public void Properties () + { + var fog = new GLKEffectPropertyFog (); + Assert.That (fog.Color.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "Color"); + + fog = new GLKBaseEffect ().Fog; + Assert.That (fog.Color.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "Color"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GLKit/EffectPropertyLightTest.cs b/tests/monotouch-test/GLKit/EffectPropertyLightTest.cs new file mode 100644 index 000000000000..d6cdd647c78e --- /dev/null +++ b/tests/monotouch-test/GLKit/EffectPropertyLightTest.cs @@ -0,0 +1,41 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using GLKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GLKit; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.GLKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EffectPropertyLightTest { + + [Test] + public void Properties () + { + var light = new GLKEffectPropertyLight (); + Assert.That (light.AmbientColor.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "AmbientColor"); + Assert.That (light.DiffuseColor.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "DiffuseColor"); + Assert.That (light.SpecularColor.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "SpecularColor"); + Assert.That (light.Position.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "Position"); + + light = new GLKBaseEffect ().Light0; + Assert.That (light.AmbientColor.ToString (), Is.EqualTo ("(0, 0, 0, 1)"), "AmbientColor"); + Assert.That (light.DiffuseColor.ToString (), Is.EqualTo ("(1, 1, 1, 1)"), "DiffuseColor"); + Assert.That (light.SpecularColor.ToString (), Is.EqualTo ("(1, 1, 1, 1)"), "SpecularColor"); + Assert.That (light.Position.ToString (), Is.EqualTo ("(0, 0, 1, 0)"), "Position"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GLKit/EffectPropertyMaterialTest.cs b/tests/monotouch-test/GLKit/EffectPropertyMaterialTest.cs new file mode 100644 index 000000000000..0ce38f1856d1 --- /dev/null +++ b/tests/monotouch-test/GLKit/EffectPropertyMaterialTest.cs @@ -0,0 +1,42 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using GLKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GLKit; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.GLKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EffectPropertytMaterialTest { + + [Test] + [Culture ("en")] + public void Properties () + { + var material = new GLKEffectPropertyMaterial (); + Assert.That (material.AmbientColor.ToString (), Is.EqualTo ("(0.2, 0.2, 0.2, 1)"), "AmbientColor"); + Assert.That (material.DiffuseColor.ToString (), Is.EqualTo ("(0.8, 0.8, 0.8, 1)"), "DiffuseColor"); + Assert.That (material.SpecularColor.ToString (), Is.EqualTo ("(0, 0, 0, 1)"), "SpecularColor"); + Assert.That (material.EmissiveColor.ToString (), Is.EqualTo ("(0, 0, 0, 1)"), "EmissiveColor"); + + material = new GLKBaseEffect ().Material; + Assert.That (material.AmbientColor.ToString (), Is.EqualTo ("(0.2, 0.2, 0.2, 1)"), "AmbientColor"); + Assert.That (material.DiffuseColor.ToString (), Is.EqualTo ("(0.8, 0.8, 0.8, 1)"), "DiffuseColor"); + Assert.That (material.SpecularColor.ToString (), Is.EqualTo ("(0, 0, 0, 1)"), "SpecularColor"); + Assert.That (material.EmissiveColor.ToString (), Is.EqualTo ("(0, 0, 0, 1)"), "EmissiveColor"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GLKit/EffectPropertyTransformTest.cs b/tests/monotouch-test/GLKit/EffectPropertyTransformTest.cs new file mode 100644 index 000000000000..24e20fbb68f2 --- /dev/null +++ b/tests/monotouch-test/GLKit/EffectPropertyTransformTest.cs @@ -0,0 +1,39 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using GLKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GLKit; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.GLKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EffectPropertytTransformTest { + + [Test] + public void Properties () + { + var transform = new GLKEffectPropertyTransform (); + Assert.That (transform.ModelViewMatrix.ToString (), Is.EqualTo ("(1, 0, 0, 0)\n(0, 1, 0, 0)\n(0, 0, 1, 0)\n(0, 0, 0, 1)"), "ModelViewMatrix"); + Assert.That (transform.ProjectionMatrix.ToString (), Is.EqualTo ("(1, 0, 0, 0)\n(0, 1, 0, 0)\n(0, 0, 1, 0)\n(0, 0, 0, 1)"), "ProjectionMatrix"); + // Is TextureMatrix supposed to be here? I can't find it in apple's docs, and it throws a selector not found exception + // Assert.That (transform.TextureMatrix.ToString (), Is.EqualTo ("(0, 0, 0, 0)"), "TextureMatrix"); + + transform = new GLKBaseEffect ().Transform; + Assert.That (transform.ModelViewMatrix.ToString (), Is.EqualTo ("(1, 0, 0, 0)\n(0, 1, 0, 0)\n(0, 0, 1, 0)\n(0, 0, 0, 1)"), "ModelViewMatrix"); + Assert.That (transform.ProjectionMatrix.ToString (), Is.EqualTo ("(1, 0, 0, 0)\n(0, 1, 0, 0)\n(0, 0, 1, 0)\n(0, 0, 0, 1)"), "ProjectionMatrix"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GLKit/KViewTest.cs b/tests/monotouch-test/GLKit/KViewTest.cs new file mode 100644 index 000000000000..15bf94e9d9df --- /dev/null +++ b/tests/monotouch-test/GLKit/KViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using GLKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GLKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.GLKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class KViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (GLKView glkv = new GLKView (frame)) { + Assert.That (glkv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GameController/ExtendedGamepadSnapshotTest.cs b/tests/monotouch-test/GameController/ExtendedGamepadSnapshotTest.cs new file mode 100644 index 000000000000..e9d92125b2e8 --- /dev/null +++ b/tests/monotouch-test/GameController/ExtendedGamepadSnapshotTest.cs @@ -0,0 +1,54 @@ +// +// Unit tests for GCExtendedGamepadSnapshot +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using GameController; +#else +using MonoTouch.Foundation; +using MonoTouch.GameController; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameController { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ExtendedGamepadSnapshotTest { + + [Test] + public void Nullability () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) + Assert.Inconclusive ("GameController is iOS7+"); + + GCExtendedGamepadSnapShotDataV100 data; + Assert.False (GCExtendedGamepadSnapshot.TryGetSnapShotData (null, out data), "TryGetSnapshotData"); + Assert.True (data.Version == 0, "Version"); + Assert.True (data.Size == 0, "Size"); + + data = new GCExtendedGamepadSnapShotDataV100 (); + Assert.True (data.Version == 0, "Version-2"); + Assert.True (data.Size == 0, "Size-2"); + + using (var nsd = data.ToNSData ()) { + Assert.True (GCExtendedGamepadSnapshot.TryGetSnapShotData (nsd, out data), "TryGetSnapshotData-2"); + Assert.True (data.Version == 0x100, "Version-3"); + Assert.True (data.Size == nsd.Length, "Size-3"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GameController/GamepadSnapshotTest.cs b/tests/monotouch-test/GameController/GamepadSnapshotTest.cs new file mode 100644 index 000000000000..f727018d480b --- /dev/null +++ b/tests/monotouch-test/GameController/GamepadSnapshotTest.cs @@ -0,0 +1,54 @@ +// +// Unit tests for GCGamepadSnapshot +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using GameController; +#else +using MonoTouch.Foundation; +using MonoTouch.GameController; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameController { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GamepadSnapshotTest { + + [Test] + public void Nullability () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) + Assert.Inconclusive ("GameController is iOS7+"); + + GCGamepadSnapShotDataV100 data; + Assert.False (GCGamepadSnapshot.TryGetSnapshotData (null, out data), "TryGetSnapshotData"); + Assert.True (data.Version == 0, "Version"); + Assert.True (data.Size == 0, "Size"); + + data = new GCGamepadSnapShotDataV100 (); + Assert.True (data.Version == 0, "Version-2"); + Assert.True (data.Size == 0, "Size-2"); + + using (var nsd = data.ToNSData ()) { + Assert.True (GCGamepadSnapshot.TryGetSnapshotData (nsd, out data), "TryGetSnapshotData-2"); + Assert.True (data.Version == 0x100, "Version-3"); + Assert.True (data.Size == nsd.Length, "Size-3"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GameKit/LeaderboardTest.cs b/tests/monotouch-test/GameKit/LeaderboardTest.cs new file mode 100644 index 000000000000..8910bea96594 --- /dev/null +++ b/tests/monotouch-test/GameKit/LeaderboardTest.cs @@ -0,0 +1,82 @@ +// +// Unit tests for GKLeaderboard +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using GameKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.GameKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LeaderboardTest { + + void Check (GKLeaderboard lb) + { +#if !__TVOS__ + Assert.Null (lb.Category, "Category"); +#endif + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + Assert.Null (lb.GroupIdentifier, "GroupIdentifier"); + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Null (lb.Identifier, "Identifier"); + } + Assert.Null (lb.LocalPlayerScore, "LocalPlayerScore"); + Assert.That (lb.MaxRange, Is.EqualTo ((nint) 0), "MaxRange"); + Assert.That (lb.PlayerScope, Is.EqualTo (GKLeaderboardPlayerScope.Global), "PlayerScope"); + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + // depending on the ctor 1,10 (or 0,0) is returned before iOS7 - but 1,25 is documented (in iOS7) + Assert.That (lb.Range.Location, Is.EqualTo ((nint) 1), "Range.Location"); + Assert.That (lb.Range.Length, Is.EqualTo ((nint) 25), "Range.Length"); + } + Assert.Null (lb.Scores, "Scores"); + Assert.That (lb.TimeScope, Is.EqualTo (GKLeaderboardTimeScope.AllTime), "TimeScope"); + Assert.Null (lb.Title, "Title"); + } + + [Test] + public void DefaultCtor () + { + using (var lb = new GKLeaderboard ()) { + Check (lb); + } + } + + [Test] + public void PlayersCtor () + { + // note: Mavericks does not like (respond to) this selector - but it did work with ML and is documented + using (var lb = new GKLeaderboard (new string [0])) { + Check (lb); + } + } + } +} + +#endif // !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/GameKit/LeaderboardViewControllerTest.cs b/tests/monotouch-test/GameKit/LeaderboardViewControllerTest.cs new file mode 100644 index 000000000000..552b2839777e --- /dev/null +++ b/tests/monotouch-test/GameKit/LeaderboardViewControllerTest.cs @@ -0,0 +1,71 @@ +// +// Unit tests for GKLeaderboardViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using GameKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LeaderboardViewControllerTest { + + [Test] + public void DefaultCtor () + { + // because of the inheritance changes in GameKit running this on iOS 5.1 and the new registrar gives an: + // MonoTouch.MonoTouchException> (Wrapper type 'MonoTouch.GameKit.GKGameCenterViewController' is missing its native ObjectiveC class 'GKGameCenterViewController'.) + // ref: https://trello.com/c/OOlimcfJ/230-changing-objc-base-class-can-be-a-breaking-change + if (!TestRuntime.CheckSystemAndSDKVersion (6, 0)) + Assert.Ignore ("Can't run before iOS 6 with the new registrar enabled"); + + using (var vc = new GKLeaderboardViewController ()) { + Assert.Null (vc.Category, "Category"); + Assert.Null (vc.Delegate, "Delegate"); + // default Scope vary by iOS version and can't be changed on iOS7 - not worth testing + } + } + + [Test] + public void CustomCtor () + { + // because of the inheritance changes in GameKit running this on iOS 5.1 and the new registrar gives an: + // MonoTouch.MonoTouchException> (Wrapper type 'MonoTouch.GameKit.GKGameCenterViewController' is missing its native ObjectiveC class 'GKGameCenterViewController'.) + // ref: https://trello.com/c/OOlimcfJ/230-changing-objc-base-class-can-be-a-breaking-change + if (!TestRuntime.CheckSystemAndSDKVersion (6, 0)) + Assert.Ignore ("Can't run before iOS 6 with the new registrar enabled"); + +#if !XAMCORE_2_0 + // initWithTimeScope:playerScope: does not exists - Apple only list it in iOS4 API diff but it's neither + // * in the web site documentation; + // * in the header files + // * a selector that respond on iOS or OSX + // -[GKLeaderboardViewController initWithTimeScope:playerScope:]: unrecognized selector sent to instance 0x150f7220 + Assert.Throws (delegate { + new GKLeaderboardViewController (GKLeaderboardTimeScope.Week, GKLeaderboardPlayerScope.Global); + }); +#endif + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/GameKit/NotificationBannerTest.cs b/tests/monotouch-test/GameKit/NotificationBannerTest.cs new file mode 100644 index 000000000000..6325c2121078 --- /dev/null +++ b/tests/monotouch-test/GameKit/NotificationBannerTest.cs @@ -0,0 +1,38 @@ +// +// Unit tests for GKNotificationBanner +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012,2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using GameKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NotificationBannerTest { + + [Test] + public void Show_NSAction_Null () + { + // Once upon a time (circa 2012) using null for the action would have crashed the application + // but it's not the case anymore (in 2015 / iOS9) and the header files says it's nullable + GKNotificationBanner.Show ("title", "message", null); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GameKit/ScoreTest.cs b/tests/monotouch-test/GameKit/ScoreTest.cs new file mode 100644 index 000000000000..9e93caeea28a --- /dev/null +++ b/tests/monotouch-test/GameKit/ScoreTest.cs @@ -0,0 +1,72 @@ +// +// Unit tests for GKScore +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using GameKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.GameKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ScoreTest { + + [Test] + public void Ctor_String () + { + // Apple deprecated `initWithCategory:` for `initWithLeaderboardIdentifier:` which *seems* to do the + // same thing, only with new names - but we need to be sure since 7.0 will map the .ctor(string) API + // to the new selector + using (var s = new GKScore ("category-or-identifier")) { +#if !__TVOS__ + Assert.That (s.Category, Is.EqualTo ("category-or-identifier"), "Category"); +#endif + Assert.That (s.Context, Is.EqualTo (0), "Context"); + Assert.NotNull (s.Date, "Date"); + Assert.Null (s.FormattedValue, "FormattedValue"); + + // this is a new API in iOS8 (it was private before that) and returned an empty instance like: + // "<(playerID:(null) alias:(null) name:(null) status:(null))>" + if (TestRuntime.CheckSystemAndSDKVersion (8, 0)) { + Assert.Null (s.Player, "Player"); + } + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + Assert.That (s.LeaderboardIdentifier, Is.EqualTo ("category-or-identifier"), "LeaderboardIdentifier"); + } + + Assert.That (s.RetainCount, Is.EqualTo ((nint) 1), "RetainCount"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GameKit/SessionTest.cs b/tests/monotouch-test/GameKit/SessionTest.cs new file mode 100644 index 000000000000..5464f78a7325 --- /dev/null +++ b/tests/monotouch-test/GameKit/SessionTest.cs @@ -0,0 +1,42 @@ +// +// Unit tests for GKSession +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using GameKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SessionTest { + + [Test] + public void NullAllowed () + { + using (var session = new GKSession (null, "displayName", GKSessionMode.Client)) { + } + + using (var session = new GKSession ("sessionID", null, GKSessionMode.Peer)) { + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKComponentSystemTests.cs b/tests/monotouch-test/GameplayKit/GKComponentSystemTests.cs new file mode 100644 index 000000000000..f75fd4e78b8a --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKComponentSystemTests.cs @@ -0,0 +1,80 @@ +// +// Unit tests for GKComponentSystem +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ +#if XAMCORE_2_0 // The GKComponentSystem framework is Unified only + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GamePlayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKComponentSystemTests { + + [SetUp] + public void Setup () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + } + + [Test] + public void InitWithComponentClassType () + { + var componentSystem = new GKComponentSystem (); + Assert.NotNull (componentSystem, "GKComponentSystem type ctor must not be null"); + Assert.AreEqual (typeof(MySubcomponent), componentSystem.ComponentType); + } + + [Test] + public void IndexerTest () + { + var componentSystem = new GKComponentSystem (); + Assert.NotNull (componentSystem, "GKComponentSystem type ctor must not be null"); + Assert.AreEqual (typeof(MySubcomponent), componentSystem.ComponentType); + + componentSystem.AddComponent (new MySubcomponent (0)); + componentSystem.AddComponent (new MySubcomponent (1)); + componentSystem.AddComponent (new MySubcomponent (2)); + + Assert.IsTrue (componentSystem.Components.Length == 3, "componentSystem.Components must be 3"); + var secondComponent = componentSystem [1] as MySubcomponent; + Assert.NotNull (secondComponent, "secondComponent must not be null"); + Assert.IsTrue (secondComponent.Id == 1, "secondComponent.Id must be 1"); + } + } + + [Preserve (AllMembers = true)] + class MySubcomponent : GKComponent { + + public int Id { get; private set; } + + public MySubcomponent (int id) + { + Id = id; + } + + public MySubcomponent (IntPtr handle) : base (handle) { } + } +} + +#endif // XAMCORE_2_0 +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKEntityTests.cs b/tests/monotouch-test/GameplayKit/GKEntityTests.cs new file mode 100644 index 000000000000..0d691084238a --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKEntityTests.cs @@ -0,0 +1,104 @@ +// +// Unit tests for GKEntity +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GamePlayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKEntityTests { + + [Test] + public void GetAndRemoveTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var entity = GKEntity.GetEntity (); + entity.AddComponent (new NumberComponent (10)); + entity.AddComponent (new NameComponent ("Ten")); + Assert.IsTrue (entity.Components.Length == 2, "entity.Components length must be 2"); + + // Test component retrieval by type + var component = entity.GetComponent (typeof(NumberComponent)) as NumberComponent; + Assert.NotNull (component, "Component must not be null"); + Assert.IsTrue (component.Id == 10, "Component Id must be 10"); + + // Test component removal by type + Assert.NotNull (entity.GetComponent (typeof (NameComponent)), "Component typeof NameComponent must not be null"); + entity.RemoveComponent (typeof(NameComponent)); + Assert.IsTrue (entity.Components.Length == 1, "entity.Components length must be 1"); + Assert.IsNull (entity.GetComponent (typeof (NameComponent)), "Component typeof NameComponent must be null"); + } + + [ExpectedException (typeof (ArgumentNullException))] + [Test] + public void BadGetComponent () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var entity = GKEntity.GetEntity (); + entity.GetComponent (null); + } + + [ExpectedException (typeof (ArgumentNullException))] + [Test] + public void BadRemoval () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var entity = GKEntity.GetEntity (); + entity.RemoveComponent (null); + } + } + + [Preserve (AllMembers = true)] + class NameComponent : GKComponent { + + public string Name { get; private set; } + + public NameComponent (string name) + { + Name = name; + } + + public NameComponent (IntPtr handle) : base (handle) { } + } + + [Preserve (AllMembers = true)] + class NumberComponent : GKComponent { + + public int Id { get; private set; } + + public NumberComponent (int id) + { + Id = id;; + } + + public NumberComponent (IntPtr handle) : base (handle) { } + } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKGridGraphTests.cs b/tests/monotouch-test/GameplayKit/GKGridGraphTests.cs new file mode 100644 index 000000000000..973c0b7ce30f --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKGridGraphTests.cs @@ -0,0 +1,142 @@ +// +// Unit tests for GKGridGraph +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GamePlayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKGridGraphTests { + + enum TileType { + Open, + Wall, + Portal, + Start + } + + int[] maze = { + 1,1,1,1,1,1,1,1,1,1, + 1,3,0,0,1,1,1,1,1,1, + 1,0,1,0,2,0,0,0,0,1, + 1,0,1,1,1,1,1,1,0,1, + 1,0,1,0,2,0,0,0,0,1, + 1,0,1,0,1,1,1,1,1,1, + 1,0,1,0,2,0,0,0,0,1, + 1,0,1,1,1,1,1,1,0,1, + 1,0,0,0,2,0,0,0,0,1, + 1,1,1,1,1,1,1,1,1,1, + }; + + [Test] + public void FromGridStartingAtTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var graph = GKGridGraph.FromGridStartingAt (Vector2i.Zero, 10, 10, false); + Assert.NotNull (graph, "GKGridGraph.FromGridStartingAt should not be null"); + + var walls = new List (10 * 10); + var spawnPoints = new List (); + GKGridGraphNode startPosition = null; + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + var tile = maze[i * 10 + j]; + switch ((TileType)tile) { + case TileType.Wall: + walls.Add (graph.GetNodeAt (new Vector2i (i, j))); + break; + case TileType.Portal: + spawnPoints.Add (graph.GetNodeAt (new Vector2i (i, j))); + break; + case TileType.Start: + startPosition = graph.GetNodeAt (new Vector2i (i, j)); + break; + default: + break; + } + } + } + + // increasing min required version due to in 9.2 we get a crash from GameplayKit + // pretty similar to this report on stackoverflow, this does not happen on 9.3 + // http://stackoverflow.com/questions/35811432/gameplaykit-gkgraph-dealloc-crash-on-ios9-2 + if (TestRuntime.CheckSystemAndSDKVersion (9, 3)) + graph.RemoveNodes (walls.ToArray ()); + + Assert.NotNull (startPosition, "startPosition must not be null"); + Assert.AreEqual (new Vector2i (1, 1), startPosition.GridPosition, "GridPosition must be (1,1)"); + Assert.That (walls.Count > 0, "walls list must be higher than zero"); + Assert.That (spawnPoints.Count > 0, "spawnPoints list must be higher than zero"); + } + + [Test] + public void InitFromGridStartingAtTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var graph = new GKGridGraph (Vector2i.Zero, 10, 10, false); + Assert.NotNull (graph, "GKGridGraph.FromGridStartingAt should not be null"); + + var walls = new List (10 * 10); + var spawnPoints = new List (); + GKGridGraphNode startPosition = null; + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + var tile = maze[i * 10 + j]; + switch ((TileType)tile) { + case TileType.Wall: + walls.Add (graph.GetNodeAt (new Vector2i (i, j))); + break; + case TileType.Portal: + spawnPoints.Add (graph.GetNodeAt (new Vector2i (i, j))); + break; + case TileType.Start: + startPosition = graph.GetNodeAt (new Vector2i (i, j)); + break; + default: + break; + } + } + } + + // increasing min required version due to in 9.2 we get a crash from GameplayKit + // pretty similar to this report on stackoverflow, this does not happen on 9.3 + // http://stackoverflow.com/questions/35811432/gameplaykit-gkgraph-dealloc-crash-on-ios9-2 + if (TestRuntime.CheckSystemAndSDKVersion (9, 3)) + graph.RemoveNodes (walls.ToArray ()); + + Assert.NotNull (startPosition, "startPosition must not be null"); + Assert.AreEqual (new Vector2i (1,1), startPosition.GridPosition, "GridPosition must be (1,1)"); + Assert.That (walls.Count > 0, "walls list must be higher than zero"); + Assert.That (spawnPoints.Count > 0, "spawnPoints list must be higher than zero"); + } + } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKPathTests.cs b/tests/monotouch-test/GameplayKit/GKPathTests.cs new file mode 100644 index 000000000000..1b70d1a295e9 --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKPathTests.cs @@ -0,0 +1,58 @@ +// +// Unit tests for GKPath +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GamePlayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKPathTests { + + Vector2[] points = new Vector2[] { + new Vector2 (0,0), new Vector2 (0,1), new Vector2 (0,2), new Vector2 (0,3), + new Vector2 (1,3), new Vector2 (1,2), new Vector2 (1,1), new Vector2 (1,0) + }; + + [Test] + public void FromPointsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var path = GKPath.FromPoints (points, 1, false); + Assert.NotNull (path, "GKPath.FromPoints should not be null"); + } + + [Test] + public void InitWithPointsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var path = new GKPath (points, 1, false); + Assert.NotNull (path, "GKPath.FromPoints should not be null"); + } + } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKPolygonObstacleTests.cs b/tests/monotouch-test/GameplayKit/GKPolygonObstacleTests.cs new file mode 100644 index 000000000000..3e6446a0e81b --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKPolygonObstacleTests.cs @@ -0,0 +1,71 @@ +// +// Unit tests for GKPolygonObstacle +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +using nuint = System.UInt32; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GamePlayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKPolygonObstacleTests { + + Vector2[] points = new Vector2[] { + new Vector2 (0,0), new Vector2 (0,1), new Vector2 (0,2), new Vector2 (0,3), + new Vector2 (1,0), new Vector2 (1,1), new Vector2 (1,2), new Vector2 (1,3) + }; + + [Test] + public void FromPointsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var obstacle = GKPolygonObstacle.FromPoints (points); + Assert.NotNull (obstacle, "GKPolygonObstacle.FromPoints should not be null"); + + var count = obstacle.VertexCount; + Assert.AreEqual (points.Length, (int)count, "GKPolygonObstacle lengt should be equal"); + + for (nuint i = 0; i < count; i++) + Assert.AreEqual (points [(int)i], obstacle.GetVertex (i), "GKPolygonObstacle vectors should be equal"); + } + + [Test] + public void InitWithPointsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + + var obstacle = new GKPolygonObstacle (points); + Assert.NotNull (obstacle, "GKPolygonObstacle ctor should not be null"); + + var count = obstacle.VertexCount; + Assert.AreEqual (points.Length, (int)count, "GKPolygonObstacle lengt should be equal"); + + for (nuint i = 0; i < count; i++) + Assert.AreEqual (points [(int)i], obstacle.GetVertex (i), "GKPolygonObstacle vectors should be equal"); + } + } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKStateMachineTests.cs b/tests/monotouch-test/GameplayKit/GKStateMachineTests.cs new file mode 100644 index 000000000000..5b5b6fce64d2 --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKStateMachineTests.cs @@ -0,0 +1,74 @@ +// +// Unit tests for GKStateMachine +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameplayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKStateMachineTests { + + [TestFixtureSetUp] + public void Setup () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + } + + [Test] + public void StateMachineTests () + { + var sm = new GKStateMachine (new GKState [] { + new ChaseState (), + new FleeState () + }); + + Assert.Null (sm.CurrentState, "CurrentState"); + + Assert.NotNull (sm, "StateMachine must not be null"); + sm.EnterState (typeof (ChaseState)); + + var chaseState = sm.GetState (typeof(ChaseState)); + Assert.NotNull (chaseState, "ChaseState must not be null"); + Assert.AreSame (chaseState, sm.CurrentState, "Must be same state"); + + var canEnterState = sm.EnterState (typeof(UndefinedState)); + Assert.IsFalse (canEnterState, "Should not be able to enter that state since we did not allow it"); + } + } + + class ChaseState : GKState { + public override bool IsValidNextState (Class stateClass) + { + return (Class.Lookup (stateClass) != typeof (UndefinedState)); + } + } + + class FleeState : GKState { } + + class UndefinedState : GKState { } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/GameplayKit/GKStateTests.cs b/tests/monotouch-test/GameplayKit/GKStateTests.cs new file mode 100644 index 000000000000..706eeeac3345 --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKStateTests.cs @@ -0,0 +1,88 @@ +// +// Unit tests for GKState +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.GameplayKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GKStateTests { + + [TestFixtureSetUp] + public void Setup () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring GameplayKit tests: Requires iOS9+"); + } + + [Test] + public void IsValidNextState () + { + var chaseState = new ValidState (); + var isValid = chaseState.IsValidNextState (typeof(InvalidState)); + Assert.IsFalse (isValid, "Type"); + + var invalid = new InvalidState (); + isValid = chaseState.IsValidNextState (invalid); + Assert.IsFalse (isValid, "Instance"); + + isValid = chaseState.IsValidNextState (invalid.Class); + Assert.IsFalse (isValid, "Class"); + } + + [Test] + public void NullIsValidNextState () + { + // this will test the (manual) binding code (and not the test implementation) + using (var state = new InvalidState ()) { + Assert.Throws (delegate { state.IsValidNextState ((Class) null); }, "Class"); + Assert.Throws (delegate { state.IsValidNextState ((Type) null); }, "Type"); + Assert.Throws (delegate { state.IsValidNextState ((GKState) null); }, "Instance"); + } + } + + [Test] + public void Concrete () + { + // GKState is an abstract type - but it does implement IsValidNextState (and accept anything) + using (var s1 = new ValidState ()) + using (var s2 = new InvalidState ()) { + Assert.True (s2.IsValidNextState (s2), "self"); + Assert.True (s2.IsValidNextState (s1), "different"); + } + } + } + + class ValidState : GKState { + public override bool IsValidNextState (Class stateClass) + { + return (Class.Lookup (stateClass) != typeof (InvalidState)); + } + } + + class InvalidState : GKState { } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/Hand.wav b/tests/monotouch-test/Hand.wav new file mode 100644 index 000000000000..e683c7162ff5 Binary files /dev/null and b/tests/monotouch-test/Hand.wav differ diff --git a/tests/monotouch-test/HealthKit/AnchoredObjectQueryTest.cs b/tests/monotouch-test/HealthKit/AnchoredObjectQueryTest.cs new file mode 100644 index 000000000000..2b2a74f52bd8 --- /dev/null +++ b/tests/monotouch-test/HealthKit/AnchoredObjectQueryTest.cs @@ -0,0 +1,51 @@ +// +// Unit tests for HKAnchoredObjectQuery +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using HealthKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.HealthKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if !XAMCORE_2_0 +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.HealthKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AnchoredObjectQueryTest { + + [Test] + public void NoAnchor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS8+"); + + using (var t = HKObjectType.GetCategoryType (HKCategoryTypeIdentifierKey.SleepAnalysis)) + using (var aoq = new HKAnchoredObjectQuery (t, null, HKAnchoredObjectQuery.NoAnchor, 0, delegate (HKAnchoredObjectQuery query, HKSample[] results, nuint newAnchor, NSError error) { + })) { + Assert.That (aoq.Handle, Is.Not.EqualTo (IntPtr.Zero), "handle"); + } + } + } +} +#endif // !__TVOS__ diff --git a/tests/monotouch-test/HealthKit/CategoryTypeIdentifierTest.cs b/tests/monotouch-test/HealthKit/CategoryTypeIdentifierTest.cs new file mode 100644 index 000000000000..121f53e3f62e --- /dev/null +++ b/tests/monotouch-test/HealthKit/CategoryTypeIdentifierTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for HKCategoryTypeIdentifier +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using HealthKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.HealthKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.HealthKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CategoryTypeIdentifier { + + [Test] + public void EnumValues_22351 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS8+"); + + foreach (HKCategoryTypeIdentifier value in Enum.GetValues (typeof (HKCategoryTypeIdentifier))) { + + switch (value) { + case HKCategoryTypeIdentifier.SleepAnalysis: + break; + default: + if (!TestRuntime.CheckiOSSystemVersion (9, 0)) + continue; + break; + } + + try { + using (var ct = HKCategoryType.Create (value)) { + Assert.That (ct.Handle, Is.Not.EqualTo (IntPtr.Zero), value.ToString ()); + } + } + catch (Exception e) { + Assert.Fail ("{0} could not be created: {1}", value, e); + } + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/HealthKit/ErrorTest.cs b/tests/monotouch-test/HealthKit/ErrorTest.cs new file mode 100644 index 000000000000..29b3091ca26e --- /dev/null +++ b/tests/monotouch-test/HealthKit/ErrorTest.cs @@ -0,0 +1,43 @@ +// +// Unit tests for HKErrorCode +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using HealthKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.HealthKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.HealthKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ErrorTest { + + [Test] + public void Domain () + { + // the enum exists but we can't load the domain before iOS8 + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS8+"); + + Assert.That (HKErrorCode.NoError.GetDomain ().ToString (), Is.EqualTo ("com.apple.healthkit"), "Domain"); + } + } +} + +#endif // __TVOS__ diff --git a/tests/monotouch-test/HealthKit/ObjectTypeTest.cs b/tests/monotouch-test/HealthKit/ObjectTypeTest.cs new file mode 100644 index 000000000000..7e0cb02735b5 --- /dev/null +++ b/tests/monotouch-test/HealthKit/ObjectTypeTest.cs @@ -0,0 +1,49 @@ +// +// Unit tests for HKObjectType +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using HealthKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.HealthKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if !XAMCORE_2_0 +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.HealthKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ObjectTypeTest { + + [Test] + public void Workout () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS8+"); + + using (var t = HKObjectType.GetWorkoutType ()) { + Assert.That (t.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + } +} +#endif // !__TVOS__ diff --git a/tests/monotouch-test/HealthKit/QuantityTypeIdentifierTest.cs b/tests/monotouch-test/HealthKit/QuantityTypeIdentifierTest.cs new file mode 100644 index 000000000000..795ec03a8cd4 --- /dev/null +++ b/tests/monotouch-test/HealthKit/QuantityTypeIdentifierTest.cs @@ -0,0 +1,62 @@ +// +// Unit tests for HKQuantityTypeIdentifier +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using HealthKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.HealthKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.HealthKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class QuantityTypeIdentifier { + + [Test] + public void EnumValues_22351 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS8+"); + + foreach (HKQuantityTypeIdentifier value in Enum.GetValues (typeof (HKQuantityTypeIdentifier))) { + + // we need to have version checks for anything added after iOS 8.0 + switch (value) { + case HKQuantityTypeIdentifier.BasalBodyTemperature: + case HKQuantityTypeIdentifier.DietaryWater: + case HKQuantityTypeIdentifier.UVExposure: + if (!TestRuntime.CheckiOSSystemVersion (9, 0)) + continue; + break; + } + + try { + using (var ct = HKQuantityType.Create (value)) { + Assert.That (ct.Handle, Is.Not.EqualTo (IntPtr.Zero), value.ToString ()); + } + } + catch (Exception e) { + Assert.Fail ("{0} could not be created: {1}", value, e); + } + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/ImageIO/CGImageSourceTest.cs b/tests/monotouch-test/ImageIO/CGImageSourceTest.cs new file mode 100644 index 000000000000..44ef783466cc --- /dev/null +++ b/tests/monotouch-test/ImageIO/CGImageSourceTest.cs @@ -0,0 +1,195 @@ +// Copyright 2012-2013 Xamarin Inc. All rights reserved + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreGraphics; +using ImageIO; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ImageIO { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CGImageSourceTest { + const string filename = "xamarin2.png"; + + [Test] + public void FromUrlTest () + { + using (var img = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + Assert.NotNull (img, "#a1"); + } + + using (var img = CGImageSource.FromUrl (NSUrl.FromFilename (filename), new CGImageOptions ())) { + Assert.NotNull (img, "#b1"); + } + + using (var img = CGImageSource.FromUrl (NSUrl.FromFilename (filename), null)) { + Assert.NotNull (img, "#c1"); + } + } + + [Test] + public void FromDataProviderTest () + { + using (var dp = new CGDataProvider (filename)) { + using (var img = CGImageSource.FromDataProvider (dp)) { + Assert.NotNull (img, "#a1"); + } + } + + using (var dp = new CGDataProvider (filename)) { + using (var img = CGImageSource.FromDataProvider (dp, new CGImageOptions ())) { + Assert.NotNull (img, "#b1"); + } + } + + using (var dp = new CGDataProvider (filename)) { + using (var img = CGImageSource.FromDataProvider (dp, null)) { + Assert.NotNull (img, "#c1"); + } + } + } + + [Test] + public void FromDataTest () + { + NSData data = NSData.FromFile (filename); + + using (var img = CGImageSource.FromData (data)) { + Assert.NotNull (img, "#a1"); + } + + using (var img = CGImageSource.FromData (data, new CGImageOptions ())) { + Assert.NotNull (img, "#b1"); + } + + using (var img = CGImageSource.FromData (data, null)) { + Assert.NotNull (img, "#c1"); + } + } + + [Test] + public void CreateImageTest () + { + using (var imgsrc = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + using (var img = imgsrc.CreateImage (0, null)) { + Assert.NotNull (img, "#a1"); + } + using (var img = imgsrc.CreateImage (0, new CGImageOptions ())) { + Assert.NotNull (img, "#b1"); + } + } + } + + [Test] + public void CreateThumbnailTest () + { + using (var imgsrc = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + using (var img = imgsrc.CreateThumbnail (0, null)) { + Assert.NotNull (img, "#a1"); + } + using (var img = imgsrc.CreateThumbnail (0, new CGImageThumbnailOptions ())) { + Assert.NotNull (img, "#b1"); + } + } + } + + [Test] + public void CreateIncrementalTest () + { + using (var img = CGImageSource.CreateIncremental (null)) { + Assert.NotNull (img, "#a1"); + } + + using (var img = CGImageSource.CreateIncremental (new CGImageOptions ())) { + Assert.NotNull (img, "#b1"); + } + } + + [Test] + public void CopyProperties () + { + // what we had to answer with 5.2 for http://stackoverflow.com/q/10753108/220643 + IntPtr lib = Dlfcn.dlopen (Constants.ImageIOLibrary, 0); + try { + NSString kCGImageSourceShouldCache = Dlfcn.GetStringConstant (lib, "kCGImageSourceShouldCache"); + NSString kCGImagePropertyPixelWidth = Dlfcn.GetStringConstant (lib, "kCGImagePropertyPixelWidth"); + NSString kCGImagePropertyPixelHeight = Dlfcn.GetStringConstant (lib, "kCGImagePropertyPixelHeight"); + + using (var imageSource = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + using (var dict = new NSMutableDictionary ()) { + dict [kCGImageSourceShouldCache] = NSNumber.FromBoolean (false); + using (var props = imageSource.CopyProperties (dict)) { + Assert.Null (props.ValueForKey (kCGImagePropertyPixelWidth), "kCGImagePropertyPixelWidth"); + Assert.Null (props.ValueForKey (kCGImagePropertyPixelHeight), "kCGImagePropertyPixelHeight"); + NSNumber n = (NSNumber) props ["FileSize"]; + // image is "optimized" for devices (and a lot bigger at 10351 bytes ;-) + Assert.That ((int) n, Is.AtLeast (7318), "FileSize"); + } + } + } + } + finally { + Dlfcn.dlclose (lib); + } + } + + [Test] + public void GetProperties () + { + using (var imageSource = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + CGImageOptions options = new CGImageOptions () { ShouldCache = false }; + + var props = imageSource.GetProperties (options); + Assert.Null (props.PixelWidth, "PixelHeight-0"); + Assert.Null (props.PixelHeight, "PixelWidth-0"); + // image is "optimized" for devices (and a lot bigger at 10351 bytes ;-) + Assert.That (props.FileSize, Is.AtLeast (7318), "FileSize"); + + props = imageSource.GetProperties (0, options); + Assert.AreEqual (57, props.PixelWidth, "PixelHeight"); + Assert.AreEqual (57, props.PixelHeight, "PixelWidth"); + Assert.AreEqual (CGImageColorModel.RGB, props.ColorModel, "ColorModel"); + Assert.AreEqual (8, props.Depth, "Depth"); + } + } + + [Test] + public void CopyMetadata () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Only on iOS7+"); + + using (var imageSource = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + CGImageOptions options = new CGImageOptions () { ShouldCacheImmediately = true }; + using (CGImageMetadata metadata = imageSource.CopyMetadata (0, options)) { + Console.WriteLine (); + } + } + } + + [Test] + public void RemoveCache () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Only on iOS7+"); + + using (var imageSource = CGImageSource.FromUrl (NSUrl.FromFilename (filename))) { + imageSource.RemoveCache (0); + } + } + } +} diff --git a/tests/monotouch-test/ImageIO/ImageDestinationTest.cs b/tests/monotouch-test/ImageIO/ImageDestinationTest.cs new file mode 100644 index 000000000000..8804b387e0e8 --- /dev/null +++ b/tests/monotouch-test/ImageIO/ImageDestinationTest.cs @@ -0,0 +1,169 @@ +// +// Unit tests for CGImageDestination +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using ImageIO; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ImageIO { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageDestinationTest { + + const string GoodUti ="public.jpeg"; // correct + const string BadUti = "public.Jpeg"; // wrong 'J' is an upper letter + + [Test] + public void FromData_BadITU () + { + using (NSMutableData destData = new NSMutableData ()) { +#if XAMCORE_2_0 // FromData => Create + Assert.Null (CGImageDestination.Create (destData, BadUti, 1), "FromData-1"); + Assert.Null (CGImageDestination.Create (destData, BadUti, 1, new CGImageDestinationOptions ()), "FromData-2"); +#else + Assert.Null (CGImageDestination.FromData (destData, BadUti, 1), "FromData-1"); + Assert.Null (CGImageDestination.FromData (destData, BadUti, 1, new CGImageDestinationOptions ()), "FromData-2"); +#endif + } + } + + [Test] + public void FromData_GoodITU () + { + using (NSMutableData destData = new NSMutableData ()) { +#if XAMCORE_2_0 // FromData => Create + using (var id = CGImageDestination.Create (destData, GoodUti, 1)) { +#else + using (var id = CGImageDestination.FromData (destData, GoodUti, 1)) { +#endif + Assert.That (id.Handle, Is.Not.EqualTo (IntPtr.Zero), "handle-1"); + } +#if XAMCORE_2_0 // FromData => Create + using (var id = CGImageDestination.Create (destData, GoodUti, 1, new CGImageDestinationOptions ())) { +#else + using (var id = CGImageDestination.FromData (destData, GoodUti, 1, new CGImageDestinationOptions ())) { +#endif + Assert.That (id.Handle, Is.Not.EqualTo (IntPtr.Zero), "handle-2"); + } + } + } + + [Test] + public void Create_DataConsumer_BadUTI () + { + using (NSMutableData destData = new NSMutableData ()) + using (var consumer = new CGDataConsumer (destData)) { + Assert.Null (CGImageDestination.Create (consumer, BadUti, 1), "Create-1"); + Assert.Null (CGImageDestination.Create (consumer, BadUti, 1, new CGImageDestinationOptions ()), "Create-2"); + } + } + + [Test] + public void Create_DataConsumer_GoodUTI () + { + using (NSMutableData destData = new NSMutableData ()) + using (var consumer = new CGDataConsumer (destData)) { + using (var id = CGImageDestination.Create (consumer, GoodUti, 1)) { + Assert.That (id.Handle, Is.Not.EqualTo (IntPtr.Zero), "handle-1"); + } + using (var id = CGImageDestination.Create (consumer, GoodUti, 1, new CGImageDestinationOptions ())) { + Assert.That (id.Handle, Is.Not.EqualTo (IntPtr.Zero), "handle-2"); + } + } + } + + [Test] + public void FromUrl_BadITU () + { + using (NSUrl url = NSUrl.FromString ("file://local")) { +#if XAMCORE_2_0 // FromUrl => Create + Assert.Null (CGImageDestination.Create (url, BadUti, 1), "FromUrl-1"); +#else + Assert.Null (CGImageDestination.FromUrl (url, BadUti, 1), "FromUrl-1"); + Assert.Null (CGImageDestination.FromUrl (url, BadUti, 1, new CGImageDestinationOptions ()), "FromUrl-2"); +#endif + } + } + + [Test] + public void AddImage () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (NSMutableData destData = new NSMutableData ()) + using (var uiimg = UIImage.FromFile (file)) + using (var img = uiimg.CGImage) +#if XAMCORE_2_0 // FromData => Create + using (var id = CGImageDestination.Create (destData, GoodUti, 1)) { +#else + using (var id = CGImageDestination.FromData (destData, GoodUti, 1)) { +#endif + id.AddImage (img, (NSDictionary) null); + } + } + + [Test] + public void AddImageAndMetadata () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS 7+"); + + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (NSMutableData destData = new NSMutableData ()) + using (var uiimg = UIImage.FromFile (file)) + using (var img = uiimg.CGImage) +#if XAMCORE_2_0 // FromData => Create + using (var id = CGImageDestination.Create (destData, GoodUti, 1)) +#else + using (var id = CGImageDestination.FromData (destData, GoodUti, 1)) +#endif + using (var mutable = new CGMutableImageMetadata ()) { + id.AddImageAndMetadata (img, mutable, (NSDictionary) null); + } + } + + [Test] + public void CopyImageSource () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS 7+"); + + using (NSData data = NSData.FromFile ("xamarin2.png")) + using (var source = CGImageSource.FromData (data)) + using (NSMutableData destData = new NSMutableData ()) +#if XAMCORE_2_0 // FromData => Create + using (var id = CGImageDestination.Create (destData, GoodUti, 1)) { +#else + using (var id = CGImageDestination.FromData (destData, GoodUti, 1)) { +#endif + NSError err; + // testing that null is allowed (no crash) so the fact that is return false and an error does not matter + Assert.False (id.CopyImageSource (source, (NSDictionary) null, out err), "CopyImageSource"); + Assert.NotNull (err, "NSError"); + } + } + + [Test] + public void TypeIdentifiers () + { + Assert.NotNull (CGImageDestination.TypeIdentifiers, "TypeIdentifiers"); + } + } +} diff --git a/tests/monotouch-test/ImageIO/ImageMetadataTagTest.cs b/tests/monotouch-test/ImageIO/ImageMetadataTagTest.cs new file mode 100644 index 000000000000..9f60d72e36fc --- /dev/null +++ b/tests/monotouch-test/ImageIO/ImageMetadataTagTest.cs @@ -0,0 +1,153 @@ +// +// CGImageMetadataTag Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ImageIO; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ImageIO { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageMetadataTagTest { + + NSString nspace = CGImageMetadataTagNamespaces.Exif; + NSString prefix = CGImageMetadataTagPrefixes.Exif; + NSString name = new NSString ("tagName"); + + [DllImport (Constants.CoreFoundationLibrary)] + extern static int CFGetRetainCount (IntPtr handle); + + [Test] + public void Ctor_Null () + { + Assert.Throws (delegate { new CGImageMetadataTag (null, prefix, name, CGImageMetadataType.Default, name); }, "1"); + Assert.Throws (delegate { new CGImageMetadataTag (nspace, prefix, null, CGImageMetadataType.Default, name); }, "3"); + Assert.Throws (delegate { new CGImageMetadataTag (nspace, prefix, null, CGImageMetadataType.Default, null); }, "4"); + } + + [Test] + public void Ctor_NSString () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + using (var value = new NSString ("value")) + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, value)) { + Assert.That (tag.Name.ToString (), Is.EqualTo ("tagName"), "Name"); + Assert.That (tag.Namespace.ToString (), Is.EqualTo ("http://ns.adobe.com/exif/1.0/"), "Namespace"); + Assert.That (tag.Prefix.ToString (), Is.EqualTo ("exif"), "Prefix"); + Assert.That (tag.Type, Is.EqualTo (CGImageMetadataType.String), "Type"); + Assert.That (tag.Value.ToString (), Is.EqualTo ("value"), "Value"); + Assert.Null (tag.GetQualifiers (), "GetQualifiers"); + } + } + + [Test] + public void Ctor_NSNumber () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + using (var value = NSNumber.FromByte (255)) + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, value)) { + Assert.That (tag.Name.ToString (), Is.EqualTo ("tagName"), "Name"); + Assert.That (tag.Namespace.ToString (), Is.EqualTo ("http://ns.adobe.com/exif/1.0/"), "Namespace"); + Assert.That (tag.Prefix.ToString (), Is.EqualTo ("exif"), "Prefix"); + Assert.That (tag.Type, Is.EqualTo (CGImageMetadataType.String), "Type"); + Assert.That (tag.Value.ToString (), Is.EqualTo ("255"), "Value"); + Assert.Null (tag.GetQualifiers (), "GetQualifiers"); + } + } + + [Test] + public void Ctor_NSArray () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + using (var value = NSArray.FromNSObjects (nspace, prefix, name)) + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, value)) { + Assert.That (tag.Name.ToString (), Is.EqualTo ("tagName"), "Name"); + Assert.That (tag.Namespace.ToString (), Is.EqualTo ("http://ns.adobe.com/exif/1.0/"), "Namespace"); + Assert.That (tag.Prefix.ToString (), Is.EqualTo ("exif"), "Prefix"); + Assert.That (tag.Type, Is.EqualTo (CGImageMetadataType.ArrayOrdered), "Type"); + Assert.That (tag.Value, Is.TypeOf (), "Value"); + Assert.Null (tag.GetQualifiers (), "GetQualifiers"); + } + } + + [Test] + public void Ctor_NSDictionary () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + using (var value = NSDictionary.FromObjectAndKey (name, prefix)) + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, value)) { + Assert.That (tag.Name.ToString (), Is.EqualTo ("tagName"), "Name"); + Assert.That (tag.Namespace.ToString (), Is.EqualTo ("http://ns.adobe.com/exif/1.0/"), "Namespace"); + Assert.That (tag.Prefix.ToString (), Is.EqualTo ("exif"), "Prefix"); + Assert.That (tag.Type, Is.EqualTo (CGImageMetadataType.Structure), "Type"); + Assert.That (tag.Value, Is.TypeOf (), "Value"); + Assert.Null (tag.GetQualifiers (), "GetQualifiers"); + } + } + + [Test] + public void Ctor_Bool_True () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, true)) { + Assert.That (CFGetRetainCount (tag.Handle), Is.EqualTo (1), "RetainCount"); + + Assert.That (tag.Name.ToString (), Is.EqualTo ("tagName"), "Name"); + Assert.That (tag.Namespace.ToString (), Is.EqualTo ("http://ns.adobe.com/exif/1.0/"), "Namespace"); + Assert.That (tag.Prefix.ToString (), Is.EqualTo ("exif"), "Prefix"); + Assert.That (tag.Type, Is.EqualTo (CGImageMetadataType.String), "Type"); + Assert.That (tag.Value.ToString (), Is.EqualTo ("True"), "Value"); + Assert.Null (tag.GetQualifiers (), "GetQualifiers"); + } + } + + [Test] + public void Ctor_Bool_False () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + var rc = name.RetainCount; + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, false)) { + using (var n = tag.Name) { + Assert.That (n.Handle, Is.EqualTo (name.Handle), "same"); + Assert.That (n.ToString (), Is.EqualTo ("tagName"), "Name"); + } + Assert.That (tag.Namespace.ToString (), Is.EqualTo ("http://ns.adobe.com/exif/1.0/"), "Namespace"); + Assert.That (tag.Prefix.ToString (), Is.EqualTo ("exif"), "Prefix"); + Assert.That (tag.Type, Is.EqualTo (CGImageMetadataType.String), "Type"); + Assert.That (tag.Value.ToString (), Is.EqualTo ("False"), "Value"); + Assert.Null (tag.GetQualifiers (), "GetQualifiers"); + } + } + } +} diff --git a/tests/monotouch-test/ImageIO/ImageMetadataTest.cs b/tests/monotouch-test/ImageIO/ImageMetadataTest.cs new file mode 100644 index 000000000000..d7e6b435f72d --- /dev/null +++ b/tests/monotouch-test/ImageIO/ImageMetadataTest.cs @@ -0,0 +1,54 @@ +// +// CGImageMetadata +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ImageIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ImageIO { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageMetadataTest { + + NSString nspace = CGImageMetadataTagNamespaces.Exif; + NSString prefix = CGImageMetadataTagPrefixes.Exif; + NSString name = new NSString ("tagName"); + NSString path = new NSString ("exif:Flash.Fired"); + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + Assert.Throws (delegate { new CGImageMetadata (null); }, "null"); + + using (var mutable = new CGMutableImageMetadata ()) + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, true)) { + mutable.SetTag (null, path, tag); + + using (var meta = new CGImageMetadata (mutable.CreateXMPData ())) { + // not surprising since it's all empty + Assert.Null (meta.CopyTagMatchingImageProperty (CGImageProperties.ExifDictionary, CGImageProperties.ExifDateTimeOriginal), "CopyTagMatchingImageProperty"); + } + } + } + } +} diff --git a/tests/monotouch-test/ImageIO/ImagePropertiesTest.cs b/tests/monotouch-test/ImageIO/ImagePropertiesTest.cs new file mode 100644 index 000000000000..29b63da77388 --- /dev/null +++ b/tests/monotouch-test/ImageIO/ImagePropertiesTest.cs @@ -0,0 +1,91 @@ +// +// CGImageProperties +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ImageIO; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ImageIO { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImagePropertiesTest { + + [Test] + public void CameraMaker () + { + // since only Canon and Nikon have dictionary key values I assume the others are "placeholder" at the moment !?! + Assert.NotNull (CGImageProperties.MakerCanonDictionary, "MakerCanonDictionary"); + Assert.NotNull (CGImageProperties.MakerNikonDictionary, "MakerNikonDictionary"); + + // iOS 8.3 finally fixed them :) + if (TestRuntime.CheckiOSSystemVersion (8,3)) { + Assert.NotNull (CGImageProperties.MakerMinoltaDictionary, "MakerMinoltaDictionary"); + Assert.NotNull (CGImageProperties.MakerFujiDictionary, "MakerFujiDictionary"); + Assert.NotNull (CGImageProperties.MakerOlympusDictionary, "MakerOlympusDictionary"); + Assert.NotNull (CGImageProperties.MakerPentaxDictionary, "MakerPentaxDictionary"); + return; + } + + // documented as new in iOS 4.0 - https://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CGImageProperties_Reference/Reference/reference.html + // but symbols are not available in iOS 5.1.1 + // this test will fail if Apple decide to include them in the future + IntPtr lib = Dlfcn.dlopen (Constants.ImageIOLibrary, 0); + try { + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyMakerMinoltaDictionary"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyMakerMinoltaDictionary"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyMakerFujiDictionary"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyMakerFujiDictionary"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyMakerOlympusDictionary"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyMakerOlympusDictionary"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyMakerPentaxDictionary"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyMakerPentaxDictionary"); + } + finally { + Dlfcn.dlclose (lib); + } + } + + [Test] + public void Exif43Fields () + { + // documented as new in iOS 4.3 - https://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CGImageProperties_Reference/Reference/reference.html + IntPtr lib = Dlfcn.dlopen (Constants.ImageIOLibrary, 0); + try { + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + // symbols are available in iOS 6.0 beta 1 + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifCameraOwnerName"), Is.Not.EqualTo (IntPtr.Zero), "kCGImagePropertyExifCameraOwnerName"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifBodySerialNumber"), Is.Not.EqualTo (IntPtr.Zero), "kCGImagePropertyExifBodySerialNumber"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensSpecification"), Is.Not.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensSpecification"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensMake"), Is.Not.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensMake"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensModel"), Is.Not.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensModel"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensSerialNumber"), Is.Not.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensSerialNumber"); + } else { + // but symbols are not available in iOS 5.1.1 + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifCameraOwnerName"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyExifCameraOwnerName"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifBodySerialNumber"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyExifBodySerialNumber"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensSpecification"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensSpecification"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensMake"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensMake"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensModel"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensModel"); + Assert.That (Dlfcn.dlsym (lib, "kCGImagePropertyExifLensSerialNumber"), Is.EqualTo (IntPtr.Zero), "kCGImagePropertyExifLensSerialNumber"); + } + } + finally { + Dlfcn.dlclose (lib); + } + } + } +} diff --git a/tests/monotouch-test/ImageIO/MutableImageMetadataTest.cs b/tests/monotouch-test/ImageIO/MutableImageMetadataTest.cs new file mode 100644 index 000000000000..d64c8da72d9a --- /dev/null +++ b/tests/monotouch-test/ImageIO/MutableImageMetadataTest.cs @@ -0,0 +1,67 @@ +// +// CGMutableImageMetadata +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ImageIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ImageIO { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MutableImageMetadataTest { + + NSString nspace = CGImageMetadataTagNamespaces.Exif; + NSString prefix = CGImageMetadataTagPrefixes.Exif; + NSString name = new NSString ("tagName"); + NSString path = new NSString ("exif:Flash.Fired"); + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS 7+"); + + using (var meta = new CGMutableImageMetadata ()) { + Console.WriteLine (meta); + NSError err; + Assert.True (meta.RegisterNamespace (CGImageMetadataTagNamespaces.Exif, CGImageMetadataTagPrefixes.Exif, out err), "RegisterNamespace"); + Assert.Null (err, "NSError"); + + // nothing to see at this stage + using (var data = meta.CreateXMPData ()) { + Assert.Null (data, "CreateXMPData-1"); + } + + using (var tag = new CGImageMetadataTag (nspace, prefix, name, CGImageMetadataType.Default, true)) { + Assert.True (meta.SetTag (null, path, tag), "SetTag"); + } + + // now we're talking + using (var data = meta.CreateXMPData ()) { + Assert.NotNull (data, "CreateXMPData-2"); + } + + Assert.True (meta.SetValue (null, path, false), "SetValue"); + + Assert.True (meta.SetValueMatchingImageProperty (CGImageProperties.ExifDictionary, CGImageProperties.ExifDateTimeOriginal, (NSDate)DateTime.Now), "SetValueMatchingImageProperty"); + } + } + } +} diff --git a/tests/monotouch-test/Info.plist b/tests/monotouch-test/Info.plist new file mode 100644 index 000000000000..28e0f6a7accd --- /dev/null +++ b/tests/monotouch-test/Info.plist @@ -0,0 +1,44 @@ + + + + + CFBundleDisplayName + MonoTouchTest + CFBundleIdentifier + com.xamarin.monotouch-test + MinimumOSVersion + 5.1.1 + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + XSAppIconAssets + Assets.xcassets/AppIcons.appiconset + UILaunchStoryboardName + LaunchScreen + UIRequiresFullScreen + + CFBundleName + MonoTouchTest + + diff --git a/tests/monotouch-test/JavascriptCore/ContextTest.cs b/tests/monotouch-test/JavascriptCore/ContextTest.cs new file mode 100644 index 000000000000..593ed35afd66 --- /dev/null +++ b/tests/monotouch-test/JavascriptCore/ContextTest.cs @@ -0,0 +1,76 @@ +// +// JSContext Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013, 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using JavaScriptCore; +#else +using MonoTouch.Foundation; +using MonoTouch.JavaScriptCore; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.JavascriptCore { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + [TestFixture] + public class ContextTest { + + [Test] + public void EvaluateScript () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("requires iOS7+"); + + using (var c = new JSContext ()) + using (JSValue r = c.EvaluateScript ("function FourthyTwo () { return 42; }; FourthyTwo ()")) { + Assert.That (r.ToInt32 (), Is.EqualTo (42), "42"); + } + } + + [Test] + public void EvaluateScript_Param () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("requires iOS7+"); + + using (var context = new JSContext ()) + using (JSValue script = context.EvaluateScript ("var square = function (x) { return x * x; }")) + using (JSValue function = context [(NSString) "square"]) + using (JSValue input = JSValue.From (2, context)) + using (JSValue result = function.Call (input)) { + Assert.That (result.ToInt32 (), Is.EqualTo (4), "4"); + } + } + + [Test] + public void EvaluateScript_Context () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("requires iOS7+"); + + using (var context = new JSContext ()) + using (JSValue value = context.EvaluateScript ("a = 3")) + using (JSValue script = context.EvaluateScript ("var square = function (x) { return x * x; }")) + using (JSValue function = context [(NSString) "square"]) + using (JSValue result = function.Call (context [(NSString) "a"])) { + Assert.That (result.ToInt32 (), Is.EqualTo (9), "9"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/JavascriptCore/JSExportTest.cs b/tests/monotouch-test/JavascriptCore/JSExportTest.cs new file mode 100644 index 000000000000..7d7fd7597279 --- /dev/null +++ b/tests/monotouch-test/JavascriptCore/JSExportTest.cs @@ -0,0 +1,93 @@ +// +// Copyright 2014 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using JavaScriptCore; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.JavaScriptCore; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +using XamarinTests.ObjCRuntime; +using MonoTouchFixtures.ObjCRuntime; + +namespace MonoTouchFixtures.JavascriptCore { + + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + [TestFixture] + public class JSExportTest { + [Test] + public void ExportTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("requires iOS7+"); + + if (RegistrarTest.CurrentRegistrar != Registrars.Static) + Assert.Ignore ("Exporting protocols to JavaScriptCore requires the static registrar."); + + var context = new JSContext (); + JSValue exc = null; + context.ExceptionHandler = (JSContext context2, JSValue exception) => { + exc = exception; + }; + var obj = new MyJavaExporter (); + context [(NSString) "obj"] = JSValue.From (obj, context); + context.EvaluateScript ("obj.myFunc ();"); + Assert.IsNull (exc, "JS exception"); + Assert.IsTrue (obj.MyFuncCalled, "Called"); + + context.EvaluateScript ("obj.hello (42);"); + context.EvaluateScript ("obj.callMeBack (function() { return 314; });"); + } + } + + // This interface will show a warning with the dynamic registrar: + // MonoTouch.RuntimeException: Detected a protocol (MonoTouchFixtures.JavascriptCore.IMyJavaExporter) inheriting from the JSExport protocol while using the dynamic registrar. It is not possible to export protocols to JavaScriptCore dynamically; the static registrar must be used (add '--registrar:static to the additional mtouch arguments in the project's iOS Build options to select the static registrar). + // This warning is expected. + [Protocol ()] + interface IMyJavaExporter : IJSExport { + [Export ("myFunc")] + void MyFunc (); + + [Export ("hello:")] + void Hello (JSValue val); + + [Export ("callMeBack:")] + void CallMeBack (JSValue callbackFunc); + } + + class MyJavaExporter : NSObject, IMyJavaExporter + { + public bool MyFuncCalled; + public void MyFunc () + { + MyFuncCalled = true; + } + + public void Hello (JSValue val) + { + Assert.IsTrue (val.IsNumber, "Hello - IsNumber"); + Assert.AreEqual (42, val.ToNumber ().Int32Value, "Hello - Number"); + } + + public void CallMeBack (JSValue callbackFunc) + { + var rv = callbackFunc.Call (); + Assert.IsTrue (rv.IsNumber, "CallMeBack - IsNumber"); + Assert.AreEqual (314, rv.ToNumber ().Int32Value, "CallMeBack - Number"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/JavascriptCore/ValueTest.cs b/tests/monotouch-test/JavascriptCore/ValueTest.cs new file mode 100644 index 000000000000..5b8b8811d7b6 --- /dev/null +++ b/tests/monotouch-test/JavascriptCore/ValueTest.cs @@ -0,0 +1,91 @@ +// +// JSValue Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using JavaScriptCore; +#else +using MonoTouch.Foundation; +using MonoTouch.JavaScriptCore; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.JavascriptCore { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + [TestFixture] + public class ValueTest { + + [Test] + public void From () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var c = new JSContext ()) { + using (var d = JSValue.From (1.0, c)) { + Assert.That (d.ToDouble (), Is.EqualTo (1.0d), "double"); + Assert.AreSame (d.Context, c, "double.Context"); + Assert.True (d.IsNumber, "double.IsNumber"); + } + } + } + + [Test] + public void Invoke () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var c = new JSContext ()) { + using (var d = JSValue.From (1.0, c)) { + Assert.That (d.Invoke ("toString").ToString (), Is.EqualTo ("1"), "toString"); + } + + using (var s1 = JSValue.From ("Hello Xamarin!", c)) + using (var s2 = JSValue.From ("Hello", c)) + using (var s3 = JSValue.From ("Bonjour", c)) { + Assert.That (s1.Invoke ("replace", s2, s3).ToString (), Is.EqualTo ("Bonjour Xamarin!"), "replace"); + + Assert.That (s1.Invoke ("replace", s2, JSValue.Null (c)).ToString (), Is.EqualTo ("null Xamarin!"), "replace-2"); + } + } + } + + [Test] + public void IsEqual () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var c = new JSContext ()) + using (var d = JSValue.From (1.0d, c)) + using (var f = JSValue.From (1.0f, c)) { + Assert.True (d.IsEqualTo (d), "=== self"); + Assert.True (d.IsEqualTo (f), "=== double/float"); // it's a number now + Assert.True (d.IsEqualTo ((NSNumber) 1.0d), "=== NSNumber"); + Assert.False (d.IsEqualTo ((NSNumber) 2.0d), "=== NSNumber-2"); + + Assert.True (d.IsEqualWithTypeCoercionTo (d), "== self"); + Assert.True (d.IsEqualWithTypeCoercionTo (f), "== double/float"); + Assert.True (d.IsEqualWithTypeCoercionTo ((NSNumber) 1.0d), "== NSNumber"); + Assert.False (d.IsEqualWithTypeCoercionTo ((NSNumber) 2.0d), "== NSNumber-2"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/LL-171A-B-B797E457-16AB-C708-1E0F-32C19DBD47B5.icc b/tests/monotouch-test/LL-171A-B-B797E457-16AB-C708-1E0F-32C19DBD47B5.icc new file mode 100644 index 000000000000..f25f01ca3b8c Binary files /dev/null and b/tests/monotouch-test/LL-171A-B-B797E457-16AB-C708-1E0F-32C19DBD47B5.icc differ diff --git a/tests/monotouch-test/LaunchScreen.storyboard b/tests/monotouch-test/LaunchScreen.storyboard new file mode 100644 index 000000000000..7981a14b773c --- /dev/null +++ b/tests/monotouch-test/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/monotouch-test/Main.cs b/tests/monotouch-test/Main.cs new file mode 100644 index 000000000000..a0205b4b42fc --- /dev/null +++ b/tests/monotouch-test/Main.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using System.Runtime.InteropServices; + +namespace monotouchtest +{ + public class Application + { +#if !__WATCHOS__ + // This is the main entry point of the application. + static void Main (string[] args) + { + // Make sure we have at least one reference to the bindings project so that mcs doesn't strip the reference to it. + GC.KeepAlive (typeof(Bindings.Test.UltimateMachine)); + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } +#endif // !__WATCHOS__ + + } +} + +class TestRuntime +{ + [DllImport ("/usr/lib/system/libdyld.dylib")] + static extern int dyld_get_program_sdk_version (); + + public const string BuildVersion_iOS9_GM = "13A340"; + + public static string GetiOSBuildVersion () + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS Build version on watchOS."); +#else + return NSString.FromHandle (Messaging.IntPtr_objc_msgSend (UIDevice.CurrentDevice.Handle, Selector.GetHandle ("buildVersion"))); +#endif + } + + public static Version GetSDKVersion () + { + var v = dyld_get_program_sdk_version (); + var major = v >> 16; + var minor = (v >> 8) & 0xFF; + var build = v & 0xFF; + return new Version (major, minor, build); + } + + // This method returns true if: + // system version >= specified version + // AND + // sdk version >= specified version + public static bool CheckiOSSystemVersion (int major, int minor) + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS System version on WatchOS."); +#else + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#endif + } + + // This method returns true if: + // system version >= specified version + // AND + // sdk version >= specified version + public static bool CheckSystemAndSDKVersion (int major, int minor) + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS System/SDK version on WatchOS."); +#else + if (!UIDevice.CurrentDevice.CheckSystemVersion (major, minor)) + return false; +#endif + + // Check if the SDK version we're built includes the version we're checking for + // We don't want to execute iOS7 tests on an iOS7 device when built with the iOS6 SDK. + return CheckSDKVersion (major, minor); + } + + public static bool CheckSDKVersion (int major, int minor) + { +#if __WATCHOS__ + throw new Exception ("Can't get iOS SDK version on WatchOS."); +#else + if (Runtime.Arch == Arch.SIMULATOR || !UIDevice.CurrentDevice.CheckSystemVersion (6, 0)) { + // dyld_get_program_sdk_version was introduced with iOS 6.0, so don't do the SDK check on older deviecs. + return true; // dyld_get_program_sdk_version doesn't return what we're looking for on the mac. + } +#endif + + var sdk = GetSDKVersion (); + if (sdk.Major > major) + return true; + if (sdk.Major == major && sdk.Minor >= minor) + return true; + return false; + } + + public static void IgnoreOnTVOS () + { +#if __TVOS__ + NUnit.Framework.Assert.Ignore ("This test is disabled on TVOS."); +#endif + } + + public static bool IsTVOS { + get { +#if __TVOS__ + return true; +#else + return false; +#endif + } + } + + public static bool RunAsync (DateTime timeout, Action action, Func check_completed) + { +#if __WATCHOS__ + throw new NotImplementedException ("TestRuntime.RunAsync"); +#else + return MonoTouchFixtures.AppDelegate.RunAsync (timeout, action, check_completed); +#endif + } +} + +// This prevents the need for putting lots of #ifdefs inside the list of usings. +#if __WATCHOS__ +namespace System.Drawing {} +namespace OpenTK {} +#endif diff --git a/tests/monotouch-test/Makefile b/tests/monotouch-test/Makefile new file mode 100644 index 000000000000..c357a4ddd975 --- /dev/null +++ b/tests/monotouch-test/Makefile @@ -0,0 +1,30 @@ + +PLATFORM=ios +ifdef COMPAT +PROFILE=devcompat +else +PROFILE=devunified +endif + +all: + make -C ../ build-$(PLATFORM)-$(PROFILE)-monotouch-test + +clean: + make -C ../ clean-$(PLATFORM)-$(PROFILE)-monotouch-test + +install: + make -C ../ install-$(PLATFORM)-$(PROFILE)-monotouch-test + +exec: + make -C ../ exec-$(PLATFORM)-$(PROFILE)-monotouch-test + +# check that all files +check-files: + @grep "Compile Include" monotouch-test.csproj | sed 's/.*Compile Include="//' | sed 's/".*//' | grep -v "^[.][.]" | sed 's_\\_/_' | sort > csproj-files + @ls -1 *.cs */*.cs | sort > cs-files + @if ! diff -u csproj-files cs-files; then \ + echo "There are test files not included in monotouch-test.csproj"; \ + rm -f csproj-files cs-files; \ + exit 1; \ + fi + @rm -f csproj-files cs-files diff --git a/tests/monotouch-test/MapKit/AnnotationViewTest.cs b/tests/monotouch-test/MapKit/AnnotationViewTest.cs new file mode 100644 index 000000000000..b40761084188 --- /dev/null +++ b/tests/monotouch-test/MapKit/AnnotationViewTest.cs @@ -0,0 +1,151 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + class AnnotationViewPoker : MKAnnotationView { + + static FieldInfo bkAnnotation; + + static AnnotationViewPoker () + { + var t = typeof (MKAnnotationView); + bkAnnotation = t.GetField ("__mt_Annotation_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + +#if XAMCORE_2_0 + public AnnotationViewPoker (IMKAnnotation annotation) : base (annotation, "reuse") +#else + public AnnotationViewPoker (NSObject annotation) : base (annotation, "reuse") +#endif + { + } + + public NSObject AnnotationBackingField { + get { + return (NSObject) bkAnnotation.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class AnnotationViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKAnnotationView av = new MKAnnotationView (frame)) { + Assert.That (av.Frame, Is.EqualTo (frame), "Frame"); + Assert.Null (av.Annotation, "Annotation"); + } + } + + [Test] + public void InitWithAnnotation () + { + // using a null 'annotation' crash - but the property can be set to null later + using (var a = new MKPolygon ()) + using (MKAnnotationView av = new MKAnnotationView (a, "reuse")) { + Assert.AreSame (a, av.Annotation, "Annotation"); + av.Annotation = null; + } + } + + [Test] + public void Annotation_BackingFields () + { + if (AnnotationViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var a = new MKPolygon ()) + using (var av = new AnnotationViewPoker (a)) { + Assert.AreSame (a, av.AnnotationBackingField, "1a"); + Assert.AreSame (a, av.Annotation, "2a"); + } + } + + [Test] + public void Default () + { + using (var def = new MKAnnotationView ()) { + Assert.IsNull (def.Annotation, "Annotation"); + Assert.AreEqual (def.CalloutOffset, PointF.Empty, "CalloutOffset"); + Assert.IsFalse (def.CanShowCallout, "CanShowCallout"); + Assert.AreEqual (def.CenterOffset, PointF.Empty, "CenterOffset"); + Assert.IsFalse (def.Draggable, "Draggable"); + Assert.That (def.DragState, Is.EqualTo (MKAnnotationViewDragState.None), "DragState"); + Assert.IsTrue (def.Enabled, "Enabled"); + Assert.IsFalse (def.Highlighted, "Highlighted"); + Assert.IsNull (def.Image, "Image"); + Assert.IsNull (def.LeftCalloutAccessoryView, "LeftCalloutAccessoryView"); + Assert.IsNull (def.ReuseIdentifier, "ReuseIdentifier"); + Assert.IsNull (def.RightCalloutAccessoryView, "RightCalloutAccessoryView"); + Assert.IsFalse (def.Selected, "Selected"); + } + } + + [Test] + public void Null () + { + using (var def = new MKAnnotationView ()) { + def.Annotation = null; + def.Annotation = new MKPolygon (); + Assert.IsNotNull (def.Annotation, "Annotation NN"); + def.Annotation = null; + Assert.IsNull (def.Annotation, "Annotation N"); + + def.Image = null; + def.Image = new UIImage (); + Assert.IsNotNull (def.Image, "Image NN"); + def.Image = null; + Assert.IsNull (def.Image, "Image N"); + + def.LeftCalloutAccessoryView = null; + def.LeftCalloutAccessoryView = new UIView (); + Assert.IsNotNull (def.LeftCalloutAccessoryView, "LeftCalloutAccessoryView NN"); + def.LeftCalloutAccessoryView = null; + Assert.IsNull (def.LeftCalloutAccessoryView, "LeftCalloutAccessoryView N"); + + def.RightCalloutAccessoryView = null; + def.RightCalloutAccessoryView = new UIView (); + Assert.IsNotNull (def.RightCalloutAccessoryView, "RightCalloutAccessoryView NN"); + def.RightCalloutAccessoryView = null; + Assert.IsNull (def.RightCalloutAccessoryView, "RightCalloutAccessoryView N"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/CircleViewTest.cs b/tests/monotouch-test/MapKit/CircleViewTest.cs new file mode 100644 index 000000000000..5bfaea6fe65a --- /dev/null +++ b/tests/monotouch-test/MapKit/CircleViewTest.cs @@ -0,0 +1,99 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + class CircleViewPoker : MKCircleView { + + static FieldInfo bkCircle; + + static CircleViewPoker () + { + var t = typeof (MKCircleView); + bkCircle = t.GetField ("__mt_Circle_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public CircleViewPoker () + { + } + + public CircleViewPoker (MKCircle circle) : base (circle) + { + } + + public MKCircle CircleBackingField { + get { + return (MKCircle) bkCircle.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class CircleViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKCircleView cv = new MKCircleView (frame)) { + Assert.That (cv.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void Defaults_BackingFields () + { + if (CircleViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var cv = new CircleViewPoker ()) { + Assert.Null (cv.CircleBackingField, "1a"); + Assert.Null (cv.Circle, "2a"); + } + } + + [Test] + public void Circle_BackingFields () + { + if (CircleViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var c = new MKCircle ()) + using (var cv = new CircleViewPoker (c)) { + Assert.AreSame (c, cv.CircleBackingField, "1a"); + Assert.AreSame (c, cv.Circle, "2a"); + } + } + } +} + +#endif // !__TVOS_ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/GeometryTest.cs b/tests/monotouch-test/MapKit/GeometryTest.cs new file mode 100644 index 000000000000..69509a13c962 --- /dev/null +++ b/tests/monotouch-test/MapKit/GeometryTest.cs @@ -0,0 +1,69 @@ +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GeometryTest { + + [Test] + public void MapPointsPerMeterAtLatitude () + { + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (0), Is.EqualTo (6.743).Within (0.001), "0"); + + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (90), Is.EqualTo (3.936).Within (0.001), "90"); + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (91), Is.EqualTo (0), "91"); + + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (-90), Is.EqualTo (2399.37).Within (0.01), "-90"); + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (-91), Is.EqualTo (0), "-91"); + + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (Double.NaN), Is.NaN, "NaN"); + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (Double.NegativeInfinity), Is.NaN, "NegativeInfinity"); + Assert.That (MKGeometry.MapPointsPerMeterAtLatitude (Double.PositiveInfinity), Is.NaN, "PositiveInfinity"); + } + + [Test] + public void MetersPerMapPointAtLatitude () + { + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (0), Is.EqualTo (0.148).Within (0.001), "0"); + + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (90), Is.EqualTo (0.254).Within (0.001), "90"); + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (91), Is.EqualTo (Double.PositiveInfinity), "91"); + + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (-90), Is.EqualTo (0.000416).Within (0.000001), "-90"); + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (-91), Is.EqualTo (Double.PositiveInfinity), "-91"); + + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (Double.NaN), Is.NaN, "NaN"); + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (Double.NegativeInfinity), Is.NaN, "NegativeInfinity"); + Assert.That (MKGeometry.MetersPerMapPointAtLatitude (Double.PositiveInfinity), Is.NaN, "PositiveInfinity"); + } + + [Test] + public void MetersBetweenMapPoints () + { + MKMapPoint a = new MKMapPoint (); + Assert.That (MKGeometry.MetersBetweenMapPoints (a, a), Is.EqualTo (0.0), "a-a"); + + MKMapPoint b = new MKMapPoint (1000, 1000); + Assert.That (MKGeometry.MetersBetweenMapPoints (b, b), Is.EqualTo (0.0), "b-b"); + + Assert.That (MKGeometry.MetersBetweenMapPoints (a, b), Is.EqualTo (18.153).Within (0.001), "a-b"); + Assert.That (MKGeometry.MetersBetweenMapPoints (b, a), Is.EqualTo (18.153).Within (0.001), "b-a"); + + MKMapPoint c = new MKMapPoint (Double.NaN, Double.NaN); + Assert.That (MKGeometry.MetersBetweenMapPoints (a, c), Is.NaN, "NaN"); + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/MapKit/LocalSearchRequestTest.cs b/tests/monotouch-test/MapKit/LocalSearchRequestTest.cs new file mode 100644 index 000000000000..6532cfa4effe --- /dev/null +++ b/tests/monotouch-test/MapKit/LocalSearchRequestTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for MKLocalSearchRequest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreLocation; +using MapKit; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LocalSearchRequestTest { + + [Test] + public void Default () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6, 1)) + Assert.Inconclusive ("Requires iOS 6.1"); + + using (var lsr = new MKLocalSearchRequest ()) { + Assert.Null (lsr.NaturalLanguageQuery, "NaturalLanguageQuery"); + Assert.That (lsr.Region.Center.Latitude, Is.EqualTo (0.0d), "Latitude"); + Assert.That (lsr.Region.Center.Longitude, Is.EqualTo (0.0d), "Longitude"); + Assert.That (lsr.Region.Span.LatitudeDelta, Is.EqualTo (0.0d), "LatitudeDelta"); + Assert.That (lsr.Region.Span.LongitudeDelta, Is.EqualTo (0.0d), "LongitudeDelta"); + + lsr.NaturalLanguageQuery = "restaurants"; + lsr.Region = new MKCoordinateRegion (new CLLocationCoordinate2D (47,-71), new MKCoordinateSpan (1,1)); + + // NaturalLanguageQuery is nullable, Region is not (value-type) + lsr.NaturalLanguageQuery = null; + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/LocalSearchTest.cs b/tests/monotouch-test/MapKit/LocalSearchTest.cs new file mode 100644 index 000000000000..290aa0c349df --- /dev/null +++ b/tests/monotouch-test/MapKit/LocalSearchTest.cs @@ -0,0 +1,74 @@ +// +// Unit tests for MKLocalSearch +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreLocation; +using MapKit; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LocalSearchTest { + + [Test] + public void Default () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6, 1)) + Assert.Inconclusive ("Requires iOS 6.1"); + } + + [Test] + public void EmptyRequest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6, 1)) + Assert.Inconclusive ("Requires iOS 6.1"); + + using (var lsr = new MKLocalSearchRequest ()) + using (MKLocalSearch ls = new MKLocalSearch (lsr)) { + lsr.Region = new MKCoordinateRegion (new CLLocationCoordinate2D (47,-71), new MKCoordinateSpan (1,1)); + bool wait = true; + ls.Start ((MKLocalSearchResponse response, NSError error) => { + wait = false; + }); + Assert.True (ls.IsSearching, "IsSearching"); + + // wait a bit before cancelling the search (so it really starts) + // otherwise IsSearching might never complete (on iOS8) and seems very random (in earlier versions) + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (2)); + ls.Cancel (); + +#if false + // give it some time to cancel - but eventually time out + int counter = 0; + while (wait && (counter < 5)) { + NSRunLoop.Main.RunUntil (DateTime.Now.AddSeconds (counter)); + counter++; + } + + Assert.False (ls.IsSearching, "IsSearching/Cancel"); +#endif + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/MapRectTest.cs b/tests/monotouch-test/MapKit/MapRectTest.cs new file mode 100644 index 000000000000..2a4c2faad9ef --- /dev/null +++ b/tests/monotouch-test/MapKit/MapRectTest.cs @@ -0,0 +1,141 @@ + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +using UIKit; +using CoreGraphics; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +using MonoTouch.CoreGraphics; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MapRectTest { + + [Test] + public void Defaults () + { + MKMapRect rect = new MKMapRect (); + Assert.False (rect.IsNull, "IsNull"); + Assert.True (rect.IsEmpty, "IsEmpty"); + Assert.False (rect.Spans180thMeridian, "default"); + Assert.True (rect.Equals (rect), "Equals"); + Assert.That (rect.ToString (), Is.EqualTo (@"{{0, 0}, {0, 0}}"), "default"); + + MKMapRect rect2 = new MKMapRect (); + Assert.True (rect == rect2, "=="); + Assert.False (rect != rect2, "!="); + Assert.That (rect.GetHashCode (), Is.EqualTo (rect2.GetHashCode ()), "GetHashCode"); + } + + [Test] + public void ContainsPoint () + { + MKMapRect rect = new MKMapRect (); + MKMapPoint point = new MKMapPoint (); + Assert.False (rect.Contains (point), "default"); + } + + [Test] + public void ContainsRect () + { + MKMapRect rect1 = new MKMapRect (); + MKMapRect rect2 = new MKMapRect (); + Assert.True (rect1.Contains (rect2), "default"); + } + + [Test] + public void Union () + { + MKMapRect rect1 = new MKMapRect (1, 2, 3, 4); + MKMapRect rect2 = new MKMapRect (4, 3, 2, 1); + MKMapRect union = MKMapRect.Union (rect1, rect2); + Assert.That (union.ToString (), Is.EqualTo (@"{{1, 2}, {5, 4}}"), "ToString"); + Assert.That (MKMapRect.Union (rect2, rect1), Is.EqualTo (union), "=="); + } + + [Test] + public void Intersection () + { + MKMapRect rect1 = new MKMapRect (1, 2, 3, 4); + MKMapRect rect2 = new MKMapRect (2, 3, 2, 1); + Assert.True (MKMapRect.Intersects (rect1, rect2), "Intersects"); + + MKMapRect n = MKMapRect.Intersection (rect1, rect2); + Assert.That (n.ToString (), Is.EqualTo (@"{{2, 3}, {2, 1}}"), "ToString"); + + MKMapRect rect3 = new MKMapRect (-2, -3, 2, 1); + Assert.False (MKMapRect.Intersects (rect1, rect3), "!Intersects"); + n = MKMapRect.Intersection (rect1, rect3); + Assert.True (n.IsNull, "IsNull"); + } + + [Test] + public void Inset () + { + MKMapRect rect = new MKMapRect (Double.PositiveInfinity, Double.PositiveInfinity, 0, 0); + MKMapRect rectin = rect.Inset (-1, 1); + Assert.True (rectin.IsNull, "IsNull"); + + rect = new MKMapRect (1, 2, 3, 4); + rectin = rect.Inset (-1, 1); + Assert.That (rectin.ToString (), Is.EqualTo (@"{{0, 3}, {5, 2}}"), "ToString"); + } + + [Test] + public void Offset () + { + MKMapRect rect = new MKMapRect (Double.PositiveInfinity, Double.PositiveInfinity, 0, 0); + MKMapRect rectoff = rect.Offset (-1, 1); + Assert.True (rectoff.IsNull, "IsNull"); + + rect = new MKMapRect (1, 2, 3, 4); + rectoff = rect.Offset (1, -1); + Assert.That (rectoff.ToString (), Is.EqualTo (@"{{2, 1}, {3, 4}}"), "ToString"); + } + + [Test] + public void Remainder () + { + MKMapRect rect = new MKMapRect (); + Assert.False (rect.Spans180thMeridian, "default"); + MKMapRect remainder = rect.Remainder (); + Assert.True (remainder.IsNull, "IsNull"); + + rect = new MKMapRect (-90, -90, 90, 90); + Assert.That (rect.Spans180thMeridian, Is.EqualTo (!TestRuntime.CheckiOSSystemVersion (7,1)), rect.ToString ()); + remainder = rect.Remainder (); + Assert.That (remainder.ToString (), Is.EqualTo (@"{{268435366, -90}, {90, 90}}"), "remainder"); + } + + [Test] + public void Divide () + { + MKMapRect rect = new MKMapRect (10, 20, 30, 40); + MKMapRect remainder; + MKMapRect slide = rect.Divide (2, CGRectEdge.MaxXEdge, out remainder); + Assert.That (slide.ToString (), Is.EqualTo (@"{{38, 20}, {2, 40}}"), "slide"); + Assert.That (remainder.ToString (), Is.EqualTo (@"{{10, 20}, {28, 40}}"), "remainder"); + } + + [Test] + public void NullRect () + { + MKMapRect nullRect = MKMapRect.Null; + MKMapRect expectedValue = new MKMapRect (double.PositiveInfinity, double.PositiveInfinity, 0, 0); + Assert.AreEqual (expectedValue, nullRect, "NullRect equals (PositiveInfinity, PositiveInfinity, 0, 0)"); + Assert.IsTrue (nullRect.IsNull, "IsNull"); + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/MapKit/MapViewTest.cs b/tests/monotouch-test/MapKit/MapViewTest.cs new file mode 100644 index 000000000000..3365250b4052 --- /dev/null +++ b/tests/monotouch-test/MapKit/MapViewTest.cs @@ -0,0 +1,311 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + class MapViewPoker : MKMapView { + + static FieldInfo bkAnnotations; + static FieldInfo bkSelectedAnnotations; + static FieldInfo bkOverlays; + + static MapViewPoker () + { + var t = typeof (MKMapView); + bkAnnotations = t.GetField ("__mt_Annotations_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkSelectedAnnotations = t.GetField ("__mt_SelectedAnnotations_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkOverlays = t.GetField ("__mt_Overlays_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public MapViewPoker () + { + } + + // if created (and even if unused) iOS will call it back later (retain) + public MapViewPoker (IntPtr p) : base (p) + { + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public NSObject [] AnnotationsBackingField { + get { + return (NSObject []) bkAnnotations.GetValue (this); + } + } + + public NSObject [] SelectedAnnotationsBackingField { + get { + return (NSObject []) bkSelectedAnnotations.GetValue (this); + } + } + + public NSObject [] OverlaysBackingField { + get { + return (NSObject []) bkOverlays.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class MapViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKMapView mv = new MKMapView (frame)) { + Assert.That (mv.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void Annotations_BackingFields () + { + if (MapViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var a = new MKCircle ()) // MKAnnotation is abstract +#if XAMCORE_2_0 + using (var o1 = new MKPolygon ()) // it must export 'coordinate' or this will fail + using (var o2 = new MKPolyline ()) +#else + using (NSObject o1 = new MKPolygon ()) // it must export 'coordinate' or this will fail + using (NSObject o2 = new MKPolyline ()) +#endif + using (var mv = new MapViewPoker ()) { + Assert.Null (mv.AnnotationsBackingField, "1a"); + Assert.That (mv.Annotations, Is.Empty, "1b"); + + mv.AddAnnotation (a); + Assert.AreSame (a, mv.AnnotationsBackingField [0], "2a"); + Assert.AreSame (a, mv.Annotations [0], "2b"); + + mv.RemoveAnnotation (a); + Assert.That (mv.AnnotationsBackingField, Is.Empty, "3a"); + Assert.That (mv.Annotations, Is.Empty, "3b"); + +#if XAMCORE_2_0 + mv.AddAnnotation (o1); +#else + mv.AddAnnotationObject (o1); +#endif + Assert.AreSame (o1, mv.AnnotationsBackingField [0], "4a"); + Assert.AreSame (o1, mv.Annotations [0], "4b"); + + mv.RemoveAnnotation (o1); + Assert.That (mv.AnnotationsBackingField, Is.Empty, "5a"); + Assert.That (mv.Annotations, Is.Empty, "5b"); + +#if XAMCORE_2_0 + mv.AddAnnotations (new IMKAnnotation[] { o1, o2 }); +#else + mv.AddAnnotationObjects (new NSObject[] { o1, o2 }); +#endif + // don't assume ordering + Assert.That (mv.AnnotationsBackingField.Length, Is.EqualTo (2), "6a"); + Assert.That (mv.Annotations.Length, Is.EqualTo (2), "6b"); + +#if XAMCORE_2_0 + mv.RemoveAnnotations (new IMKAnnotation[] { o2, o1 }); +#else + mv.RemoveAnnotations (new NSObject[] { o2, o1 }); +#endif + Assert.That (mv.AnnotationsBackingField, Is.Empty, "7a"); + Assert.That (mv.Annotations, Is.Empty, "7b"); + } + } + + [Test] + public void SelectedAnnotations_BackingFields () + { + if (MapViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) { + // This test selects annotations on a map view, but according to apple's docs + // and a lot of googling this will not necessarily work until the map view is + // show. Since we can't relinquish control of the UI thread, we have no option + // but ignoring this test. For now I've only seen it fail on iOS 7 DP4. + Assert.Inconclusive ("This test is not deterministic on iOS7 DP4."); + } + + using (var a = new MKCircle ()) // MKAnnotation is abstract +#if XAMCORE_2_0 + using (var o1 = new MKPolygon ()) // it must export 'coordinate' or this will fail + using (var o2 = new MKPolyline ()) +#else + using (NSObject o1 = new MKPolygon ()) // it must export 'coordinate' or this will fail + using (NSObject o2 = new MKPolyline ()) +#endif + using (var mv = new MapViewPoker ()) { + Assert.Null (mv.SelectedAnnotationsBackingField, "1a"); + Assert.Null (mv.SelectedAnnotations, "1b"); // not an empty array + + mv.SelectAnnotation (a, false); + Assert.AreSame (a, mv.SelectedAnnotationsBackingField [0], "2a"); + Assert.AreSame (a, mv.SelectedAnnotations [0], "2b"); + + // sanity + Assert.Null (mv.AnnotationsBackingField, "3a"); + Assert.That (mv.Annotations, Is.Empty, "3b"); + +#if XAMCORE_2_0 + mv.SelectedAnnotations = new IMKAnnotation[] { o1, o2 }; +#else + mv.SelectedAnnotations = new NSObject[] { o1, o2 }; +#endif + // note: when assigning the property only the first item is selected (by design) + // so we're not exactly backing up correctly (we still hold 'o2') + // OTOH we do not want to recursively [PostGet] the same property (unless handled by the generator) + Assert.That (mv.SelectedAnnotationsBackingField.Length, Is.EqualTo (2), "4a"); + Assert.That (mv.SelectedAnnotations.Length, Is.EqualTo (1), "4b"); + + mv.DeselectAnnotation (o1, false); + // since only 'o1' was really selected, unselecting it will return null + Assert.Null (mv.SelectedAnnotationsBackingField, "5a"); + Assert.Null (mv.SelectedAnnotations, "5b"); // not an empty array + } + } + + [Test] + public void Overlays_BackingFields () + { + if (MapViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + +#if XAMCORE_2_0 + using (var o1 = new MKPolygon ()) // it must export 'boundingMapRect' or this will fail + using (var o2 = new MKPolyline ()) +#else + using (NSObject o1 = new MKPolygon ()) // it must export 'boundingMapRect' or this will fail + using (NSObject o2 = new MKPolyline ()) +#endif + using (var mv = new MapViewPoker ()) { +#if XAMCORE_2_0 + var overlays = new IMKOverlay [] { o1, o2 }; +#else + var overlays = new NSObject [] { o1, o2 }; +#endif + Assert.Null (mv.OverlaysBackingField, "1a"); + Assert.Null (mv.Overlays, "1b"); // not an empty array + + mv.AddOverlay (o1); + Assert.AreSame (o1, mv.OverlaysBackingField [0], "2a"); + Assert.AreSame (o1, mv.Overlays [0], "2b"); + + mv.InsertOverlay (o2, 0); + Assert.That (mv.OverlaysBackingField.Length, Is.EqualTo (2), "3a"); + Assert.That (mv.Overlays.Length, Is.EqualTo (2), "3b"); + + mv.RemoveOverlay (o1); + Assert.AreSame (o2, mv.OverlaysBackingField [0], "4a"); + Assert.AreSame (o2, mv.Overlays [0], "4b"); + + mv.InsertOverlayAbove (o1, o2); + Assert.That (mv.OverlaysBackingField.Length, Is.EqualTo (2), "5a"); + Assert.That (mv.Overlays.Length, Is.EqualTo (2), "5b"); + + mv.RemoveOverlay (o2); + Assert.AreSame (o1, mv.OverlaysBackingField [0], "6a"); + Assert.AreSame (o1, mv.Overlays [0], "6b"); + + mv.InsertOverlayBelow (o2, o1); + Assert.That (mv.OverlaysBackingField.Length, Is.EqualTo (2), "7a"); + Assert.That (mv.Overlays.Length, Is.EqualTo (2), "7b"); + + mv.RemoveOverlays (overlays); + Assert.That (mv.OverlaysBackingField, Is.Empty, "8a"); + Assert.That (mv.Overlays, Is.Empty, "8b"); + + mv.AddOverlays (overlays); + Assert.That (mv.OverlaysBackingField.Length, Is.EqualTo (2), "9a"); + Assert.That (mv.Overlays.Length, Is.EqualTo (2), "9b"); + } + } + + [Test] + public void Overlays () + { + using (var polygon = new MKPolygon ()) + using (var polyline = new MKPolyline ()) + using (var circle = new MKCircle ()) + using (MKMapView mv = new MKMapView ()) { + // old API accepted NSObject (limited protocol support) + mv.AddOverlay (polygon); + Assert.That (mv.Overlays.Length, Is.EqualTo (1), "1"); + mv.RemoveOverlay (polygon); + Assert.That (mv.Overlays, Is.Empty, "2"); + +#if XAMCORE_2_0 + IMKOverlay[] list = { polygon, polyline, circle }; +#else + NSObject[] list = { polygon, polyline, circle }; +#endif + mv.AddOverlays (list); + Assert.That (mv.Overlays.Length, Is.EqualTo (3), "3"); + mv.RemoveOverlays (list); + Assert.That (mv.Overlays, Is.Empty, "4"); + } + } + + [Test] + public void Overlays7 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires 7.0+"); + + using (var polygon = new MKPolygon ()) + using (var polyline = new MKPolyline ()) + using (var circle = new MKCircle ()) + using (var tile = new MKTileOverlay ()) + using (MKMapView mv = new MKMapView ()) { + // new API accepted MKOverlay (better protocol support) + mv.AddOverlay (polygon, MKOverlayLevel.AboveLabels); + mv.AddOverlay (tile, MKOverlayLevel.AboveLabels); + Assert.That (mv.Overlays.Length, Is.EqualTo (2), "1"); + mv.RemoveOverlay (tile); + mv.RemoveOverlay (polygon); + Assert.That (mv.Overlays, Is.Empty, "2"); + + IMKOverlay[] list = { polygon, polyline, circle, tile }; + mv.AddOverlays (list, MKOverlayLevel.AboveRoads); + Assert.That (mv.Overlays.Length, Is.EqualTo (4), "3"); + mv.RemoveOverlays (list); + Assert.That (mv.Overlays, Is.Empty, "4"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/OverlayPathRendererTest.cs b/tests/monotouch-test/MapKit/OverlayPathRendererTest.cs new file mode 100644 index 000000000000..3d5f4389ee88 --- /dev/null +++ b/tests/monotouch-test/MapKit/OverlayPathRendererTest.cs @@ -0,0 +1,58 @@ +// +// MKOverlayPathRenderer Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreLocation; +using MapKit; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class OverlayPathRendererTest { + + [Test] + public void DefaultCtor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS 7.0"); + + using (var opr = new MKOverlayPathRenderer ()) { + Assert.Null (opr.Path, "Path"); + } + } + + [Test] + public void CtorOverlay () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS 7.0"); + + var loc = new CLLocationCoordinate2D (40, 70); + using (var overlay = MKCircle.Circle (loc, 2000)) + using (var opr = new MKOverlayPathRenderer (overlay)) { + Assert.Null (opr.Path, "Path"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/OverlayPathViewTest.cs b/tests/monotouch-test/MapKit/OverlayPathViewTest.cs new file mode 100644 index 000000000000..51ae61db4327 --- /dev/null +++ b/tests/monotouch-test/MapKit/OverlayPathViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class OverlayPathViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKOverlayPathView opv = new MKOverlayPathView (frame)) { + Assert.That (opv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/OverlayViewTest.cs b/tests/monotouch-test/MapKit/OverlayViewTest.cs new file mode 100644 index 000000000000..971156cd9904 --- /dev/null +++ b/tests/monotouch-test/MapKit/OverlayViewTest.cs @@ -0,0 +1,90 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if !__WATCHOS__ +using System.Drawing; +#endif +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + class OverlayViewPoker : MKOverlayView { + + static FieldInfo bkOverlay; + + static OverlayViewPoker () + { + var t = typeof (MKOverlayView); + bkOverlay = t.GetField ("__mt_Overlay_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + +#if XAMCORE_2_0 + public OverlayViewPoker (IMKOverlay overlay) : base (overlay) +#else + public OverlayViewPoker (NSObject overlay) : base (overlay) +#endif + { + } + + public NSObject OverlayBackingField { + get { + return (NSObject) bkOverlay.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class OverlayViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKOverlayView ov = new MKOverlayView (frame)) { + Assert.That (ov.Frame, Is.EqualTo (frame), "Frame"); + Assert.Null (ov.Overlay, "Overlay"); + } + } + + [Test] + public void Overlay_BackingFields () + { + if (OverlayViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var c = new MKCircle ()) + using (var ov = new OverlayViewPoker (c)) { + Assert.AreSame (c, ov.Overlay, "1a"); + Assert.AreSame (c, ov.Overlay, "2a"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/PinAnnotationViewTest.cs b/tests/monotouch-test/MapKit/PinAnnotationViewTest.cs new file mode 100644 index 000000000000..6f79d0e9dad3 --- /dev/null +++ b/tests/monotouch-test/MapKit/PinAnnotationViewTest.cs @@ -0,0 +1,69 @@ +// +// MKPinAnnotationView Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012, 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PinAnnotationViewTest { + + [Test] + public void Ctor_Annotation () + { + using (var a = new MKPolyline ()) + using (MKPinAnnotationView av = new MKPinAnnotationView (a, "reuse")) { + Assert.AreSame (a, av.Annotation, "Annotation"); + + if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) // Crashes with EXC_BAD_ACCESS (SIGABRT) if < iOS 7.0 + Assert.False (av.AnimatesDrop, "AnimatesDrop"); + + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + return; + Assert.That (av.PinColor, Is.EqualTo (MKPinAnnotationColor.Red), "PinColor"); + Assert.NotNull (av.PinTintColor, "PinTintColor"); + } + } + + [Test] + public void InitWithFrame () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) // Crashes with EXC_BAD_ACCESS (SIGABRT) if < iOS 7.0 + Assert.Inconclusive ("Crashes with EXC_BAD_ACCESS (SIGABRT) if < iOS 7.0"); + + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (var av = new MKPinAnnotationView (frame)) { + Assert.That (av.Frame.ToString (), Is.EqualTo (frame.ToString ()), "Frame"); // fp comparison fails + Assert.Null (av.Annotation, "Annotation"); + Assert.False (av.AnimatesDrop, "AnimatesDrop"); + + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + return; + Assert.That (av.PinColor, Is.EqualTo (MKPinAnnotationColor.Red), "PinColor"); + Assert.Null (av.PinTintColor, "PinTintColor"); // differs from the other init call + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/PolygonTest.cs b/tests/monotouch-test/MapKit/PolygonTest.cs new file mode 100644 index 000000000000..223229db4e9c --- /dev/null +++ b/tests/monotouch-test/MapKit/PolygonTest.cs @@ -0,0 +1,121 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreLocation; +using MapKit; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PolygonTest { + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromPoints_Null () + { + MKPolygon.FromPoints (null); + } + + [Test] + public void FromPoints_Interior_Null () + { + MKPolygon pg = MKPolygon.FromPoints (new MKMapPoint [] { }, null); + CheckEmpty (pg); + } + + void CheckEmpty (MKPolygon pg) + { + // MKAnnotation + Assert.That (pg.Coordinate.Longitude, Is.NaN, "Coordinate.Longitude"); + Assert.That (pg.Coordinate.Latitude, Is.NaN, "Coordinate.Latitude"); + Assert.Null (pg.Title, "Title"); + Assert.Null (pg.Subtitle, "Subtitle"); + // MKOverlay + Assert.True (Double.IsPositiveInfinity (pg.BoundingMapRect.Origin.X), "BoundingMapRect.Origin.X"); + Assert.True (Double.IsPositiveInfinity (pg.BoundingMapRect.Origin.Y), "BoundingMapRect.Origin.Y"); + Assert.True (Double.IsNegativeInfinity (pg.BoundingMapRect.Size.Height), "BoundingMapRect.Size.Height"); + Assert.True (Double.IsNegativeInfinity (pg.BoundingMapRect.Size.Width), "BoundingMapRect.Size.Width"); + Assert.False (pg.Intersects (pg.BoundingMapRect), "Intersect/Self"); + MKMapRect rect = new MKMapRect (0, 0, 0, 0); + Assert.False (pg.Intersects (rect), "Intersect/Empty"); + + ShapeTest.CheckShape (pg); + } + + [Test] + public void FromPoints_Empty () + { + MKPolygon pg = MKPolygon.FromPoints (new MKMapPoint [] { }); + CheckEmpty (pg); + } + + [Test] + public void FromPoints_Interior_Empty () + { + MKPolygon pg = MKPolygon.FromPoints (new MKMapPoint [] { }, new MKPolygon [] { }); + CheckEmpty (pg); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromCoordinates_Null () + { + MKPolygon.FromCoordinates (null); + } + + [Test] + public void FromCoordinates_Interior_Null () + { + MKPolygon pg = MKPolygon.FromCoordinates (new CLLocationCoordinate2D [] { }, null); + CheckEmpty (pg); + } + + [Test] + public void FromCoordinates_Empty () + { + MKPolygon pg = MKPolygon.FromCoordinates (new CLLocationCoordinate2D [] { }); + CheckEmpty (pg); + } + + [Test] + public void FromCoordinates_Interior_Empty () + { + MKPolygon pg = MKPolygon.FromCoordinates (new CLLocationCoordinate2D [] { }, new MKPolygon [] { }); + CheckEmpty (pg); + } + +#if false + // Annotations that support dragging should implement this method to update the position of the annotation. + // keyword is SHOULD - it's not working for MKPolygon + // http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html#//apple_ref/occ/intf/MKAnnotation + [Test] + public void setCoordinate_Selector () + { + MKPolygon pg = MKPolygon.FromPoints (new MKMapPoint [] { }); + try { + pg.Coordinate = new CLLocationCoordinate2D (10, 20); + } + catch (MonoTouchException mte) { + Assert.True (mte.Message.Contains ("unrecognized selector sent to instance")); + } + catch { + Assert.Fail ("API could be working/implemented"); + } + } +#endif + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/PolygonViewTest.cs b/tests/monotouch-test/MapKit/PolygonViewTest.cs new file mode 100644 index 000000000000..3608612db268 --- /dev/null +++ b/tests/monotouch-test/MapKit/PolygonViewTest.cs @@ -0,0 +1,99 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + class PolygonViewPoker : MKPolygonView { + + static FieldInfo bkPolygon; + + static PolygonViewPoker () + { + var t = typeof (MKPolygonView); + bkPolygon = t.GetField ("__mt_Polygon_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public PolygonViewPoker () + { + } + + public PolygonViewPoker (MKPolygon polygon) : base (polygon) + { + } + + public MKPolygon PolygonBackingField { + get { + return (MKPolygon) bkPolygon.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class PolygonViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKPolygonView pv = new MKPolygonView (frame)) { + Assert.That (pv.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void Defaults_BackingFields () + { + if (PolygonViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var pv = new PolygonViewPoker ()) { + Assert.Null (pv.PolygonBackingField, "1a"); + Assert.Null (pv.Polygon, "2a"); + } + } + + [Test] + public void Polygon_BackingFields () + { + if (PolygonViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var p = new MKPolygon ()) + using (var pv = new PolygonViewPoker (p)) { + Assert.AreSame (p, pv.PolygonBackingField, "1a"); + Assert.AreSame (p, pv.Polygon, "2a"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/PolylineTest.cs b/tests/monotouch-test/MapKit/PolylineTest.cs new file mode 100644 index 000000000000..34e2cbb446ea --- /dev/null +++ b/tests/monotouch-test/MapKit/PolylineTest.cs @@ -0,0 +1,103 @@ +// Copyright 2011, 2013 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreLocation; +using MapKit; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PolylineTest { + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromPoints_Null () + { + MKPolyline.FromPoints (null); + } + + void CheckEmpty (MKPolyline pl) + { + // MKAnnotation + Assert.That (pl.Coordinate.Longitude, Is.NaN, "Coordinate.Longitude"); + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.That (pl.Coordinate.Latitude, Is.EqualTo (-90f), "Coordinate.Latitude"); + else + Assert.That (pl.Coordinate.Latitude, Is.NaN, "Coordinate.Latitude"); + Assert.Null (pl.Title, "Title"); + Assert.Null (pl.Subtitle, "Subtitle"); + // MKOverlay + Assert.True (Double.IsPositiveInfinity (pl.BoundingMapRect.Origin.X), "BoundingMapRect.Origin.X"); + Assert.True (Double.IsPositiveInfinity (pl.BoundingMapRect.Origin.Y), "BoundingMapRect.Origin.Y"); + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + Assert.That (pl.BoundingMapRect.Size.Height, Is.EqualTo (0.0f), "BoundingMapRect.Size.Height"); + Assert.That (pl.BoundingMapRect.Size.Width, Is.EqualTo (0.0f), "BoundingMapRect.Size.Width"); + } else { + Assert.True (Double.IsNegativeInfinity (pl.BoundingMapRect.Size.Height), "BoundingMapRect.Size.Height"); + Assert.True (Double.IsNegativeInfinity (pl.BoundingMapRect.Size.Width), "BoundingMapRect.Size.Width"); + } + Assert.False (pl.Intersects (pl.BoundingMapRect), "Intersect/Self"); + MKMapRect rect = new MKMapRect (0, 0, 0, 0); + Assert.False (pl.Intersects (rect), "Intersect/Empty"); + + ShapeTest.CheckShape (pl); + } + + [Test] + public void From_PointEmpty () + { + MKPolyline pl = MKPolyline.FromPoints (new MKMapPoint [] { }); + CheckEmpty (pl); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FromCoordinates_Null () + { + MKPolyline.FromCoordinates (null); + } + + [Test] + public void FromCoordinates_Empty () + { + MKPolyline pl = MKPolyline.FromCoordinates (new CLLocationCoordinate2D [] { }); + CheckEmpty (pl); + } + +#if false + // Annotations that support dragging should implement this method to update the position of the annotation. + // keyword is SHOULD - it's not working for MKPolyline + // http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html#//apple_ref/occ/intf/MKAnnotation + [Test] + public void setCoordinate_Selector () + { + MKPolyline pl = MKPolyline.FromPoints (new MKMapPoint [] { }); + try { + pl.Coordinate = new CLLocationCoordinate2D (10, 20); + } + catch (MonoTouchException mte) { + Assert.True (mte.Message.Contains ("unrecognized selector sent to instance")); + } + catch { + Assert.Fail ("API could be working/implemented"); + } + } +#endif + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/PolylineViewTest.cs b/tests/monotouch-test/MapKit/PolylineViewTest.cs new file mode 100644 index 000000000000..f017e4199ca7 --- /dev/null +++ b/tests/monotouch-test/MapKit/PolylineViewTest.cs @@ -0,0 +1,98 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MapKit { + + class PolylineViewPoker : MKPolylineView { + + static FieldInfo bkPolyline; + + static PolylineViewPoker () + { + var t = typeof (MKPolylineView); + bkPolyline = t.GetField ("__mt_Polyline_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public PolylineViewPoker () + { + } + + public PolylineViewPoker (MKPolyline polyline) : base (polyline) + { + } + + public MKPolyline PolylineBackingField { + get { + return (MKPolyline) bkPolyline.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class PolylineViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MKPolylineView pl = new MKPolylineView (frame)) { + Assert.That (pl.Frame, Is.EqualTo (frame), "Frame"); + } + } + [Test] + public void Defaults_BackingFields () + { + if (PolylineViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var pv = new PolylineViewPoker ()) { + Assert.Null (pv.PolylineBackingField, "1a"); + Assert.Null (pv.Polyline, "2a"); + } + } + + [Test] + public void Polygon_BackingFields () + { + if (PolylineViewPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var p = new MKPolyline ()) + using (var pv = new PolylineViewPoker (p)) { + Assert.AreSame (p, pv.PolylineBackingField, "1a"); + Assert.AreSame (p, pv.Polyline, "2a"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/ShapeTest.cs b/tests/monotouch-test/MapKit/ShapeTest.cs new file mode 100644 index 000000000000..062586ea81a6 --- /dev/null +++ b/tests/monotouch-test/MapKit/ShapeTest.cs @@ -0,0 +1,38 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using CoreLocation; +using MapKit; +#else +using MonoTouch.CoreLocation; +using MonoTouch.Foundation; +using MonoTouch.MapKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ShapeTest { + + // used for types that inherits from MKShape + static public void CheckShape (MKShape shape) + { + // MKShape provides read/write properties for Title and Subtitle + // even if they are read-only according to MKAnnotation + // http://xamarin.assistly.com/agent/case/5441 + shape.Title = "Title"; + Assert.That (shape.Title, Is.EqualTo ("Title"), "Title/set/get"); + shape.Subtitle = "Subtitle"; + Assert.That (shape.Subtitle, Is.EqualTo ("Subtitle"), "Subtitle/set/get"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MapKit/UserTrackingBarButtonItemTest.cs b/tests/monotouch-test/MapKit/UserTrackingBarButtonItemTest.cs new file mode 100644 index 000000000000..33ca3f023146 --- /dev/null +++ b/tests/monotouch-test/MapKit/UserTrackingBarButtonItemTest.cs @@ -0,0 +1,98 @@ +// +// MKUserTrackingBarButtonItem Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using MapKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.MapKit; +using MonoTouch.ObjCRuntime; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.MapKit { + + class UserTrackingBarButtonItemPoker : MKUserTrackingBarButtonItem { + + static FieldInfo bkMapView; + + static UserTrackingBarButtonItemPoker () + { + var t = typeof (MKUserTrackingBarButtonItem); + bkMapView = t.GetField ("__mt_MapView_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public UserTrackingBarButtonItemPoker (MKMapView view) : base (view) + { + } + + public MKMapView MapViewBackingField { + get { + return (MKMapView) bkMapView.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class UserTrackingBarButtonItemTest { + + [Test] + public void Ctor_Defaults () + { + using (var a = new NSObject ()) + using (MKUserTrackingBarButtonItem ut = new MKUserTrackingBarButtonItem ()) { + Assert.Null (ut.MapView, "MapView"); + } + } + + [Test] + public void Ctor_MKMapView () + { + if (!TestRuntime.CheckSDKVersion (7, 0)) + Assert.Ignore ("This test crashes with the iOS 6 SDK and an iOS 7 device [iOS bug] (so just force at least an iOS 7 SDK)"); + + using (MKMapView mv = new MKMapView ()) + using (MKUserTrackingBarButtonItem ut = new MKUserTrackingBarButtonItem (mv)) { + Assert.AreSame (mv, ut.MapView, "MapView"); + } + } + + [Test] + public void MapView_BackingFields () + { + if (!TestRuntime.CheckSDKVersion (7, 0)) + Assert.Ignore ("This test crashes with the iOS 6 SDK and an iOS 7 device [iOS bug] (so just force at least an iOS 7 SDK)"); + + if (UserTrackingBarButtonItemPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var mv = new MKMapView ()) + using (var ut = new UserTrackingBarButtonItemPoker (mv)) { + Assert.AreSame (mv, ut.MapViewBackingField, "1a"); + Assert.AreSame (mv, ut.MapView, "2a"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MediaAccessibility/AudibleMediaTest.cs b/tests/monotouch-test/MediaAccessibility/AudibleMediaTest.cs new file mode 100644 index 000000000000..8062ad13a621 --- /dev/null +++ b/tests/monotouch-test/MediaAccessibility/AudibleMediaTest.cs @@ -0,0 +1,46 @@ +// +// MAAudibleMedia Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using MediaAccessibility; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaAccessibility; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaAccessibility { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class AudibleMediaTest { + + [Test] + public void PreferredCharacteristics () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Ignore ("requires iOS8+"); + + if (TestRuntime.CheckSystemAndSDKVersion (9, 0)) { + Assert.NotNull (MAAudibleMedia.GetPreferredCharacteristics ()); + } else { + Assert.Null (MAAudibleMedia.GetPreferredCharacteristics ()); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MediaAccessibility/CaptionAppearanceTest.cs b/tests/monotouch-test/MediaAccessibility/CaptionAppearanceTest.cs new file mode 100644 index 000000000000..fb388a488029 --- /dev/null +++ b/tests/monotouch-test/MediaAccessibility/CaptionAppearanceTest.cs @@ -0,0 +1,59 @@ +// +// MACaptionAppearance Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using MediaAccessibility; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaAccessibility; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaAccessibility { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class CaptionAppearanceTest { + +#if !XAMCORE_3_0 + [Test] + public void Fields () + { + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + Assert.NotNull (MACaptionAppearance.MediaCharacteristicDescribesMusicAndSoundForAccessibility, "MediaCharacteristicDescribesMusicAndSoundForAccessibility"); + Assert.NotNull (MACaptionAppearance.MediaCharacteristicTranscribesSpokenDialogForAccessibility, "MediaCharacteristicTranscribesSpokenDialogForAccessibility"); + Assert.NotNull (MACaptionAppearance.SettingsChangedNotification, "SettingsChangedNotification"); + } else { + Assert.Null (MACaptionAppearance.MediaCharacteristicDescribesMusicAndSoundForAccessibility, "MediaCharacteristicDescribesMusicAndSoundForAccessibility"); + Assert.Null (MACaptionAppearance.MediaCharacteristicTranscribesSpokenDialogForAccessibility, "MediaCharacteristicTranscribesSpokenDialogForAccessibility"); + Assert.Null (MACaptionAppearance.SettingsChangedNotification, "SettingsChangedNotification"); + } + } +#endif // !XAMCORE_3_0 + + [Test] + [Culture ("en")] // this setting depends on locale of the device according to apple docs on MACaptionAppearanceGetDisplayType, we know english works + public void GetDisplayType () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("requires iOS7+"); + + Assert.That (MACaptionAppearance.GetDisplayType (MACaptionAppearanceDomain.Default), Is.EqualTo (MACaptionAppearanceDisplayType.Automatic), "Default"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/MediaItemArtworkTest.cs b/tests/monotouch-test/MediaPlayer/MediaItemArtworkTest.cs new file mode 100644 index 000000000000..dfe2f532fec6 --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/MediaItemArtworkTest.cs @@ -0,0 +1,42 @@ +// Copyright 2014 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.IO; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MediaItemArtworkTest { + + [Test] + public void ImageWithSize () + { + // trying to reproduce issue from bug #23619 - but turned out to be an iOS8 bug + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var img = UIImage.FromFile (file)) + using (var mia = new MPMediaItemArtwork (img)) { + Assert.That (img.Size.ToString (), Is.EqualTo ("{Width=32, Height=32}"), "original"); + var upscale = mia.ImageWithSize (new SizeF (100, 100)); + Assert.That (upscale.Size.ToString (), Is.EqualTo ("{Width=32, Height=32}"), "upscale"); + var downscale = mia.ImageWithSize (new SizeF (16, 16)); + Assert.That (downscale.Size.ToString (), Is.EqualTo ("{Width=32, Height=32}"), "downscale"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/MediaItemTest.cs b/tests/monotouch-test/MediaPlayer/MediaItemTest.cs new file mode 100644 index 000000000000..278a27a7efcc --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/MediaItemTest.cs @@ -0,0 +1,80 @@ +// Copyright 2014 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MediaItemTest { + + [Test] + public void DefaultValues () + { + if (Runtime.Arch != Arch.DEVICE) + Assert.Inconclusive ("This test only works on device (the simulator does not have an iPod Music library)."); + + using (var q = new MPMediaQuery ()) { + var items = q.Items; + if (items.Length == 0) + Assert.Inconclusive ("This test needs music in the music library on the device."); + + var six_dot_oh = TestRuntime.CheckSystemAndSDKVersion (6, 0); + + foreach (var i in items) { + object dummy; + Assert.DoesNotThrow (() => dummy = i.AlbumArtist, "AlbumArtist"); + Assert.DoesNotThrow (() => dummy = i.AlbumArtistPersistentID, "AlbumArtistPersistentID"); + Assert.DoesNotThrow (() => dummy = i.AlbumPersistentID, "AlbumPersistentID"); + Assert.DoesNotThrow (() => dummy = i.AlbumTitle, "AlbumTitle"); + Assert.DoesNotThrow (() => dummy = i.AlbumTrackCount, "AlbumTrackCount"); + Assert.DoesNotThrow (() => dummy = i.AlbumTrackNumber, "AlbumTrackNumber"); + Assert.DoesNotThrow (() => dummy = i.Artist, "Artist"); + Assert.DoesNotThrow (() => dummy = i.ArtistPersistentID, "ArtistPersistentID"); + Assert.DoesNotThrow (() => dummy = i.Artwork, "Artwork"); + Assert.DoesNotThrow (() => dummy = i.AssetURL, "AssetURL"); + Assert.DoesNotThrow (() => dummy = i.BeatsPerMinute, "BeatsPerMinute"); + Assert.DoesNotThrow (() => dummy = i.BookmarkTime, "BookmarkTime"); + Assert.DoesNotThrow (() => dummy = i.Comments, "Comments"); + Assert.DoesNotThrow (() => dummy = i.Composer, "Composer"); + Assert.DoesNotThrow (() => dummy = i.ComposerPersistentID, "ComposerPersistentID"); + Assert.DoesNotThrow (() => dummy = i.DiscCount, "DiscCount"); + Assert.DoesNotThrow (() => dummy = i.DiscNumber, "DiscNumber"); + Assert.DoesNotThrow (() => dummy = i.Genre, "Genre"); + Assert.DoesNotThrow (() => dummy = i.GenrePersistentID, "GenrePersistentID"); + if (six_dot_oh) + Assert.DoesNotThrow (() => dummy = i.IsCloudItem, "IsCloudItem"); + Assert.DoesNotThrow (() => dummy = i.IsCompilation, "IsCompilation"); + Assert.DoesNotThrow (() => dummy = i.LastPlayedDate, "LastPlayedDate"); + Assert.DoesNotThrow (() => dummy = i.Lyrics, "Lyrics"); + Assert.DoesNotThrow (() => dummy = i.MediaType, "MediaType"); + Assert.DoesNotThrow (() => dummy = i.PersistentID, "PersistentID"); + Assert.DoesNotThrow (() => dummy = i.PlaybackDuration, "PlaybackDuration"); + Assert.DoesNotThrow (() => dummy = i.PlayCount, "PlayCount"); + Assert.DoesNotThrow (() => dummy = i.PodcastPersistentID, "PodcastPersistentID"); + Assert.DoesNotThrow (() => dummy = i.PodcastTitle, "PodcastTitle"); + Assert.DoesNotThrow (() => dummy = i.Rating, "Rating"); + Assert.DoesNotThrow (() => dummy = i.ReleaseDate, "ReleaseDate"); + Assert.DoesNotThrow (() => dummy = i.SkipCount, "SkipCount"); + Assert.DoesNotThrow (() => dummy = i.Title, "Title"); + Assert.DoesNotThrow (() => dummy = i.UserGrouping, "UserGrouping"); + } + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/MoviePlayerControllerTest.cs b/tests/monotouch-test/MediaPlayer/MoviePlayerControllerTest.cs new file mode 100644 index 000000000000..9ffd6ab8189b --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/MoviePlayerControllerTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for MPMoviePlayerController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using UIKit; +using iAd; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.UIKit; +using MonoTouch.iAd; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MoviePlayerControllerTest { + +#if !XAMCORE_2_0 + [Test] + public void PreparePrerollAds_Old () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7,0)) + Assert.Inconclusive ("Requires 7.0+"); + + MPMoviePlayerController mpc = null; + mpc.PreparePrerollAds (); + } +#endif + + [Test] + public void PreparePrerollAds_New () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7,0)) + Assert.Inconclusive ("Requires 7.0+"); + + MPMoviePlayerController.PrepareForPrerollAds (); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/PlayableContentManagerTest.cs b/tests/monotouch-test/MediaPlayer/PlayableContentManagerTest.cs new file mode 100644 index 000000000000..edff0932d5e0 --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/PlayableContentManagerTest.cs @@ -0,0 +1,73 @@ +// +// Unit tests for MPPlayableContentManager +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PlayableContentManagerTest { + + class DataSource : MPPlayableContentDataSource { +#if XAMCORE_2_0 + #region implemented abstract members of MPPlayableContentDataSource + public override MPContentItem ContentItem (NSIndexPath indexPath) + { + throw new NotImplementedException (); + } + public override nint NumberOfChildItems (NSIndexPath indexPath) + { + throw new NotImplementedException (); + } + #endregion +#endif + } + + class Delegate : MPPlayableContentDelegate { + } + + [Test] + public void Shared () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 1)) + Assert.Inconclusive ("Requires 7.1+"); + + MPPlayableContentManager shared = MPPlayableContentManager.Shared; + Assert.Null (shared.DataSource, "DataSource"); + Assert.Null (shared.Delegate, "Delegate"); + + try { + using (var ds = new DataSource ()) + using (var dg = new Delegate ()) { + shared.DataSource = ds; + shared.Delegate = dg; + } + } + finally { + shared.DataSource = null; + shared.Delegate = null; + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/RemoteCommandCenterTest.cs b/tests/monotouch-test/MediaPlayer/RemoteCommandCenterTest.cs new file mode 100644 index 000000000000..1ca152e0ae1f --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/RemoteCommandCenterTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for MPRemoteCommandCenter +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class RemoteCommandCenterTest { + + [Test] + public void Shared () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 1)) + Assert.Inconclusive ("Requires 7.1+"); + + MPRemoteCommandCenter shared = MPRemoteCommandCenter.Shared; + Assert.NotNull (shared.BookmarkCommand, "BookmarkCommand"); + Assert.NotNull (shared.ChangePlaybackRateCommand, "ChangePlaybackRateCommand"); + Assert.NotNull (shared.DislikeCommand, "DislikeCommand"); + Assert.NotNull (shared.LikeCommand, "LikeCommand"); + Assert.NotNull (shared.NextTrackCommand, "NextTrackCommand"); + Assert.NotNull (shared.PauseCommand, "PauseCommand"); + Assert.NotNull (shared.PlayCommand, "PlayCommand"); + Assert.NotNull (shared.PreviousTrackCommand, "PreviousTrackCommand"); + Assert.NotNull (shared.SeekBackwardCommand, "SeekBackwardCommand"); + Assert.NotNull (shared.SeekForwardCommand, "SeekForwardCommand"); + Assert.NotNull (shared.SkipBackwardCommand, "SkipBackwardCommand"); + Assert.NotNull (shared.SkipForwardCommand, "SkipForwardCommand"); + Assert.NotNull (shared.StopCommand, "StopCommand"); + Assert.NotNull (shared.TogglePlayPauseCommand, "TogglePlayPauseCommand"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/SkipIntervalCommandTest.cs b/tests/monotouch-test/MediaPlayer/SkipIntervalCommandTest.cs new file mode 100644 index 000000000000..43b65d8583c6 --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/SkipIntervalCommandTest.cs @@ -0,0 +1,52 @@ +// +// Unit tests for MPSkipIntervalCommand +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SkipIntervalCommandTest { + + static bool manualBindingDone; + [Test] + public void ManualBinding () + { + if (manualBindingDone) + Assert.Ignore ("This test can only be executed once, it modifies global state."); + manualBindingDone = true; + + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 1)) + Assert.Inconclusive ("Requires 7.1+"); + + MPSkipIntervalCommand skip = MPRemoteCommandCenter.Shared.SkipBackwardCommand; + + Assert.Null (skip.PreferredIntervals, "PreferredIntervals"); + double[] intervals = new [] { 1.0d, 3.14d }; + skip.PreferredIntervals = intervals; + + Assert.That (skip.PreferredIntervals, Is.EqualTo (intervals), "identical"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MediaPlayer/VolumeViewTest.cs b/tests/monotouch-test/MediaPlayer/VolumeViewTest.cs new file mode 100644 index 000000000000..bb7c8ce15fb4 --- /dev/null +++ b/tests/monotouch-test/MediaPlayer/VolumeViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using MediaPlayer; +#else +using MonoTouch.Foundation; +using MonoTouch.MediaPlayer; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MediaPlayer { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VolumeViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (MPVolumeView vv = new MPVolumeView (frame)) { + Assert.That (vv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MediaToolbox/AudioProcessingTapTest.cs b/tests/monotouch-test/MediaToolbox/AudioProcessingTapTest.cs new file mode 100644 index 000000000000..7b081931f22b --- /dev/null +++ b/tests/monotouch-test/MediaToolbox/AudioProcessingTapTest.cs @@ -0,0 +1,79 @@ +// +// Unit tests for MTAudioProcessingTap +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2012 Xamarin Inc, All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +using MediaToolbox; +using AudioToolbox; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.MediaToolbox; +using MonoTouch.AudioToolbox; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.MediaToolbox +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class AudioProcessingTapTest + { + [DllImport (Constants.CoreFoundationLibrary)] + extern static nint CFGetRetainCount (IntPtr handle); + + [Test] + public unsafe void Initialization () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("MediaToolbox is new in 6.0"); + + var cb = new MTAudioProcessingTapCallbacks ( +#if XAMCORE_2_0 + delegate(MTAudioProcessingTap tap, nint numberFrames, MTAudioProcessingTapFlags flags, AudioBuffers bufferList, out nint numberFramesOut, out MTAudioProcessingTapFlags flagsOut) { +#else + delegate(MTAudioProcessingTap tap, long numberFrames, MTAudioProcessingTapFlags flags, AudioBuffers bufferList, out long numberFramesOut, out MTAudioProcessingTapFlags flagsOut) { +#endif + numberFramesOut = 2; + flagsOut = MTAudioProcessingTapFlags.StartOfStream; + }); + + cb.Initialize = delegate(MTAudioProcessingTap tap, out void* tapStorage) { + tapStorage = (void*)44; + }; + + IntPtr handle; + using (var res = new MTAudioProcessingTap (cb, MTAudioProcessingTapCreationFlags.PreEffects)) + { + handle = res.Handle; + Assert.AreEqual (44, (int)res.GetStorage ()); + Assert.That (CFGetRetainCount (handle), Is.EqualTo ((nint) 1), "RC"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MediaToolbox/FormatNamesTest.cs b/tests/monotouch-test/MediaToolbox/FormatNamesTest.cs new file mode 100644 index 000000000000..fe2ac8fc4759 --- /dev/null +++ b/tests/monotouch-test/MediaToolbox/FormatNamesTest.cs @@ -0,0 +1,61 @@ + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreMedia; +using Foundation; +using UIKit; +using MediaToolbox; +#else +using MonoTouch.Foundation; +using MonoTouch.CoreMedia; +using MonoTouch.MediaToolbox; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MediaToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FormatNamesTest { + + [Test] + [Culture ("en")] + public void LocalizedNameForMediaType () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS 9.0"); + + Assert.That (CMMediaType.Audio.GetLocalizedName (), Is.EqualTo ("Sound"), "Audio"); + Assert.That (CMMediaType.ClosedCaption.GetLocalizedName (), Is.EqualTo ("Closed Caption"), "ClosedCaption"); + Assert.That (CMMediaType.Metadata.GetLocalizedName (), Is.EqualTo ("meta"), "Metadata"); + Assert.That (CMMediaType.Muxed.GetLocalizedName (), Is.EqualTo ("Muxed"), "Muxed"); + Assert.That (CMMediaType.Subtitle.GetLocalizedName (), Is.EqualTo ("Subtitle"), "Subtitle"); + Assert.That (CMMediaType.Text.GetLocalizedName (), Is.EqualTo ("Text"), "Text"); + Assert.That (CMMediaType.TimeCode.GetLocalizedName (), Is.EqualTo ("Timecode"), "TimeCode"); + Assert.That (CMMediaType.Video.GetLocalizedName (), Is.EqualTo ("Video"), "Video"); + + // incorrect + Assert.That (((CMMediaType)1).GetLocalizedName (), Is.EqualTo (String.Empty), "-1"); + } + + [Test] + [Culture ("en")] + public void LocalizedNameForMediaSubType () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS 9.0"); + + Assert.That (CMMediaType.ClosedCaption.GetLocalizedName ((uint) CMClosedCaptionFormatType.ATSC), Is.EqualTo ("ATSC/52 part-4"), "ATSC"); + Assert.That (CMMediaType.ClosedCaption.GetLocalizedName ((uint) CMClosedCaptionFormatType.CEA608), Is.EqualTo ("CEA 608"), "CEA608"); + Assert.That (CMMediaType.ClosedCaption.GetLocalizedName ((uint) CMClosedCaptionFormatType.CEA708), Is.EqualTo ("CEA 708"), "CEA708"); + + // sounds incorrect - maybe it gets mapped to another value (like a default dictionary of 4CC values) + Assert.That (CMMediaType.Audio.GetLocalizedName ((uint) CMClosedCaptionFormatType.ATSC), Is.EqualTo ("atcc"), "incorrect"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MessageUI/MailComposeViewControllerTest.cs b/tests/monotouch-test/MessageUI/MailComposeViewControllerTest.cs new file mode 100644 index 000000000000..31e48636238b --- /dev/null +++ b/tests/monotouch-test/MessageUI/MailComposeViewControllerTest.cs @@ -0,0 +1,49 @@ +// +// Unit tests for MFMailComposeViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; + +using MessageUI; +#else +using MonoTouch.Foundation; +using MonoTouch.MessageUI; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MessageUI { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MailComposeViewControllerTest { + + [Test] + public void TextShadowOffset_7443 () + { + if (!MFMailComposeViewController.CanSendMail) + Assert.Inconclusive ("Not configured to send emails"); + + var cancelAttributes = new UITextAttributes (); + cancelAttributes.TextShadowOffset = new UIOffset (0, -1); + UIBarButtonItem.AppearanceWhenContainedIn (typeof(UISearchBar)).SetTitleTextAttributes (cancelAttributes, UIControlState.Disabled); + using (var mail = new MFMailComposeViewController ()) { + // we're happy the .ctor did not crash (only on iOS6) because the dictionary had a null key (typo) + Assert.That (mail.Handle, Is.Not.EqualTo (IntPtr.Zero)); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/Metal/ClearValueTest.cs b/tests/monotouch-test/Metal/ClearValueTest.cs new file mode 100644 index 000000000000..e42be634205a --- /dev/null +++ b/tests/monotouch-test/Metal/ClearValueTest.cs @@ -0,0 +1,55 @@ + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Metal; +#else +using MonoTouch.Metal; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.Metal +{ + [TestFixture] + public class ClearValueTest + { + [Test] + public void Constructor () + { + MTLClearValue value; + + value = new MTLClearValue (); + + Assert.AreEqual (0, value.Color.Alpha, "1-color-alpha"); + Assert.AreEqual (0, value.Color.Blue, "1-color-blue"); + Assert.AreEqual (0, value.Color.Green, "1-color-green"); + Assert.AreEqual (0, value.Color.Red, "1-color-red"); + Assert.AreEqual (0, value.Depth, "1-depth"); + Assert.AreEqual (0, value.Stencil, "1-stencil"); + + value = new MTLClearValue (0.2f); + + Assert.AreEqual (0.2f, value.Depth, "2-depth"); + + value = new MTLClearValue (123); + + Assert.AreEqual (123, value.Stencil, "3-stencil"); + + value = new MTLClearValue (-2); + + Assert.AreEqual (-2, value.Depth, "4-depth"); + + value = new MTLClearValue (new MTLClearColor (1, 2, 3, 4)); + + Assert.AreEqual (4, value.Color.Alpha, "5-color-alpha"); + Assert.AreEqual (3, value.Color.Blue, "5-color-blue"); + Assert.AreEqual (2, value.Color.Green, "5-color-green"); + Assert.AreEqual (1, value.Color.Red, "5-color-red"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/Metal/DeviceTest.cs b/tests/monotouch-test/Metal/DeviceTest.cs new file mode 100644 index 000000000000..e27201c50e6c --- /dev/null +++ b/tests/monotouch-test/Metal/DeviceTest.cs @@ -0,0 +1,40 @@ + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Metal; +#else +using MonoTouch.Metal; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.Metal { + + [TestFixture] + public class DeviceTest { + + [Test] + public void System () + { + var d = MTLDevice.SystemDefault; + // some older hardware won't have a default + if (d == null) + Assert.Inconclusive ("Metal is not supported"); + + // if we get an instance it must be valid, i.e. not an empty wrapper + Assert.That (d.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + + // and if we ask again we need to get a valid instance again + d.Dispose (); + Assert.That (d.Handle, Is.EqualTo (IntPtr.Zero), "Disposed"); + + d = MTLDevice.SystemDefault; + Assert.That (d.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle-2"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MetalPerformanceShaders/KernelTest.cs b/tests/monotouch-test/MetalPerformanceShaders/KernelTest.cs new file mode 100644 index 000000000000..15e87c84cad0 --- /dev/null +++ b/tests/monotouch-test/MetalPerformanceShaders/KernelTest.cs @@ -0,0 +1,47 @@ +// Copyright 2015 Xamarin Inc. All rights reserved. + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Metal; +using MetalPerformanceShaders; +using UIKit; +#else +using MonoTouch.Metal; +using MonoTouch.MetalPerformanceShaders; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.MetalPerformanceShaders { + + [TestFixture] + public class KernelTest { + + [Test] + public void RectNoClip () + { + var d = MTLDevice.SystemDefault; + // some older hardware won't have a default + if (d == null) + Assert.Inconclusive ("Metal is not supported"); + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.Inconclusive ("MetalPerformanceShaders requires iOS 9.0+"); + + var r = MPSKernel.RectNoClip; + var o = r.Origin; + Assert.That (o.X, Is.EqualTo (0), "X"); + Assert.That (o.Y, Is.EqualTo (0), "Y"); + Assert.That (o.Z, Is.EqualTo (0), "Z"); + var s = r.Size; + Assert.That (s.Depth, Is.EqualTo (-1), "Depth"); + Assert.That (s.Height, Is.EqualTo (-1), "Height"); + Assert.That (s.Width, Is.EqualTo (-1), "Width"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MobileCoreServices/UTTypeTest.cs b/tests/monotouch-test/MobileCoreServices/UTTypeTest.cs new file mode 100644 index 000000000000..3010ac17f1cb --- /dev/null +++ b/tests/monotouch-test/MobileCoreServices/UTTypeTest.cs @@ -0,0 +1,160 @@ +// +// Unit tests for UTType +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012, 2015 Xamarin Inc. All rights reserved. +// + +using System; + +#if XAMCORE_2_0 +using Foundation; +using MobileCoreServices; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.MobileCoreServices; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MobileCoreServices { + + [TestFixture] + [Preserve (AllMembers = true)] + public class UTTypeTest { + + [Test] + public void NSStringConstants () + { + Assert.NotNull (UTType.ExportedTypeDeclarationsKey, "ExportedTypeDeclarationsKey"); + Assert.NotNull (UTType.ImportedTypeDeclarationsKey, "ImportedTypeDeclarationsKey"); + Assert.NotNull (UTType.IdentifierKey, "IdentifierKey"); + Assert.NotNull (UTType.TagSpecificationKey, "TagSpecificationKey"); + Assert.NotNull (UTType.ConformsToKey, "ConformsToKey"); + Assert.NotNull (UTType.DescriptionKey, "DescriptionKey"); + Assert.NotNull (UTType.IconFileKey, "IconFileKey"); + Assert.NotNull (UTType.ReferenceURLKey, "ReferenceURLKey"); + Assert.NotNull (UTType.VersionKey, "VersionKey"); + + Assert.NotNull (UTType.TagClassFilenameExtension, "TagClassFilenameExtension"); + Assert.NotNull (UTType.TagClassMIMEType, "TagClassMIMEType"); + + Assert.NotNull (UTType.Item, "Item"); + Assert.NotNull (UTType.Content, "Content"); + Assert.NotNull (UTType.CompositeContent, "CompositeContent"); + Assert.NotNull (UTType.Application, "Application"); + Assert.NotNull (UTType.Message, "Message"); + Assert.NotNull (UTType.Contact, "Contact"); + Assert.NotNull (UTType.Archive, "Archive"); + Assert.NotNull (UTType.DiskImage, "DiskImage"); + + Assert.NotNull (UTType.Data, "Data"); + Assert.NotNull (UTType.Directory, "Directory"); + Assert.NotNull (UTType.Resolvable, "Resolvable"); + Assert.NotNull (UTType.SymLink, "SymLink"); + Assert.NotNull (UTType.MountPoint, "MountPoint"); + Assert.NotNull (UTType.AliasFile, "AliasFile"); + Assert.NotNull (UTType.AliasRecord, "AliasRecord"); + Assert.NotNull (UTType.URL, "URL"); + Assert.NotNull (UTType.FileURL, "FileURL"); + + Assert.NotNull (UTType.Text, "Text"); + Assert.NotNull (UTType.PlainText, "PlainText"); + Assert.NotNull (UTType.UTF8PlainText, "UTF8PlainText"); + Assert.NotNull (UTType.UTF16ExternalPlainText, "UTF16ExternalPlainText"); + Assert.NotNull (UTType.UTF16PlainText, "UTF16PlainText"); + Assert.NotNull (UTType.RTF, "RTF"); + Assert.NotNull (UTType.HTML, "HTML"); + Assert.NotNull (UTType.XML, "XML"); + Assert.NotNull (UTType.SourceCode, "SourceCode"); + Assert.NotNull (UTType.CSource, "CSource"); + Assert.NotNull (UTType.ObjectiveCSource, "ObjectiveCSource"); + Assert.NotNull (UTType.CPlusPlusSource, "CPlusPlusSource"); + Assert.NotNull (UTType.ObjectiveCPlusPlusSource, "ObjectiveCPlusPlusSource"); + Assert.NotNull (UTType.CHeader, "CHeader"); + Assert.NotNull (UTType.CPlusPlusHeader, "CPlusPlusHeader"); + Assert.NotNull (UTType.JavaSource, "JavaSource"); + + Assert.NotNull (UTType.PDF, "PDF"); + Assert.NotNull (UTType.RTFD, "RTFD"); + Assert.NotNull (UTType.FlatRTFD, "FlatRTFD"); + Assert.NotNull (UTType.TXNTextAndMultimediaData, "TXNTextAndMultimediaData"); + Assert.NotNull (UTType.WebArchive, "WebArchive"); + + Assert.NotNull (UTType.Image, "Image"); + Assert.NotNull (UTType.JPEG, "JPEG"); + Assert.NotNull (UTType.JPEG2000, "JPEG2000"); + Assert.NotNull (UTType.TIFF, "TIFF"); + Assert.NotNull (UTType.GIF, "GIF"); + Assert.NotNull (UTType.PNG, "PNG"); + Assert.NotNull (UTType.QuickTimeImage, "QuickTimeImage"); + Assert.NotNull (UTType.AppleICNS, "AppleICNS"); + Assert.NotNull (UTType.BMP, "BMP"); + Assert.NotNull (UTType.ICO, "ICO"); + + Assert.NotNull (UTType.AudiovisualContent, "AudiovisualContent"); + Assert.NotNull (UTType.Movie, "Movie"); + Assert.NotNull (UTType.Video, "Video"); + Assert.NotNull (UTType.Audio, "Audio"); + Assert.NotNull (UTType.QuickTimeMovie, "QuickTimeMovie"); + Assert.NotNull (UTType.MPEG, "MPEG"); + Assert.NotNull (UTType.MPEG4, "MPEG4"); + Assert.NotNull (UTType.MP3, "MP3"); + Assert.NotNull (UTType.MPEG4Audio, "MPEG4Audio"); + Assert.NotNull (UTType.AppleProtectedMPEG4Audio, "AppleProtectedMPEG4Audio"); + + Assert.NotNull (UTType.Folder, "Folder"); + Assert.NotNull (UTType.Volume, "Volume"); + Assert.NotNull (UTType.Package, "Package"); + Assert.NotNull (UTType.Bundle, "Bundle"); + Assert.NotNull (UTType.Framework, "Framework"); + + Assert.NotNull (UTType.ApplicationBundle, "ApplicationBundle"); + Assert.NotNull (UTType.ApplicationFile, "ApplicationFile"); + + Assert.NotNull (UTType.VCard, "VCard"); + + Assert.NotNull (UTType.InkText, "InkText"); + + if (TestRuntime.CheckiOSSystemVersion (9, 0)) + Assert.NotNull (UTType.SwiftSource, "SwiftSource"); + } + + [Test] + public void GetPreferredTag () + { + Assert.NotNull (UTType.GetPreferredTag (UTType.PDF, UTType.TagClassFilenameExtension), "GetPreferredTag"); + } + + [Test] + public void GetDeclaration () + { + Assert.NotNull (UTType.GetDeclaration (UTType.PDF)); + } + + [Test] + public void GetDeclaringBundleURL () + { + Assert.NotNull (UTType.GetDeclaringBundleURL (UTType.PDF)); + } + + [Test] + public void CreatePreferredIdentifier () + { + string[] extensions = new [] { ".html", ".css", ".jpg", ".js", ".otf" }; + // random failure reported in #36708 (on some iPad2 only) + for (int i=0; i < 100; i++) { + foreach (var ext in extensions) { + var result = UTType.CreatePreferredIdentifier (UTType.TagClassMIMEType, ext, null); + Assert.NotNull (result, ext + i.ToString ()); + } + } + } + } +} diff --git a/tests/monotouch-test/ModelIO/MDLLight.cs b/tests/monotouch-test/ModelIO/MDLLight.cs new file mode 100644 index 000000000000..ffc79953a9a3 --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLLight.cs @@ -0,0 +1,82 @@ +// +// MDLLight Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +using UIKit; +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLLightTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + using (var obj = new MDLLight ()) { + obj.GetIrradiance (Vector3.Zero); + obj.GetIrradiance (Vector3.Zero, CGColorSpace.CreateGenericRgb ()); + } + } + } + + [Test] + public void IrradianceAtPointTest () + { + using (var obj = new MDLLight ()) { + var color = obj.GetIrradiance (new Vector3 (1, 2, 3)); + if (Runtime.Arch == Arch.SIMULATOR && Environment.OSVersion.Version.Major < 15) { + Assert.IsNull (color, "color 1"); + } else { + Assert.IsNotNull (color, "color 1"); + } + } + + using (var obj = new MDLLight ()) { + var color = obj.GetIrradiance (new Vector3 (1, 2, 3), CGColorSpace.CreateGenericRgb ()); + if (Runtime.Arch == Arch.SIMULATOR && Environment.OSVersion.Version.Major < 15) { + Assert.IsNull (color, "color 2"); + } else { + Assert.IsNotNull (color, "color 2"); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs b/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs new file mode 100644 index 000000000000..545593a37d6f --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs @@ -0,0 +1,197 @@ +// +// MDLMaterialProperty Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLMaterialPropertyTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + object dummy; + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion)) { + dummy = obj.Color; + dummy = obj.Float2Value; + dummy = obj.Float3Value; + dummy = obj.Float4Value; + dummy = obj.FloatValue; + dummy = obj.Matrix4x4; + dummy = obj.Name; + dummy = obj.Semantic; + obj.SetProperties (new MDLMaterialProperty ("foo", MDLMaterialSemantic.AmbientOcclusion)); + dummy = obj.StringValue; + dummy = obj.TextureSamplerValue; + dummy = obj.Type; + dummy = obj.UrlValue; + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, Vector3.Zero)) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, new MDLTextureSampler ())) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, "string value")) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, new NSUrl ("http://foo.com"))) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, Matrix4.Identity)) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, Vector4.Zero)) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, UIColor.Black.CGColor)) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, Vector2.Zero)) { + } + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, 1.23f)) { + } + } + } + + + [Test] + public void Ctors () + { + Vector2 V2; + Vector3 V3; + Vector4 V4; + Matrix4 M4; + MDLTextureSampler tsv; + NSUrl url; + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion)) { + Assert.AreEqual (MDLMaterialSemantic.AmbientOcclusion, obj.Semantic, "1 Semantic"); + Assert.IsNull (obj.Color, "1 Color"); + Asserts.AreEqual (Vector2.Zero, obj.Float2Value, "1 Float2Value"); + Asserts.AreEqual (Vector3.Zero, obj.Float3Value, "1 Float3Value"); + Asserts.AreEqual (Vector4.Zero, obj.Float4Value, "1 Float4Value"); + Assert.AreEqual (0.0f, obj.FloatValue, "1 FloatValue"); + Asserts.AreEqual (Matrix4.Identity, obj.Matrix4x4, "1 Matrix4x4"); + Assert.AreEqual ("name", obj.Name, "1 Name"); + Assert.IsNull (obj.StringValue, "1 StringValue"); + Assert.IsNull (obj.TextureSamplerValue, "1 TextureSamplerValue"); + Assert.AreEqual (MDLMaterialPropertyType.Float, obj.Type, "1 Type"); + Assert.IsNull (obj.UrlValue, "1 UrlValue"); + + V2 = new Vector2 (1, 2); + V3 = new Vector3 (3, 4, 5); + V4 = new Vector4 (6, 7, 8, 9); + M4 = new Matrix4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + tsv = new MDLTextureSampler (); + url = new NSUrl ("http://xamarin.com"); + + obj.Semantic = MDLMaterialSemantic.Anisotropic; + Assert.AreEqual (MDLMaterialSemantic.Anisotropic, obj.Semantic, "2 Semantic"); + + obj.Color = UIColor.Blue.CGColor; + Assert.AreEqual (UIColor.Blue.CGColor.ToString (), obj.Color.ToString (), "2 Color"); + + obj.Float2Value = V2; + Asserts.AreEqual (V2, obj.Float2Value, "2 Float2Value"); + + obj.Float3Value = V3; + Asserts.AreEqual (V3, obj.Float3Value, "2 Float3Value"); + + obj.Float4Value = V4; + Asserts.AreEqual (V4, obj.Float4Value, "2 Float4Value"); + + obj.FloatValue = 3.14f; + Assert.AreEqual (3.14f, obj.FloatValue, "2 FloatValue"); + + obj.Matrix4x4 = M4; + // It looks like the Matrix4 setter is ignored, assigning a matrix + // doesn't work in Xcode either. + Asserts.AreEqual (Matrix4.Identity, obj.Matrix4x4, "2 Matrix4x4"); + + obj.Name = "new name"; + Assert.AreEqual ("new name", obj.Name, "2 Name"); + + obj.StringValue = "string value"; + Assert.AreEqual ("string value", obj.StringValue, "2 StringValue"); + + obj.TextureSamplerValue = tsv; + Assert.AreEqual (tsv.Handle, obj.TextureSamplerValue.Handle, "2 TextureSamplerValue"); + + Assert.AreEqual (MDLMaterialPropertyType.Texture, obj.Type, "2 Type"); + + // Looks like the URLValue can't change after construction + obj.UrlValue = url; + Assert.IsNull (obj.UrlValue, "2 UrlValue"); + } + + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, url)) { + Assert.AreEqual (url.Handle, obj.UrlValue.Handle, "3 UrlValue"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, V3)) { + Asserts.AreEqual (V3, obj.Float3Value, "4 Float3Value"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, tsv)) { + Assert.AreEqual (tsv.Handle, obj.TextureSamplerValue.Handle, "5 TextureSamplerValue"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, "string value")) { + Assert.AreEqual ("string value", obj.StringValue, "6 StringValue"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, M4)) { + Asserts.AreEqual (M4, obj.Matrix4x4, "7 Matrix4x4"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, V4)) { + Asserts.AreEqual (V4, obj.Float4Value, "8 Float4Value"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, UIColor.Red.CGColor)) { + Assert.AreEqual (UIColor.Blue.CGColor.ToString (), obj.Color.ToString (), "9 Color"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, V2)) { + Asserts.AreEqual (V2, obj.Float2Value, "10 Float2Value"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, 3.1415f)) { + Assert.AreEqual (3.1415f, obj.FloatValue, "11 FloatValue"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLMesh.cs b/tests/monotouch-test/ModelIO/MDLMesh.cs new file mode 100644 index 000000000000..f3cf2a9cccfb --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLMesh.cs @@ -0,0 +1,198 @@ +// +// MDLLight Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLMeshTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + object dummy; + using (var obj = MDLMesh.CreateBox (Vector3.Zero, Vector3i.Zero, MDLGeometryType.Triangles, true, null)) { + obj.AddAttribute ("foo", MDLVertexFormat.Char); +// obj.AddNormals (null, 0); // throws NSInvalidArgumentException, need to figure out valid arguments +// obj.AddTangentBasis ("foo", "bar", "zap"); // throws "Need float or half UV components Need float or half UV components" +// obj.AddTangentBasisWithNormals ("foo", "bar", "zap"); // throws "Need float or half UV components Reason: Need float or half UV components" + dummy = obj.BoundingBox; +// obj.GenerateAmbientOcclusionTexture (1, 1, new MDLObject [] { }, "name", "name"); +// obj.GenerateAmbientOcclusionVertexColors (1, 1, new MDLObject[] {}, "name"); +// obj.GenerateAmbientOcclusionVertexColors (1.1, 1, new MDLObject[] [] { }, "name"); +// obj.GenerateLightMapTexture (Vector2i.Zero, new MDLLight[] {}, new MDLObject[] {}, "str", "str"); +// obj.GenerateLightMapVertexColors (new MDLLight[] { }, new MDLObject[] { }, "v"); + obj.MakeVerticesUnique (); + dummy = obj.Submeshes; + dummy = obj.VertexBuffers; + dummy = obj.VertexCount; + dummy = obj.VertexDescriptor; + } + + using (var obj = MDLMesh.CreateCylindroid (1, Vector2.Zero, 3, 0, MDLGeometryType.Triangles, false, null)) { + } + using (var obj = MDLMesh.CreateEllipsoid (Vector3.Zero, 3, 2, MDLGeometryType.Triangles, false, false, null)) { + } + using (var obj = MDLMesh.CreateEllipticalCone (0, Vector2.Zero, 3, 1, MDLGeometryType.Triangles, false, null)) { + } + using (var obj = MDLMesh.CreateIcosahedron (0, false, null)) { + } + using (var obj = MDLMesh.CreatePlane (new Vector2 (1, 1), new Vector2i (1, 1), MDLGeometryType.Triangles, null)) { + } +// using (var obj = MDLMesh.CreateSubdividedMesh (new MDLMesh (), 0, 0)) { +// } + + } + } + + [Test] + public void CreateBoxTest () + { + Vector3 V3 = new Vector3 (1, 2, 3); + Vector3i V3i = new Vector3i (4, 5, 6); + + using (var obj = MDLMesh.CreateBox (V3, V3i, MDLGeometryType.Triangles, true, null)) { + Assert.IsNotNull (obj, "obj"); + Asserts.AreEqual (new MDLAxisAlignedBoundingBox { MaxBounds = new Vector3 (0.5f, 1, 1.5f), MinBounds = new Vector3 (-0.5f, -1, -1.5f) }, obj.BoundingBox, "BoundingBox"); + Assert.AreEqual (1, obj.Submeshes.Count, "Submeshes Count"); + Assert.AreEqual (1, obj.VertexBuffers.Length, "VertexBuffers Count"); + // iOS 9.3 is the basis of tvOS 9.2 (hopefully they'll get in sync with iOS 10+) +#if __TVOS__ + bool nine3 = UIDevice.CurrentDevice.CheckSystemVersion (9, 2); +#else + bool nine3 = UIDevice.CurrentDevice.CheckSystemVersion (9, 3); +#endif + Assert.AreEqual (nine3 ? 214 : 24, obj.VertexCount, "VertexCount"); + Assert.AreEqual (31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count"); + Assert.AreEqual (31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count"); + } + } + + [Test] + public void CreatePlaneTest () + { + var V2 = new Vector2 (3, 3); + var V2i = new Vector2i (3, 3); + + using (var obj = MDLMesh.CreatePlane (V2, V2i, MDLGeometryType.Triangles, null)) { + Assert.IsNotNull (obj, "obj"); + Asserts.AreEqual (new MDLAxisAlignedBoundingBox { MaxBounds = new Vector3 (1.5f, 0, 1.5f), MinBounds = new Vector3 (-1.5f, 0, -1.5f) }, obj.BoundingBox, "BoundingBox"); + Assert.AreEqual (1, obj.Submeshes.Count, "Submeshes Count"); + Assert.AreEqual (1, obj.VertexBuffers.Length, "VertexBuffers Count"); + Assert.AreEqual (16, obj.VertexCount, "VertexCount"); + Assert.AreEqual (31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count"); + Assert.AreEqual (31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count"); + } + } + + [Test] + public void CreateEllipsoidTest () + { + Vector3 V3 = new Vector3 (1, 1, 1); + + using (var obj = MDLMesh.CreateEllipsoid (V3, 3, 3, MDLGeometryType.Triangles, true, true, null)) { + Assert.IsNotNull (obj, "obj"); + Asserts.AreEqual (new MDLAxisAlignedBoundingBox { MaxBounds = new Vector3 (0.866025448f, 1f, 0.75f), MinBounds = new Vector3 (-0.433012784f, 0.49999997f, -0.75000006f) }, obj.BoundingBox, "BoundingBox"); + Assert.AreEqual (1, obj.Submeshes.Count, "Submeshes Count"); + Assert.AreEqual (1, obj.VertexBuffers.Length, "VertexBuffers Count"); + Assert.AreEqual (9, obj.VertexCount, "VertexCount"); + Assert.AreEqual (31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count"); + Assert.AreEqual (31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count"); + } + } + + [Test] + public void CreateCylindroidTest () + { + var V2 = new Vector2 (1, 1); + + using (var obj = MDLMesh.CreateCylindroid (1, V2, 3, 1, MDLGeometryType.Triangles, true, null)) { + Assert.IsNotNull (obj, "obj"); + Asserts.AreEqual (new MDLAxisAlignedBoundingBox { MaxBounds = new Vector3 (1f, 0.5f, 1f), MinBounds = new Vector3 (-0.866025388f, -0.5f, -0.866025388f) }, obj.BoundingBox, "BoundingBox"); + Assert.AreEqual (1, obj.Submeshes.Count, "Submeshes Count"); + Assert.AreEqual (1, obj.VertexBuffers.Length, "VertexBuffers Count"); + Assert.AreEqual (18, obj.VertexCount, "VertexCount"); + Assert.AreEqual (31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count"); + Assert.AreEqual (31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count"); + } + } + + [Test] + public void CreateEllipticalConeTest () + { + var V2 = new Vector2 (1, 1); + + using (var obj = MDLMesh.CreateEllipticalCone (5, V2, 3, 1, MDLGeometryType.Triangles, true, null)) { + Assert.IsNotNull (obj, "obj"); + Asserts.AreEqual (new MDLAxisAlignedBoundingBox { MaxBounds = new Vector3 (0.866025448f, 0f, 1f), MinBounds = new Vector3 (-0.866025388f, -5f, -0.50000006f) }, obj.BoundingBox, "BoundingBox"); + Assert.AreEqual (1, obj.Submeshes.Count, "Submeshes Count"); + Assert.AreEqual (1, obj.VertexBuffers.Length, "VertexBuffers Count"); + Assert.AreEqual (13, obj.VertexCount, "VertexCount"); + Assert.AreEqual (31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count"); + Assert.AreEqual (31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count"); + } + } + +// FIXME: figure out valid input arguments for GenerateAmbientOcclusionTexture +// [Test] +// public void GenerateAmbientOcclusionTextureTest () +// { +// var V2 = new Vector2 (1, 1); +// var V2i = new Vector2i (1, 2); +// +// using (var obj = MDLMesh.CreateEllipticalCone (5, V2, 3, 1, MDLGeometryKind.Triangles, true, null)) { +// Assert.IsTrue (obj.GenerateAmbientOcclusionTexture (V2i, 1, 1, new MDLObject[] { }, "vname", "mname"), "GenerateAmbientOcclusionTexture"); +// } +// } +// +// FIXME: figure out valid input arguments for GenerateLightMapTexture +// [Test] +// public void GenerateLightMapTextureTest () +// { +// var V2 = new Vector2 (1, 1); +// var V2i = new Vector2i (1, 2); +// +// using (var obj = MDLMesh.CreateEllipticalCone (5, V2, 3, 1, MDLGeometryKind.Triangles, true, null)) { +// Assert.IsTrue (obj.GenerateLightMapTexture (V2i, new MDLLight[] {}, new MDLObject[] { }, "vname", "mname"), "GenerateLightMapTexture"); +// } +// } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLObject.cs b/tests/monotouch-test/ModelIO/MDLObject.cs new file mode 100644 index 000000000000..e20d4728c47a --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLObject.cs @@ -0,0 +1,69 @@ +// +// MDLLight Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +using UIKit; +using ModelIO; +using ObjCRuntime; +using SceneKit; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +using MonoTouch.SceneKit; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLObjectTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + using (var obj = new MDLObject ()) { + object dummy; + obj.SetComponent (new MDLTransform (), new Protocol ("MDLComponent")); + obj.IsComponentConforming (new Protocol ("MDLComponent")); + dummy = obj.Parent; + dummy = obj.Transform; + obj.AddChild (new MDLObject ()); + obj.GetBoundingBox (0); + } + } + } + + [Test] + public void GetBoundingBox () + { + using (var obj = MDLObject.FromNode (SCNNode.FromGeometry (SCNBox.Create (1, 1, 1, 0)))) { + var bb = obj.GetBoundingBox (0); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLTexture.cs b/tests/monotouch-test/ModelIO/MDLTexture.cs new file mode 100644 index 000000000000..745e5b25c071 --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLTexture.cs @@ -0,0 +1,124 @@ +// +// MDLTexture Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLTextureTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + object dummy; + using (var obj = new MDLTexture (null, true, null, Vector2i.Zero, 12, 2, MDLTextureChannelEncoding.Float16, false)) { + dummy = obj.ChannelCount; + dummy = obj.ChannelEncoding; + dummy = obj.Dimensions; + dummy = obj.IsCube; + dummy = obj.MipLevelCount; + dummy = obj.Name; + dummy = obj.RowStride; + obj.GetTexelDataWithBottomLeftOrigin (); + obj.GetTexelDataWithBottomLeftOrigin (1, false); + obj.GetTexelDataWithTopLeftOrigin (); + obj.GetTexelDataWithTopLeftOrigin (1, false); + } + using (var obj = new MDLTexture ()) { + } + } + } + + [Test] + public void Ctor () + { + var V2 = new Vector2i (123, 456); + + using (var obj = new MDLTexture (null, true, null, V2, 12, 2, MDLTextureChannelEncoding.Float16, false)) { + Asserts.AreEqual (V2, obj.Dimensions, "dimensions"); + } + } + + [Test] + public void CreateIrradianceTextureCubeTest_a () + { + var V2 = new Vector2i (3, 3); + + using (var obj = new MDLTexture ()) { + using (var txt = MDLTexture.CreateIrradianceTextureCube (obj, "name", V2)) { + Assert.IsNotNull (txt, "Ain't Null"); + Assert.AreEqual (4, txt.ChannelCount, "ChannelCount"); + Assert.AreEqual (MDLTextureChannelEncoding.UInt8, txt.ChannelEncoding, "ChannelEncoding"); + Assert.AreEqual (new Vector2i (3, 18), txt.Dimensions, "Dimensions"); + Assert.AreEqual (2, txt.MipLevelCount, "MipLevelCount"); + Assert.AreEqual (12, txt.RowStride, "RowStride"); + } + } + } + + [Test] + public void CreateIrradianceTextureCubeTest_b () + { + var V2 = new Vector2i (3, 3); + + using (var obj = new MDLTexture ()) { + using (var txt = MDLTexture.CreateIrradianceTextureCube (obj, "name", V2, 0.1234f)) { + Assert.IsNotNull (txt, "Ain't Null"); + Assert.AreEqual (4, txt.ChannelCount, "ChannelCount"); + Assert.AreEqual (MDLTextureChannelEncoding.UInt8, txt.ChannelEncoding, "ChannelEncoding"); + Assert.AreEqual (new Vector2i (3, 18), txt.Dimensions, "Dimensions"); + Assert.AreEqual (1, txt.MipLevelCount, "MipLevelCount"); + Assert.AreEqual (12, txt.RowStride, "RowStride"); + } + } + } + + [Test] + public void DimensionsTest () + { + var V2 = new Vector2i (123, 456); + + using (var txt = new MDLTexture ()) { + Asserts.AreEqual (Vector2i.Zero, txt.Dimensions, "a"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLTransform.cs b/tests/monotouch-test/ModelIO/MDLTransform.cs new file mode 100644 index 000000000000..2bcdc7457721 --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLTransform.cs @@ -0,0 +1,142 @@ +// +// MDLTransform Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLTransformTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + object dummy; + using (var obj = new MDLTransform (Matrix4.Identity)) { + dummy = obj.Matrix; + dummy = obj.MaximumTime; + dummy = obj.MinimumTime; + dummy = obj.Rotation; + obj.GetRotation (0); + dummy = obj.Scale; + obj.GetScale (0); + obj.SetIdentity (); + obj.SetLocalTransform (Matrix4.Identity); + obj.SetRotation (Vector3.Zero, 0); + obj.SetScale (Vector3.Zero, 0); + obj.SetTranslation (Vector3.Zero, 0); + dummy = obj.Translation; + obj.GetTranslation (0); + } + } + } + + [Test] + public void Ctors () + { + Matrix4 id = Matrix4.Identity; + var V3 = new Vector3 (1, 2, 3); + + using (var obj = new MDLTransform (id)) { + Asserts.AreEqual (Vector3.Zero, obj.Translation, "Translation"); + Asserts.AreEqual (Vector3.One, obj.Scale, "Scale"); + Asserts.AreEqual (Vector3.Zero, obj.Rotation, "Rotation"); + Asserts.AreEqual (id, obj.Matrix, "Matrix"); + + obj.Translation = V3; + Asserts.AreEqual (V3, obj.Translation, "Translation 2"); + } + + using (var obj = new MDLTransform (id)) { + V3 *= 2; + obj.Scale = V3; + Asserts.AreEqual (V3, obj.Scale, "Scale 2"); + } + + using (var obj = new MDLTransform (id)) { + V3 *= 2; + obj.Rotation = V3; + Asserts.AreEqual (V3, obj.Rotation, "Rotation 2"); + } + + using (var obj = new MDLTransform (id)) { + V3 *= 2; + obj.Rotation = V3; + Asserts.AreEqual (V3, obj.Rotation, "Rotation 2"); + } + } + + [Test] + public void ScaleAtTimeTest () + { + var matrix = Matrix4.Identity; + var V3 = new Vector3 (1, 2, 3); + + using (var obj = new MDLTransform (matrix)) { + obj.SetScale (V3, 0); + Asserts.AreEqual (V3, obj.GetScale (0), "ScaleAtTime"); + } + } + + [Test] + public void TranslationAtTimeTest () + { + var matrix = Matrix4.Identity; + var V3 = new Vector3 (1, 2, 3); + + using (var obj = new MDLTransform (matrix)) { + obj.SetTranslation (V3, 0); + Asserts.AreEqual (V3, obj.GetTranslation (0), "TranslationAtTime"); + } + } + + [Test] + public void RotationAtTimeTest () + { + var matrix = Matrix4.Identity; + var V3 = new Vector3 (1, 2, 3); + + using (var obj = new MDLTransform (matrix)) { + obj.SetRotation (V3, 0); + Asserts.AreEqual (V3, obj.GetRotation (0), "RotationAtTime"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLVertexAttribute.cs b/tests/monotouch-test/ModelIO/MDLVertexAttribute.cs new file mode 100644 index 000000000000..8046dc0c16a8 --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLVertexAttribute.cs @@ -0,0 +1,99 @@ +// +// MDLVertexAttribute Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLVertexAttributeTest { + [TestFixtureSetUp] + public void Setup () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("Requires iOS9+"); + + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments + // when resizing the cache of method selectors for a type. So here we call all selectors we can + // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410). + object dummy; + using (var obj = new MDLVertexAttribute ()) { + dummy = obj.BufferIndex; + dummy = obj.Format; + dummy = obj.InitializationValue; + dummy = obj.Name; + dummy = obj.Offset; + } + } + } + + [Test] + public void Ctors () + { + using (var obj = new MDLVertexAttribute ("name", MDLVertexFormat.Float3, 1, 2)) { + Assert.AreEqual ("name", obj.Name, "Name"); + Assert.AreEqual (MDLVertexFormat.Float3, obj.Format, "Format"); + Assert.AreEqual (1, obj.Offset, "Offset"); + Assert.AreEqual (2, obj.BufferIndex, "BufferIndex"); + Asserts.AreEqual (new Vector4 (0, 0, 0, 1), obj.InitializationValue, "InitializationValue"); + } + } + + [Test] + public void Properties () + { + var V4 = new Vector4 (1, 2, 3, 4); + + using (var obj = new MDLVertexAttribute ("name", MDLVertexFormat.Float3, 1, 2)) { + obj.Name = "new name"; + Assert.AreEqual ("new name", obj.Name, "Name"); + + obj.Format = MDLVertexFormat.Float2; + Assert.AreEqual (MDLVertexFormat.Float2, obj.Format, "Format"); + + obj.Offset = 4; + Assert.AreEqual (4, obj.Offset, "Offset"); + + obj.BufferIndex = 9; + Assert.AreEqual (9, obj.BufferIndex, "BufferIndex"); + } + + using (var obj = new MDLVertexAttribute ("name", MDLVertexFormat.Float3, 1, 2)) { + obj.InitializationValue = V4; + Asserts.AreEqual (V4, obj.InitializationValue, "InitializationValue"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/MultipeerConnectivity/PeerIDTest.cs b/tests/monotouch-test/MultipeerConnectivity/PeerIDTest.cs new file mode 100644 index 000000000000..10078d29fb30 --- /dev/null +++ b/tests/monotouch-test/MultipeerConnectivity/PeerIDTest.cs @@ -0,0 +1,55 @@ +// +// MCPeerID Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using MultipeerConnectivity; +#else +using MonoTouch.Foundation; +using MonoTouch.MultipeerConnectivity; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.MultipeerConnectivity { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class PeerIDTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var peer = new MCPeerID ()) { + Assert.Null (peer.DisplayName, "DisplayName"); + } + } + + [Test] + public void LocalPeer () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var peer = new MCPeerID ("myself")) { + Assert.That (peer.DisplayName, Is.EqualTo ("myself"), "DisplayName"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/MultipeerConnectivity/SessionTest.cs b/tests/monotouch-test/MultipeerConnectivity/SessionTest.cs new file mode 100644 index 000000000000..3b74216a0af6 --- /dev/null +++ b/tests/monotouch-test/MultipeerConnectivity/SessionTest.cs @@ -0,0 +1,121 @@ +// +// MCSession Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using MultipeerConnectivity; +using ObjCRuntime; +using Security; +#else +using MonoTouch.Foundation; +using MonoTouch.MultipeerConnectivity; +using MonoTouch.ObjCRuntime; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +using MonoTouchFixtures.Security; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif +namespace MonoTouchFixtures.MultipeerConnectivity { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class SessionTest { + + [Test] + public void CtorPeer () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var peer = new MCPeerID ("me")) + using (var s = new MCSession (peer)) { + Assert.AreSame (s.MyPeerID, peer, "MyPeerID"); + Assert.Null (s.SecurityIdentity, "SecurityIdentity"); + var pref = UIDevice.CurrentDevice.CheckSystemVersion (9,0) ? MCEncryptionPreference.Required : MCEncryptionPreference.Optional; + Assert.That (s.EncryptionPreference, Is.EqualTo (pref), "EncryptionPreference"); + Assert.That (s.ConnectedPeers, Is.Empty, "ConnectedPeers"); + } + } + + [Test] + public void Ctor_OptionalIdentity () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var peer = new MCPeerID ("me")) + using (var s = new MCSession (peer, null, MCEncryptionPreference.None)) { + Assert.AreSame (s.MyPeerID, peer, "MyPeerID"); + Assert.Null (s.SecurityIdentity, "SecurityIdentity"); + Assert.That (s.EncryptionPreference, Is.EqualTo (MCEncryptionPreference.None), "EncryptionPreference"); + Assert.That (s.ConnectedPeers, Is.Empty, "ConnectedPeers"); + } + } + + [Test] + public void Ctor_Identity () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var id = IdentityTest.GetIdentity ()) + using (var peer = new MCPeerID ("me")) + using (var s = new MCSession (peer, id, MCEncryptionPreference.Required)) { + Assert.AreSame (s.MyPeerID, peer, "MyPeerID"); + Assert.That (s.SecurityIdentity.Count, Is.EqualTo ((nuint) 1), "SecurityIdentity"); + Assert.That (s.SecurityIdentity.GetItem (0).Handle, Is.EqualTo (id.Handle), "SecurityIdentity"); + Assert.That (s.EncryptionPreference, Is.EqualTo (MCEncryptionPreference.Required), "EncryptionPreference"); + Assert.That (s.ConnectedPeers, Is.Empty, "ConnectedPeers"); + } + } + + [Test] + public void Ctor_Identity_Certificates () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var id = IdentityTest.GetIdentity ()) + using (var trust = new SecTrust (id.Certificate, SecPolicy.CreateBasicX509Policy ())) + using (var peer = new MCPeerID ("me")) { + SecCertificate [] certs = new SecCertificate [trust.Count]; + for (int i=0; i < trust.Count; i++) + certs [i] = trust [i]; + + using (var s = new MCSession (peer, id, certs, MCEncryptionPreference.Required)) { + Assert.AreSame (s.MyPeerID, peer, "MyPeerID"); + // it's a self-signed certificate that's used for the identity + // so it's not added twice to the collection being returned + Assert.That (s.SecurityIdentity.Count, Is.EqualTo (1), "SecurityIdentity"); + Assert.That (s.SecurityIdentity.GetItem (0).Handle, Is.EqualTo (certs [0].Handle), "SecurityIdentity"); + Assert.That (s.EncryptionPreference, Is.EqualTo (MCEncryptionPreference.Required), "EncryptionPreference"); + Assert.That (s.ConnectedPeers, Is.Empty, "ConnectedPeers"); + } + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/NativeTypesTest.cs b/tests/monotouch-test/NativeTypesTest.cs new file mode 100644 index 000000000000..c4b7992a9630 --- /dev/null +++ b/tests/monotouch-test/NativeTypesTest.cs @@ -0,0 +1,153 @@ +// +// Unit tests for native types (nint, nuint, nfloat) +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if XAMCORE_2_0 + +using System; +using System.Globalization; + +using Foundation; +using ObjCRuntime; +using Security; + +using NUnit.Framework; + +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; + +namespace MonoTouchFixtures.System { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NativeTypes { + + [Test] + public void CompareTo () + { + Assert.That (((nint)0).CompareTo ((nint)0), Is.EqualTo (0), "compareto 1"); + Assert.That (((nint)0).CompareTo ((nint)1), Is.EqualTo (-1), "compareto 2"); + Assert.That (((nint)1).CompareTo ((nint)0), Is.EqualTo (1), "compareto 3"); + Assert.That (((nint)0).CompareTo ((object)(nint)0), Is.EqualTo (0), "compareto 4"); + Assert.That (((nint)0).CompareTo ((object)(nint)1), Is.EqualTo (-1), "compareto 5"); + Assert.That (((nint)1).CompareTo ((object)(nint)0), Is.EqualTo (1), "compareto 6"); + Assert.That (((nint)1).CompareTo (null), Is.EqualTo (1), "compareto 7"); + + + Assert.That (((nuint)0).CompareTo ((nuint)0), Is.EqualTo (0), "compareto nuint 1"); + Assert.That (((nuint)0).CompareTo ((nuint)1), Is.EqualTo (-1), "compareto nuint 2"); + Assert.That (((nuint)1).CompareTo ((nuint)0), Is.EqualTo (1), "compareto nuint 3"); + Assert.That (((nuint)0).CompareTo ((object)(nuint)0), Is.EqualTo (0), "compareto nuint 4"); + Assert.That (((nuint)0).CompareTo ((object)(nuint)1), Is.EqualTo (-1), "compareto nuint 5"); + Assert.That (((nuint)1).CompareTo ((object)(nuint)0), Is.EqualTo (1), "compareto nuint 6"); + Assert.That (((nuint)1).CompareTo (null), Is.EqualTo (1), "compareto nuint 7"); + + Assert.That (((nfloat)0).CompareTo ((nfloat)0), Is.EqualTo (0), "compareto nfloat 1"); + Assert.That (((nfloat)0).CompareTo ((nfloat)1), Is.EqualTo (-1), "compareto nfloat 2"); + Assert.That (((nfloat)1).CompareTo ((nfloat)0), Is.EqualTo (1), "compareto nfloat 3"); + Assert.That (((nfloat)0).CompareTo ((object)(nfloat)0), Is.EqualTo (0), "compareto nfloat 4"); + Assert.That (((nfloat)0).CompareTo ((object)(nfloat)1), Is.EqualTo (-1), "compareto nfloat 5"); + Assert.That (((nfloat)1).CompareTo ((object)(nfloat)0), Is.EqualTo (1), "compareto nfloat 6"); + Assert.That (((nfloat)1).CompareTo (null), Is.EqualTo (1), "compareto nfloat 7"); + } + + [Test] + public void Equals () + { + Assert.IsTrue (((nint) 0).Equals ((nint) 0), "eq nint 1"); + Assert.IsTrue (((nint) 0).Equals ((object) (nint) 0), "eq nint 2"); + Assert.IsFalse (((nint) 0).Equals (null), "eq nint 3"); + + Assert.IsTrue (((nuint) 0).Equals ((nuint) 0), "eq nuint 1"); + Assert.IsTrue (((nuint) 0).Equals ((object) (nuint) 0), "eq nuint 2"); + Assert.IsFalse (((nuint) 0).Equals (null), "eq nuint 3"); + + Assert.IsTrue (((nfloat) 0).Equals ((nfloat) 0), "eq nfloat 1"); + Assert.IsTrue (((nfloat) 0).Equals ((object) (nfloat) 0), "eq nfloat 2"); + Assert.IsFalse (((nfloat) 0).Equals (null), "eq nfloat 3"); + } + + [Test] + public void IsInfinity () + { + Assert.IsTrue (nfloat.IsInfinity (nfloat.PositiveInfinity), "PositiveInfinity"); + Assert.IsTrue (nfloat.IsInfinity (nfloat.NegativeInfinity), "NegativeInfinity"); + Assert.IsTrue (!nfloat.IsInfinity (12), "12"); + Assert.IsTrue (!nfloat.IsInfinity (nfloat.NaN), "NaN"); + } + + [Test] + public void IsNan () + { + Assert.IsTrue (nfloat.IsNaN (nfloat.NaN), "Nan"); + Assert.IsTrue (!nfloat.IsNaN (12), "12"); + Assert.IsTrue (!nfloat.IsNaN (nfloat.PositiveInfinity), "PositiveInfinity"); + Assert.IsTrue (!nfloat.IsNaN (nfloat.PositiveInfinity), "NegativeInfinity"); + } + + [Test] + public void IsNegativeInfinity () + { + Assert.IsTrue (nfloat.IsNegativeInfinity (nfloat.NegativeInfinity), "IsNegativeInfinity"); + Assert.IsTrue (!nfloat.IsNegativeInfinity (12), "12"); + Assert.IsTrue (!nfloat.IsNegativeInfinity (nfloat.NaN), "NaN"); + } + + [Test] + public void IsPositiveInfinity () + { + Assert.IsTrue (nfloat.IsPositiveInfinity (nfloat.PositiveInfinity), "PositiveInfinity"); + Assert.IsTrue (!nfloat.IsPositiveInfinity (12), "12"); + Assert.IsTrue (!nfloat.IsPositiveInfinity (nfloat.NaN), "NaN"); + } + + [Test] + public void PositiveInfinity_Cast () + { + float f = float.PositiveInfinity; + Assert.IsTrue (float.IsPositiveInfinity (f), "float PositiveInfinity"); + nfloat n = (nfloat) f; // no-op on 32 bits arch + Assert.IsTrue (nfloat.IsPositiveInfinity (n), "nfloat PositiveInfinity 1"); + + double d = double.PositiveInfinity; + Assert.IsTrue (double.IsPositiveInfinity (d), "double PositiveInfinity"); + n = (nfloat) d; // no-op on 64 bits arch + Assert.IsTrue (nfloat.IsPositiveInfinity (n), "nfloat PositiveInfinity 2"); + } + + [Test] + public void NegativeInfinity_Cast () + { + float f = float.NegativeInfinity; + Assert.IsTrue (float.IsNegativeInfinity (f), "float NegativeInfinity"); + nfloat n = (nfloat) f; // no-op on 32 bits arch + Assert.IsTrue (nfloat.IsNegativeInfinity (n), "nfloat NegativeInfinity 1"); + + double d = double.NegativeInfinity; + Assert.IsTrue (double.IsNegativeInfinity (d), "double NegativeInfinity"); + n = (nfloat) d; // no-op on 64 bits arch + Assert.IsTrue (nfloat.IsNegativeInfinity (n), "nfloat NegativeInfinity 2"); + } + + [Test] + public void NaN_Cast () + { + float f = float.NaN; + Assert.IsTrue (float.IsNaN (f), "float NaN"); + nfloat n = (nfloat) f; // no-op on 32 bits arch + Assert.IsTrue (nfloat.IsNaN (n), "nfloat NaN 1"); + + double d = double.NaN; + Assert.IsTrue (double.IsNaN (d), "double NaN"); + n = (nfloat) d; // no-op on 64 bits arch + Assert.IsTrue (nfloat.IsNaN (n), "nfloat NaN 2"); + } + } +} +#endif diff --git a/tests/monotouch-test/NetworkExtension/OnDemandTest.cs b/tests/monotouch-test/NetworkExtension/OnDemandTest.cs new file mode 100644 index 000000000000..8e21d3adc7d6 --- /dev/null +++ b/tests/monotouch-test/NetworkExtension/OnDemandTest.cs @@ -0,0 +1,160 @@ +// +// Unit tests for OnDemand VPN / rules +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using NetworkExtension; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.NetworkExtension; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.NetworkExtension { + + [TestFixture] + [Preserve (AllMembers = true)] + public class OnDemandTest { + + void OnDemandRule (NEOnDemandRule rule) + { + Assert.Null (rule.DnsSearchDomainMatch, "DnsSearchDomainMatch"); + rule.DnsSearchDomainMatch = new string [] { "1" }; + Assert.That (rule.DnsSearchDomainMatch.Length, Is.EqualTo (1), "DnsSearchDomainMatch-2"); + rule.DnsSearchDomainMatch = null; + Assert.Null (rule.DnsSearchDomainMatch, "DnsSearchDomainMatch-3"); + + Assert.Null (rule.DnsServerAddressMatch, ""); + rule.DnsServerAddressMatch = new string [] { "1", "2" }; + Assert.That (rule.DnsServerAddressMatch.Length, Is.EqualTo (2), "DnsServerAddressMatch-2"); + rule.DnsServerAddressMatch = null; + Assert.Null (rule.DnsServerAddressMatch, "DnsServerAddressMatch-3"); + + Assert.That (rule.InterfaceTypeMatch, Is.EqualTo ((NEOnDemandRuleInterfaceType)0), "InterfaceTypeMatch"); + rule.InterfaceTypeMatch = NEOnDemandRuleInterfaceType.WiFi; + Assert.That (rule.InterfaceTypeMatch, Is.EqualTo (NEOnDemandRuleInterfaceType.WiFi), "InterfaceTypeMatch-2"); + + Assert.Null (rule.ProbeUrl, "ProbeUrl"); + using (var url = new NSUrl ("http://www.xamarin.com")) { + rule.ProbeUrl = url; + Assert.AreSame (url, rule.ProbeUrl, "ProbeUrl-2"); + } + rule.ProbeUrl = null; + Assert.Null (rule.ProbeUrl, "ProbeUrl-3"); + + Assert.Null (rule.SsidMatch, "SsidMatch"); + rule.SsidMatch = new string [] { "1", "2", "3" }; + Assert.That (rule.SsidMatch.Length, Is.EqualTo (3), "SsidMatch-2"); + rule.SsidMatch = null; + Assert.Null (rule.SsidMatch, "SsidMatch-3"); + } + + [Test] + public void OnDemandRuleConnect () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + using (var rule = new NEOnDemandRuleConnect ()) { + Assert.That (rule.Action, Is.EqualTo (NEOnDemandRuleAction.Connect), "Action"); + OnDemandRule (rule); + } + } + + [Test] + public void OnDemandRuleDisconnect () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + using (var rule = new NEOnDemandRuleDisconnect ()) { + Assert.That (rule.Action, Is.EqualTo (NEOnDemandRuleAction.Disconnect), "Action"); + OnDemandRule (rule); + } + } + + [Test] + public void OnDemandRuleIgnore () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + using (var rule = new NEOnDemandRuleIgnore ()) { + Assert.That (rule.Action, Is.EqualTo (NEOnDemandRuleAction.Ignore), "Action"); + OnDemandRule (rule); + } + } + + [Test] + public void NEOnDemandRuleEvaluateConnection () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + using (var rule = new NEOnDemandRuleEvaluateConnection ()) { + Assert.That (rule.Action, Is.EqualTo (NEOnDemandRuleAction.EvaluateConnection), "Action"); + OnDemandRule (rule); + // + Assert.IsNull (rule.ConnectionRules, "ConnectionRules"); + rule.ConnectionRules = new NEEvaluateConnectionRule [] { + new NEEvaluateConnectionRule () + }; + Assert.IsNotNull (rule.ConnectionRules, "ConnectionRules-2"); + rule.ConnectionRules = null; + Assert.IsNull (rule.ConnectionRules, "ConnectionRules-3"); + } + } + + [Test] + public void EvaluateConnectionRule_Default () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + using (var rule = new NEEvaluateConnectionRule ()) { + Assert.That (rule.Action, Is.EqualTo ((NEEvaluateConnectionRuleAction) 0), "Action"); + Assert.Null (rule.MatchDomains, "MatchDomains"); + Assert.Null (rule.ProbeUrl, "ProbeUrl"); + Assert.Null (rule.UseDnsServers, "UseDnsServers"); + } + } + + [Test] + public void EvaluateConnectionRule () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + using (var rule = new NEEvaluateConnectionRule (new [] { "xamarin.com" }, NEEvaluateConnectionRuleAction.ConnectIfNeeded)) { + Assert.That (rule.Action, Is.EqualTo (NEEvaluateConnectionRuleAction.ConnectIfNeeded), "Action"); + Assert.That (rule.MatchDomains [0], Is.EqualTo ("xamarin.com"), "MatchDomains"); + Assert.Null (rule.ProbeUrl, "ProbeUrl"); + using (var url = new NSUrl ("http://www.xamarin.com")) { + rule.ProbeUrl = url; + Assert.AreSame (url, rule.ProbeUrl, "ProbeUrl-2"); + } + rule.ProbeUrl = null; + Assert.Null (rule.ProbeUrl, "ProbeUrl-3"); + + Assert.Null (rule.UseDnsServers, "UseDnsServers"); + rule.UseDnsServers = new [] { "8.8.8.8" }; + Assert.That (rule.UseDnsServers [0], Is.EqualTo ("8.8.8.8"), "UseDnsServers-2"); + rule.UseDnsServers = null; + Assert.Null (rule.UseDnsServers, "UseDnsServers-3"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/NetworkExtension/VpnManagerTest.cs b/tests/monotouch-test/NetworkExtension/VpnManagerTest.cs new file mode 100644 index 000000000000..8b6f6dfaddab --- /dev/null +++ b/tests/monotouch-test/NetworkExtension/VpnManagerTest.cs @@ -0,0 +1,65 @@ +// +// Unit tests for NEVpnManager +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using NetworkExtension; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.NetworkExtension; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.NetworkExtension { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VpnManagerTest { + + [Test] + public void SharedManager () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + var shared = NEVpnManager.SharedManager; + // https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW59 + // Enabling Personal VPN (iOS Only) + if (shared == null) + Assert.Inconclusive ("Requires enabling Personal PVN (entitlements)"); + + Assert.That (shared.Connection.Status, Is.EqualTo (NEVpnStatus.Invalid), "Connection"); + Assert.False (shared.Enabled, "Enabled"); + if (TestRuntime.CheckSystemAndSDKVersion (9, 0)) { + Assert.AreEqual ("MonoTouchTest", shared.LocalizedDescription, "LocalizedDescription"); + } else { + Assert.IsNull (shared.LocalizedDescription, "LocalizedDescription"); + } + Assert.False (shared.OnDemandEnabled, "OnDemandEnabled"); + Assert.Null (shared.OnDemandRules, "OnDemandRules"); + Assert.Null (shared.Protocol, "Protocol"); + } + + [Test] + public void Fields () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS 8.0+"); + + Assert.That (NEVpnManager.ErrorDomain.ToString (), Is.EqualTo ("NEVPNErrorDomain"), "ErrorDomain"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/ObjCRuntime/BlocksTest.cs b/tests/monotouch-test/ObjCRuntime/BlocksTest.cs new file mode 100644 index 000000000000..3a5369ae6d90 --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/BlocksTest.cs @@ -0,0 +1,75 @@ +// +// Unit tests for Blocks +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BlocksTest { + [DllImport ("/usr/lib/libobjc.dylib")] + extern static IntPtr objc_getClass (string name); + + [DllImport("/usr/lib/libobjc.dylib")] + static extern IntPtr imp_implementationWithBlock(ref BlockLiteral block); + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern bool class_addMethod (IntPtr cls, IntPtr name, IntPtr imp, string types); + + [Test] + public void TestSetupBlock () + { + using (var obj = new TestClass ()) { + TestClass.OnCallback = ((IntPtr blockArgument, IntPtr self, IntPtr argument) => + { + Assert.AreNotEqual (IntPtr.Zero, blockArgument, "block"); + Assert.AreEqual (obj.Handle, self, "self"); + Assert.AreEqual (argument, (IntPtr) 0x12345678, "argument"); + }); + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("testBlocks:"), (IntPtr) 0x12345678); + } + } + + class TestClass : NSObject { + [MonoPInvokeCallback (typeof (TestBlockCallbackDelegate))] + static void TestBlockCallback (IntPtr block, IntPtr self, IntPtr argument) + { + OnCallback (block, self, argument); + } + + static TestBlockCallbackDelegate callback = new TestBlockCallbackDelegate (TestBlockCallback); + + public delegate void TestBlockCallbackDelegate (IntPtr block, IntPtr self, IntPtr argument); + public static TestBlockCallbackDelegate OnCallback; + + static TestClass () + { + var cls = Class.GetHandle (typeof (TestClass)); + var block = new BlockLiteral (); + block.SetupBlock (callback, null); + var imp = imp_implementationWithBlock (ref block); + class_addMethod (cls, Selector.GetHandle ("testBlocks:"), imp, "v@:^v"); + } + } + } +} diff --git a/tests/monotouch-test/ObjCRuntime/CategoryTest.cs b/tests/monotouch-test/ObjCRuntime/CategoryTest.cs new file mode 100644 index 000000000000..587fc821668d --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/CategoryTest.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#if !__TVOS__ +using MapKit; +#endif +#if !__WATCHOS__ +using CoreAnimation; +#endif +using CoreGraphics; +using CoreLocation; +using MonoTouchException=ObjCRuntime.RuntimeException; +using NativeException=Foundation.MonoTouchException; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#if !__TVOS__ +using MonoTouch.MapKit; +#endif +using MonoTouch.CoreAnimation; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreLocation; +using MonoTouch.UIKit; +using MonoTouchException=MonoTouch.RuntimeException; +using NativeException=MonoTouch.Foundation.MonoTouchException; +#endif +using OpenTK; +using NUnit.Framework; +using Bindings.Test; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +using CatAttrib=ObjCRuntime.CategoryAttribute; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +using CatAttrib=MonoTouch.ObjCRuntime.CategoryAttribute; +#endif + +namespace MonoTouchFixtures { + [CatAttrib (typeof (NSString))] + public static class MyStringCategory + { + [Export ("toUpper")] + static string ToUpper () + { + return "TOUPPER"; + } + + [Export ("toUpper:")] + static string ToUpper (string str) + { + return str.ToUpper (); + } + + [Export ("toLower")] + static string ToLower (this NSString str) + { + return ((string) str).ToLower (); + } + + [Export ("joinLower:")] + static string JoinLower (this NSString str, string str2) + { + return (((string) str) + str2).ToLower (); + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class CategoryTest + { + [Test] + public void Static () + { + using (var str = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend (new NSString ("").ClassHandle, Selector.GetHandle ("toUpper")))) { + Assert.AreEqual ("TOUPPER", str.ToString (), "#1"); + } + + using (var istr = (NSString) "test-string") { + using (var str = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr (new NSString ("").ClassHandle, Selector.GetHandle ("toUpper:"), istr.Handle))) { + Assert.AreEqual ("TEST-STRING", str.ToString (), "#2"); + } + } + } + + [Test] + public void Instance () + { + using (var istr = (NSString) "SoMeUpPeRcAsElEtTeRs") { + using (var str = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend (istr.Handle, Selector.GetHandle ("toLower")))) { + Assert.AreEqual ("someuppercaseletters", str.ToString (), "#1"); + } + } + using (var istr = (NSString) "fIrSt") { + using (var istr2 = (NSString) "secOND") { + using (var str = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr (istr.Handle, Selector.GetHandle ("joinLower:"), istr2.Handle))) { + Assert.AreEqual ("firstsecond", str.ToString (), "#2"); + } + } + } + } + +#if !__WATCHOS__ + [Test] + public void NavigationControllerOverride () + { + TestRuntime.IgnoreOnTVOS (); // shouldAutorotate is not available on TVOS. + + try { + bool category_invoked = false; + var vc = new UIViewController (); + vc.View.BackgroundColor = UIColor.Yellow; + var nc = new UINavigationController (vc); + Rotation_IOS6.ShouldAutoRotateCallback = () => { + category_invoked = true; + vc.View.BackgroundColor = UIColor.Green; + }; + MonoTouchFixtures.AppDelegate.PresentModalViewController (nc, 0.5); + Assert.That (category_invoked); + } finally { + Rotation_IOS6.ShouldAutoRotateCallback = null; + } + } +#endif // !__WATCHOS__ + } + +#if !__WATCHOS__ + [CatAttrib (typeof (UINavigationController))] + static class Rotation_IOS6 { + public static Action ShouldAutoRotateCallback; + [Export ("shouldAutorotate")] + static bool ShouldAutoRotate (this UINavigationController self) + { + if (ShouldAutoRotateCallback != null) + ShouldAutoRotateCallback (); + return true; + } + } +#endif // !__WATCHOS__ +} + diff --git a/tests/monotouch-test/ObjCRuntime/ClassTest.classlist.cs b/tests/monotouch-test/ObjCRuntime/ClassTest.classlist.cs new file mode 100644 index 000000000000..5a3ac604c613 --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/ClassTest.classlist.cs @@ -0,0 +1,1007 @@ +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +class BUG33981_0 : NSObject {} +class BUG33981_1 : NSObject {} +class BUG33981_2 : NSObject {} +class BUG33981_3 : NSObject {} +class BUG33981_4 : NSObject {} +class BUG33981_5 : NSObject {} +class BUG33981_6 : NSObject {} +class BUG33981_7 : NSObject {} +class BUG33981_8 : NSObject {} +class BUG33981_9 : NSObject {} +class BUG33981_10 : NSObject {} +class BUG33981_11 : NSObject {} +class BUG33981_12 : NSObject {} +class BUG33981_13 : NSObject {} +class BUG33981_14 : NSObject {} +class BUG33981_15 : NSObject {} +class BUG33981_16 : NSObject {} +class BUG33981_17 : NSObject {} +class BUG33981_18 : NSObject {} +class BUG33981_19 : NSObject {} +class BUG33981_20 : NSObject {} +class BUG33981_21 : NSObject {} +class BUG33981_22 : NSObject {} +class BUG33981_23 : NSObject {} +class BUG33981_24 : NSObject {} +class BUG33981_25 : NSObject {} +class BUG33981_26 : NSObject {} +class BUG33981_27 : NSObject {} +class BUG33981_28 : NSObject {} +class BUG33981_29 : NSObject {} +class BUG33981_30 : NSObject {} +class BUG33981_31 : NSObject {} +class BUG33981_32 : NSObject {} +class BUG33981_33 : NSObject {} +class BUG33981_34 : NSObject {} +class BUG33981_35 : NSObject {} +class BUG33981_36 : NSObject {} +class BUG33981_37 : NSObject {} +class BUG33981_38 : NSObject {} +class BUG33981_39 : NSObject {} +class BUG33981_40 : NSObject {} +class BUG33981_41 : NSObject {} +class BUG33981_42 : NSObject {} +class BUG33981_43 : NSObject {} +class BUG33981_44 : NSObject {} +class BUG33981_45 : NSObject {} +class BUG33981_46 : NSObject {} +class BUG33981_47 : NSObject {} +class BUG33981_48 : NSObject {} +class BUG33981_49 : NSObject {} +class BUG33981_50 : NSObject {} +class BUG33981_51 : NSObject {} +class BUG33981_52 : NSObject {} +class BUG33981_53 : NSObject {} +class BUG33981_54 : NSObject {} +class BUG33981_55 : NSObject {} +class BUG33981_56 : NSObject {} +class BUG33981_57 : NSObject {} +class BUG33981_58 : NSObject {} +class BUG33981_59 : NSObject {} +class BUG33981_60 : NSObject {} +class BUG33981_61 : NSObject {} +class BUG33981_62 : NSObject {} +class BUG33981_63 : NSObject {} +class BUG33981_64 : NSObject {} +class BUG33981_65 : NSObject {} +class BUG33981_66 : NSObject {} +class BUG33981_67 : NSObject {} +class BUG33981_68 : NSObject {} +class BUG33981_69 : NSObject {} +class BUG33981_70 : NSObject {} +class BUG33981_71 : NSObject {} +class BUG33981_72 : NSObject {} +class BUG33981_73 : NSObject {} +class BUG33981_74 : NSObject {} +class BUG33981_75 : NSObject {} +class BUG33981_76 : NSObject {} +class BUG33981_77 : NSObject {} +class BUG33981_78 : NSObject {} +class BUG33981_79 : NSObject {} +class BUG33981_80 : NSObject {} +class BUG33981_81 : NSObject {} +class BUG33981_82 : NSObject {} +class BUG33981_83 : NSObject {} +class BUG33981_84 : NSObject {} +class BUG33981_85 : NSObject {} +class BUG33981_86 : NSObject {} +class BUG33981_87 : NSObject {} +class BUG33981_88 : NSObject {} +class BUG33981_89 : NSObject {} +class BUG33981_90 : NSObject {} +class BUG33981_91 : NSObject {} +class BUG33981_92 : NSObject {} +class BUG33981_93 : NSObject {} +class BUG33981_94 : NSObject {} +class BUG33981_95 : NSObject {} +class BUG33981_96 : NSObject {} +class BUG33981_97 : NSObject {} +class BUG33981_98 : NSObject {} +class BUG33981_99 : NSObject {} +class BUG33981_100 : NSObject {} +class BUG33981_101 : NSObject {} +class BUG33981_102 : NSObject {} +class BUG33981_103 : NSObject {} +class BUG33981_104 : NSObject {} +class BUG33981_105 : NSObject {} +class BUG33981_106 : NSObject {} +class BUG33981_107 : NSObject {} +class BUG33981_108 : NSObject {} +class BUG33981_109 : NSObject {} +class BUG33981_110 : NSObject {} +class BUG33981_111 : NSObject {} +class BUG33981_112 : NSObject {} +class BUG33981_113 : NSObject {} +class BUG33981_114 : NSObject {} +class BUG33981_115 : NSObject {} +class BUG33981_116 : NSObject {} +class BUG33981_117 : NSObject {} +class BUG33981_118 : NSObject {} +class BUG33981_119 : NSObject {} +class BUG33981_120 : NSObject {} +class BUG33981_121 : NSObject {} +class BUG33981_122 : NSObject {} +class BUG33981_123 : NSObject {} +class BUG33981_124 : NSObject {} +class BUG33981_125 : NSObject {} +class BUG33981_126 : NSObject {} +class BUG33981_127 : NSObject {} +class BUG33981_128 : NSObject {} +class BUG33981_129 : NSObject {} +class BUG33981_130 : NSObject {} +class BUG33981_131 : NSObject {} +class BUG33981_132 : NSObject {} +class BUG33981_133 : NSObject {} +class BUG33981_134 : NSObject {} +class BUG33981_135 : NSObject {} +class BUG33981_136 : NSObject {} +class BUG33981_137 : NSObject {} +class BUG33981_138 : NSObject {} +class BUG33981_139 : NSObject {} +class BUG33981_140 : NSObject {} +class BUG33981_141 : NSObject {} +class BUG33981_142 : NSObject {} +class BUG33981_143 : NSObject {} +class BUG33981_144 : NSObject {} +class BUG33981_145 : NSObject {} +class BUG33981_146 : NSObject {} +class BUG33981_147 : NSObject {} +class BUG33981_148 : NSObject {} +class BUG33981_149 : NSObject {} +class BUG33981_150 : NSObject {} +class BUG33981_151 : NSObject {} +class BUG33981_152 : NSObject {} +class BUG33981_153 : NSObject {} +class BUG33981_154 : NSObject {} +class BUG33981_155 : NSObject {} +class BUG33981_156 : NSObject {} +class BUG33981_157 : NSObject {} +class BUG33981_158 : NSObject {} +class BUG33981_159 : NSObject {} +class BUG33981_160 : NSObject {} +class BUG33981_161 : NSObject {} +class BUG33981_162 : NSObject {} +class BUG33981_163 : NSObject {} +class BUG33981_164 : NSObject {} +class BUG33981_165 : NSObject {} +class BUG33981_166 : NSObject {} +class BUG33981_167 : NSObject {} +class BUG33981_168 : NSObject {} +class BUG33981_169 : NSObject {} +class BUG33981_170 : NSObject {} +class BUG33981_171 : NSObject {} +class BUG33981_172 : NSObject {} +class BUG33981_173 : NSObject {} +class BUG33981_174 : NSObject {} +class BUG33981_175 : NSObject {} +class BUG33981_176 : NSObject {} +class BUG33981_177 : NSObject {} +class BUG33981_178 : NSObject {} +class BUG33981_179 : NSObject {} +class BUG33981_180 : NSObject {} +class BUG33981_181 : NSObject {} +class BUG33981_182 : NSObject {} +class BUG33981_183 : NSObject {} +class BUG33981_184 : NSObject {} +class BUG33981_185 : NSObject {} +class BUG33981_186 : NSObject {} +class BUG33981_187 : NSObject {} +class BUG33981_188 : NSObject {} +class BUG33981_189 : NSObject {} +class BUG33981_190 : NSObject {} +class BUG33981_191 : NSObject {} +class BUG33981_192 : NSObject {} +class BUG33981_193 : NSObject {} +class BUG33981_194 : NSObject {} +class BUG33981_195 : NSObject {} +class BUG33981_196 : NSObject {} +class BUG33981_197 : NSObject {} +class BUG33981_198 : NSObject {} +class BUG33981_199 : NSObject {} +class BUG33981_200 : NSObject {} +class BUG33981_201 : NSObject {} +class BUG33981_202 : NSObject {} +class BUG33981_203 : NSObject {} +class BUG33981_204 : NSObject {} +class BUG33981_205 : NSObject {} +class BUG33981_206 : NSObject {} +class BUG33981_207 : NSObject {} +class BUG33981_208 : NSObject {} +class BUG33981_209 : NSObject {} +class BUG33981_210 : NSObject {} +class BUG33981_211 : NSObject {} +class BUG33981_212 : NSObject {} +class BUG33981_213 : NSObject {} +class BUG33981_214 : NSObject {} +class BUG33981_215 : NSObject {} +class BUG33981_216 : NSObject {} +class BUG33981_217 : NSObject {} +class BUG33981_218 : NSObject {} +class BUG33981_219 : NSObject {} +class BUG33981_220 : NSObject {} +class BUG33981_221 : NSObject {} +class BUG33981_222 : NSObject {} +class BUG33981_223 : NSObject {} +class BUG33981_224 : NSObject {} +class BUG33981_225 : NSObject {} +class BUG33981_226 : NSObject {} +class BUG33981_227 : NSObject {} +class BUG33981_228 : NSObject {} +class BUG33981_229 : NSObject {} +class BUG33981_230 : NSObject {} +class BUG33981_231 : NSObject {} +class BUG33981_232 : NSObject {} +class BUG33981_233 : NSObject {} +class BUG33981_234 : NSObject {} +class BUG33981_235 : NSObject {} +class BUG33981_236 : NSObject {} +class BUG33981_237 : NSObject {} +class BUG33981_238 : NSObject {} +class BUG33981_239 : NSObject {} +class BUG33981_240 : NSObject {} +class BUG33981_241 : NSObject {} +class BUG33981_242 : NSObject {} +class BUG33981_243 : NSObject {} +class BUG33981_244 : NSObject {} +class BUG33981_245 : NSObject {} +class BUG33981_246 : NSObject {} +class BUG33981_247 : NSObject {} +class BUG33981_248 : NSObject {} +class BUG33981_249 : NSObject {} +class BUG33981_250 : NSObject {} +class BUG33981_251 : NSObject {} +class BUG33981_252 : NSObject {} +class BUG33981_253 : NSObject {} +class BUG33981_254 : NSObject {} +class BUG33981_255 : NSObject {} +class BUG33981_256 : NSObject {} +class BUG33981_257 : NSObject {} +class BUG33981_258 : NSObject {} +class BUG33981_259 : NSObject {} +class BUG33981_260 : NSObject {} +class BUG33981_261 : NSObject {} +class BUG33981_262 : NSObject {} +class BUG33981_263 : NSObject {} +class BUG33981_264 : NSObject {} +class BUG33981_265 : NSObject {} +class BUG33981_266 : NSObject {} +class BUG33981_267 : NSObject {} +class BUG33981_268 : NSObject {} +class BUG33981_269 : NSObject {} +class BUG33981_270 : NSObject {} +class BUG33981_271 : NSObject {} +class BUG33981_272 : NSObject {} +class BUG33981_273 : NSObject {} +class BUG33981_274 : NSObject {} +class BUG33981_275 : NSObject {} +class BUG33981_276 : NSObject {} +class BUG33981_277 : NSObject {} +class BUG33981_278 : NSObject {} +class BUG33981_279 : NSObject {} +class BUG33981_280 : NSObject {} +class BUG33981_281 : NSObject {} +class BUG33981_282 : NSObject {} +class BUG33981_283 : NSObject {} +class BUG33981_284 : NSObject {} +class BUG33981_285 : NSObject {} +class BUG33981_286 : NSObject {} +class BUG33981_287 : NSObject {} +class BUG33981_288 : NSObject {} +class BUG33981_289 : NSObject {} +class BUG33981_290 : NSObject {} +class BUG33981_291 : NSObject {} +class BUG33981_292 : NSObject {} +class BUG33981_293 : NSObject {} +class BUG33981_294 : NSObject {} +class BUG33981_295 : NSObject {} +class BUG33981_296 : NSObject {} +class BUG33981_297 : NSObject {} +class BUG33981_298 : NSObject {} +class BUG33981_299 : NSObject {} +class BUG33981_300 : NSObject {} +class BUG33981_301 : NSObject {} +class BUG33981_302 : NSObject {} +class BUG33981_303 : NSObject {} +class BUG33981_304 : NSObject {} +class BUG33981_305 : NSObject {} +class BUG33981_306 : NSObject {} +class BUG33981_307 : NSObject {} +class BUG33981_308 : NSObject {} +class BUG33981_309 : NSObject {} +class BUG33981_310 : NSObject {} +class BUG33981_311 : NSObject {} +class BUG33981_312 : NSObject {} +class BUG33981_313 : NSObject {} +class BUG33981_314 : NSObject {} +class BUG33981_315 : NSObject {} +class BUG33981_316 : NSObject {} +class BUG33981_317 : NSObject {} +class BUG33981_318 : NSObject {} +class BUG33981_319 : NSObject {} +class BUG33981_320 : NSObject {} +class BUG33981_321 : NSObject {} +class BUG33981_322 : NSObject {} +class BUG33981_323 : NSObject {} +class BUG33981_324 : NSObject {} +class BUG33981_325 : NSObject {} +class BUG33981_326 : NSObject {} +class BUG33981_327 : NSObject {} +class BUG33981_328 : NSObject {} +class BUG33981_329 : NSObject {} +class BUG33981_330 : NSObject {} +class BUG33981_331 : NSObject {} +class BUG33981_332 : NSObject {} +class BUG33981_333 : NSObject {} +class BUG33981_334 : NSObject {} +class BUG33981_335 : NSObject {} +class BUG33981_336 : NSObject {} +class BUG33981_337 : NSObject {} +class BUG33981_338 : NSObject {} +class BUG33981_339 : NSObject {} +class BUG33981_340 : NSObject {} +class BUG33981_341 : NSObject {} +class BUG33981_342 : NSObject {} +class BUG33981_343 : NSObject {} +class BUG33981_344 : NSObject {} +class BUG33981_345 : NSObject {} +class BUG33981_346 : NSObject {} +class BUG33981_347 : NSObject {} +class BUG33981_348 : NSObject {} +class BUG33981_349 : NSObject {} +class BUG33981_350 : NSObject {} +class BUG33981_351 : NSObject {} +class BUG33981_352 : NSObject {} +class BUG33981_353 : NSObject {} +class BUG33981_354 : NSObject {} +class BUG33981_355 : NSObject {} +class BUG33981_356 : NSObject {} +class BUG33981_357 : NSObject {} +class BUG33981_358 : NSObject {} +class BUG33981_359 : NSObject {} +class BUG33981_360 : NSObject {} +class BUG33981_361 : NSObject {} +class BUG33981_362 : NSObject {} +class BUG33981_363 : NSObject {} +class BUG33981_364 : NSObject {} +class BUG33981_365 : NSObject {} +class BUG33981_366 : NSObject {} +class BUG33981_367 : NSObject {} +class BUG33981_368 : NSObject {} +class BUG33981_369 : NSObject {} +class BUG33981_370 : NSObject {} +class BUG33981_371 : NSObject {} +class BUG33981_372 : NSObject {} +class BUG33981_373 : NSObject {} +class BUG33981_374 : NSObject {} +class BUG33981_375 : NSObject {} +class BUG33981_376 : NSObject {} +class BUG33981_377 : NSObject {} +class BUG33981_378 : NSObject {} +class BUG33981_379 : NSObject {} +class BUG33981_380 : NSObject {} +class BUG33981_381 : NSObject {} +class BUG33981_382 : NSObject {} +class BUG33981_383 : NSObject {} +class BUG33981_384 : NSObject {} +class BUG33981_385 : NSObject {} +class BUG33981_386 : NSObject {} +class BUG33981_387 : NSObject {} +class BUG33981_388 : NSObject {} +class BUG33981_389 : NSObject {} +class BUG33981_390 : NSObject {} +class BUG33981_391 : NSObject {} +class BUG33981_392 : NSObject {} +class BUG33981_393 : NSObject {} +class BUG33981_394 : NSObject {} +class BUG33981_395 : NSObject {} +class BUG33981_396 : NSObject {} +class BUG33981_397 : NSObject {} +class BUG33981_398 : NSObject {} +class BUG33981_399 : NSObject {} +class BUG33981_400 : NSObject {} +class BUG33981_401 : NSObject {} +class BUG33981_402 : NSObject {} +class BUG33981_403 : NSObject {} +class BUG33981_404 : NSObject {} +class BUG33981_405 : NSObject {} +class BUG33981_406 : NSObject {} +class BUG33981_407 : NSObject {} +class BUG33981_408 : NSObject {} +class BUG33981_409 : NSObject {} +class BUG33981_410 : NSObject {} +class BUG33981_411 : NSObject {} +class BUG33981_412 : NSObject {} +class BUG33981_413 : NSObject {} +class BUG33981_414 : NSObject {} +class BUG33981_415 : NSObject {} +class BUG33981_416 : NSObject {} +class BUG33981_417 : NSObject {} +class BUG33981_418 : NSObject {} +class BUG33981_419 : NSObject {} +class BUG33981_420 : NSObject {} +class BUG33981_421 : NSObject {} +class BUG33981_422 : NSObject {} +class BUG33981_423 : NSObject {} +class BUG33981_424 : NSObject {} +class BUG33981_425 : NSObject {} +class BUG33981_426 : NSObject {} +class BUG33981_427 : NSObject {} +class BUG33981_428 : NSObject {} +class BUG33981_429 : NSObject {} +class BUG33981_430 : NSObject {} +class BUG33981_431 : NSObject {} +class BUG33981_432 : NSObject {} +class BUG33981_433 : NSObject {} +class BUG33981_434 : NSObject {} +class BUG33981_435 : NSObject {} +class BUG33981_436 : NSObject {} +class BUG33981_437 : NSObject {} +class BUG33981_438 : NSObject {} +class BUG33981_439 : NSObject {} +class BUG33981_440 : NSObject {} +class BUG33981_441 : NSObject {} +class BUG33981_442 : NSObject {} +class BUG33981_443 : NSObject {} +class BUG33981_444 : NSObject {} +class BUG33981_445 : NSObject {} +class BUG33981_446 : NSObject {} +class BUG33981_447 : NSObject {} +class BUG33981_448 : NSObject {} +class BUG33981_449 : NSObject {} +class BUG33981_450 : NSObject {} +class BUG33981_451 : NSObject {} +class BUG33981_452 : NSObject {} +class BUG33981_453 : NSObject {} +class BUG33981_454 : NSObject {} +class BUG33981_455 : NSObject {} +class BUG33981_456 : NSObject {} +class BUG33981_457 : NSObject {} +class BUG33981_458 : NSObject {} +class BUG33981_459 : NSObject {} +class BUG33981_460 : NSObject {} +class BUG33981_461 : NSObject {} +class BUG33981_462 : NSObject {} +class BUG33981_463 : NSObject {} +class BUG33981_464 : NSObject {} +class BUG33981_465 : NSObject {} +class BUG33981_466 : NSObject {} +class BUG33981_467 : NSObject {} +class BUG33981_468 : NSObject {} +class BUG33981_469 : NSObject {} +class BUG33981_470 : NSObject {} +class BUG33981_471 : NSObject {} +class BUG33981_472 : NSObject {} +class BUG33981_473 : NSObject {} +class BUG33981_474 : NSObject {} +class BUG33981_475 : NSObject {} +class BUG33981_476 : NSObject {} +class BUG33981_477 : NSObject {} +class BUG33981_478 : NSObject {} +class BUG33981_479 : NSObject {} +class BUG33981_480 : NSObject {} +class BUG33981_481 : NSObject {} +class BUG33981_482 : NSObject {} +class BUG33981_483 : NSObject {} +class BUG33981_484 : NSObject {} +class BUG33981_485 : NSObject {} +class BUG33981_486 : NSObject {} +class BUG33981_487 : NSObject {} +class BUG33981_488 : NSObject {} +class BUG33981_489 : NSObject {} +class BUG33981_490 : NSObject {} +class BUG33981_491 : NSObject {} +class BUG33981_492 : NSObject {} +class BUG33981_493 : NSObject {} +class BUG33981_494 : NSObject {} +class BUG33981_495 : NSObject {} +class BUG33981_496 : NSObject {} +class BUG33981_497 : NSObject {} +class BUG33981_498 : NSObject {} +class BUG33981_499 : NSObject {} +class BUG33981_500 : NSObject {} +class BUG33981_501 : NSObject {} +class BUG33981_502 : NSObject {} +class BUG33981_503 : NSObject {} +class BUG33981_504 : NSObject {} +class BUG33981_505 : NSObject {} +class BUG33981_506 : NSObject {} +class BUG33981_507 : NSObject {} +class BUG33981_508 : NSObject {} +class BUG33981_509 : NSObject {} +class BUG33981_510 : NSObject {} +class BUG33981_511 : NSObject {} +class BUG33981_512 : NSObject {} +class BUG33981_513 : NSObject {} +class BUG33981_514 : NSObject {} +class BUG33981_515 : NSObject {} +class BUG33981_516 : NSObject {} +class BUG33981_517 : NSObject {} +class BUG33981_518 : NSObject {} +class BUG33981_519 : NSObject {} +class BUG33981_520 : NSObject {} +class BUG33981_521 : NSObject {} +class BUG33981_522 : NSObject {} +class BUG33981_523 : NSObject {} +class BUG33981_524 : NSObject {} +class BUG33981_525 : NSObject {} +class BUG33981_526 : NSObject {} +class BUG33981_527 : NSObject {} +class BUG33981_528 : NSObject {} +class BUG33981_529 : NSObject {} +class BUG33981_530 : NSObject {} +class BUG33981_531 : NSObject {} +class BUG33981_532 : NSObject {} +class BUG33981_533 : NSObject {} +class BUG33981_534 : NSObject {} +class BUG33981_535 : NSObject {} +class BUG33981_536 : NSObject {} +class BUG33981_537 : NSObject {} +class BUG33981_538 : NSObject {} +class BUG33981_539 : NSObject {} +class BUG33981_540 : NSObject {} +class BUG33981_541 : NSObject {} +class BUG33981_542 : NSObject {} +class BUG33981_543 : NSObject {} +class BUG33981_544 : NSObject {} +class BUG33981_545 : NSObject {} +class BUG33981_546 : NSObject {} +class BUG33981_547 : NSObject {} +class BUG33981_548 : NSObject {} +class BUG33981_549 : NSObject {} +class BUG33981_550 : NSObject {} +class BUG33981_551 : NSObject {} +class BUG33981_552 : NSObject {} +class BUG33981_553 : NSObject {} +class BUG33981_554 : NSObject {} +class BUG33981_555 : NSObject {} +class BUG33981_556 : NSObject {} +class BUG33981_557 : NSObject {} +class BUG33981_558 : NSObject {} +class BUG33981_559 : NSObject {} +class BUG33981_560 : NSObject {} +class BUG33981_561 : NSObject {} +class BUG33981_562 : NSObject {} +class BUG33981_563 : NSObject {} +class BUG33981_564 : NSObject {} +class BUG33981_565 : NSObject {} +class BUG33981_566 : NSObject {} +class BUG33981_567 : NSObject {} +class BUG33981_568 : NSObject {} +class BUG33981_569 : NSObject {} +class BUG33981_570 : NSObject {} +class BUG33981_571 : NSObject {} +class BUG33981_572 : NSObject {} +class BUG33981_573 : NSObject {} +class BUG33981_574 : NSObject {} +class BUG33981_575 : NSObject {} +class BUG33981_576 : NSObject {} +class BUG33981_577 : NSObject {} +class BUG33981_578 : NSObject {} +class BUG33981_579 : NSObject {} +class BUG33981_580 : NSObject {} +class BUG33981_581 : NSObject {} +class BUG33981_582 : NSObject {} +class BUG33981_583 : NSObject {} +class BUG33981_584 : NSObject {} +class BUG33981_585 : NSObject {} +class BUG33981_586 : NSObject {} +class BUG33981_587 : NSObject {} +class BUG33981_588 : NSObject {} +class BUG33981_589 : NSObject {} +class BUG33981_590 : NSObject {} +class BUG33981_591 : NSObject {} +class BUG33981_592 : NSObject {} +class BUG33981_593 : NSObject {} +class BUG33981_594 : NSObject {} +class BUG33981_595 : NSObject {} +class BUG33981_596 : NSObject {} +class BUG33981_597 : NSObject {} +class BUG33981_598 : NSObject {} +class BUG33981_599 : NSObject {} +class BUG33981_600 : NSObject {} +class BUG33981_601 : NSObject {} +class BUG33981_602 : NSObject {} +class BUG33981_603 : NSObject {} +class BUG33981_604 : NSObject {} +class BUG33981_605 : NSObject {} +class BUG33981_606 : NSObject {} +class BUG33981_607 : NSObject {} +class BUG33981_608 : NSObject {} +class BUG33981_609 : NSObject {} +class BUG33981_610 : NSObject {} +class BUG33981_611 : NSObject {} +class BUG33981_612 : NSObject {} +class BUG33981_613 : NSObject {} +class BUG33981_614 : NSObject {} +class BUG33981_615 : NSObject {} +class BUG33981_616 : NSObject {} +class BUG33981_617 : NSObject {} +class BUG33981_618 : NSObject {} +class BUG33981_619 : NSObject {} +class BUG33981_620 : NSObject {} +class BUG33981_621 : NSObject {} +class BUG33981_622 : NSObject {} +class BUG33981_623 : NSObject {} +class BUG33981_624 : NSObject {} +class BUG33981_625 : NSObject {} +class BUG33981_626 : NSObject {} +class BUG33981_627 : NSObject {} +class BUG33981_628 : NSObject {} +class BUG33981_629 : NSObject {} +class BUG33981_630 : NSObject {} +class BUG33981_631 : NSObject {} +class BUG33981_632 : NSObject {} +class BUG33981_633 : NSObject {} +class BUG33981_634 : NSObject {} +class BUG33981_635 : NSObject {} +class BUG33981_636 : NSObject {} +class BUG33981_637 : NSObject {} +class BUG33981_638 : NSObject {} +class BUG33981_639 : NSObject {} +class BUG33981_640 : NSObject {} +class BUG33981_641 : NSObject {} +class BUG33981_642 : NSObject {} +class BUG33981_643 : NSObject {} +class BUG33981_644 : NSObject {} +class BUG33981_645 : NSObject {} +class BUG33981_646 : NSObject {} +class BUG33981_647 : NSObject {} +class BUG33981_648 : NSObject {} +class BUG33981_649 : NSObject {} +class BUG33981_650 : NSObject {} +class BUG33981_651 : NSObject {} +class BUG33981_652 : NSObject {} +class BUG33981_653 : NSObject {} +class BUG33981_654 : NSObject {} +class BUG33981_655 : NSObject {} +class BUG33981_656 : NSObject {} +class BUG33981_657 : NSObject {} +class BUG33981_658 : NSObject {} +class BUG33981_659 : NSObject {} +class BUG33981_660 : NSObject {} +class BUG33981_661 : NSObject {} +class BUG33981_662 : NSObject {} +class BUG33981_663 : NSObject {} +class BUG33981_664 : NSObject {} +class BUG33981_665 : NSObject {} +class BUG33981_666 : NSObject {} +class BUG33981_667 : NSObject {} +class BUG33981_668 : NSObject {} +class BUG33981_669 : NSObject {} +class BUG33981_670 : NSObject {} +class BUG33981_671 : NSObject {} +class BUG33981_672 : NSObject {} +class BUG33981_673 : NSObject {} +class BUG33981_674 : NSObject {} +class BUG33981_675 : NSObject {} +class BUG33981_676 : NSObject {} +class BUG33981_677 : NSObject {} +class BUG33981_678 : NSObject {} +class BUG33981_679 : NSObject {} +class BUG33981_680 : NSObject {} +class BUG33981_681 : NSObject {} +class BUG33981_682 : NSObject {} +class BUG33981_683 : NSObject {} +class BUG33981_684 : NSObject {} +class BUG33981_685 : NSObject {} +class BUG33981_686 : NSObject {} +class BUG33981_687 : NSObject {} +class BUG33981_688 : NSObject {} +class BUG33981_689 : NSObject {} +class BUG33981_690 : NSObject {} +class BUG33981_691 : NSObject {} +class BUG33981_692 : NSObject {} +class BUG33981_693 : NSObject {} +class BUG33981_694 : NSObject {} +class BUG33981_695 : NSObject {} +class BUG33981_696 : NSObject {} +class BUG33981_697 : NSObject {} +class BUG33981_698 : NSObject {} +class BUG33981_699 : NSObject {} +class BUG33981_700 : NSObject {} +class BUG33981_701 : NSObject {} +class BUG33981_702 : NSObject {} +class BUG33981_703 : NSObject {} +class BUG33981_704 : NSObject {} +class BUG33981_705 : NSObject {} +class BUG33981_706 : NSObject {} +class BUG33981_707 : NSObject {} +class BUG33981_708 : NSObject {} +class BUG33981_709 : NSObject {} +class BUG33981_710 : NSObject {} +class BUG33981_711 : NSObject {} +class BUG33981_712 : NSObject {} +class BUG33981_713 : NSObject {} +class BUG33981_714 : NSObject {} +class BUG33981_715 : NSObject {} +class BUG33981_716 : NSObject {} +class BUG33981_717 : NSObject {} +class BUG33981_718 : NSObject {} +class BUG33981_719 : NSObject {} +class BUG33981_720 : NSObject {} +class BUG33981_721 : NSObject {} +class BUG33981_722 : NSObject {} +class BUG33981_723 : NSObject {} +class BUG33981_724 : NSObject {} +class BUG33981_725 : NSObject {} +class BUG33981_726 : NSObject {} +class BUG33981_727 : NSObject {} +class BUG33981_728 : NSObject {} +class BUG33981_729 : NSObject {} +class BUG33981_730 : NSObject {} +class BUG33981_731 : NSObject {} +class BUG33981_732 : NSObject {} +class BUG33981_733 : NSObject {} +class BUG33981_734 : NSObject {} +class BUG33981_735 : NSObject {} +class BUG33981_736 : NSObject {} +class BUG33981_737 : NSObject {} +class BUG33981_738 : NSObject {} +class BUG33981_739 : NSObject {} +class BUG33981_740 : NSObject {} +class BUG33981_741 : NSObject {} +class BUG33981_742 : NSObject {} +class BUG33981_743 : NSObject {} +class BUG33981_744 : NSObject {} +class BUG33981_745 : NSObject {} +class BUG33981_746 : NSObject {} +class BUG33981_747 : NSObject {} +class BUG33981_748 : NSObject {} +class BUG33981_749 : NSObject {} +class BUG33981_750 : NSObject {} +class BUG33981_751 : NSObject {} +class BUG33981_752 : NSObject {} +class BUG33981_753 : NSObject {} +class BUG33981_754 : NSObject {} +class BUG33981_755 : NSObject {} +class BUG33981_756 : NSObject {} +class BUG33981_757 : NSObject {} +class BUG33981_758 : NSObject {} +class BUG33981_759 : NSObject {} +class BUG33981_760 : NSObject {} +class BUG33981_761 : NSObject {} +class BUG33981_762 : NSObject {} +class BUG33981_763 : NSObject {} +class BUG33981_764 : NSObject {} +class BUG33981_765 : NSObject {} +class BUG33981_766 : NSObject {} +class BUG33981_767 : NSObject {} +class BUG33981_768 : NSObject {} +class BUG33981_769 : NSObject {} +class BUG33981_770 : NSObject {} +class BUG33981_771 : NSObject {} +class BUG33981_772 : NSObject {} +class BUG33981_773 : NSObject {} +class BUG33981_774 : NSObject {} +class BUG33981_775 : NSObject {} +class BUG33981_776 : NSObject {} +class BUG33981_777 : NSObject {} +class BUG33981_778 : NSObject {} +class BUG33981_779 : NSObject {} +class BUG33981_780 : NSObject {} +class BUG33981_781 : NSObject {} +class BUG33981_782 : NSObject {} +class BUG33981_783 : NSObject {} +class BUG33981_784 : NSObject {} +class BUG33981_785 : NSObject {} +class BUG33981_786 : NSObject {} +class BUG33981_787 : NSObject {} +class BUG33981_788 : NSObject {} +class BUG33981_789 : NSObject {} +class BUG33981_790 : NSObject {} +class BUG33981_791 : NSObject {} +class BUG33981_792 : NSObject {} +class BUG33981_793 : NSObject {} +class BUG33981_794 : NSObject {} +class BUG33981_795 : NSObject {} +class BUG33981_796 : NSObject {} +class BUG33981_797 : NSObject {} +class BUG33981_798 : NSObject {} +class BUG33981_799 : NSObject {} +class BUG33981_800 : NSObject {} +class BUG33981_801 : NSObject {} +class BUG33981_802 : NSObject {} +class BUG33981_803 : NSObject {} +class BUG33981_804 : NSObject {} +class BUG33981_805 : NSObject {} +class BUG33981_806 : NSObject {} +class BUG33981_807 : NSObject {} +class BUG33981_808 : NSObject {} +class BUG33981_809 : NSObject {} +class BUG33981_810 : NSObject {} +class BUG33981_811 : NSObject {} +class BUG33981_812 : NSObject {} +class BUG33981_813 : NSObject {} +class BUG33981_814 : NSObject {} +class BUG33981_815 : NSObject {} +class BUG33981_816 : NSObject {} +class BUG33981_817 : NSObject {} +class BUG33981_818 : NSObject {} +class BUG33981_819 : NSObject {} +class BUG33981_820 : NSObject {} +class BUG33981_821 : NSObject {} +class BUG33981_822 : NSObject {} +class BUG33981_823 : NSObject {} +class BUG33981_824 : NSObject {} +class BUG33981_825 : NSObject {} +class BUG33981_826 : NSObject {} +class BUG33981_827 : NSObject {} +class BUG33981_828 : NSObject {} +class BUG33981_829 : NSObject {} +class BUG33981_830 : NSObject {} +class BUG33981_831 : NSObject {} +class BUG33981_832 : NSObject {} +class BUG33981_833 : NSObject {} +class BUG33981_834 : NSObject {} +class BUG33981_835 : NSObject {} +class BUG33981_836 : NSObject {} +class BUG33981_837 : NSObject {} +class BUG33981_838 : NSObject {} +class BUG33981_839 : NSObject {} +class BUG33981_840 : NSObject {} +class BUG33981_841 : NSObject {} +class BUG33981_842 : NSObject {} +class BUG33981_843 : NSObject {} +class BUG33981_844 : NSObject {} +class BUG33981_845 : NSObject {} +class BUG33981_846 : NSObject {} +class BUG33981_847 : NSObject {} +class BUG33981_848 : NSObject {} +class BUG33981_849 : NSObject {} +class BUG33981_850 : NSObject {} +class BUG33981_851 : NSObject {} +class BUG33981_852 : NSObject {} +class BUG33981_853 : NSObject {} +class BUG33981_854 : NSObject {} +class BUG33981_855 : NSObject {} +class BUG33981_856 : NSObject {} +class BUG33981_857 : NSObject {} +class BUG33981_858 : NSObject {} +class BUG33981_859 : NSObject {} +class BUG33981_860 : NSObject {} +class BUG33981_861 : NSObject {} +class BUG33981_862 : NSObject {} +class BUG33981_863 : NSObject {} +class BUG33981_864 : NSObject {} +class BUG33981_865 : NSObject {} +class BUG33981_866 : NSObject {} +class BUG33981_867 : NSObject {} +class BUG33981_868 : NSObject {} +class BUG33981_869 : NSObject {} +class BUG33981_870 : NSObject {} +class BUG33981_871 : NSObject {} +class BUG33981_872 : NSObject {} +class BUG33981_873 : NSObject {} +class BUG33981_874 : NSObject {} +class BUG33981_875 : NSObject {} +class BUG33981_876 : NSObject {} +class BUG33981_877 : NSObject {} +class BUG33981_878 : NSObject {} +class BUG33981_879 : NSObject {} +class BUG33981_880 : NSObject {} +class BUG33981_881 : NSObject {} +class BUG33981_882 : NSObject {} +class BUG33981_883 : NSObject {} +class BUG33981_884 : NSObject {} +class BUG33981_885 : NSObject {} +class BUG33981_886 : NSObject {} +class BUG33981_887 : NSObject {} +class BUG33981_888 : NSObject {} +class BUG33981_889 : NSObject {} +class BUG33981_890 : NSObject {} +class BUG33981_891 : NSObject {} +class BUG33981_892 : NSObject {} +class BUG33981_893 : NSObject {} +class BUG33981_894 : NSObject {} +class BUG33981_895 : NSObject {} +class BUG33981_896 : NSObject {} +class BUG33981_897 : NSObject {} +class BUG33981_898 : NSObject {} +class BUG33981_899 : NSObject {} +class BUG33981_900 : NSObject {} +class BUG33981_901 : NSObject {} +class BUG33981_902 : NSObject {} +class BUG33981_903 : NSObject {} +class BUG33981_904 : NSObject {} +class BUG33981_905 : NSObject {} +class BUG33981_906 : NSObject {} +class BUG33981_907 : NSObject {} +class BUG33981_908 : NSObject {} +class BUG33981_909 : NSObject {} +class BUG33981_910 : NSObject {} +class BUG33981_911 : NSObject {} +class BUG33981_912 : NSObject {} +class BUG33981_913 : NSObject {} +class BUG33981_914 : NSObject {} +class BUG33981_915 : NSObject {} +class BUG33981_916 : NSObject {} +class BUG33981_917 : NSObject {} +class BUG33981_918 : NSObject {} +class BUG33981_919 : NSObject {} +class BUG33981_920 : NSObject {} +class BUG33981_921 : NSObject {} +class BUG33981_922 : NSObject {} +class BUG33981_923 : NSObject {} +class BUG33981_924 : NSObject {} +class BUG33981_925 : NSObject {} +class BUG33981_926 : NSObject {} +class BUG33981_927 : NSObject {} +class BUG33981_928 : NSObject {} +class BUG33981_929 : NSObject {} +class BUG33981_930 : NSObject {} +class BUG33981_931 : NSObject {} +class BUG33981_932 : NSObject {} +class BUG33981_933 : NSObject {} +class BUG33981_934 : NSObject {} +class BUG33981_935 : NSObject {} +class BUG33981_936 : NSObject {} +class BUG33981_937 : NSObject {} +class BUG33981_938 : NSObject {} +class BUG33981_939 : NSObject {} +class BUG33981_940 : NSObject {} +class BUG33981_941 : NSObject {} +class BUG33981_942 : NSObject {} +class BUG33981_943 : NSObject {} +class BUG33981_944 : NSObject {} +class BUG33981_945 : NSObject {} +class BUG33981_946 : NSObject {} +class BUG33981_947 : NSObject {} +class BUG33981_948 : NSObject {} +class BUG33981_949 : NSObject {} +class BUG33981_950 : NSObject {} +class BUG33981_951 : NSObject {} +class BUG33981_952 : NSObject {} +class BUG33981_953 : NSObject {} +class BUG33981_954 : NSObject {} +class BUG33981_955 : NSObject {} +class BUG33981_956 : NSObject {} +class BUG33981_957 : NSObject {} +class BUG33981_958 : NSObject {} +class BUG33981_959 : NSObject {} +class BUG33981_960 : NSObject {} +class BUG33981_961 : NSObject {} +class BUG33981_962 : NSObject {} +class BUG33981_963 : NSObject {} +class BUG33981_964 : NSObject {} +class BUG33981_965 : NSObject {} +class BUG33981_966 : NSObject {} +class BUG33981_967 : NSObject {} +class BUG33981_968 : NSObject {} +class BUG33981_969 : NSObject {} +class BUG33981_970 : NSObject {} +class BUG33981_971 : NSObject {} +class BUG33981_972 : NSObject {} +class BUG33981_973 : NSObject {} +class BUG33981_974 : NSObject {} +class BUG33981_975 : NSObject {} +class BUG33981_976 : NSObject {} +class BUG33981_977 : NSObject {} +class BUG33981_978 : NSObject {} +class BUG33981_979 : NSObject {} +class BUG33981_980 : NSObject {} +class BUG33981_981 : NSObject {} +class BUG33981_982 : NSObject {} +class BUG33981_983 : NSObject {} +class BUG33981_984 : NSObject {} +class BUG33981_985 : NSObject {} +class BUG33981_986 : NSObject {} +class BUG33981_987 : NSObject {} +class BUG33981_988 : NSObject {} +class BUG33981_989 : NSObject {} +class BUG33981_990 : NSObject {} +class BUG33981_991 : NSObject {} +class BUG33981_992 : NSObject {} +class BUG33981_993 : NSObject {} +class BUG33981_994 : NSObject {} +class BUG33981_995 : NSObject {} +class BUG33981_996 : NSObject {} +class BUG33981_997 : NSObject {} +class BUG33981_998 : NSObject {} +class BUG33981_999 : NSObject {} +class BUG33981_1000 : NSObject {} diff --git a/tests/monotouch-test/ObjCRuntime/ClassTest.cs b/tests/monotouch-test/ObjCRuntime/ClassTest.cs new file mode 100644 index 000000000000..c00d40b382e9 --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/ClassTest.cs @@ -0,0 +1,130 @@ +// +// Unit tests for Class +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ClassTest { + [DllImport ("/usr/lib/libobjc.dylib")] + extern static IntPtr objc_getClass (string name); + + // based on https://xamarin.assistly.com/agent/case/6816 + [Register ("ZählerObject")] + class ZählerObject : NSObject { + } + + [Test] + public void getClassTest () + { + IntPtr p = objc_getClass ("ZählerNotExists"); + Assert.That (p, Is.EqualTo (IntPtr.Zero), "DoesNotExists"); + + p = objc_getClass ("ZählerObject"); + Assert.That (p, Is.Not.EqualTo (IntPtr.Zero), "ä"); + } + + [Test] + public void LookupTest () + { + IntPtr p = objc_getClass ("ZählerObject"); + var m = typeof (Class).GetMethod ("Lookup", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof (IntPtr) }, null); + Type t = (Type) m.Invoke (null, new object [] { objc_getClass ("ZählerObject") }); + Assert.That (t, Is.EqualTo (typeof (ZählerObject)), "Lookup"); + Assert.That (p, Is.Not.EqualTo (IntPtr.Zero), "Class"); + } + + // Not sure what to do about this one, it doesn't compile with the static registrar (since linking fails) +#if DYNAMIC_REGISTRAR + [Test] + public void ThrowOnMissingNativeClassTest () + { + bool saved = Class.ThrowOnInitFailure; + + Class.ThrowOnInitFailure = true; + try { + Assert.Throws (() => new InexistentClass (), "a"); + } finally { + Class.ThrowOnInitFailure = saved; + } + } + + [Register ("Inexistent", true)] + public class InexistentClass : NSObject { + public override IntPtr ClassHandle { + get { + return Class.GetHandle (GetType ().Name); + } + } + } +#endif + + [Test] + public void Bug33981 () + { + var types = new List (); + foreach (var type in GetType ().Assembly.GetTypes ()) { + if (type.IsSubclassOf (typeof (NSObject)) && type.Name.StartsWith ("BUG33981")) + types.Add (type); + } + + Assert.That (types.Count, Is.GreaterThan (50), "test type enumeration"); + + const int n = 5; + var threads = new Thread [n]; + var cntr = new int [n]; + Exception ex = null; + var startPistol = new ManualResetEvent (false); + var stopLine = new CountdownEvent (n); + for (int i = 0; i < n; i++) { + var idx = i; + threads [i] = new Thread (() => { + startPistol.WaitOne (); + try { + foreach (var type in types) { + var c = Class.GetHandle (type.Name); + if (c != IntPtr.Zero) { + try { + Class.Lookup (new Class (c)); + } catch (Exception e) { + ex = e; + return; + } + cntr [idx]++; + } + } + } finally { + stopLine.Signal (); + } + }); + threads [i].IsBackground = true; + threads [i].Start (); + } + startPistol.Set (); + stopLine.Wait (); + + Assert.IsNull (ex); + } + } +} diff --git a/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs b/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs new file mode 100644 index 000000000000..e1044b225dc5 --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs @@ -0,0 +1,42 @@ +// +// Unit tests for Dlfcn +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DlfcnTest { + + [Test] + public void OpenClose_libSystem () + { + IntPtr handle = Dlfcn.dlopen ("/usr/lib/libSystem.dylib", 0); + Assert.That (handle, Is.Not.EqualTo (IntPtr.Zero), "dlopen"); + var err = Dlfcn.dlclose (handle); + if ((Runtime.Arch == Arch.DEVICE) && TestRuntime.CheckiOSSystemVersion (9,0)) { + // Apple is doing some funky stuff with dlopen... this condition is to track if this change during betas + Assert.That (err, Is.EqualTo (-1), "dlclose"); + } else { + Assert.That (err, Is.EqualTo (0), "dlclose"); + } + } + } +} diff --git a/tests/monotouch-test/ObjCRuntime/ExceptionsTest.cs b/tests/monotouch-test/ObjCRuntime/ExceptionsTest.cs new file mode 100644 index 000000000000..debc16715cce --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/ExceptionsTest.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#if !__WATCHOS__ +using UIKit; +#endif +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; +using Bindings.Test; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ExceptionsTest { + +#if __WATCHOS__ + MarshalObjectiveCExceptionMode defaultObjectiveCExceptionMode = MarshalObjectiveCExceptionMode.ThrowManagedException; + MarshalManagedExceptionMode defaultManagedExceptionMode = MarshalManagedExceptionMode.ThrowObjectiveCException; +#else + MarshalObjectiveCExceptionMode defaultObjectiveCExceptionMode = MarshalObjectiveCExceptionMode.UnwindManagedCode; + MarshalManagedExceptionMode defaultManagedExceptionMode = MarshalManagedExceptionMode.UnwindNativeCode; +#endif + + static List objcEventArgs; + static List managedEventArgs; + static MarshalManagedExceptionMode? managedTargetMode; + static MarshalObjectiveCExceptionMode? objcTargetMode; + + static void ObjExceptionHandler (object sender, MarshalObjectiveCExceptionEventArgs args) + { + objcEventArgs.Add (new MarshalObjectiveCExceptionEventArgs () { + Exception = args.Exception, + ExceptionMode = args.ExceptionMode, + }); + if (objcTargetMode.HasValue) + args.ExceptionMode = objcTargetMode.Value; + } + + static void ManagedExceptionHandler (object sender, MarshalManagedExceptionEventArgs args) + { + managedEventArgs.Add (new MarshalManagedExceptionEventArgs () { + Exception = args.Exception, + ExceptionMode = args.ExceptionMode, + }); + if (managedTargetMode.HasValue) + args.ExceptionMode = managedTargetMode.Value; + } + + static void ClearExceptionData () + { + objcEventArgs = new List (); + managedEventArgs = new List (); + objcTargetMode = null; + managedTargetMode = null; + } + + static void InstallHandlers () + { + ClearExceptionData (); + Runtime.MarshalManagedException += ManagedExceptionHandler; + Runtime.MarshalObjectiveCException += ObjExceptionHandler; + } + + static void UninstallHandlers () + { + Runtime.MarshalManagedException -= ManagedExceptionHandler; + Runtime.MarshalObjectiveCException -= ObjExceptionHandler; + } + + [Test] + public void ObjCException () + { +#if !__WATCHOS__ + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("This test requires wrapper functions, which are not enabled for monotouch-test on device."); +#endif + +#if !DEBUG && !__WATCHOS__ + if (Runtime.Arch != Arch.DEVICE) + Assert.Ignore ("This test only works in debug mode in the simulator."); +#endif + InstallHandlers (); + + try { + using (var e = new ObjCExceptionTest ()) { + MonoTouchException thrownException = null; + try { + objcTargetMode = MarshalObjectiveCExceptionMode.ThrowManagedException; + e.ThrowObjCException (); + Assert.Fail ("managed exception not thrown"); + } catch (MonoTouchException ex) { + thrownException = ex; + } + Assert.AreEqual ("exception was thrown", thrownException.Reason, "objc reason"); + Assert.AreEqual ("Some exception", thrownException.Name, "objc name"); + Assert.AreEqual (1, objcEventArgs.Count, "objc exception"); + Assert.AreEqual (thrownException.NSException.Handle, objcEventArgs [0].Exception.Handle, "objc exception"); + Assert.AreEqual (defaultObjectiveCExceptionMode, objcEventArgs [0].ExceptionMode, "objc mode"); + Assert.AreEqual (0, managedEventArgs.Count, "managed exception"); + } + } finally { + UninstallHandlers (); + } + } + + class ManagedExceptionTest : ObjCExceptionTest { + public Exception Exception; + public override void ThrowManagedException () + { + Exception = new ApplicationException ("3,14"); + throw Exception; + } + } + + [Test] + public void ManagedExceptionPassthrough () + { + Exception thrownException = null; + +#if !__WATCHOS__ + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("This test requires wrapper functions, which are not enabled for monotouch-test on device."); +#endif + +#if !DEBUG && !__WATCHOS__ + if (Runtime.Arch != Arch.DEVICE) + Assert.Ignore ("This test only works in debug mode in the simulator."); +#endif + + InstallHandlers (); + try { + using (var e = new ManagedExceptionTest ()) { + try { + objcTargetMode = MarshalObjectiveCExceptionMode.ThrowManagedException; + managedTargetMode = MarshalManagedExceptionMode.ThrowObjectiveCException; + e.InvokeManagedExceptionThrower (); + Assert.Fail ("no exception thrown 1"); + } catch (Exception ex) { + thrownException = ex; + } + Assert.AreSame (e.Exception, thrownException, "exception"); + Assert.AreEqual ("3,14", thrownException.Message, "1 thrown message"); + Assert.AreSame (typeof (ApplicationException), thrownException.GetType (), "1 thrown type"); + Assert.AreEqual (1, objcEventArgs.Count, "1 objc exception"); + Assert.AreEqual (defaultObjectiveCExceptionMode, objcEventArgs [0].ExceptionMode, "1 objc mode"); + Assert.AreEqual ("System.ApplicationException", objcEventArgs [0].Exception.Name, "1 objc reason"); + Assert.AreEqual ("3,14", objcEventArgs [0].Exception.Reason, "1 objc message"); + Assert.AreEqual (1, managedEventArgs.Count, "1 managed count"); + Assert.AreEqual (defaultManagedExceptionMode, managedEventArgs [0].ExceptionMode, "1 managed mode"); + Assert.AreSame (thrownException, managedEventArgs [0].Exception, "1 managed exception"); + + ClearExceptionData (); + try { + objcTargetMode = MarshalObjectiveCExceptionMode.ThrowManagedException; + managedTargetMode = MarshalManagedExceptionMode.ThrowObjectiveCException; + e.InvokeManagedExceptionThrowerAndRethrow (); + Assert.Fail ("no exception thrown 2"); + } catch (Exception ex) { + thrownException = ex; + } + Assert.AreNotSame (e.Exception, thrownException, "exception"); + Assert.AreSame (typeof (MonoTouchException), thrownException.GetType (), "2 thrown type"); + Assert.AreEqual ("Caught exception", ((MonoTouchException) thrownException).Name, "2 thrown name"); + Assert.AreEqual ("exception was rethrown", ((MonoTouchException) thrownException).Reason, "2 thrown reason"); + Assert.AreEqual (1, objcEventArgs.Count, "2 objc exception"); + Assert.AreEqual (defaultObjectiveCExceptionMode, objcEventArgs [0].ExceptionMode, "2 objc mode"); + Assert.AreEqual ("Caught exception", objcEventArgs [0].Exception.Name, "2 objc reason"); + Assert.AreEqual ("exception was rethrown", objcEventArgs [0].Exception.Reason, "2 objc message"); + Assert.AreEqual (1, managedEventArgs.Count, "2 managed count"); + Assert.AreEqual (defaultManagedExceptionMode, managedEventArgs [0].ExceptionMode, "2 managed mode"); + Assert.AreSame (e.Exception, managedEventArgs [0].Exception, "2 managed exception"); + + ClearExceptionData (); + objcTargetMode = MarshalObjectiveCExceptionMode.ThrowManagedException; + managedTargetMode = MarshalManagedExceptionMode.ThrowObjectiveCException; + e.InvokeManagedExceptionThrowerAndCatch (); // no exception. + Assert.AreEqual (0, objcEventArgs.Count, "3 objc exception"); + Assert.AreEqual (1, managedEventArgs.Count, "3 managed count"); + Assert.AreEqual (defaultManagedExceptionMode, managedEventArgs [0].ExceptionMode, "3 managed mode"); + Assert.AreSame (e.Exception, managedEventArgs [0].Exception, "3 managed exception"); + } + } finally { + UninstallHandlers (); + } + } + } +} diff --git a/tests/monotouch-test/ObjCRuntime/Messaging.cs b/tests/monotouch-test/ObjCRuntime/Messaging.cs new file mode 100644 index 000000000000..791ee24368fc --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/Messaging.cs @@ -0,0 +1,244 @@ +using System; +using System.Runtime.InteropServices; +using System.Drawing; + +#if XAMCORE_2_0 +#if !__WATCHOS__ +using CoreAnimation; +#endif +#if !__TVOS__ +using MapKit; +#endif +using Foundation; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.MapKit; +using MonoTouch.Foundation; +#endif +using OpenTK; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +#if XAMCORE_2_0 +namespace ObjCRuntime +#else +namespace MonoTouch.ObjCRuntime +#endif +{ + public static class Messaging + { + internal const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib"; + + public struct objc_super { + public IntPtr Handle; + public IntPtr SuperHandle; + } + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_IntPtr_PointF_ref_PointF (IntPtr receiver, IntPtr selector, IntPtr scrollView, PointF velocity, ref PointF targetContentOffset); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSendSuper")] + public extern static void void_objc_msgSendSuper (ref objc_super receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_ref_IntPtr (IntPtr receiver, IntPtr selector, ref IntPtr value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_out_IntPtr (IntPtr receiver, IntPtr selector, out IntPtr value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_IntPtr_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1, IntPtr p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static nint nint_objc_msgSend_IntPtr_nint (IntPtr receiver, IntPtr selector, IntPtr p1, nint p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_IntPtr_ref_BlockLiteral (IntPtr receiver, IntPtr selector, IntPtr p1, ref BlockLiteral p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_IntPtr_IntPtr_IntPtr_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_IntPtr_IntPtr_IntPtr_NSRange_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1, IntPtr p2, IntPtr p3, NSRange p4, IntPtr p5); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_int (IntPtr receiver, IntPtr selector, int value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_long (IntPtr receiver, IntPtr selector, long value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_int_int_long (IntPtr receiver, IntPtr selector, int p1, int p2, long p3); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_long_int_long (IntPtr receiver, IntPtr selector, long p1, int p2, long p3); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_int (IntPtr receiver, IntPtr selector, int p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_long (IntPtr receiver, IntPtr selector, long p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static int int_objc_msgSend_int (IntPtr receiver, IntPtr selector, int p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_ref_IntPtr (IntPtr receiver, IntPtr selector, ref IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_IntPtr_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1, IntPtr p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_double_double (IntPtr receiver, IntPtr selector, double a, double b); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_bool (IntPtr receiver, IntPtr selector, bool p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static double Double_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static float float_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static bool bool_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static int int_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static long long_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static int int_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static bool bool_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static bool bool_objc_msgSend_IntPtr_int (IntPtr receiver, IntPtr selector, IntPtr p1, int p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static IntPtr IntPtr_objc_msgSend_SizeF (IntPtr receiver, IntPtr selector, SizeF p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static PointF PointF_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static SizeF SizeF_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static void void_objc_msgSend_RectangleF (IntPtr receiver, IntPtr selector, RectangleF p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_int (IntPtr receiver, IntPtr selector, int p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1); + +#if !__TVOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_MKCoordinateRegion_IntPtr (IntPtr receiver, IntPtr selector, MKCoordinateRegion p1, IntPtr p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_MKMapRect (IntPtr receiver, IntPtr selector, MKMapRect p1); +#endif // !__TVOS__ + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_RectangleF (IntPtr receiver, IntPtr selector, RectangleF p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_RectangleF_int (IntPtr receiver, IntPtr selector, RectangleF p1, int p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_RectangleF_IntPtr (IntPtr receiver, IntPtr selector, RectangleF p1, IntPtr p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_RectangleF_RectangleF_float (IntPtr receiver, IntPtr selector, RectangleF p1, RectangleF p2, float p3); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static RectangleF RectangleF_objc_msgSend_RectangleF_RectangleF_RectangleF (IntPtr receiver, IntPtr selector, RectangleF p1, RectangleF p2, RectangleF p3); + +#if !__WATCHOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static Matrix3 Matrix3_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + public extern static CATransform3D CATransform3D_objc_msgSend (IntPtr receiver, IntPtr selector); +#endif // !__WATCHOS__ + +#if !__TVOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_MKMapRect (out RectangleF buf, IntPtr receiver, IntPtr selector, MKMapRect p1); +#endif // !__TVOS__ + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret (out RectangleF buf, IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void PointF_objc_msgSend_stret (out PointF buf, IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void SizeF_objc_msgSend_stret (out SizeF buf, IntPtr receiver, IntPtr selector); + +#if !__WATCHOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void Matrix3_objc_msgSend_stret (out Matrix3 buf, IntPtr receiver, IntPtr selector); +#endif // !__WATCHOS__ + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_int (out RectangleF buf, IntPtr receiver, IntPtr selector, int p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_IntPtr (out RectangleF buf, IntPtr receiver, IntPtr selector, IntPtr p1); + +#if !__TVOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_MKCoordinateRegion_IntPtr (out RectangleF buf, IntPtr receiver, IntPtr selector, MKCoordinateRegion p1, IntPtr p2); +#endif // !__TVOS__ + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_RectangleF (out RectangleF buf, IntPtr receiver, IntPtr selector, RectangleF p1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_RectangleF_int (out RectangleF buf, IntPtr receiver, IntPtr selector, RectangleF p1, int p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_RectangleF_IntPtr (out RectangleF buf, IntPtr receiver, IntPtr selector, RectangleF p1, IntPtr p2); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_RectangleF_RectangleF_float (out RectangleF buf, IntPtr receiver, IntPtr selector, RectangleF p1, RectangleF p2, float p3); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void RectangleF_objc_msgSend_stret_RectangleF_RectangleF_RectangleF (out RectangleF buf, IntPtr receiver, IntPtr selector, RectangleF p1, RectangleF p2, RectangleF p3); + +#if !__WATCHOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + public extern static void CATransform3D_objc_msgSend_stret (out CATransform3D buf, IntPtr receiver, IntPtr selector); +#endif // !__WATCHOS__ + } +} + diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs new file mode 100644 index 000000000000..86f54dea9dc2 --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs @@ -0,0 +1,2468 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Threading; + +#if XAMCORE_2_0 +#if !__TVOS__ && !__WATCHOS__ +using AddressBook; +using AddressBookUI; +#endif +using Foundation; +using UIKit; +using ObjCRuntime; +#if !__TVOS__ +using MapKit; +#endif +#if !__WATCHOS__ +using CoreAnimation; +#endif +using CoreGraphics; +using CoreLocation; +#if !__TVOS__ +using Contacts; +#endif +using MonoTouchException=ObjCRuntime.RuntimeException; +using NativeException=Foundation.MonoTouchException; +#else +using MonoTouch; +using MonoTouch.AddressBook; +using MonoTouch.AddressBookUI; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.MapKit; +using MonoTouch.CoreAnimation; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreLocation; +using MonoTouch.UIKit; +using MonoTouchException=MonoTouch.RuntimeException; +using NativeException=MonoTouch.Foundation.MonoTouchException; +#endif +using OpenTK; +using NUnit.Framework; +using Bindings.Test; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +using XamarinTests.ObjCRuntime; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class RegistrarTest { +#if !XAMCORE_2_0 + // This should throw an exception at build time (device) or at registration time (startup on simulator). + // Putting it here for now so I don't forget. + [Export ()] + public bool? IsRegistered { get; set; } +#endif + + public static Registrars CurrentRegistrar { + get { + return RegistrarSharedTest.CurrentRegistrar; + } + } + + [Test] + public void TestProperties () + { + RegistrarTestClass obj = new RegistrarTestClass (); + IntPtr receiver = obj.Handle; + int dummy = 314; + + // readonly, attribute on property + CallProperty (receiver, "Property1", ref obj.called_Property1Getter, "#Instance-1-r"); + CallProperty (receiver, "setProperty1:", ref dummy, "#Instance-1-w", true); + // rw, attribute on property + CallProperty (receiver, "Property2", ref obj.called_Property2Getter, "#Instance-2-r"); + CallProperty (receiver, "setProperty2:", ref obj.called_Property2Setter, "#Instance-2-w"); + // writeonly, attribute on property + //CallProperty (receiver, "Property3", ref dummy, "#Instance-3-r", true); + CallProperty (receiver, "setProperty3:", ref obj.called_Property3Setter, "#Instance-3-w"); + + // readonly, atteribute on getter + CallProperty (receiver, "Property4", ref obj.called_Property4Getter, "#Instance-4-r"); + CallProperty (receiver, "setProperty4:", ref dummy, "#Instance-4-w", true); + // rw, attribyte on getter/setter + CallProperty (receiver, "Property5", ref obj.called_Property5Getter, "#Instance-5-r"); + CallProperty (receiver, "setProperty5:", ref dummy, "#Instance-5-w1", true); + CallProperty (receiver, "WProperty5:", ref obj.called_Property5Setter, "#Instance-5-w2"); + // writeonly, attribute on setter + CallProperty (receiver, "setProperty6:", ref dummy, "#Instance-6-r", true); + CallProperty (receiver, "Property6:", ref obj.called_Property6Setter, "#Instance-6-w"); + } + + [Test] + public void TestStaticProperties () + { + IntPtr receiver = Class.GetHandle ("RegistrarTestClass"); + int dummy = 314; + + RegistrarTestClass.called_StaticProperty1Getter = 0; + RegistrarTestClass.called_StaticProperty2Getter = 0; + RegistrarTestClass.called_StaticProperty4Getter = 0; + RegistrarTestClass.called_StaticProperty5Getter = 0; + RegistrarTestClass.called_StaticProperty2Setter = 0; + RegistrarTestClass.called_StaticProperty3Setter = 0; + RegistrarTestClass.called_StaticProperty5Setter = 0; + RegistrarTestClass.called_StaticProperty6Setter = 0; + + // readonly, attribute on property + CallProperty (receiver, "StaticProperty1", ref RegistrarTestClass.called_StaticProperty1Getter, "#Static-1-r"); + CallProperty (receiver, "setStaticProperty1:", ref dummy, "#Static-1-w", true); + // rw, attribute on property + CallProperty (receiver, "StaticProperty2", ref RegistrarTestClass.called_StaticProperty2Getter, "#Static-2-r"); + CallProperty (receiver, "setStaticProperty2:", ref RegistrarTestClass.called_StaticProperty2Setter, "#Static-2-w"); + // writeonly, attribute on property + CallProperty (receiver, "StaticProperty3", ref dummy, "#Static-3-r", true); + CallProperty (receiver, "setStaticProperty3:", ref RegistrarTestClass.called_StaticProperty3Setter, "#Static-3-w"); + + // readonly, atteribute on getter + CallProperty (receiver, "StaticProperty4", ref RegistrarTestClass.called_StaticProperty4Getter, "#Static-4-r"); + CallProperty (receiver, "setStaticProperty4:", ref dummy, "#Static-4-w", true); + // rw, attribyte on getter/setter + CallProperty (receiver, "StaticProperty5", ref RegistrarTestClass.called_StaticProperty5Getter, "#Static-5-r"); + CallProperty (receiver, "setStaticProperty5:", ref dummy, "#Static-5-w1", true); + CallProperty (receiver, "WStaticProperty5:", ref RegistrarTestClass.called_StaticProperty5Setter, "#Static-5-w2"); + // writeonly, attribute on setter + CallProperty (receiver, "setStaticProperty6:", ref dummy, "#Static-6-r", true); + CallProperty (receiver, "StaticProperty6:", ref RegistrarTestClass.called_StaticProperty6Setter, "#Static-6-w"); + } + + void CallProperty (IntPtr receiver, string selector, ref int called_var, string id, bool expectFailure = false) + { + if (Runtime.Arch == Arch.DEVICE && expectFailure) { + Console.WriteLine ("Skipping '{0}', it's expected to throw a 'Selector not found exception', but on device it seems to crash instead", selector); + return; + } + + try { + Messaging.bool_objc_msgSend (receiver, new Selector (selector).Handle); + Assert.That (!expectFailure, id + "-expected-failure-but-succeeded"); + Assert.That (called_var == 1, id + "-called-var"); + } catch (NativeException ex) { + Assert.That (expectFailure, id + "-expected-success-but-failed: " + ex.Message); + } + } + + [Test] + public void TestINativeObject () + { + IntPtr receiver = Class.GetHandle ("RegistrarTestClass"); + IntPtr ptr; + CGPath path; + + if ((CurrentRegistrar & Registrars.AllStatic) == 0) + Assert.Ignore ("This test only passes with the static registrars."); + + Assert.False (Messaging.bool_objc_msgSend_IntPtr (receiver, new Selector ("INativeObject1:").Handle, IntPtr.Zero), "#a1"); + Assert.True (Messaging.bool_objc_msgSend_IntPtr (receiver, new Selector ("INativeObject1:").Handle, new CGPath ().Handle), "#a2"); + + Assert.That (Messaging.IntPtr_objc_msgSend_bool (receiver, new Selector ("INativeObject2:").Handle, false), Is.EqualTo (IntPtr.Zero), "#b1"); + Assert.That (Messaging.IntPtr_objc_msgSend_bool (receiver, new Selector ("INativeObject2:").Handle, true), Is.Not.EqualTo (IntPtr.Zero), "#b2"); + + void_objc_msgSend_out_IntPtr_bool (receiver, new Selector ("INativeObject3:create:").Handle, out ptr, true); + Assert.That (ptr, Is.Not.EqualTo (IntPtr.Zero), "#c1"); + void_objc_msgSend_out_IntPtr_bool (receiver, new Selector ("INativeObject3:create:").Handle, out ptr, false); + Assert.That (ptr, Is.EqualTo (IntPtr.Zero), "#c2"); + + path = null; + ptr = IntPtr.Zero; + Assert.False (bool_objc_msgSend_ref_intptr (receiver, new Selector ("INativeObject4:").Handle, ref ptr), "#d1"); + Assert.That (ptr, Is.EqualTo (IntPtr.Zero), "#d2"); + path = new CGPath (); + ptr = path.Handle; + Assert.True (bool_objc_msgSend_ref_intptr (receiver, new Selector ("INativeObject4:").Handle, ref ptr), "#d3"); + Assert.That (ptr, Is.EqualTo (path.Handle), "#d4"); + + ptr = Messaging.IntPtr_objc_msgSend_bool (receiver, new Selector ("INativeObject5:").Handle, false); + Assert.That (ptr, Is.EqualTo (IntPtr.Zero), "#e1"); + ptr = Messaging.IntPtr_objc_msgSend_bool (receiver, new Selector ("INativeObject5:").Handle, true); + Assert.That (ptr, Is.Not.EqualTo (IntPtr.Zero), "#e2"); + path = new CGPath (ptr); + path.AddArc (1, 2, 3, 4, 5, false); // this should crash if we get back a bogus ptr + } + + [Test] + public void TestVirtual () + { + // bug #4426 + DerivedRegistrar1 d1 = new DerivedRegistrar1 (); + DerivedRegistrar2 d2 = new DerivedRegistrar2 (); + Selector sel = new Selector ("VirtualMethod"); + + string a = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (d1.Handle, sel.Handle)).ToString (); + string b = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (d2.Handle, sel.Handle)).ToString (); + + Assert.That (a, Is.EqualTo (d1.GetType ().Name), "#a"); + Assert.That (b, Is.EqualTo (d2.GetType ().Name), "#b"); + } + + [Test] + public void TestOutNSString () + { + var obj = new RegistrarTestClass (); + var sel = new Selector ("testOutNSString:"); + IntPtr ptr; + + void_objc_msgSend_out_IntPtr (obj.Handle, sel.Handle, out ptr); + + Assert.AreEqual ("Santa is coming", NSString.FromHandle (ptr), "#santa"); + } + + [Test] + public void TestInheritedStaticMethods () + { + if ((CurrentRegistrar & Registrars.AllNew) == 0) + Assert.Ignore ("This test only passes with the new registrars."); + + // bug #6170 + int rv; + + rv = Messaging.int_objc_msgSend (Class.GetHandle (typeof(StaticBaseClass)), Selector.GetHandle ("foo")); + Assert.AreEqual (rv, 314, "#base"); + rv = Messaging.int_objc_msgSend (Class.GetHandle (typeof(StaticDerivedClass)), Selector.GetHandle ("foo")); + Assert.AreEqual (rv, 314, "#derived"); + } + + [Test] + public void TestStructAndOut () + { + var obj = new RegistrarTestClass (); + var sel = new Selector ("testOutParametersWithStructs:in:out:"); + NSError value = new NSError (); + IntPtr ptr; + SizeF size = new SizeF (1, 2); + + void_objc_msgSend_SizeF_IntPtr_out_IntPtr (obj.Handle, sel.Handle, size, value.Handle, out ptr); + + Assert.AreEqual (value.Handle, ptr, "#1"); + } + +#if !__TVOS__ && !__WATCHOS__ + [MonoPInvokeCallback (typeof (DActionArity1V1))] + static void DActionArity1V1Func (IntPtr block, UIBackgroundFetchResult result) + { + } + + [Test] + public void TestAction () + { + using (var obj = new RegistrarTestClass ()) { + var sel = new Selector ("testAction:"); + var block = new BlockLiteral (); + var tramp = new DActionArity1V1 (DActionArity1V1Func); + var del = new DActionArity1V1 (DActionArity1V1Func); + block.SetupBlock (tramp, del); + void_objc_msgSend_ref_BlockLiteral (obj.Handle, sel.Handle, ref block); + block.CleanupBlock (); + } + } +#endif // !__TVOS__ && !__WATCHOS__ + + class TS1 : NSObject {} + class TS2 : NSObject {} + class TS3 : NSObject {} + class TS4 : NSObject {} + class TS5 : NSObject {} + class TS6 : NSObject {} + class TS7 : NSObject {} + class TS8 : NSObject {} + class TS9 : NSObject {} + class TS10 : NSObject {} + + static bool tested_thread_safety; + + [Test] + public void TestThreadSafety () + { + // Create X number of threads. + // Each thread waits for a signal from the main thread to go ahead with the actual test. + + if (tested_thread_safety) + Assert.Ignore ("This test can only be executed once. To run it again restart the test app."); + tested_thread_safety = true; + + var threads = new Thread [5]; + var types = new Type [] { typeof(TS1), typeof(TS2), typeof(TS3), typeof(TS4), typeof(TS5), typeof (TS6), typeof (TS7), typeof (TS8), typeof (TS9), typeof (TS10) }; + var exceptions = new List (); + var wait = new ManualResetEvent (false); + var start_counter = new CountdownEvent (threads.Length); + var end_counter = new CountdownEvent (threads.Length); + + for (int i = 0; i < threads.Length; i++) { + threads [i] = new Thread (() => { + try { + start_counter.Signal (); // signal "I'm ready" + wait.WaitOne (); // wait for go-ahead + // Do the actual test. + // We fetch the class handle for the types in question in several threads at once. + // This will cause the registrar to try to register the type, but that should only + // be done once. + foreach (var t in types) + Class.GetHandle (t); + } catch (Exception ex) { + lock (exceptions) + exceptions.Add (ex); + } finally { + end_counter.Signal (); // signal "I'm done" + } + }) { + IsBackground = true, + }; + threads [i].Start (); + } + + // Wait for X "I'm ready" signals + Assert.IsTrue (start_counter.Wait (1000), "all threads didn't spin up in 1s"); + + wait.Set (); // let the threads go wild. + + Assert.IsTrue (end_counter.Wait (5000), "all threads didn't finish testing in 5s"); + + for (int i = 0; i < threads.Length; i++) { + Assert.IsTrue (threads [i].Join (1000), "join #" + i.ToString ()); + } + + if (exceptions.Count > 0) { + Assert.Fail ("Expected no exceptions, but got:\n{0}", + new AggregateException (exceptions).ToString ()); + } + } + + [Test] + public void TestRetainReturnValue () + { + IntPtr ptr; + + // The NSAutoreleasePool is to flush any pending 'autorelease' calls. + // We fetch the managed object to make sure there are no lingering + // managed objects (otherwise we wouldn't know if the GC had freed + // the managed object or not). + + using (var obj = new RegistrarTestClass ()) { + + using (var pool = new NSAutoreleasePool ()) + ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("testRetainArray")); + using (var rv = Runtime.GetNSObject (ptr)) { + Assert.AreEqual (2, rv.RetainCount, "array"); + Assert.AreSame (typeof(NSArray), rv.GetType (), "array type"); + rv.DangerousRelease (); + } + + using (var pool = new NSAutoreleasePool ()) + ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("testReturnINativeObject")); + using (var rv = Runtime.GetNSObject (ptr)) { + Assert.AreEqual (2, rv.RetainCount, "inativeobject"); + Assert.AreSame (typeof(NSObject), rv.GetType (), "inativeobject type"); + rv.DangerousRelease (); + } + + using (var pool = new NSAutoreleasePool ()) + ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("testRetainNSObject")); + using (var rv = Runtime.GetNSObject (ptr)) { + Assert.AreEqual (2, rv.RetainCount, "nsobject"); + Assert.AreSame (typeof(NSObject), rv.GetType (), "nsobject type"); + rv.DangerousRelease (); + } + + using (var pool = new NSAutoreleasePool ()) + ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("testRetainString")); + using (var rv = Runtime.GetNSObject (ptr)) { + Assert.AreEqual (2, rv.RetainCount, "string"); + Assert.IsTrue (rv is NSString, "string type"); + rv.DangerousRelease (); + } + } + + using (var obj = new DerivedRegistrar1 ()) { + using (var pool = new NSAutoreleasePool ()) + ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("testOverriddenRetainNSObject")); + using (var rv = Runtime.GetNSObject (ptr)) { + Assert.AreEqual (2, rv.RetainCount, "overridden nsobject"); + Assert.AreSame (typeof(NSObject), rv.GetType (), "overridden nsobject type"); + rv.DangerousRelease (); + } + + } + } + + class Props : NSObject { + [Export ("myProp")] + public string MyProp { + get; + set; + } + } + + [Test] + public void TestObjCProperties () + { + var class_handle = Class.GetHandle (typeof(Props)); + Assert.AreNotEqual (IntPtr.Zero, class_getProperty (class_handle, "myProp")); + } + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_getProperty (IntPtr cls, string name); + + [Test] + public void TestNonVirtualProperty () + { + if (CurrentRegistrar == Registrars.OldDynamic) + Assert.Ignore ("This test does not pass with the legacy dynamic registrar."); + + using (var obj = new DerivedRegistrar1 ()) { + Assert.IsTrue (Messaging.bool_objc_msgSend (obj.Handle, Selector.GetHandle ("b1"))); + } + } + + [Test] + public void TestGeneric () + { + if ((CurrentRegistrar & Registrars.AllNew) == 0) + Assert.Ignore ("Generic NSObjects are only supported with the new registrars."); + +#if !OLDSTATICREGISTRAR + var g1 = new GenericTestClass (); + var g2 = new GenericTestClass (); + var g3 = new DerivedGenericTestClass (); + var g4 = new DerivedGenericTestClass (); + var sel = new Selector ("GetTypeFullName").Handle; + + string t1 = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (g1.Handle, sel)).ToString (); + string t2 = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (g2.Handle, sel)).ToString (); + string t3 = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (g3.Handle, sel)).ToString (); + string t4 = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (g4.Handle, sel)).ToString (); + + Assert.AreEqual (g1.GetTypeFullName (), t1, "#t1"); + Assert.AreEqual (g2.GetTypeFullName (), t2, "#t2"); + Assert.AreEqual (g3.GetTypeFullName (), t3, "#t3"); + Assert.AreEqual (g4.GetTypeFullName (), t4, "#t4"); + + var openClass = Class.GetHandle ("Open_1"); + var handle = Messaging.IntPtr_objc_msgSend (openClass, Selector.GetHandle ("alloc")); + try { + handle = Messaging.IntPtr_objc_msgSend (handle, Selector.GetHandle ("init")); + Assert.Fail ("Expected [[Open_1 alloc] init] to fail."); + } catch (MonoTouchException mex) { + Assert.AreEqual ("Cannot construct an instance of the type 'MonoTouchFixtures.ObjCRuntime.RegistrarTest+Open`1' from Objective-C because the type is generic.", mex.Message); + } finally { + Messaging.void_objc_msgSend (handle, Selector.GetHandle ("release")); // or should this be dealloc directly? + } + + Assert.DoesNotThrow (() => new Open (), "Create managed open instance"); + + // It's possible to create an instance of a closed class. + var closedClass = Class.GetHandle (typeof (Closed)); + handle = Messaging.IntPtr_objc_msgSend (closedClass, Selector.GetHandle ("alloc")); + handle = Messaging.IntPtr_objc_msgSend (handle, Selector.GetHandle ("init")); + Messaging.void_objc_msgSend (handle, Selector.GetHandle ("release")); + + Assert.DoesNotThrow (() => new Closed (), "Created managed closed instance"); +#endif + } + + [Test] + public void TestNestedGenericType () + { + if ((CurrentRegistrar & Registrars.AllNew) == 0) + Assert.Ignore ("Generic NSObjects are only supported with the new registrars."); + +#if !OLDSTATICREGISTRAR + var foo = new NestedParent.Nested (); + var obj = new NSObject (); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("foo:"), obj.Handle); + obj.Dispose (); + foo.Dispose (); +#endif + } + + [Test] + public void TestInstanceMethodOnOpenGenericType () + { + if ((CurrentRegistrar & Registrars.AllNew) == 0) + Assert.Ignore ("Generic NSObjects are only supported with the new registrars."); + +#if !OLDSTATICREGISTRAR + { + var foo = new Open (); + + var view = new NSSet (); + var expectedU = typeof(NSSet); + var expectedV = typeof(string); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("bar:"), IntPtr.Zero); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("bar:"), view.Handle); + Assert.AreSame (view, foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + var arr = NSArray.FromNSObjects (view); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("zap:"), IntPtr.Zero); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("zap:"), arr.Handle); + Assert.AreSame (view, ((object[])foo.LastArg) [0]); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (foo.Handle, Selector.GetHandle ("xyz")), "xyz"); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (foo.Handle, Selector.GetHandle ("barzap")), "barzap"); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("setBarzap:"), IntPtr.Zero); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("setBarzap:"), view.Handle); + Assert.AreSame (view, foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + arr.Dispose (); + view.Dispose (); + foo.Dispose (); + } + + { + var foo = new Open (); + + var view = new NSObject (); + var expectedU = typeof(NSObject); + var expectedV = typeof(int); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("bar:"), IntPtr.Zero); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("bar:"), view.Handle); + Assert.AreSame (view, foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + var arr = NSArray.FromNSObjects (view); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("zap:"), IntPtr.Zero); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("zap:"), arr.Handle); + Assert.AreSame (view, ((object[])foo.LastArg) [0]); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (foo.Handle, Selector.GetHandle ("xyz")), "xyz"); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (foo.Handle, Selector.GetHandle ("barzap")), "barzap"); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("setBarzap:"), IntPtr.Zero); + Assert.IsNull (foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + Messaging.void_objc_msgSend_IntPtr (foo.Handle, Selector.GetHandle ("setBarzap:"), view.Handle); + Assert.AreSame (view, foo.LastArg); + Assert.AreEqual (expectedU, foo.UType); + Assert.AreEqual (expectedV, foo.VType); + + arr.Dispose (); + view.Dispose (); + foo.Dispose (); + } +#endif + } + +#if !__WATCHOS__ + [Test] + public void TestGenericUIView () + { +#if !OLDSTATICREGISTRAR + using (var iview = new NullableIntView (new RectangleF (0, 0, 100, 100))) { + using (var strview = new StringView (new RectangleF (0, 0, 100, 100))) { + Messaging.void_objc_msgSend_RectangleF (iview.Handle, Selector.GetHandle ("drawRect:"), RectangleF.Empty); + Assert.AreEqual (typeof(int?), iview.TypeT, "int?"); + Assert.AreEqual ("NullableIntView", iview.TypeName, "int? typename"); + Messaging.void_objc_msgSend_RectangleF (strview.Handle, Selector.GetHandle ("drawRect:"), RectangleF.Empty); + Assert.AreEqual (typeof(string), strview.TypeT, "string"); + Assert.AreEqual ("StringView", strview.TypeName, "string typename"); + } + } +#endif + } +#endif // !__WATCHOS__ + +#if !__WATCHOS__ + [Test] + public void TestNativeEnum () + { + //public virtual void TestNativeEnum1 (UITextWritingDirection twd) + using (var obj = new RegistrarTestClass ()) { + if (IntPtr.Size == 4) { + Messaging.void_objc_msgSend_int (obj.Handle, Selector.GetHandle ("testNativeEnum1:"), (int) UITextWritingDirection.RightToLeft); + } else { + Messaging.void_objc_msgSend_long (obj.Handle, Selector.GetHandle ("testNativeEnum1:"), (long) UITextWritingDirection.RightToLeft); + } + + if (IntPtr.Size == 4) { + Messaging.void_objc_msgSend_int_int_long (obj.Handle, Selector.GetHandle ("testNativeEnum1:"), (int) UITextWritingDirection.RightToLeft, 31415, 3141592); + } else { + Messaging.void_objc_msgSend_long_int_long (obj.Handle, Selector.GetHandle ("testNativeEnum1:"), (long) UITextWritingDirection.RightToLeft, 31415, 3141592); + } + + if (IntPtr.Size == 4) { + Assert.AreEqual ((int) UIPopoverArrowDirection.Right, Messaging.int_objc_msgSend (obj.Handle, Selector.GetHandle ("testNativeEnum2")), "testNativeEnum2"); + Messaging.void_objc_msgSend_int (obj.Handle, Selector.GetHandle ("setTestNativeEnum2:"), (int) UIPopoverArrowDirection.Left); + } else { + Assert.AreEqual ((long) UIPopoverArrowDirection.Right, Messaging.long_objc_msgSend (obj.Handle, Selector.GetHandle ("testNativeEnum2")), "testNativeEnum2"); + Messaging.void_objc_msgSend_long (obj.Handle, Selector.GetHandle ("setTestNativeEnum2:"), (long) UIPopoverArrowDirection.Left); + } + } + } +#endif // !__WATCHOS__ + + [Test] + public void Bug23289 () + { + using (var obj = new RegistrarTestClass ()) { + using (var arr = new NSMutableArray (1)) { + var cl = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (CLLocation)), Selector.GetHandle ("alloc")); + cl = Messaging.IntPtr_objc_msgSend_double_double (cl, Selector.GetHandle ("initWithLatitude:longitude:"), 1, 2); + Messaging.void_objc_msgSend_IntPtr (arr.Handle, Selector.GetHandle ("addObject:"), cl); + Messaging.bool_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("testBug23289:"), arr.Handle); + Messaging.void_objc_msgSend (cl, Selector.GetHandle ("release")); + } + } + } + + [Test] + public void TestCGPointParameter () + { + using (var obj = new RegistrarTestClass ()) { + var pnt1 = new PointF (123, 456); + PointF pnt2 = new PointF (); + void_objc_msgSend_CGPoint_ref_CGPoint (obj.Handle, Selector.GetHandle ("testCGPoint:out:"), pnt1, ref pnt2); + Assert.AreEqual (123, pnt2.X, "X"); + Assert.AreEqual (456, pnt2.Y, "Y"); + } + } + + const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib"; + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_out_IntPtr (IntPtr receiver, IntPtr selector, out IntPtr value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_ref_IntPtr (IntPtr receiver, IntPtr selector, ref IntPtr value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_out_IntPtr_bool (IntPtr receiver, IntPtr selector, out IntPtr path, bool create); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static bool bool_objc_msgSend_ref_intptr (IntPtr receiver, IntPtr selector, ref IntPtr path); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_SizeF_IntPtr_out_IntPtr (IntPtr receiver, IntPtr selector, SizeF size, IntPtr input, out IntPtr value); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_ref_BlockLiteral (IntPtr receiver, IntPtr selector, ref BlockLiteral block); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_CGPoint_ref_CGPoint (IntPtr receiver, IntPtr selector, PointF p1, ref PointF p2); + +#region Exported type + [Register ("RegistrarTestClass")] + class RegistrarTestClass : NSObject + { + public virtual bool B1 { + [Export ("b1")] + get { + return false; + } + } + + // static properties + public static int called_StaticProperty1Getter; + [Export ("StaticProperty1")] + static bool StaticProperty1 { + get { + called_StaticProperty1Getter++; + return true; + } + } + + public static int called_StaticProperty2Getter; + public static int called_StaticProperty2Setter; + [Export ("StaticProperty2")] + static bool StaticProperty2 { + get { + called_StaticProperty2Getter++; + return true; + } + set { + called_StaticProperty2Setter++; + } + } + + public static int called_StaticProperty3Setter; + [Export ("StaticProperty3")] + static bool StaticProperty3 { + set { + called_StaticProperty3Setter++; + } + } + + public static int called_StaticProperty4Getter; + static bool StaticProperty4 { + [Export ("StaticProperty4")] + get { + called_StaticProperty4Getter++; + return true; + } + } + + public static int called_StaticProperty5Getter; + public static int called_StaticProperty5Setter; + static bool StaticProperty5 { + [Export ("StaticProperty5")] + get { + called_StaticProperty5Getter++; + return true; + } + [Export ("WStaticProperty5:")] // can't use same name as getter, and don't use the default "set_" prefix either (to ensure we're not exporting the default prefix always) + set { + called_StaticProperty5Setter++; + } + } + + public static int called_StaticProperty6Setter; + static bool StaticProperty6 { + [Export ("StaticProperty6:")] + set { + called_StaticProperty6Setter++; + } + } + + // instance properties + public int called_Property1Getter; + [Export ("Property1")] + bool Property1 { + get { + called_Property1Getter++; + return true; + } + } + + public int called_Property2Getter; + public int called_Property2Setter; + [Export ("Property2")] + bool Property2 { + get { + called_Property2Getter++; + return true; + } + set { + called_Property2Setter++; + } + } + + public int called_Property3Setter; + [Export ("Property3")] + bool Property3 { + set { + called_Property3Setter++; + } + } + + public int called_Property4Getter; + bool Property4 { + [Export ("Property4")] + get { + called_Property4Getter++; + return true; + } + } + + public int called_Property5Getter; + public int called_Property5Setter; + bool Property5 { + [Export ("Property5")] + get { + called_Property5Getter++; + return true; + } + [Export ("WProperty5:")] // can't use same name as getter, and don't use the default "set_" prefix either (to ensure we're not exporting the default prefix always) + set { + called_Property5Setter++; + } + } + + public int called_Property6Setter; + bool Property6 { + [Export ("Property6:")] + set { + called_Property6Setter++; + } + } + + [Export ("INativeObject1:")] + static bool INativeObject1 (CGPath img /*CGPath is a INativeObject */) + { + return img != null; + } + + [Export ("INativeObject2:")] + static CGPath INativeObject2 (bool create) + { + return create ? new CGPath () : null; + } + + [Export ("INativeObject3:create:")] + static void INativeObject3 (out CGPath path, bool create) + { + path = create ? new CGPath () : null; + } + + [Export ("INativeObject4:")] + static bool INativeObject4 (ref CGPath path) + { + return path != null; + } + + [Export ("INativeObject5:")] + static CGPath INativeObject5 (bool create) + { + return create ? new CGPath () : null; + } + + [Export ("VirtualMethod")] + public virtual string VirtualMethod () + { + return "base"; + } + + [Export ("testNSAction:")] + public void TestNSAction (Action action) + { + } + + [Export ("testOutNSString:")] + public void TestOutNSString (out string value) + { + value = "Santa is coming"; + } + + [Export ("testOutParametersWithStructs:in:out:")] + public void TestOutParameters (SizeF a, NSError @in, out NSError value) + { + // bug 16078 + value = @in; + } + +#if !__TVOS__ && !__WATCHOS__ + [Export ("testAction:")] + public void TestAction ([BlockProxy (typeof (NIDActionArity1V1))] Action action) + { + // bug ? + } +#endif // !__TVOS__ && !__WATCHOS__ + + [return: ReleaseAttribute ()] + [Export ("testRetainArray")] + public NSObject[] TestRetainArray () + { + return new NSObject[] { new NSObject () }; + } + + [Export ("testBug23289:")] + public bool TestBug23289 (CLLocation [] array) + { + return true; + } + + [return: ReleaseAttribute ()] + [Export ("testReturnINativeObject")] + public INativeObject TestRetainINativeObject () + { + return new NSObject (); + } + + [return: ReleaseAttribute ()] + [Export ("testRetainNSObject")] + public NSObject TestRetainNSObject () + { + return new NSObject (); + } + + [return: ReleaseAttribute ()] + [Export ("testRetainString")] + public string TestRetainString () + { + return "some string that does not match a constant NSString"; + } + + [return: ReleaseAttribute ()] + [Export ("testOverriddenRetainNSObject")] + public virtual NSObject TestOverriddenRetainNSObject () + { + return new NSObject (); + } + +#if !__WATCHOS__ + [Export ("testNativeEnum1:")] + public virtual void TestNativeEnum1 (UITextWritingDirection twd) + { + Assert.That (Enum.GetValues (typeof (UITextWritingDirection)), Contains.Item (twd), "TestNativeEnum1"); + } + + public virtual UIPopoverArrowDirection TestNativeEnum2 { + [Export ("testNativeEnum2")] + get { + return UIPopoverArrowDirection.Right; + } + [Export ("setTestNativeEnum2:")] + set { + Assert.AreEqual (UIPopoverArrowDirection.Left, value, "setTestNativeEnum2:"); + } + } + + + [Export ("testNativeEnum3:a:b:")] + public virtual void TestNativeEnum1 (UITextWritingDirection twd, int a, long b) + { + Assert.That (Enum.GetValues (typeof (UITextWritingDirection)), Contains.Item (twd), "TestNativeEnum3"); + Assert.AreEqual (31415, a, "TestNativeEnum3 a"); + Assert.AreEqual (3141592, b, "TestNativeEnum3 b"); + } +#endif // !__WATCHOS__ + + [Export ("testCGPoint:out:")] + public void TestCGPoint (PointF pnt, ref PointF pnt2) + { + pnt2.X = pnt.X; + pnt2.Y = pnt.Y; + } +#if !OLDSTATICREGISTRAR +#if !__WATCHOS__ + [Export ("arrayOfINativeObject")] + public IUIKeyInput[] NativeObjects { get { return null; } } +#endif // !__WATCHOS__ +#endif + } + +#if !__TVOS__ && !__WATCHOS__ + [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)] + internal delegate void DActionArity1V1 (IntPtr block, UIBackgroundFetchResult obj); + + // + // This class bridges native block invocations that call into C# + // + static internal class SDActionArity1V1 { + static internal readonly DActionArity1V1 Handler = Invoke; + + [MonoPInvokeCallback (typeof (DActionArity1V1))] + static unsafe void Invoke (IntPtr block, UIBackgroundFetchResult obj) { + var descriptor = (BlockLiteral *) block; + var del = (global::System.Action) (descriptor->Target); + if (del != null) + del (obj); + } + } /* class SDActionArity1V1 */ + + internal class NIDActionArity1V1 { + IntPtr blockPtr; + DActionArity1V1 invoker; + + [Preserve (Conditional=true)] + public unsafe NIDActionArity1V1 (BlockLiteral *block) + { + blockPtr = (IntPtr) block; + invoker = block->GetDelegateForBlock (); + } + [Preserve (Conditional=true)] + public unsafe static global::System.Action Create (IntPtr block) + { + return new NIDActionArity1V1 ((BlockLiteral *) block).Invoke; + } + + [Preserve (Conditional=true)] + unsafe void Invoke (UIBackgroundFetchResult obj) + { + invoker (blockPtr, obj); + } + } /* class NIDActionArity1V1 */ +#endif // !__TVOS__ + + + [Register ("StaticBaseClass")] + class StaticBaseClass : NSObject + { + [Export ("foo")] + public static int Foo () + { + return 314; + } + } + + [Register ("StaticDerivedClass")] + class StaticDerivedClass : StaticBaseClass + { + } + + [Register ("DerivedRegistrar1")] + class DerivedRegistrar1 : RegistrarTestClass + { + public override string VirtualMethod () + { + return "DerivedRegistrar1"; + } + + public override NSObject TestOverriddenRetainNSObject () + { + return base.TestOverriddenRetainNSObject (); + } + + [Export ("b1")] + public new bool B1 { + get { + return true; + } + } + } + + [Register ("DerivedRegistrar2")] + class DerivedRegistrar2 : DerivedRegistrar1 + { + public override string VirtualMethod () + { + return "DerivedRegistrar2"; + } + } + + [Register ("GenericBaseClass")] + class GenericBaseClass : NSObject + { + [Export ("GetTypeFullName")] + public virtual string GetTypeFullName () + { + return GetType ().FullName; + } + } + +#if !OLDSTATICREGISTRAR + [Register ("Open_1")] + class Open : NSObject {} + class Closed : Open + { + [Export ("foo")] + public void Foo () + { + } + + [Export ("bar")] + public static void Bar () + { + } + + [Export ("zap:")] + public void Zap (string arg) + { + } + } + + class Open : NSObject where U: NSObject + { + public object LastArg; + public object UType; + public object VType; + + [Export ("bar:")] + public void Bar (U arg) + { + UType = typeof(U); + VType = typeof(V); + LastArg = arg; + } + + [Export ("zap:")] + public void Zap (U[] arg) + { + UType = typeof(U); + VType = typeof(V); + LastArg = arg; + } + + [Export ("xyz")] + public U XyZ () + { + UType = typeof(U); + VType = typeof(V); + LastArg = null; + return null; + } + + [Export ("barzap")] + public U BarZap { + get { + UType = typeof(U); + VType = typeof(V); + LastArg = null; + return null; + } + set { + UType = typeof(U); + VType = typeof(V); + LastArg = value; + } + } + } + + // This T is also valid/usable + class Open1 : NSObject where T : NSObject {} + class Open2 : NSObject where T : C {} + class C : NSObject {} + + class ClosedGenericParameter : NSObject { + // TODO: create test for this once we can call delegates with a null function pointer. + [Export ("foo:")] + public void Foo (Action func) {} + } + + [Register ("GenericTestClass")] + class GenericTestClass : GenericBaseClass + { + public GenericTestClass () + { + } + + [Export ("initWithA:")] + public GenericTestClass (int a) + { + } + + [Export ("initWithB:")] + public GenericTestClass (long b) + { + } + + public override string GetTypeFullName () + { + return typeof (T).FullName; + } + } + + class DerivedGenericTestClass : GenericTestClass + { + public override string GetTypeFullName () + { + return base.GetTypeFullName (); + } + } +#endif // !OLDSTATICREGISTRAR + + [Test] + public void TestRegisteredName () + { + if ((CurrentRegistrar & Registrars.AllNew) == 0) + Assert.Ignore ("This test only works with the new registrars (because of the generic types used here)"); + +#if !OLDSTATICREGISTRAR + Assert.AreEqual ("MonoTouchFixtures_ObjCRuntime_RegistrarTest_ConstrainedGenericType_1", new Class (typeof(ConstrainedGenericType<>)).Name); + Assert.AreEqual ("MonoTouchFixtures_ObjCRuntime_RegistrarTest_ConstrainedGenericType_1", new Class (typeof(ConstrainedGenericType)).Name); + Assert.AreEqual ("MonoTouchFixtures_ObjCRuntime_RegistrarTest_NestedParent_1_Nested", new Class (typeof(NestedParent.Nested)).Name); + Assert.AreEqual ("UnderlyingEnumValues", new Class (typeof(UnderlyingEnumValues)).Name); + Assert.AreEqual ("MonoTouchFixtures_ObjCRuntime_RegistrarTest_Nested1_Dummy", new Class (typeof(Nested1.Dummy)).Name); + Assert.AreEqual ("MonoTouchFixtures_ObjCRuntime_RegistrarTest_C", new Class (typeof (C)).Name); +#endif + } + + void ThrowsICEIfDebug (TestDelegate code, string message, bool execute_release_mode = true) + { +// The type checks have been disabled for now. +//#if DEBUG +// Assert.Throws (code, message); +//#else + if (execute_release_mode) + Assert.DoesNotThrow (code, message); +//#endif + } + + [Test] + public void TestConstrainedGenericType () + { + IntPtr value; + +#if !OLDSTATICREGISTRAR + using (var obj = new ConstrainedGenericType ()) { + using (var view = new NSSet ()) { + using (var nsobj = new NSObject ()) { + // m1 + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m1:"), IntPtr.Zero); + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m1:"), view.Handle); + ThrowsICEIfDebug (() => Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m1:"), nsobj.Handle), "m1: ICE"); + + // m2 + value = IntPtr.Zero; + void_objc_msgSend_out_IntPtr (obj.Handle, Selector.GetHandle ("m2:"), out value); + Assert.AreEqual (IntPtr.Zero, value); + + value = view.Handle; + void_objc_msgSend_out_IntPtr (obj.Handle, Selector.GetHandle ("m2:"), out value); + Assert.AreEqual (IntPtr.Zero, value); + + value = new IntPtr (0xdeadbeef); + void_objc_msgSend_out_IntPtr (obj.Handle, Selector.GetHandle ("m2:"), out value); + Assert.AreEqual (IntPtr.Zero, value); + + // m3 + value = IntPtr.Zero; + void_objc_msgSend_ref_IntPtr (obj.Handle, Selector.GetHandle ("m3:"), ref value); + Assert.AreEqual (IntPtr.Zero, value); + + value = view.Handle; + void_objc_msgSend_ref_IntPtr (obj.Handle, Selector.GetHandle ("m3:"), ref value); + Assert.AreEqual (view.Handle, value); + + value = nsobj.Handle; + ThrowsICEIfDebug (() => void_objc_msgSend_ref_IntPtr (obj.Handle, Selector.GetHandle ("m3:"), ref value), "m3 ICE"); + + // m4 + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m4:"), IntPtr.Zero); + ThrowsICEIfDebug (() => Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m4:"), nsobj.Handle), "m4 ICE", false); + using (var arr = NSArray.FromNSObjects (nsobj)) { + ThrowsICEIfDebug (() => Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m4:"), arr.Handle), "m4 ICE 2"); + } + + using (var arr = NSArray.FromNSObjects (view)) { + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("m4:"), arr.Handle); + } + + // r1 + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("r1"))); + + // r2 + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("r2"))); + + // p1 + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("p1"))); + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP1:"), IntPtr.Zero); + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP1:"), view.Handle); + ThrowsICEIfDebug (() => Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP1:"), nsobj.Handle), "setP1: ICE"); + + // p2 + Assert.AreEqual (IntPtr.Zero, Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("p2"))); + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP2:"), IntPtr.Zero); + ThrowsICEIfDebug (() => Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP2:"), nsobj.Handle), "setP2: ICE", false); + + using (var arr = NSArray.FromNSObjects (nsobj)) { + ThrowsICEIfDebug (() => Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP2:"), arr.Handle), "setP2: ICE2"); + } + + using (var arr = NSArray.FromNSObjects (view)) { + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("setP2:"), arr.Handle); + } + + } + } + } +#endif // !OLDSTATICREGISTRAR + } + +#if !__WATCHOS__ + [Test] + public void TestCopyWithZone () + { + using (var cc = new CopyClass ()) { + Assert.AreEqual (cc.Handle, Messaging.IntPtr_objc_msgSend_IntPtr (cc.Handle, Selector.GetHandle ("copyWithZone:"), IntPtr.Zero), "a"); + Assert.IsFalse (cc.had_zone.Value, "had_zone"); + } + } + + // This verifies that a very incorrect implementation of NSTableViewCell isn't shared with UITableViewCell. + class CopyClass : UITableViewCell, INSCopying { + public bool? had_zone; + + [Export ("copyWithZone:")] + public NSObject Copy (NSZone zone) + { + had_zone = zone != null; + DangerousRetain (); + return this; + } + } +#endif // !__WATCHOS__ + + [Test] + public void TestProtocolRegistration () + { + var iProtocol = typeof (IProtocol).FullName.Replace (".", "_").Replace ("+", "_"); + Assert.AreNotEqual (IntPtr.Zero, Runtime.GetProtocol (iProtocol), "IProtocol"); + Assert.IsTrue (Messaging.bool_objc_msgSend_IntPtr (Class.GetHandle (typeof (MyProtocolImplementation)), Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol (iProtocol)), "Interface/IProtocol"); +#if !__TVOS__ && !__WATCHOS__ + Assert.IsTrue (Messaging.bool_objc_msgSend_IntPtr (Class.GetHandle (typeof (Test24970)), Selector.GetHandle ("conformsToProtocol:"), Protocol.GetHandle ("UIApplicationDelegate")), "UIApplicationDelegate/17669"); +#endif + // We don't support [Adopts] (yet at least). +// Assert.IsTrue (Messaging.bool_objc_msgSend_IntPtr (Class.GetHandle (typeof (ConformsToProtocolTestClass)), Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol ("NSCoding")), "Adopts/ConformsToProtocolTestClass"); + } + + [Test] + public void TestTypeEncodings () + { + var cl = new Class (typeof (TestTypeEncodingsClass)); + var sig = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr (cl.Handle, Selector.GetHandle ("methodSignatureForSelector:"), Selector.GetHandle ("foo::::::::::::::::"))); + var boolEncoding = IntPtr.Size == 8 ? "B" : "c"; + var exp = new string [] { "@", ":", "^v", "C", "c", "c", "s", "S", "i", "I", "q", "Q", "f", "d", boolEncoding, "@", ":", "#" }; + + Assert.AreEqual (exp.Length, sig.NumberOfArguments, "NumberOfArguments"); +// for (uint i = 0; i < exp.Length; i++) { +// var p = Marshal.PtrToStringAuto (sig.GetArgumentType (i)); +// Console.WriteLine ("{0}: {1}", i, p); +// } + for (uint i = 0; i < exp.Length; i++) { + var p = Marshal.PtrToStringAuto (sig.GetArgumentType (i)); + Assert.AreEqual (exp [i], p, "#{0}", i); + } + } + + class TestTypeEncodingsClass : NSObject + { + [Export ("foo::::::::::::::::")] + public static void Foo (IntPtr p1, byte p2, sbyte p3, char p4, short p5, ushort p6, int p7, uint p8, long p9, ulong p10, float p11, double p12, bool p13, string p14, Selector p15, Class p16) + { + + } + } + +#if !__TVOS__ // No MapKit in TVOS +#if !__WATCHOS__ // WatchOS has MapKit, but not MKMapView +#if XAMCORE_2_0 + [Test] + public void TestNativeObjectArray () + { + using (var i1 = new MKPointAnnotation ()) { + using (var i2 = new MKPointAnnotation ()) { + using (var array = NSArray.FromObjects (i1, i2)) { + using (var obj = new NativeObjectArrayType ()) { + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("addAnnotations:"), array.Handle); + Assert.AreEqual (2, obj.Annotations.Length, "length"); + Assert.AreSame (i1, obj.Annotations [0], "i1"); + Assert.AreSame (i2, obj.Annotations [1], "i2"); + } + } + } + } + + using (var array = new NSMutableArray ()) { + using (var i1 = new MKPointAnnotation ()) { + using (var i2 = new MKPointAnnotation ()) { + array.Add (i1); + array.Add (i2); + } + } + + using (var obj = new NativeObjectArrayType ()) { + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("addAnnotations:"), array.Handle); + Assert.AreEqual (2, obj.Annotations.Length, "length #2"); + Assert.IsNotNull (obj.Annotations [0], "i1 #2"); + Assert.IsNotNull (obj.Annotations [1], "i2 #2"); + } + } + } + + public class NativeObjectArrayType : MKMapView + { + public IMKAnnotation[] Annotations; + public override void AddAnnotations(params IMKAnnotation[] annotations) + { + this.Annotations = annotations; + } + } +#endif +#endif // !__WATCHOS__ +#endif // !__TVOS__ + +#if !OLDSTATICREGISTRAR + class ConstrainedGenericType : NSObject where T: NSObject + { + [Export ("m1:")] + public void M1 (T t) { } + + [Export ("m2:")] + public void M2 (out T t) { t = null; } + + [Export ("m3:")] + public void M3 (ref T t) { } + + [Export ("m4:")] + public void M4 (T[] t) { } + + [Export ("r1")] + public T R1 () { return null; } + + [Export ("r2")] + public T[] R2 () { return null; } + + [Export ("p1")] + public T P1 { get { return null; } set { } } + + [Export ("p2")] + public T[] P2 { get { return null; } set { } } + } + + class Generic2 : NSObject where T: NSObject + { + public string Method; + + [Export ("M1")] + public T M1 () + { + Method = "M1"; + return null; + } + + [Export ("M2:")] + public void M2 (T arg1) + { + Method = "M2"; + } + } + + class NestedParent where T:NSObject { + public class Nested : NSObject { + [Export ("foo:")] + public void Foo (T foo) { + } + } + } + + +#if !__WATCHOS__ + class CustomView : UIView { + public object TypeName; + public object TypeT; + + public CustomView (RectangleF rect) : base (rect) {} + public override void Draw (RectangleF rect) + { + TypeT = typeof (T); + TypeName = GetType ().Name; + } + } + + class StringView : CustomView { + public StringView (RectangleF rect) : base (rect) {} + } + + class NullableIntView : CustomView { + public NullableIntView (RectangleF rect) : base (rect) {} + } +#endif // !__WATCHOS__ + + class GenericConstrainedBase : NSObject where T: NSObject + { + public T FooT; + public string FooType; + + [Export ("foo:")] + public virtual void Foo (T obj) + { + FooT = obj; + FooType = "Base"; + } + } + + class GenericConstrainedDerived : GenericConstrainedBase where T:NSObject + { + public override void Foo (T obj) + { + FooT = obj; + FooType = "Derived"; + } + } + + // Due to how registration works, this may throw an exception at startup (if the test fails) + // which will eventually prevent other unit tests from passing. Unfortunately there is no + // easy way to tell if *this* class was registered properly (we can check for subsequent classes + // from the same assembly, but alas 'subsequent' is undefined, since the order classes are + // registered is not defined). Hopefully an exception message in the application output + // and some other tests failing will be enough. + class OutletTestClass : NSObject { + [Outlet] + public string Foo { get; set; } + } + + [Test] + public void GenericVirtualTest () + { + using (var obj = new GenericConstrainedDerived ()) { + Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("foo:"), obj.Handle); + Assert.AreEqual ("Derived", obj.FooType, "Derived"); + Assert.AreSame (obj, obj.FooT, "obj"); + } + } + + class AnyT : NSObject { + } + + [Test] + public void ConformsToProtocolTest () + { + using (var obj = new AnyT ()) { + Messaging.bool_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol ("NSObject")); + } + } + + [Test] + public void ConformsToProtocolTest2 () + { + using (var obj = new ConformsToProtocolTestClass ()) { + Assert.IsTrue (Messaging.bool_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol ("NSCoding"))); + Assert.IsFalse (Messaging.bool_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol ("NSCopying"))); + } + + using (var obj = new ConformsToProtocolTestClass ()) { + Assert.IsTrue (Messaging.bool_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol ("NSCoding"))); + Assert.IsFalse (Messaging.bool_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("conformsToProtocol:"), Runtime.GetProtocol ("NSCopying"))); + } + } + + [Adopts ("NSCoding")] + public class ConformsToProtocolTestClass : NSObject { + } + + [Adopts ("NSCoding")] + public class ConformsToProtocolTestClass : NSObject where T: NSObject { + } + +#endif // !OLDSTATICREGISTRAR + + [Register ("UnderlyingEnumValues")] + class UnderlyingEnumValues : NSObject + { + enum B : byte { a }; + enum SB : sbyte { a }; + enum S : short { a }; + enum US : ushort { a }; + enum I : int { a }; + enum UI : uint { a }; + enum L : long { a }; + enum UL : ulong { a }; + + [Export ("Foo:a:b:c:d:e:f:g:h")] + void Foo (B b, SB sb, S s, US us, I i, UI ui, L l, UL ul) + { + } + } + + // It should be possible to export two identically named nested types. + // Note that this is will fail during build (static registrar) or startup (dynamic registrar) (if it's broken of course). + class Nested1 { + public class Dummy : NSObject { } + } + class Nested2 { + class Dummy : NSObject { } + } +#endregion + + [Protocol] + interface IProtocol { + [Export ("foo")] + [Preserve (Conditional = true)] + int Foo (); + + [Preserve (Conditional = true)] + int Bar { [Export ("bar")] get; [Export ("setBar:")] set; } + + [Preserve] + [Export ("block", ArgumentSemantic.Retain)] + Action Block { get; set; } + } + + class MyProtocolImplementation : NSObject, IProtocol { + public int Foo () + { + return 31415; + } + + public int Bar { + get { return 31415926; } + set { } + } + + public Action Block { + get { return null; } + set { } + } + } + + [Test] + public void IProtocolTest () + { + var o = new MyProtocolImplementation (); + Assert.AreEqual (31415, Messaging.int_objc_msgSend (o.Handle, Selector.GetHandle ("foo")), "#method"); + Assert.AreEqual (31415926, Messaging.int_objc_msgSend (o.Handle, Selector.GetHandle ("bar")), "#getter"); + Assert.DoesNotThrow (() => { Messaging.void_objc_msgSend_int (o.Handle, Selector.GetHandle ("setBar:"), 2); }, "#setter"); + } + + [Test] + public void FakeTypeTest () + { + IntPtr obj2_ptr = IntPtr.Zero; + + try { + using (var obj1 = new FakeType1 ()) { + var cls = Class.GetHandle ("FakeType2"); + obj2_ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle ("FakeType2"), Selector.GetHandle ("alloc")); + obj2_ptr = Messaging.IntPtr_objc_msgSend (obj2_ptr, Selector.GetHandle ("init")); + Assert.AreNotEqual (IntPtr.Zero, obj2_ptr, "not zero"); + Messaging.bool_objc_msgSend_IntPtr (obj1.Handle, Selector.GetHandle ("fakeTypeTest:"), obj2_ptr); + } + } finally { + Messaging.void_objc_msgSend (obj2_ptr, Selector.GetHandle ("release")); + } + } + + [Register ("FakeType1")] + class FakeType1 : NSObject { + public FakeType1 (IntPtr ptr) + : base (ptr) + { + } + + public FakeType1 () + { + } + + [Export ("fakeTypeTest:")] + public bool FakeTypeTest (FakeType1 ft) + { + var cls = new Class (Messaging.IntPtr_objc_msgSend (ft.Handle, Selector.GetHandle ("class"))); + Assert.AreEqual ("FakeType2", cls.Name); + return true; + } + } + + // There's a FakeType2 class defined in libtest.m + // It's defined there in order to be able to create + // an instance of a native class without a managed + // peer. + + public void Test_D () + { + using (var tc = new ObjCRegistrarTest ()) { + Verify (tc, Pd1: 0); + Assert.AreEqual (0, tc.D (), "1"); + tc.Pd1 = 1.2; + Assert.AreEqual (1.2, tc.D (), "2"); + Verify (tc, Pd1: 1.2); + } + } + + [Test] + public void Test_Sd () + { + using (var tc = new ObjCRegistrarTest ()) { + Assert.AreEqual (0, tc.Sd ().d1, "1"); + Verify (tc, PSd1: new Sd () ); + tc.PSd = new Sd () { d1 = 1.23 }; + Assert.AreEqual (1.23, tc.Sd ().d1, "2"); + Verify (tc, PSd1: new Sd () { d1 = 1.23 }); + } + } + + void Verify (ObjCRegistrarTest obj, string msg = null, + int? Pi1 = null, + int? Pi2 = null, + int? Pi3 = null, + int? Pi4 = null, + int? Pi5 = null, + int? Pi6 = null, + int? Pi7 = null, + int? Pi8 = null, + int? Pi9 = null, + float? Pf1 = null, + float? Pf2 = null, + float? Pf3 = null, + float? Pf4 = null, + float? Pf5 = null, + float? Pf6 = null, + float? Pf7 = null, + float? Pf8 = null, + float? Pf9 = null, + double? Pd1 = null, + double? Pd2 = null, + double? Pd3 = null, + double? Pd4 = null, + double? Pd5 = null, + double? Pd6 = null, + double? Pd7 = null, + double? Pd8 = null, + double? Pd9 = null, + char? Pc1 = null, + char? Pc2 = null, + char? Pc3 = null, + char? Pc4 = null, + char? Pc5 = null, + char? Pc6 = null, + char? Pc7 = null, + char? Pc8 = null, + char? Pc9 = null, + + Siid? PSiid1 = null, + Sd? PSd1 = null, + Sf? PSf1 = null) + { + if (Pi1.HasValue) + Assert.AreEqual (obj.Pi1, Pi1.Value, "Pi1"); + if (Pi2.HasValue) + Assert.AreEqual (obj.Pi2, Pi2.Value, "Pi2"); + if (Pi3.HasValue) + Assert.AreEqual (obj.Pi3, Pi3.Value, "Pi3"); + if (Pi4.HasValue) + Assert.AreEqual (obj.Pi4, Pi4.Value, "Pi4"); + if (Pi5.HasValue) + Assert.AreEqual (obj.Pi5, Pi5.Value, "Pi5"); + if (Pi6.HasValue) + Assert.AreEqual (obj.Pi6, Pi6.Value, "Pi6"); + if (Pi7.HasValue) + Assert.AreEqual (obj.Pi7, Pi7.Value, "Pi7"); + if (Pi8.HasValue) + Assert.AreEqual (obj.Pi8, Pi8.Value, "Pi8"); + if (Pi9.HasValue) + Assert.AreEqual (obj.Pi9, Pi9.Value, "Pi9"); + if (Pf1.HasValue) + Assert.AreEqual (obj.Pf1, Pf1.Value, "Pf1"); + if (Pf2.HasValue) + Assert.AreEqual (obj.Pf2, Pf2.Value, "Pf2"); + if (Pf3.HasValue) + Assert.AreEqual (obj.Pf3, Pf3.Value, "Pf3"); + if (Pf4.HasValue) + Assert.AreEqual (obj.Pf4, Pf4.Value, "Pf4"); + if (Pf5.HasValue) + Assert.AreEqual (obj.Pf5, Pf5.Value, "Pf5"); + if (Pf6.HasValue) + Assert.AreEqual (obj.Pf6, Pf6.Value, "Pf6"); + if (Pf7.HasValue) + Assert.AreEqual (obj.Pf7, Pf7.Value, "Pf7"); + if (Pf8.HasValue) + Assert.AreEqual (obj.Pf8, Pf8.Value, "Pf8"); + if (Pf9.HasValue) + Assert.AreEqual (obj.Pf9, Pf9.Value, "Pf9"); + if (Pd1.HasValue) + Assert.AreEqual (obj.Pd1, Pd1.Value, "Pd1"); + if (Pd2.HasValue) + Assert.AreEqual (obj.Pd2, Pd2.Value, "Pd2"); + if (Pd3.HasValue) + Assert.AreEqual (obj.Pd3, Pd3.Value, "Pd3"); + if (Pd4.HasValue) + Assert.AreEqual (obj.Pd4, Pd4.Value, "Pd4"); + if (Pd5.HasValue) + Assert.AreEqual (obj.Pd5, Pd5.Value, "Pd5"); + if (Pd6.HasValue) + Assert.AreEqual (obj.Pd6, Pd6.Value, "Pd6"); + if (Pd7.HasValue) + Assert.AreEqual (obj.Pd7, Pd7.Value, "Pd7"); + if (Pd8.HasValue) + Assert.AreEqual (obj.Pd8, Pd8.Value, "Pd8"); + if (Pd9.HasValue) + Assert.AreEqual (obj.Pd9, Pd9.Value, "Pd9"); + if (Pc1.HasValue) + Assert.AreEqual (obj.Pc1, Pc1.Value, "Pc1"); + if (Pc2.HasValue) + Assert.AreEqual (obj.Pc2, Pc2.Value, "Pc2"); + if (Pc3.HasValue) + Assert.AreEqual (obj.Pc3, Pc3.Value, "Pc3"); + if (Pc4.HasValue) + Assert.AreEqual (obj.Pc4, Pc4.Value, "Pc4"); + if (Pc5.HasValue) + Assert.AreEqual (obj.Pc5, Pc5.Value, "Pc5"); +// if (Pc6.HasValue) +// Assert.AreEqual (obj.Pc6, Pc6.Value, "Pc6"); +// if (Pc7.HasValue) +// Assert.AreEqual (obj.Pc7, Pc7.Value, "Pc7"); +// if (Pc8.HasValue) +// Assert.AreEqual (obj.Pc8, Pc8.Value, "Pc8"); +// if (Pc9.HasValue) +// Assert.AreEqual (obj.Pc9, Pc9.Value, "Pc9"); + + if (PSiid1.HasValue) + Assert.AreEqual (obj.PSiid, PSiid1.Value, "PSiid1"); + + if (PSd1.HasValue) + Assert.AreEqual (obj.PSd, PSd1.Value, "PSd1"); + + if (PSf1.HasValue) + Assert.AreEqual (obj.PSf, PSf1.Value, "PSf1"); + } + + public class TestClass : ObjCRegistrarTest + { + } + +#if !__TVOS__ && !__WATCHOS__ + class Test24970 : UIApplicationDelegate { + // This method uses the [Transient] attribute. + public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations (UIApplication application, UIWindow forWindow) + { + throw new NotImplementedException (); + } + } + + [Test] + public void CustomAppDelegatePerformFetchTest () + { + using (var obj = new CustomApplicationDelegate ()) { + BlockLiteral block = new BlockLiteral (); + var performed = false; + Action del = (v) => { + performed = true; + }; + + block.SetupBlock (CustomApplicationDelegate.SDActionArity1V42.Handler, del); + + Messaging.void_objc_msgSend_IntPtr_ref_BlockLiteral (obj.Handle, Selector.GetHandle ("application:performFetchWithCompletionHandler:"), UIApplication.SharedApplication.Handle, ref block); + + block.CleanupBlock (); + + Assert.IsTrue (performed); + } + } + + class CustomApplicationDelegate : UIApplicationDelegate { + [Export ("application:performFetchWithCompletionHandler:")] + public new void PerformFetch (UIApplication application, [BlockProxy (typeof (NIDActionArity1V42))] Action completionHandler) + { + completionHandler (UIBackgroundFetchResult.NoData); + } + + [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)] + internal delegate void DActionArity1V42 (IntPtr block, nuint obj); + + internal static class SDActionArity1V42 { + static internal readonly DActionArity1V42 Handler = Invoke; + + [MonoPInvokeCallback (typeof (DActionArity1V42))] + static unsafe void Invoke (IntPtr block, nuint obj) { + var descriptor = (BlockLiteral *) block; + var del = (global::System.Action) (descriptor->Target); + if (del != null) + del ((UIBackgroundFetchResult) (global::System.UInt64) obj); + } + } /* class SDActionArity1V42 */ + + internal class NIDActionArity1V42 { + IntPtr blockPtr; + DActionArity1V42 invoker; + + [Preserve (Conditional=true)] + public unsafe NIDActionArity1V42 (BlockLiteral *block) + { + blockPtr = _Block_copy ((IntPtr) block); + invoker = block->GetDelegateForBlock (); + } + + [Preserve (Conditional=true)] + ~NIDActionArity1V42 () + { + _Block_release (blockPtr); + } + + [Preserve (Conditional=true)] + public unsafe static Action Create (IntPtr block) + { + return new NIDActionArity1V42 ((BlockLiteral *) block).Invoke; + } + + [Preserve (Conditional=true)] + unsafe void Invoke (UIBackgroundFetchResult obj) + { + invoker (blockPtr, (nuint) (UInt64) obj); + } + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr _Block_copy (IntPtr ptr); + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern void _Block_release (IntPtr ptr); + } + + } +#endif // !__TVOS__ && !__WATCHOS__ + + [Protocol] + [Model] + class Test25781 : NSObject { } + class Test25781D : Test25781 {} + + [Test] + public void TestProtocolAndRegister () + { + // Having [Protocol] [Register] (and nothing else), doesn't make any sense. + // Yet we've created these in btouch, so we need to define what they + // actually do (nothing at all). + + Assert.AreEqual (IntPtr.Zero, Class.GetHandle ("TestProtocolRegister")); + + // However deriving from those nonsensical classes must do something + // (at the very least because anything else would be a breaking change). + Assert.AreNotEqual (IntPtr.Zero, Class.GetHandle ("DerivedTestProtocolRegister")); + } + + [Protocol] + [Register ("TestProtocolRegister")] + class TestProtocolRegister : NSObject {} + + [Register ("DerivedTestProtocolRegister")] + class DerivedTestProtocolRegister : TestProtocolRegister {} + + class D1 : NSObject { + public string ctor1; + + [Export ("initWithFoo:")] + public D1 (int foo) + { + ctor1 = "foo"; + } + + [Export ("initWithBar:")] + public D1 (long bar) + { + ctor1 = "bar"; + } + } + + class D2 : D1 { + public readonly int Value = 3; + public string ctor2; + + [Export ("initWithFoo:")] + public D2 (int foo) : base (foo) + { + ctor2 = "foo"; + } + } + + class E1 : NSObject { + protected E1 (IntPtr ptr) : base (ptr) + { + } + + [Export ("initWithFoo:")] + public E1 (int foo) + { + } + + [Export ("initWithBar:")] + public E1 (long bar) + { + } + } + + class E2 : E1 { + public readonly int Value = 3; + + protected E2 (IntPtr ptr) : base (ptr) + { + } + + [Export ("initWithFoo:")] + public E2 (int foo) : base (foo) + { + } + + [Export ("M1:")] + public int M1 (int v) + { + return v; + } + } + + class G1 : NSObject { + protected G1 (IntPtr ptr) : base (ptr) + { + } + + [Export ("M1:")] + public int M1 (int v) + { + return v; + } + } + + class G2 : G1 { + public readonly int Value = 3; + + protected G2 (IntPtr ptr) : base (ptr) + { + } + + [Export ("M2:")] + public int M2 (int v) + { + return v; + } + } + + [Test] + public void TestCtors () + { + IntPtr ptr = IntPtr.Zero; + + try { + // ctor inheritance: derived + base class ctors are called. + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (D2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend_int (ptr, Selector.GetHandle ("initWithFoo:"), 1); + var obj = Runtime.GetNSObject (ptr); + Assert.AreEqual (3, obj.Value, "a"); + Assert.AreEqual ("foo", obj.ctor1, "a ctor1"); + Assert.AreEqual ("foo", obj.ctor2, "a ctor2"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + + try { + // ctor inheritance: initWithBar: is only defined in the base class (managed base class) + // In this case we create a managed wrapper of the base class, not the derived class. I'm not + // sure this is by design or by accident, but that's how we're behaving right now at least + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (D2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend_long (ptr, Selector.GetHandle ("initWithBar:"), 2); + // Unable to cast object of type 'AppDelegate+D1' to type 'AppDelegate+D2' + Assert.Throws (() => Runtime.GetNSObject (ptr), "b ex"); + var obj = Runtime.GetNSObject (ptr); + Assert.AreEqual ("bar", obj.ctor1, "b ctor1"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + + try { + // ctor inheritance: init is defined in the native base class. + // Since no managed ctor apply, we need the (IntPtr) ctor (in this case there isn't one) + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (D2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init")); + // Failed to marshal the Objective-C object 0x7adf5920 (type: AppDelegate_D2). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'AppDelegate+D2' does not have a constructor that takes one IntPtr argument). + Assert.Throws (() => Runtime.GetNSObject (ptr), "c"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + + try { + // ctor inheritance: init is defined in the native base class. + // Since no managed ctor apply, we need the (IntPtr) ctor (which is provided in this case) + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (E2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init")); + var obj = Runtime.GetNSObject (ptr); + Assert.AreEqual (3, obj.Value, "d"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + + try { + // ctor inheritance: only applicable ctor is the native one. + // No managed ctor is called (and no wrapper is created) when the native object is created. + // Instead the managed wrapper is created (and managed (IntPtr) ctor called) when + // we first need it. + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (E2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init")); + Assert.IsNull (Runtime.TryGetNSObject (ptr), "e null"); + int rv = Messaging.int_objc_msgSend_int (ptr, Selector.GetHandle ("M1:"), 31415); + Assert.IsNotNull (Runtime.TryGetNSObject (ptr), "e not null"); + Assert.AreEqual (31415, rv, "e1"); + var obj = Runtime.GetNSObject (ptr); + Assert.AreEqual (3, obj.Value, "e2"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + + try { + // ctor inheritance: only applicable ctor is the native one. + // No managed ctor is called (and no wrapper is created) when the native object is created. + // Instead the managed wrapper is created (and managed (IntPtr) ctor called) when + // we first need it. + // In this case the invoked managed method (which creates the wrapper) is defined + // in a subclass of a generic type. + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (G2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init")); + Assert.IsNull (Runtime.TryGetNSObject (ptr), "f null"); + int rv = Messaging.int_objc_msgSend_int (ptr, Selector.GetHandle ("M1:"), 31415); + Assert.IsNotNull (Runtime.TryGetNSObject (ptr), "f not null"); + Assert.AreEqual (31415, rv, "f1"); + var obj = Runtime.GetNSObject (ptr); + Assert.AreEqual (3, obj.Value, "f2"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + + try { + // ctor inheritance: only applicable ctor is the native one. + // No managed ctor is called (and no wrapper is created) when the native object is created. + // Instead the managed wrapper is created (and managed (IntPtr) ctor called) when + // we first need it. + // In this case the invoked managed method (which creates the wrapper) is defined + // in a generic type. + ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (G2)), Selector.GetHandle ("alloc")); + ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init")); + Assert.IsNull (Runtime.TryGetNSObject (ptr), "g null"); + int rv = Messaging.int_objc_msgSend_int (ptr, Selector.GetHandle ("M2:"), 31415); + Assert.IsNotNull (Runtime.TryGetNSObject (ptr), "g not null"); + Assert.AreEqual (31415, rv, "g1"); + var obj = Runtime.GetNSObject (ptr); + Assert.AreEqual (3, obj.Value, "g2"); + } finally { + Messaging.void_objc_msgSend (ptr, Selector.GetHandle ("release")); + } + } + +#if !__WATCHOS__ + class Bug28757A : NSObject, IUITableViewDataSource + { + public virtual nint RowsInSection (UITableView tableView, nint section) + { + return 1; + } + public UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) + { + return null; + } + } + + class Bug28757B : Bug28757A + { + public override nint RowsInSection (UITableView tableView, nint section) + { + return 2; + } + } +#endif // !__WATCHOS__ + +#if !__WATCHOS__ + [Test] + public void TestInheritedProtocols () + { + using (var obj = new Bug28757B ()) { + Assert.AreEqual (2, Messaging.nint_objc_msgSend_IntPtr_nint (obj.Handle, Selector.GetHandle ("tableView:numberOfRowsInSection:"), IntPtr.Zero, 0), "#test"); + } + } +#endif // !__WATCHOS + +#if !__WATCHOS__ + [Test] + public void InOutProtocolMethodArgument () + { + using (var obj = new Scroller ()) { + var velocity = new PointF (1, 2); + var targetContentOffset = new PointF (3, 4); + Messaging.void_objc_msgSend_IntPtr_PointF_ref_PointF (obj.Handle, Selector.GetHandle ("scrollViewWillEndDragging:withVelocity:targetContentOffset:"), IntPtr.Zero, velocity, ref targetContentOffset); + Console.WriteLine (targetContentOffset); + Assert.AreEqual ("{X=123, Y=345}", targetContentOffset.ToString (), "ref output"); + } + } +#endif // !__WATCHOS + +#if !__WATCHOS__ + class Scroller : NSObject, IUIScrollViewDelegate + { + [Export ("scrollViewWillEndDragging:withVelocity:targetContentOffset:")] + public void WillEndDragging (UIScrollView scrollView, PointF velocity, ref PointF targetContentOffset) + { + Assert.AreEqual ("{X=1, Y=2}", velocity.ToString (), "velocity"); + Assert.AreEqual ("{X=3, Y=4}", targetContentOffset.ToString (), "targetContentOffset"); + targetContentOffset = new PointF (123, 345); + } + } +#endif // !__WATCHOS__ + +#if !__TVOS__ && !__WATCHOS__// No ABPeoplePickerNavigationControllerDelegate + [Test] + public void VoidPtrToINativeObjectArgument () + { + using (var obj = new ABPeoplePickerNavigationControllerDelegateImpl ()) { + using (var person = new ABPerson ()) { + Messaging.void_objc_msgSend_IntPtr_IntPtr (obj.Handle, Selector.GetHandle ("peoplePickerNavigationController:didSelectPerson:"), IntPtr.Zero, person.Handle); + Assert.AreEqual (person.Handle, obj.personHandle, "1"); + } + } + } + + class ABPeoplePickerNavigationControllerDelegateImpl : ABPeoplePickerNavigationControllerDelegate + { + public IntPtr personHandle; + public override void DidSelectPerson (ABPeoplePickerNavigationController peoplePicker, ABPerson selectedPerson) + { + personHandle = selectedPerson.Handle; + } + } +#endif // !__TVOS__ + +#if !__TVOS__ // No Contacts framework in TVOS +#if XAMCORE_2_0 // The Contacts framework is Unified only + [Test] + public void GenericAPI () + { + if (!TestRuntime.CheckiOSSystemVersion (9, 0)) + Assert.Inconclusive ("Contacts is iOS9+"); + + using (var contact = new CNMutableContact ()) { + var dt = new NSDateComponents () { + Year = 1923, + }; + var handle = Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (Class.GetHandle (typeof (CNLabeledValue<>)), Selector.GetHandle ("labeledValueWithLabel:value:"), IntPtr.Zero, dt.Handle); + var array = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof(NSArray)), Selector.GetHandle ("arrayWithObject:"), handle); + Messaging.void_objc_msgSend_IntPtr (contact.Handle, Selector.GetHandle ("setDates:"), array); + + Assert.AreEqual (1923, contact.Dates [0].Value.Year, "Dates"); + } + + using (var contact = new SubclassedContact ()) { + var dates = Messaging.IntPtr_objc_msgSend (contact.Handle, Selector.GetHandle ("dates")); + var obj = Runtime.GetNSObject (dates); + Assert.AreEqual (typeof (NSArray), obj.GetType (), "2 date type"); + var arr = (NSArray) obj; + Assert.AreEqual (1, arr.Count, "2 count"); + } + + using (var contact = new SubclassedContact ()) { + var dates = Messaging.IntPtr_objc_msgSend (contact.Handle, Selector.GetHandle ("dates")); + var arr = NSArray.ArrayFromHandle> (dates); + Assert.AreEqual (1, arr.Length, "3 length"); + } + } + + class SubclassedContact : CNContact { + public override CNLabeledValue [] Dates { + get { + return new CNLabeledValue [] { + new CNLabeledValue ("label", new NSDateComponents () + { + Day = 24, + }) + }; + } + } + } +#endif // XAMCORE_2_0 +#endif // !__TVOS__ + + [Test] + public void Bug34224 () + { + using (var obj = new Bug34224Class ()) { + IntPtr ptr = new IntPtr (123); + Messaging.void_objc_msgSend_ref_IntPtr (obj.Handle, Selector.GetHandle ("ref:"), ref ptr); + Assert.AreEqual (new IntPtr (456), ptr, "# ref"); + + Messaging.void_objc_msgSend_out_IntPtr (obj.Handle, Selector.GetHandle ("out:"), out ptr); + Assert.AreEqual (new IntPtr (567), ptr, "# out"); + } + } + + // Bug 34224 + class Bug34224Class : NSObject { + [Export ("ref:")] + public void Ref (ref IntPtr p1) + { + Assert.AreEqual (new IntPtr (123), p1, "ref C"); + p1 = new IntPtr (456); + } + + [Export ("out:")] + public void Out (out IntPtr p1) + { + p1 = new IntPtr (567); + } + } + + class Bug34440Class : NSObject { + [Export ("bug34440")] + Selector Bug34440 () + { + return new Selector ("bug34440"); + } + + [Export ("classReturn")] + Class ClassReturn () + { + return new Class (typeof (Bug34440Class)); + } + } + + [Test] + public void SelectorReturnValue () + { + using (var obj = new Bug34440Class ()) { + var ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("bug34440")); + Assert.AreEqual (Selector.GetHandle ("bug34440"), ptr, "selector"); + ptr = Messaging.IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("classReturn")); + Assert.AreEqual (Class.GetHandle (typeof (Bug34440Class)), ptr, "class"); + } + } + + [Test] + public void BlockReturnTest () + { + using (var obj = new BlockReturnTestClass ()) { + Assert.IsTrue (obj.TestBlocks (), "TestBlocks"); + } + } + + class BlockReturnTestClass : ObjCRegistrarTest { + public override RegistrarTestBlock MethodReturningBlock () + { + return v => { + Assert.AreEqual (0xdeadf00d, v, "input"); + return 0x1337b001; + }; + } + + public override RegistrarTestBlock PropertyReturningBlock { + get { + return v => { + Assert.AreEqual (0xdeadf11d, v, "input"); + return 0x7b001133; + }; + } + } + } + + [Test] + public void PropertySetters () + { + var cls = Class.GetHandle (typeof (PropertySetterTestClass)); + Assert.AreNotEqual (IntPtr.Zero, class_getInstanceMethod (cls, Selector.GetHandle ("setá:")), "a 1"); + using (var obj = new PropertySetterTestClass ()) { + obj.SetValueForKey (new NSString ("AAA"), (NSString) "á"); + Assert.AreEqual ("AAA", (string) (NSString) obj.ValueForKey ((NSString) "á"), "A getvalue"); + Assert.AreEqual ("AAA", obj.A, "A setvalue"); + + obj.SetValueForKey (new NSString ("BBB"), (NSString) "b"); + Assert.AreEqual ("BBB", (string) (NSString) obj.ValueForKey ((NSString) "b"), "B getvalue"); + Assert.AreEqual ("BBB", obj.B, "B setvalue"); + } + } + + class PropertySetterTestClass : NSObject { + [Export ("á")] + public string A { get; set; } + + [Export ("b")] + public string B { get; set; } + } + + [Test] + public void ConstructorChaining () + { + using (var obj = new CtorChaining2 (2)) { + Assert.IsTrue (obj.InitCalled, "Init called"); + Assert.IsTrue (obj.InitCallsInitCalled, "InitCallsInit called"); + } + } + + class CtorChaining2 : CtorChaining1 + { + public CtorChaining2 () + { + } + + public CtorChaining2 (int value) + : base (value) + { + } + } + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_getInstanceMethod (IntPtr cls, IntPtr sel); + + [Test] + public void OutOverriddenWithoutOutAttribute () + { + using (var tmp = new NSObject ()) { + using (var obj = new Registrar_OutExportDerivedClass ()) { + IntPtr tmpH = tmp.Handle; + var rv = Messaging.IntPtr_objc_msgSend_ref_IntPtr (obj.Handle, Selector.GetHandle ("func:"), ref tmpH); + Assert.AreEqual (IntPtr.Zero, tmpH, "input"); + Assert.AreEqual (IntPtr.Zero, rv, "output"); + } + } + } + + class ProtocolArgumentClass : NSObject + { + [Export("someMethod:")] + IntPtr SomeMethod (Protocol protocol) + { + return protocol.Handle; + } + } + + [Test] + public void ProtocolArgument () + { + using (var obj = new ProtocolArgumentClass ()) { + var nsobjProtocol = Protocol.GetHandle ("NSObject"); + var ptr = Messaging.IntPtr_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("someMethod:"), nsobjProtocol); + Assert.AreEqual (nsobjProtocol, ptr, "result"); + Assert.AreNotEqual (IntPtr.Zero, ptr, "nsobject"); + } + } + +#if debug_code + static void DumpClass (Type type) + { + var cls = Class.GetHandle (type); + Console.WriteLine ("Type: {0} => Class: {1}", type.FullName, class_getName (cls)); + + uint count; + var methods = class_copyMethodList (cls, out count); + Console.WriteLine (" {0} methods.", count); + for (uint i = 0; i < count; i++) { + var method = Marshal.ReadIntPtr (methods, (int) (IntPtr.Size * i)); + Console.WriteLine (" #{0}: Name: {1} Type Encoding: {2}", i + 1, Selector.FromHandle (method_getName (method)).Name, method_getTypeEncoding (method)); + } + } + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_copyMethodList (IntPtr cls, out uint outCount); + + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "class_getName")] + static extern IntPtr _class_getName (IntPtr cls); + + static string class_getName (IntPtr cls) + { + return Marshal.PtrToStringAnsi (_class_getName (cls)); + } + + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "method_getTypeEncoding")] + static extern IntPtr _method_getTypeEncoding (IntPtr method); + + static string method_getTypeEncoding (IntPtr method) + { + return Marshal.PtrToStringAnsi (_method_getTypeEncoding (method)); + } + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr method_getName (IntPtr method); +#endif + } +} diff --git a/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs b/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs new file mode 100644 index 000000000000..857b43b8bd01 --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs @@ -0,0 +1,569 @@ +using System; +using System.Diagnostics; +#if !__WATCHOS__ +using System.Drawing; +#endif +using System.Runtime.InteropServices; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#if !__WATCHOS__ +using SpriteKit; +#endif +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.ObjCRuntime { + + static class AssociatedObjects { + public enum AssociationPolicy { // uintptr_t + Assign = 0, + RetainNonAtomic = 1, + CopyNonAtomic = 3, + Retain = 0x301, + Copy = 0x303, + } + + [DllImport (Messaging.LIBOBJC_DYLIB)] + static extern void objc_setAssociatedObject (IntPtr obj, IntPtr key, IntPtr value, IntPtr policy); + + public static void SetAssociatedObject (this NSObject self, IntPtr key, NSObject value, AssociationPolicy policy) + { + objc_setAssociatedObject (self.Handle, key, value.Handle, new IntPtr ((int) policy)); + } + + public static IntPtr GetAssociatedPointer (this NSObject self, IntPtr key) + { + throw new NotImplementedException (); + } + + public static void RemoveAssociatedObjects (this NSObject self) + { + throw new NotImplementedException (); + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class RuntimeTest { + static bool connectMethodTestDone; + [Test] + public void ConnectMethodTest () + { + if (connectMethodTestDone) + Assert.Ignore ("This test can only be executed once, it modifies global state."); + connectMethodTestDone = true; + // Bug 20013. This should not throw a KeyNotFoundException. + Runtime.ConnectMethod (typeof (ConnectMethodClass).GetMethod ("Method"), new Selector ("method")); + } + + class ConnectMethodClass : NSObject { + public void Method () { } + } + + [Test] + public void GetNSObject_IntPtrZero () + { + Assert.Null (Runtime.GetNSObject (IntPtr.Zero)); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void RegisterAssembly_null () + { + Runtime.RegisterAssembly (null); + } + +#if !__WATCHOS__ && !__TVOS__ + [Test] + public void StartWWAN () + { + Assert.Throws (delegate { Runtime.StartWWAN (null); }, "null"); + Assert.Throws (delegate { Runtime.StartWWAN (new Uri ("ftp://www.xamarin.com")); }, "ftp"); + Runtime.StartWWAN (new Uri ("http://www.xamarin.com")); + } +#endif + + [Test] + public void GetNSObject_Subclass () + { + using (var c = new NSHttpCookie ("name", "value")) { + // we want to ensure we get the NSMutableDictionary even if we ask for (the base) NSDictionary + var d = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend (c.Handle, Selector.GetHandle ("properties"))); + Assert.That (d, Is.TypeOf (), "NSMutableDictionary"); + } + } + +#if !__WATCHOS__ + [Test] + public void GetNSObject_Different_Class () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + IntPtr class_ptr = Class.GetHandle ("SKPhysicsBody"); + SizeF size = new SizeF (3, 2); + using (var body = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_SizeF (class_ptr, Selector.GetHandle ("bodyWithRectangleOfSize:"), size))) { + // This would normally return a PKPhysicsBody which is not a subclass but answers the same selectors + // as a SKPhysicsBody. That's an issue since we can't register PKPhysicsBody (Apple won't like it since + // it's a private type) and the non-generic version of GetNSObject (and bindings) would throw an + // InvalidaCastException (since it's Class will resolve to NSObject) + // note: that's the internal PhysicKit shared by UIKit and SpriteKit + Assert.That (body, Is.TypeOf (), "SKPhysicsBody"); + } + } +#endif // !__WATCHOS__ + + [Test] + public void GetNSObject_Posing_Class () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("NSUrlSession requires iOS7+"); + + NSUrlSession session = NSUrlSession.SharedSession; + using (var request = new NSUrlRequest (new NSUrl ("http://www.example.com"))) { + // In iOS 8 the native CreateDownloadTask function returns an instance of a + // __NSCFLocalDownloadTask, which does not derive from + // NSUrlSessionDownloadTask (which is the documented/expected return type from + // CreateDownloadTask). But __NSCFLocalDownloadTask does override + // isKindOfClass: to return true if asked about NSUrlSessionDownloadTask. + // In other words it's posing as a NSUrlSessionDownloadTask. + using (var o = session.CreateDownloadTask (request)) { + } + } + } + + [Test] + public void UsableUntilDead () + { + // The test can be inconclusive once in a while. + // 100 times in a row is a bit too much though. + for (int i = 0; i < 100; i++) { + if (UsableUntilDeadImpl ()) + return; + } + + Assert.Inconclusive ("Failed to collect the notification object at least once in 100 runs."); + } + + public bool UsableUntilDeadImpl () + { + // This test ensure that the main thread can send messages to a garbage collected object, + // until the final 'release' message for the managed reference has been sent + // (on the main thread). + + var notifierHandle = IntPtr.Zero; + +// bool isDeallocated = false; + Action deallocated = () => { + //Console.WriteLine ("Final release!"); +// isDeallocated = true; + }; + + ManualResetEvent isCollected = new ManualResetEvent (false); + Action collected = () => { + //Console.WriteLine ("Garbage collected!"); + isCollected.Set (); + }; + + bool isNotified = false; + Action notified = () => { + //Console.WriteLine ("Notified"); + isNotified = true; + }; + + // Create an object whose handle we store in a local variable. We do not + // store the object itself, since we want the object to be garbage collected. + var t = new Thread (() => { + var obj = new Notifier (collected, notified); + ReleaseNotifier.NotifyWhenDeallocated (obj, deallocated); + notifierHandle = obj.Handle; + }) { + IsBackground = true, + }; + t.Start (); + t.Join (); + + // Now we have a handle to an object that may be garbage collected at any time. + int counter = 0; + do { + GC.Collect (); + GC.WaitForPendingFinalizers (); + } while (counter++ < 10 && !isCollected.WaitOne (10)); + + // Now we have a handle to a garbage collected object. + if (!isCollected.WaitOne (0)) { + // Objects may randomly not end up collected (at least in Boehm), because + // other objects may happen to contain a random value pointing to the + // object we're waiting to become freed. + return false; + } + + // Send a message to the collected object. + Messaging.void_objc_msgSend (notifierHandle, Selector.GetHandle ("notify")); + Assert.IsTrue (isNotified, "notified"); + + // We're done. Cleanup. + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (0.1)); + // Don't verify cleanup, it's not consistent. + // And in any case it's not what this test is about. +// Assert.IsTrue (isDeallocated, "released"); + + return true; + } + + class Notifier : NSObject { + Action collected; + Action notified; + + public Notifier (Action collected, Action notified) + { + this.collected = collected; + this.notified = notified; + } + + ~Notifier () + { + collected (); + } + + [Export ("notify")] + void Notify () + { + Console.WriteLine ("{0} Notified", DateTime.Now.ToString ()); + notified (); + } + } + + class Level1 : NSObject {} // we need two levels of subclassing, since the XI will override 'release' on the first one, and we need to override it as well. + class ReleaseNotifier : Level1 { + Action deallocated; + bool enabled; + + ReleaseNotifier (Action deallocated) + { + this.deallocated = deallocated; + } + + [Export ("release")] + new void Release () + { + if (enabled) + deallocated (); + Messaging.objc_super super; + super.Handle = Handle; + super.SuperHandle = ClassHandle; + Messaging.void_objc_msgSendSuper (ref super, Selector.GetHandle ("release")); + } + + public static void NotifyWhenDeallocated (NSObject obj, Action deallocated) + { + // Add an associated object which will be 'released'd when the obj + // to watch is deallocated. When 'release' is sent, then invoke + // the 'deallocated' callback. + var notifier = new ReleaseNotifier (deallocated); + obj.SetAssociatedObject (IntPtr.Zero, notifier, AssociatedObjects.AssociationPolicy.Retain); + notifier.Dispose (); // remove any managed references. + notifier.enabled = true; // notify on the next 'release' message. + } + } + + [Test] + public void FinalizationRaceCondition () + { + if ((IntPtr.Size == 8) && TestRuntime.CheckiOSSystemVersion (9,0)) + Assert.Ignore ("NSString retainCount is nuint.MaxValue, so we won't collect them"); + + NSDictionary dict = null; + + var thread = new Thread (() => { + dict = new NSMutableDictionary(); + dict["Hello"] = new NSString(@"World"); + dict["Bye"] = new NSString(@"Bye"); + }) + { + IsBackground = true + }; + thread.Start (); + thread.Join (); + + var getter1 = new Func ((key) => dict [key] as NSString); + var getter2 = new Func ((key) => dict [key] as NSString); + + var broken = 0; + var count = 0; + + thread = new Thread (() => { + var watch = new Stopwatch (); + watch.Start (); + + while (broken == 0 && watch.ElapsedMilliseconds < 10000) { + // try getting using Systen.String key + string hello = getter1("Hello"); + if (hello == null) + broken = 1; + + string bye = getter1("Bye"); + if (bye == null) + broken = 2; + + // try getting using NSString key + string nHello = getter2(new NSString(@"Hello")); + string nBye = getter2(new NSString(@"Bye")); + + if (nHello == null) + broken = 3; + + if (nBye == null) + broken = 4; + + count++; + } + }) { + IsBackground = true, + }; + thread.Start (); + while (!thread.Join (1)) + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (0.1)); + + Assert.AreEqual (0, broken, string.Format ("broken after {0} iterations", count)); + } + + [Test] + public void ConnectMethod () + { + var minfo = typeof (RuntimeTest).GetMethod ("ConnectMethod"); + Assert.Throws (() => Runtime.ConnectMethod (null, new Selector ("")), "1"); + Assert.Throws (() => Runtime.ConnectMethod (minfo, null), "2"); + Assert.Throws (() => Runtime.ConnectMethod (null, minfo, new ExportAttribute ("foo")), "3"); + Assert.Throws (() => Runtime.ConnectMethod (typeof (RuntimeTest), null, new ExportAttribute ("foo")), "4"); + Assert.Throws (() => Runtime.ConnectMethod (typeof (RuntimeTest), minfo, (ExportAttribute) null), "5"); + + Assert.Throws (() => Runtime.ConnectMethod (typeof (RuntimeTest), minfo, new Selector ("foo")), "6"); + Assert.Throws (() => Runtime.ConnectMethod (typeof (A), minfo, new Selector ("foo")), "7"); + } + + static bool connectMethod1Done; + [Test] + public void ConnectMethod1 () + { + if (connectMethod1Done) + Assert.Ignore ("This is a one-shot test. Restart to run again."); + connectMethod1Done = true; + + Runtime.ConnectMethod (typeof (A).GetMethod ("Test"), new Selector ("test1")); + + using (var a = new A ()) + Messaging.void_objc_msgSend (a.Handle, Selector.GetHandle ("test1")); + } + + static bool connectMethod2Done; + [Test] + public void ConnectMethod2 () + { + if (connectMethod2Done) + Assert.Ignore ("This is a one-shot test. Restart to run again."); + connectMethod2Done = true; + + // the method is not declared on the type we're connecting to,but a completely different type. + Runtime.ConnectMethod (typeof (A), typeof (RuntimeTest).GetMethod ("Test2"), new Selector ("test2")); + + Messaging.void_objc_msgSend (Class.GetHandle (typeof (A)), Selector.GetHandle ("test2")); + Assert.IsTrue (calledTest2); + } + + static bool calledTest2; + public static void Test2 () + { + calledTest2 = true; + } + + + static bool connectMethod3Done; + [Test] + public void ConnectMethod3 () + { + if (connectMethod3Done) + Assert.Ignore ("This is a one-shot test. Restart to run again."); + connectMethod3Done = true; + + Runtime.ConnectMethod (typeof (NSString), typeof (RuntimeTest).GetMethod ("Test3"), new Selector ("test3")); + + Messaging.void_objc_msgSend (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("test3")); + Assert.IsTrue (calledTest3); + } + + static bool calledTest3; + public static void Test3 () + { + calledTest3 = true; + } + + class A : NSObject { + public void Test() { + Console.WriteLine ("Tested!"); + } + } + + [Test] + public void GetINativeObjectTest () + { + // create a string and try to get it. + IntPtr strptr = IntPtr.Zero; + IntPtr valueptr; + NSString obj; + try { + strptr = Marshal.StringToHGlobalAuto ("value"); + + valueptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strptr); + Assert.Throws (() => Runtime.GetINativeObject (valueptr, false), "INativeObject"); + + valueptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strptr); + obj = Runtime.GetINativeObject (valueptr, false) as NSString; + Assert.AreEqual ("value", (string) obj, "NSObject"); + + valueptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strptr); + obj = Runtime.GetINativeObject (valueptr, false) as NSString; + Assert.AreEqual ("value", (string) obj, "NSString"); + + valueptr = Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle (typeof (NSString)), Selector.GetHandle ("stringWithUTF8String:"), strptr); + var nscopying = Runtime.GetINativeObject (valueptr, false); + Assert.NotNull (nscopying, "INSCopying"); + } finally { + Marshal.FreeHGlobal (strptr); + } + } + + [Test] + public void NSAutoreleasePoolInThreadPool () + { + var count = 100; + var counter = new CountdownEvent (count); + var obj = new NSObject (); + + for (int i = 0; i < count; i++) { + ThreadPool.QueueUserWorkItem ((v) => { + obj.DangerousRetain ().DangerousAutorelease (); + counter.Signal (); + }); + } + + Assert.IsTrue (counter.Wait (TimeSpan.FromSeconds (5)), "timed out"); + // there is a race condition here: we don't necessarily know when the + // threadpool's autorelease pools are freed (in theory we can have X + // threadpool threads stopped just after the 'counter.Signal' line, + // before unwinding to the autorelease pool's dispose frame). So + // assert that the retain count has decreased, but not that it has + // decreased to 1 + var max_iterations = 100; + var iterations = 0; + while ((long) obj.RetainCount > (long) count / 2 && iterations++ < max_iterations) { + Thread.Sleep (100); + } + Assert.That (obj.RetainCount, Is.Not.GreaterThan (count / 2), "RC. Iterations: " + iterations); + + obj.Dispose (); + } + + + class ResurrectedObjectsDisposedTestClass : NSObject { + [Export ("invokeMe:wait:")] + static bool InvokeMe (NSObject obj, int invokerWait) + { + Thread.Sleep (invokerWait); + + return obj.Handle != IntPtr.Zero; + } + } + + [Test] + [TestCase (typeof (NSObject))] + [TestCase (typeof (ResurrectedObjectsDisposedTestClass))] + public void ResurrectedObjectsDisposedTest (Type type) + { + var invokerClassHandle = Class.GetHandle (typeof (ResurrectedObjectsDisposedTestClass)); + + // Create a number of native objects with no managed wrappers. + // We create more than one to try to minimize the random effects + // of the GC (a random value somewhere can keep a single object + // from being collected, but the chances of X random values keeping + // X objects from being collected are much lower). + // Also the consequences if the GC doesn't collect an object is + // that the test unexpectedly succeeds. + // 10 objects seem to be a fine number that will cause pretty much + // all test executions to fail. + var objects = new IntPtr [10]; + for (int i = 0; i < objects.Length; i++) + objects [i] = Messaging.IntPtr_objc_msgSend (Messaging.IntPtr_objc_msgSend (Class.GetHandle (type), Selector.GetHandle ("alloc")), Selector.GetHandle ("init")); + + // Create a thread that creates managed wrappers for all of the above native objects. + // We do this on a separate thread so that the GC finds no pointers to the managed + // objects in any thread. + var t1 = new Thread (() => { + for (int i = 0; i < objects.Length; i++) + Messaging.bool_objc_msgSend_IntPtr_int (invokerClassHandle, Selector.GetHandle ("invokeMe:wait:"), objects [i], 0); + }); + t1.Start (); + t1.Join (); + + // Collect all those managed wrappers, and make sure their finalizers are executed. + GC.Collect (); + GC.WaitForPendingFinalizers (); + + // Now all the managed wrappers should be on NSObject's drain queue on the main thread. + + // Spin up a thread for every native object, and invoke a managed method + // that will fetch the managed wrapper and then wait for a while (500ms), + // before verifying that the managed object hasn't been disposed while waiting. + var invokerWait = 500; + var threads = new Thread [objects.Length]; + var brokenCount = 0; + var countdown = new CountdownEvent (threads.Length); + for (int t = 0; t < threads.Length; t++) { + var tt = t; + var thread = new Thread (() => { + var ok = Messaging.bool_objc_msgSend_IntPtr_int (invokerClassHandle, Selector.GetHandle ("invokeMe:wait:"), objects [tt], invokerWait); + if (!ok) { + //Console.WriteLine ("Broken #{0}: 0x{1}", tt, objects [tt].ToString ("x")); + Interlocked.Increment (ref brokenCount); + } + countdown.Signal (); + }); + thread.Start (); + } + + // Now all those threads should be waiting. + + // Run the runloop on the main thread, which will drain the managed wrappers + // on NSObject's drain queue. + while (!countdown.IsSet) { + NSRunLoop.Current.RunUntil ((NSDate) DateTime.Now.AddSeconds (0.1)); + } + + // Release all the native objects we created + for (int i = 0; i < objects.Length; i++) + Messaging.void_objc_msgSend (objects [i], Selector.GetHandle ("release")); + + Assert.AreEqual (0, brokenCount, "broken count"); + } + } +} diff --git a/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs b/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs new file mode 100644 index 000000000000..60ed2f8bed8c --- /dev/null +++ b/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs @@ -0,0 +1,1307 @@ +using System; +using System.Drawing; +using System.Globalization; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#if !__TVOS__ +using MapKit; +#endif +#if !__WATCHOS__ +using CoreAnimation; +#endif +using CoreLocation; +#if !__WATCHOS__ +using CoreMedia; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.MapKit; +using MonoTouch.CoreAnimation; +using MonoTouch.CoreLocation; +using MonoTouch.CoreMedia; +#endif +using OpenTK; +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TrampolineTest { + public static readonly nfloat pi = 3.14159f; + + public bool IsSim64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.SIMULATOR; } } + public bool IsSim32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.SIMULATOR; } } + public bool IsArm64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.DEVICE; } } + public bool IsArm32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.DEVICE; } } + +#if !__WATCHOS__ + [Test] + public void StretTrampolineTest () + { + CMTimeRange tr; + using (var obj = new StretTrampolines ()) { + if (IsArm64) { + tr = CMTimeRange_objc_msgSend (obj.Handle, Selector.GetHandle ("myTimeRange")); + } else { + CMTimeRange_objc_msgSend (out tr, obj.Handle, Selector.GetHandle ("myTimeRange")); + } + } + Assert.AreEqual (12, tr.Duration.Value); + Assert.AreEqual (1, tr.Duration.TimeScale); + Assert.AreEqual (1, tr.Start.Value); + Assert.AreEqual (1, tr.Start.TimeScale); + } +#endif // !__WATCHOS__ + + [Test] + public void StretIIIITrampolineTest () + { + StretTrampolines obj = new StretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); + IIIIStruct rv = new IIIIStruct (); + double rvd; + float rvf; + + if (IsSim64 || IsArm64) { + rv = IIIIStruct_objc_msgSend (obj.Handle, new Selector ("Test_IIIIStruct").Handle); + } else { + IIIIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IIIIStruct").Handle); + } + Assert.That ("[1;2;3;4]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = IIIIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIIIIStruct").Handle); + } else { + IIIIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIIIIStruct").Handle); + } + Assert.That ("[10;20;30;40]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = IIIIStruct_objc_msgSend (obj.Handle, new Selector ("Test_IIIIStructProperty").Handle); + } else { + IIIIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IIIIStructProperty").Handle); + } + Assert.That ("[100;200;300;400]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = IIIIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIIIIStructProperty").Handle); + } else { + IIIIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIIIIStructProperty").Handle); + } + Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = IIIIStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticIIIIStruct_out_Float:").Handle, out rvf); + } else { + IIIIStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticIIIIStruct_out_Float:").Handle, out rvf); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[10;20;300;4000]" == rv.ToString ()); + Assert.That (rvf == 3.15f); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = IIIIStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_IIIIStruct_out_Double:").Handle, out rvd); + } else { + IIIIStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_IIIIStruct_out_Double:").Handle, out rvd); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[1;20;300;4000]" == rv.ToString ()); + Assert.That (rvd == 3.14); + + } + + [Test] + public void StretFFFFTrampolineTest () + { + StretTrampolines obj = new StretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); + var rv = new FFFFStruct (); + double rvd; + float rvf; + + if (IsSim64 || IsArm64) { + rv = FFFFStruct_objc_msgSend (obj.Handle, new Selector ("Test_FFFFStruct").Handle); + } else { + FFFFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FFFFStruct").Handle); + } + Assert.That ("[1;2;3;4]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = FFFFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFFFFStruct").Handle); + } else { + FFFFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFFFFStruct").Handle); + } + Assert.That ("[10;20;30;40]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = FFFFStruct_objc_msgSend (obj.Handle, new Selector ("Test_FFFFStructProperty").Handle); + } else { + FFFFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FFFFStructProperty").Handle); + } + Assert.That ("[100;200;300;400]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = FFFFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFFFFStructProperty").Handle); + } else { + FFFFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFFFFStructProperty").Handle); + } + Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = FFFFStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticFFFFStruct_out_Float:").Handle, out rvf); + } else { + FFFFStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticFFFFStruct_out_Float:").Handle, out rvf); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[10;20;300;4000]" == rv.ToString ()); + Assert.That (rvf == 3.15f); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = FFFFStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_FFFFStruct_out_Double:").Handle, out rvd); + } else { + FFFFStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_FFFFStruct_out_Double:").Handle, out rvd); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[1;20;300;4000]" == rv.ToString ()); + Assert.That (rvd == 3.14); + } + + [Test] + public void StretFIFITrampolineTest () + { + StretTrampolines obj = new StretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); + var rv = new FIFIStruct (); + double rvd; + float rvf; + + if (IsSim64 || IsArm64) { + rv = FIFIStruct_objc_msgSend (obj.Handle, new Selector ("Test_FIFIStruct").Handle); + } else { + FIFIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FIFIStruct").Handle); + } + Assert.That ("[1;2;3;4]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = FIFIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFIFIStruct").Handle); + } else { + FIFIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFIFIStruct").Handle); + } + Assert.That ("[10;20;30;40]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = FIFIStruct_objc_msgSend (obj.Handle, new Selector ("Test_FIFIStructProperty").Handle); + } else { + FIFIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FIFIStructProperty").Handle); + } + Assert.That ("[100;200;300;400]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = FIFIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFIFIStructProperty").Handle); + } else { + FIFIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFIFIStructProperty").Handle); + } + Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = FIFIStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticFIFIStruct_out_Float:").Handle, out rvf); + } else { + FIFIStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticFIFIStruct_out_Float:").Handle, out rvf); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[10;20;300;4000]" == rv.ToString ()); + Assert.That (rvf == 3.15f); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = FIFIStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_FIFIStruct_out_Double:").Handle, out rvd); + } else { + FIFIStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_FIFIStruct_out_Double:").Handle, out rvd); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[1;20;300;4000]" == rv.ToString ()); + Assert.That (rvd == 3.14); + } + + [Test] + public void StretIFIFTrampolineTest () + { + StretTrampolines obj = new StretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); + var rv = new IFIFStruct (); + double rvd; + float rvf; + + if (IsSim64 || IsArm64) { + rv = IFIFStruct_objc_msgSend (obj.Handle, new Selector ("Test_IFIFStruct").Handle); + } else { + IFIFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IFIFStruct").Handle); + } + Assert.That ("[1;2;3;4]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = IFIFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIFIFStruct").Handle); + } else { + IFIFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIFIFStruct").Handle); + } + Assert.That ("[10;20;30;40]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = IFIFStruct_objc_msgSend (obj.Handle, new Selector ("Test_IFIFStructProperty").Handle); + } else { + IFIFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IFIFStructProperty").Handle); + } + Assert.That ("[100;200;300;400]" == rv.ToString ()); + if (IsSim64 || IsArm64) { + rv = IFIFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIFIFStructProperty").Handle); + } else { + IFIFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIFIFStructProperty").Handle); + } + Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = IFIFStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticIFIFStruct_out_Float:").Handle, out rvf); + } else { + IFIFStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticIFIFStruct_out_Float:").Handle, out rvf); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[10;20;300;4000]" == rv.ToString ()); + Assert.That (rvf == 3.15f); + + rvd = rvf = 0; + if (IsSim64 || IsArm64) { + rv = IFIFStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_IFIFStruct_out_Double:").Handle, out rvd); + } else { + IFIFStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_IFIFStruct_out_Double:").Handle, out rvd); + } + //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); + Assert.That ("[1;20;300;4000]" == rv.ToString ()); + Assert.That (rvd == 3.14); + } + + + + [Test] + public void DoubleReturnTest () + { + DoubleStretTrampolines obj = new DoubleStretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("DoubleStretTrampolines"); + + Assert.That (0 == Messaging.Double_objc_msgSend (obj.Handle, new Selector ("Test_Zero").Handle), "#1"); + Assert.That (0 == Messaging.Double_objc_msgSend (class_ptr, new Selector ("Test_StaticZero").Handle), "#2"); + Assert.That (0 == Messaging.Double_objc_msgSend (obj.Handle, new Selector ("Test_ZeroProperty").Handle), "#3"); + Assert.That (0 == Messaging.Double_objc_msgSend (class_ptr, new Selector ("Test_StaticZeroProperty").Handle), "#4"); + } + + [Test] + public void FloatReturnTest () + { + FloatStretTrampolines obj = new FloatStretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("FloatStretTrampolines"); + + Assert.That (0 == Messaging.float_objc_msgSend (obj.Handle, new Selector ("Test_Zero").Handle), "#1"); + Assert.That (0 == Messaging.float_objc_msgSend (class_ptr, new Selector ("Test_StaticZero").Handle), "#2"); + Assert.That (0 == Messaging.float_objc_msgSend (obj.Handle, new Selector ("Test_ZeroProperty").Handle), "#3"); + Assert.That (0 == Messaging.float_objc_msgSend (class_ptr, new Selector ("Test_StaticZeroProperty").Handle), "#4"); + } + + [Test] + public void LoooongTest () + { + LongTrampolines obj = new LongTrampolines (); + long a = 3; + long b = 5; + long c = 15; + long d = 29; + long e; + + void_objc_msgSend_long_long_ref_long_ref_long (obj.Handle, new Selector ("ManyLongs:b:c:d:").Handle, a, b, out c, out d); + Assert.That (c == a + b, "#a1"); + Assert.That (d == b - a, "#a2"); + + c = 15; + d = 29; + + e = long_objc_msgSend_long_long_out_long_out_long (obj.Handle, new Selector ("VeryManyLongs:b:c:d:").Handle, a, b, out c, out d); + Assert.That (a + b + c + d == e, "#b1"); + Assert.That (c == a + b, "#b2"); + Assert.That (d == a - b, "#b3"); + } + + const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib"; + +#if !__WATCHOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static OpenTK.Matrix4 Matrix4_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void Matrix4_objc_msgSend_stret (out OpenTK.Matrix4 retval, IntPtr receiver, IntPtr selector); +#endif // !__WATCHOS__ + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void IIIIStruct_objc_msgSend_stret (out IIIIStruct retval, IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static IIIIStruct IIIIStruct_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void IIIIStruct_objc_msgSend_stret_out_double (out IIIIStruct retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static IIIIStruct IIIIStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void IIIIStruct_objc_msgSend_stret_out_float (out IIIIStruct retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static IIIIStruct IIIIStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); + + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void FFFFStruct_objc_msgSend_stret (out FFFFStruct retval, IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static FFFFStruct FFFFStruct_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void FFFFStruct_objc_msgSend_stret_out_double (out FFFFStruct retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static FFFFStruct FFFFStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void FFFFStruct_objc_msgSend_stret_out_float (out FFFFStruct retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static FFFFStruct FFFFStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); + + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void IFIFStruct_objc_msgSend_stret (out IFIFStruct retval, IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static IFIFStruct IFIFStruct_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void IFIFStruct_objc_msgSend_stret_out_double (out IFIFStruct retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static IFIFStruct IFIFStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void IFIFStruct_objc_msgSend_stret_out_float (out IFIFStruct retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static IFIFStruct IFIFStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); + + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void FIFIStruct_objc_msgSend_stret (out FIFIStruct retval, IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static FIFIStruct FIFIStruct_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void FIFIStruct_objc_msgSend_stret_out_double (out FIFIStruct retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static FIFIStruct FIFIStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void FIFIStruct_objc_msgSend_stret_out_float (out FIFIStruct retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static FIFIStruct FIFIStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); + + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void double_objc_msgSend_stret_out_double (out double retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void double_objc_msgSend_stret_out_float (out double retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void float_objc_msgSend_stret_out_double (out float retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void float_objc_msgSend_stret_out_float (out float retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void PointF_objc_msgSend_stret_out_double (out PointF retval, IntPtr receiver, IntPtr selector, out double arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void PointF_objc_msgSend_stret_out_float (out PointF retval, IntPtr receiver, IntPtr selector, out float arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void RectangleF_objc_msgSend_stret_IntPtr_IntPtr_RectangleF (out RectangleF retval, IntPtr receiver, IntPtr selector, IntPtr a, IntPtr b, RectangleF c); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static RectangleF RectangleF_objc_msgSend_IntPtr_IntPtr_RectangleF (IntPtr receiver, IntPtr selector, IntPtr a, IntPtr b, RectangleF c); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_out_NSError (IntPtr receiver, IntPtr selector, out IntPtr error, int arg1); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static void void_objc_msgSend_long_long_ref_long_ref_long (IntPtr receiver, IntPtr selector, long arg1, long arg2, out long arg3, out long arg4); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static long long_objc_msgSend_long_long_out_long_out_long (IntPtr receiver, IntPtr selector, long arg1, long arg2, out long arg3, out long arg4); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static bool bool_objc_msgSend_out_PointF (IntPtr receiver, IntPtr selector, out PointF point); + + +#if !__WATCHOS__ + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] + extern static CMTimeRange CMTimeRange_objc_msgSend (IntPtr receiver, IntPtr selector); + + [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] + extern static void CMTimeRange_objc_msgSend (out CMTimeRange retval, IntPtr receiver, IntPtr selector); +#endif // !__WATCHOS__ + + void AreAlmostEqual (RectangleF left, RectangleF right, string message) + { + var delta = 0.000001f; + Assert.AreEqual (left.X, right.X, delta, message); + Assert.AreEqual (left.Y, right.Y, delta, message); + Assert.AreEqual (left.Width, right.Width, delta, message); + Assert.AreEqual (left.Height, right.Height, delta, message); + } + + [Test] + public void FloatingPointStretTrampolineTest () + { + RectangleF rect, rect2, rect3, rect4; +#if !__TVOS__ + MKCoordinateRegion mkregion; + MKMapRect mkmaprect; +#endif + FloatingPointStretTrampolines obj = new FloatingPointStretTrampolines (); + IntPtr class_ptr = Class.GetHandle ("FloatingPointStretTrampolines"); + NSString tmp_obj = obj.StringObj; +#if !__WATCHOS__ + Matrix3 matrix3; + Matrix4 matrix4; + CATransform3D catransform3d; +#endif // !__WATCHOS__ + int i; + + rect2 = new RectangleF (1.2f, 2.3f, 3.4f, 4.5f); + if (IsArm64) { + rect = RectangleF_objc_msgSend_IntPtr_IntPtr_RectangleF (obj.Handle, new Selector ("testRectangleF_string_string_RectangleF:b:c:").Handle, new NSString ("a").Handle, new NSString ("b").Handle, rect2); + } else { + RectangleF_objc_msgSend_stret_IntPtr_IntPtr_RectangleF (out rect, obj.Handle, new Selector ("testRectangleF_string_string_RectangleF:b:c:").Handle, new NSString ("a").Handle, new NSString ("b").Handle, rect2); + } + Assert.That (rect == new RectangleF (rect2.X * pi, rect2.Y * pi, rect2.Width * pi, rect2.Height * pi), "#testRectangleF_string_string_RectangleF:b:c:"); + + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend (obj.Handle, new Selector ("testRectangleF").Handle); + } else { + Messaging.RectangleF_objc_msgSend_stret (out rect, obj.Handle, new Selector ("testRectangleF").Handle); + } + Assert.That (rect == new RectangleF (1.2f, 2.3f, 3.4f, 4.5f), "#testRectangleF"); + + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend (class_ptr, new Selector ("staticTestRectangleF").Handle); + } else { + Messaging.RectangleF_objc_msgSend_stret (out rect, class_ptr, new Selector ("staticTestRectangleF").Handle); + } + Assert.That (rect == new RectangleF (1.2f, 2.3f, 3.4f, 4.5f), "#static testRectangleF"); + + i = 152; + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_int (obj.Handle, new Selector ("testRectangleF_int:").Handle, 152); + } else { + Messaging.RectangleF_objc_msgSend_stret_int (out rect, obj.Handle, new Selector ("testRectangleF_int:").Handle, 152); + } + Assert.That (rect == new RectangleF (i + .1f, i + .2f, i + .3f, i + .4f), "#ret RectF-int", "#testRectangleF_int:"); + + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_IntPtr (obj.Handle, new Selector ("testRectangleF_IntPtr:").Handle, tmp_obj.Handle); + } else { + Messaging.RectangleF_objc_msgSend_stret_IntPtr (out rect, obj.Handle, new Selector ("testRectangleF_IntPtr:").Handle, tmp_obj.Handle); + } + AreAlmostEqual (rect, new RectangleF (pi + 0.4f, pi + 0.3f, pi + 0.2f, pi + 0.1f), "#ret RectF-IntPtr"); + +#if !__TVOS__ + mkregion = new MKCoordinateRegion (new CLLocationCoordinate2D (123.456, 345.678), new MKCoordinateSpan (987.654, 654.321)); + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_MKCoordinateRegion_IntPtr (obj.Handle, new Selector ("testRectangleF_MCCoordinateRegion_IntPtr:str:").Handle, mkregion, tmp_obj.Handle); + } else { + Messaging.RectangleF_objc_msgSend_stret_MKCoordinateRegion_IntPtr (out rect, obj.Handle, new Selector ("testRectangleF_MCCoordinateRegion_IntPtr:str:").Handle, mkregion, tmp_obj.Handle); + } + Assert.That (rect == new RectangleF (123.456f+pi, 345.678f-pi, 987.654f*pi, 654.321f/pi), "#testRectangleF_MCCoordinateRegion_IntPtr:str:"); + + mkmaprect = new MKMapRect (111.1, 222.2, 333.3, 444.4); + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_MKMapRect (obj.Handle, new Selector ("testRectangleF_MKMapRect:").Handle, mkmaprect); + } else { + Messaging.RectangleF_objc_msgSend_stret_MKMapRect (out rect, obj.Handle, new Selector ("testRectangleF_MKMapRect:").Handle, mkmaprect); + } + Assert.That (rect == new RectangleF (111.1f, 222.2f, 333.3f, 444.4f), "#testRectangleF_MKMapRect:"); +#endif // !__TVOS__ + + rect2 = new RectangleF (9.9f, 8.8f, 7.7f, 6.6f); + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_RectangleF (obj.Handle, new Selector ("testRectangleF_RectangleF:").Handle, rect2); + } else { + Messaging.RectangleF_objc_msgSend_stret_RectangleF (out rect, obj.Handle, new Selector ("testRectangleF_RectangleF:").Handle, rect2); + } + Assert.That (rect == rect2, "#testRectangleF_RectangleF:"); + + rect2 = new RectangleF (5.44f, 4.33f, 3.22f, 2.11f); + i = 8; + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_RectangleF_int (obj.Handle, new Selector ("testRectangleF_RectangleF_int:i:").Handle, rect2, 8); + } else { + Messaging.RectangleF_objc_msgSend_stret_RectangleF_int (out rect, obj.Handle, new Selector ("testRectangleF_RectangleF_int:i:").Handle, rect2, 8); + } + AreAlmostEqual (rect, new RectangleF (5.44f*i, 4.33f+i, 3.22f-i, 2.11f/i), "testRectangleF_RectangleF_int:i:"); + + rect2 = new RectangleF (5.4f, 4.3f, 3.2f, 2.1f); + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_RectangleF_IntPtr (obj.Handle, new Selector ("testRectangleF_RectangleF_IntPtr:str:").Handle, rect2, tmp_obj.Handle); + } else { + Messaging.RectangleF_objc_msgSend_stret_RectangleF_IntPtr (out rect, obj.Handle, new Selector ("testRectangleF_RectangleF_IntPtr:str:").Handle, rect2, tmp_obj.Handle); + } + Assert.That (rect == new RectangleF (5.4f*pi, 4.3f+pi, 3.2f-pi, 2.1f/pi)); + + rect2 = new RectangleF (1, 2, 3, 4); + rect3 = new RectangleF (9, 8, 7, 6); + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_RectangleF_RectangleF_float ( obj.Handle, new Selector ("testRectangleF_RectangleF_RectangleF_float:b:c:").Handle, rect2, rect3, (float) pi); + } else { + Messaging.RectangleF_objc_msgSend_stret_RectangleF_RectangleF_float (out rect, obj.Handle, new Selector ("testRectangleF_RectangleF_RectangleF_float:b:c:").Handle, rect2, rect3, (float) pi); + } + Assert.That (rect == new RectangleF (1 * 9 * pi, 2 * 8 * pi, 3 * 7 * pi, 4 * 6 * pi), "#testRectangleF_RectangleF_RectangleF_float:b:c:"); + + rect2 = new RectangleF (1, 2, 3, 4); + rect3 = new RectangleF (9, 8, 7, 6); + rect4 = new RectangleF (10, 20, 30, 40); + if (IsArm64) { + rect = Messaging.RectangleF_objc_msgSend_RectangleF_RectangleF_RectangleF (obj.Handle, new Selector ("testRectangleF_RectangleF_RectangleF_RectangleF:b:c:").Handle, rect2, rect3, rect4); + } else { + Messaging.RectangleF_objc_msgSend_stret_RectangleF_RectangleF_RectangleF (out rect, obj.Handle, new Selector ("testRectangleF_RectangleF_RectangleF_RectangleF:b:c:").Handle, rect2, rect3, rect4); + } + Assert.That (rect == new RectangleF (20, 30, 40, 50), "#testRectangleF_RectangleF_RectangleF_RectangleF:b:c:"); + +#if !__WATCHOS__ + if (IsArm64) { + matrix3 = Messaging.Matrix3_objc_msgSend (obj.Handle, new Selector ("testMatrix3").Handle); + } else { + Messaging.Matrix3_objc_msgSend_stret (out matrix3, obj.Handle, new Selector ("testMatrix3").Handle); + } + Assert.That (matrix3.Equals (new Matrix3 (1, 2, 3, 4, 5, 6, 7, 8, 9)), "#testMatrix3"); + + if (IsArm64) { + matrix4 = Matrix4_objc_msgSend (obj.Handle, new Selector ("testMatrix4").Handle); + } else { + Matrix4_objc_msgSend_stret (out matrix4, obj.Handle, new Selector ("testMatrix4").Handle); + } + Assert.That (matrix4.Equals (new Matrix4 (9, 8, 7, 6, 5, 4, 3, 2, 1, 9, 8, 7, 6, 5, 4, 3)), "#testMatrix4"); + + if (IsArm64) { + catransform3d = Messaging.CATransform3D_objc_msgSend (obj.Handle, new Selector ("testCATransform3D").Handle); + } else { + Messaging.CATransform3D_objc_msgSend_stret (out catransform3d, obj.Handle, new Selector ("testCATransform3D").Handle); + } + CATransform3D res = new CATransform3D (); + res.m11 = 11.1f; + res.m22 = 22.2f; + res.m33 = 33.3f; + res.m44 = 44.4f; + Assert.That (catransform3d.Equals (res), "#testCATransform3D"); +#endif // !__WATCHOS__ + + PointF point; + SizeF size; + + if (IsArm32) { + Messaging.PointF_objc_msgSend_stret (out point, obj.Handle, new Selector ("testPointF").Handle); + } else { + point = Messaging.PointF_objc_msgSend (obj.Handle, new Selector ("testPointF").Handle); + } + Assert.That (point == new PointF (pi*2, pi*20), "#testPointF"); + + if (IsArm32) { + Messaging.SizeF_objc_msgSend_stret (out size, obj.Handle, new Selector ("testSizeF").Handle); + } else { + size = Messaging.SizeF_objc_msgSend (obj.Handle, new Selector ("testSizeF").Handle); + } + Assert.That (size == new SizeF (pi*3, pi*30), "#testSizeF"); + } + + [Test] + public void OutValueTypeTest () + { + var obj = new OutParams (); + PointF point = new PointF (3, 14); + bool res; + + res = bool_objc_msgSend_out_PointF (obj.Handle, new Selector ("Test_PointF:").Handle, out point); + Assert.That (res, "#res"); + Assert.That (point.X, Is.EqualTo ((nfloat) 3.1415f), "#x"); + Assert.That (point.Y, Is.EqualTo ((nfloat) 0), "#y"); + } + + [Test] + public void OutParamTest () + { + var obj = new OutParams (); + NSError error = new NSError (new NSString ("doomed"), 314); + IntPtr errorptr = error.Handle; + + void_objc_msgSend_out_NSError (obj.Handle, new Selector ("Test_NSError:arg1:").Handle, out errorptr, 0); + error = errorptr == IntPtr.Zero ? null : Runtime.GetNSObject (errorptr); + Assert.That (error, Is.Null, "#1"); + + void_objc_msgSend_out_NSError (obj.Handle, new Selector ("Test_NSError:arg1:").Handle, out errorptr, 1); + error = Runtime.GetNSObject (errorptr); + Assert.That (error.Domain, Is.EqualTo ("domain"), "#2 - domain"); + Assert.That (error.Code, Is.EqualTo ((nint) 1), "#3 - code"); + } + + [Test] + public void ArrayTest () + { + var obj = new ArrayTrampolines (); + string[] arr = new string [] { "abc" }; + int c; + + c = Messaging.int_objc_msgSend_IntPtr (obj.Handle, new Selector ("Test_StringArray:").Handle, NSArray.FromStrings (arr).Handle); + + Assert.That (c == 1, "#a1"); + Assert.That (arr [0] == "abc"); // array elements aren't copied back out (maybe they should be?) + + arr = NSArray.StringArrayFromHandle (Messaging.IntPtr_objc_msgSend (obj.Handle, new Selector ("Test_StringArrayReturn").Handle)); + + Assert.That (arr.Length == 1, "#b1"); + Assert.That (arr [0] == "def", "#b2"); + + arr = NSArray.StringArrayFromHandle (Messaging.IntPtr_objc_msgSend (obj.Handle, new Selector ("Test_StringArrayNullReturn").Handle)); + Assert.IsNull (arr, "#c1"); + + c = Messaging.int_objc_msgSend_IntPtr (obj.Handle, new Selector ("Test_StringArray:").Handle, IntPtr.Zero); + Assert.AreEqual (-1, c, "#d1"); + } + + [Test] + public void IntPtrTest () + { + var obj = new IntPtrTrampolines (); + bool res; + + res = Messaging.bool_objc_msgSend_IntPtr (obj.Handle, new Selector ("IsZero:").Handle, IntPtr.Zero); + Assert.That (res, "#1"); + res = Messaging.bool_objc_msgSend_IntPtr (obj.Handle, new Selector ("IsZero:").Handle, new IntPtr (1)); + Assert.That (!res, "#2"); + } + + [Test] + public void X64ArgumentOverflow () + { + using (var obj = new MiscTrampolines ()) { + Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_NSRange_IntPtr (obj.Handle, Selector.GetHandle ("x64argumentoverflow:::::"), new IntPtr (1), new IntPtr (2), new IntPtr (3), new NSRange (4, 5), new IntPtr (6)); + } + } + } + + [Preserve (AllMembers = true)] + [Register ("MiscTrampolines")] + public class MiscTrampolines : NSObject + { + [Export ("x64argumentoverflow:::::")] + void X64ArgumentOverflow (nint a, nint b, nint c, NSRange overflow, nint d) + { + Assert.AreEqual ((nint) 1, a, "1"); + Assert.AreEqual ((nint) 2, b, "2"); + Assert.AreEqual ((nint) 3, c, "3"); + Assert.AreEqual ((nint) 4, overflow.Location, "length"); + Assert.AreEqual ((nint) 5, overflow.Length, "location"); + Assert.AreEqual ((nint) 6, d, "4"); + } + } + + [Register ("IntPtrTrampolines")] + [Preserve (AllMembers = true)] + public class IntPtrTrampolines : NSObject + { + [Export ("IsZero:")] + bool IsZero (IntPtr foo) + { + return foo == IntPtr.Zero; + } + } + + [Register ("ArrayTrampolines")] + [Preserve (AllMembers = true)] + public class ArrayTrampolines : NSObject + { + [Export ("Test_StringArray:")] + int Test_StringArray (string[] arr) + { + if (arr == null) + return -1; + if (arr.Length == 0) + return 0; + arr [0] = "def"; + return arr.Length; + } + + [Export ("Test_StringArrayReturn")] + string[] Test_StringArrayReturn () + { + return new string [] { "def" }; + } + + [Export ("Test_StringArrayNullReturn")] + string[] Test_StringArrayNullReturn () + { + return null; + } + } + + [Register ("OutParams")] + [Preserve (AllMembers = true)] + public class OutParams : NSObject + { + [Export ("Test_NSError:arg1:")] + void Test_NSError (out NSError error, int arg1) + { + switch (arg1) { + case 0: + error = null; + break; + case 1: + error = new NSError (new NSString ("domain"), 1); + break; + default: + throw new ArgumentOutOfRangeException ("arg1"); + } + } + [Export ("Test_PointF:")] + bool Test_PointF (out PointF point) + { + point = new PointF (3.1415f, 0); + return true; + } + } + + [Preserve (AllMembers = true)] + public struct IIIIStruct + { + public int A, B, C, D; + + public IIIIStruct (int a, int b, int c, int d) + { + A = a; + B = b; + C = c; + D = d; + } + + public override string ToString () + { + return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); + } + } + + [Preserve (AllMembers = true)] + public struct FFFFStruct + { + public float A, B, C, D; + + public FFFFStruct (float a, float b, float c, float d) + { + A = a; + B = b; + C = c; + D = d; + } + + public override string ToString () + { + return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); + } + } + + [Preserve (AllMembers = true)] + public struct FIFIStruct + { + public float A; + public int B; + public float C; + public int D; + + public FIFIStruct (float a, int b, float c, int d) + { + A = a; + B = b; + C = c; + D = d; + } + + public override string ToString () + { + return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); + } + } + + [Preserve (AllMembers = true)] + public struct IFIFStruct + { + public int A; + public float B; + public int C; + public float D; + + public IFIFStruct (int a, float b, int c, float d) + { + A = a; + B = b; + C = c; + D = d; + } + + public override string ToString () + { + return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); + } + } + + [Preserve (AllMembers = true)] + [Register ("LongTrampolines")] + public class LongTrampolines : NSObject + { + [Export ("ManyLongs:b:c:d:")] + void ManyLongs (long a, long b, ref long c, ref long d) + { + //Console.WriteLine ("a: {0} b: {1} c: {2} d: {3}", a, b, c, d); + c = a + b; + d = b - a; + } + + [Export ("VeryManyLongs:b:c:d:")] + long VeryManyLongs (long a, long b, out long c, out long d) + { + c = a + b; + d = a - b; + //Console.WriteLine ("a: {0} b: {1} c: {2} d: {3}", a, b, c, d); + return a + b + c + d; + } + } + + [Register ("StretTrampolines")] + [Preserve (AllMembers = true)] + public class StretTrampolines : NSObject + { + /* IIII */ + + [Export ("Test_IIIIStruct")] + IIIIStruct Test_IIIIStruct () + { + return new IIIIStruct (1, 2, 3, 4); + } + + [Export ("Test_StaticIIIIStruct")] + static IIIIStruct Test_StaticIIIIStruct () + { + return new IIIIStruct (10, 20, 30, 40); + } + + IIIIStruct Test_IIIIStructProperty { + [Export ("Test_IIIIStructProperty")] + get { return new IIIIStruct (100, 200, 300, 400); } + } + + static IIIIStruct Test_StaticIIIIStructProperty { + [Export ("Test_StaticIIIIStructProperty")] + get { return new IIIIStruct (1000, 2000, 3000, 4000); } + } + + [Export ("Test_IIIIStruct_out_Double:")] + IIIIStruct Test_IIIIStruct_out_Double (out double foo) + { + foo = 3.14; + return new IIIIStruct (1, 20, 300, 4000); + } + + [Export ("Test_StaticIIIIStruct_out_Float:")] + static IIIIStruct Test_StaticIIIIStruct_out_Float (out float foo) + { + foo = 3.15f; + return new IIIIStruct (10, 20, 300, 4000); + } + + /* FFFF */ + + [Export ("Test_FFFFStruct")] + FFFFStruct Test_FFFFStruct () + { + return new FFFFStruct (1, 2, 3, 4); + } + + [Export ("Test_StaticFFFFStruct")] + static FFFFStruct Test_StaticFFFFStructStruct () + { + return new FFFFStruct (10, 20, 30, 40); + } + + FFFFStruct Test_FFFFStructtStructProperty { + [Export ("Test_FFFFStructProperty")] + get { return new FFFFStruct (100, 200, 300, 400); } + } + + static FFFFStruct Test_StaticFFFFStructProperty { + [Export ("Test_StaticFFFFStructProperty")] + get { return new FFFFStruct (1000, 2000, 3000, 4000); } + } + + [Export ("Test_FFFFStruct_out_Double:")] + FFFFStruct Test_FFFFStruct_out_Double (out double foo) + { + foo = 3.14; + return new FFFFStruct (1, 20, 300, 4000); + } + + [Export ("Test_StaticFFFFStruct_out_Float:")] + static FFFFStruct Test_StaticFFFFStruct_out_Float (out float foo) + { + foo = 3.15f; + return new FFFFStruct (10, 20, 300, 4000); + } + + /* FIFI */ + + [Export ("Test_FIFIStruct")] + FIFIStruct Test_FIFIStruct () + { + return new FIFIStruct (1, 2, 3, 4); + } + + [Export ("Test_StaticFIFIStruct")] + static FIFIStruct Test_StaticFIFIStructStruct () + { + return new FIFIStruct (10, 20, 30, 40); + } + + FIFIStruct Test_FIFIStructtStructProperty { + [Export ("Test_FIFIStructProperty")] + get { return new FIFIStruct (100, 200, 300, 400); } + } + + static FIFIStruct Test_StaticFIFIStructProperty { + [Export ("Test_StaticFIFIStructProperty")] + get { return new FIFIStruct (1000, 2000, 3000, 4000); } + } + + [Export ("Test_FIFIStruct_out_Double:")] + FIFIStruct Test_FIFIStruct_out_Double (out double foo) + { + foo = 3.14; + return new FIFIStruct (1, 20, 300, 4000); + } + + [Export ("Test_StaticFIFIStruct_out_Float:")] + static FIFIStruct Test_StaticFIFIStruct_out_Float (out float foo) + { + foo = 3.15f; + return new FIFIStruct (10, 20, 300, 4000); + } + + /* IFIF */ + + [Export ("Test_IFIFStruct")] + IFIFStruct Test_IFIFStruct () + { + return new IFIFStruct (1, 2, 3, 4); + } + + [Export ("Test_StaticIFIFStruct")] + static IFIFStruct Test_StaticIFIFStructStruct () + { + return new IFIFStruct (10, 20, 30, 40); + } + + IFIFStruct Test_IFIFStructtStructProperty { + [Export ("Test_IFIFStructProperty")] + get { return new IFIFStruct (100, 200, 300, 400); } + } + + static IFIFStruct Test_StaticIFIFStructProperty { + [Export ("Test_StaticIFIFStructProperty")] + get { return new IFIFStruct (1000, 2000, 3000, 4000); } + } + + [Export ("Test_IFIFStruct_out_Double:")] + IFIFStruct Test_IFIFStruct_out_Double (out double foo) + { + foo = 3.14; + return new IFIFStruct (1, 20, 300, 4000); + } + + [Export ("Test_StaticIFIFStruct_out_Float:")] + static IFIFStruct Test_StaticIFIFStruct_out_Float (out float foo) + { + foo = 3.15f; + return new IFIFStruct (10, 20, 300, 4000); + } + +#if !__WATCHOS__ + [Export ("myTimeRange")] + CMTimeRange TimeRange { + get { + var rv = new CMTimeRange () { Duration = new CMTime (12, 1), Start = new CMTime (1, 1) }; + return rv; + } + } +#endif // !__WATCHOS__ + } + + + [Register ("DoubleStretTrampolines")] + [Preserve (AllMembers = true)] + public class DoubleStretTrampolines : NSObject + { + [Export ("Test_Zero")] + double Test_Zero () + { + return 0; + } + + [Export ("Test_StaticZero")] + static double Test_StaticZero () + { + return 0; + } + + double Test_ZeroProperty { + [Export ("Test_ZeroProperty")] + get { return 0; } + } + + static double Test_StaticZeroProperty { + [Export ("Test_StaticZeroProperty")] + get { return 0; } + } + + [Export ("Test_Double_out_Double:")] + double Test_Double_out_Double (out double foo) + { + foo = 3.16f; + return 3.16; + } + + [Export ("Test_StaticDouble_out_Float:")] + static double Test_StaticDouble_out_Float (out float foo) + { + foo = 3.17f; + return 3.17; + } + } + + [Register ("FloatStretTrampolines")] + [Preserve (AllMembers = true)] + public class FloatStretTrampolines : NSObject + { + [Export ("Test_Zero")] + float Test_Zero () + { + return 0; + } + + [Export ("Test_StaticZero")] + static float Test_StaticZero () + { + return 0; + } + + float Test_ZeroProperty { + [Export ("Test_ZeroProperty")] + get { return 0; } + } + + static float Test_StaticZeroProperty { + [Export ("Test_StaticZeroProperty")] + get { return 0; } + } + + [Export ("Test_Float_out_Double:")] + float Test_Float_out_Double (out double foo) + { + foo = 3.18f; + return 3.18f; + } + + [Export ("Test_StaticFloat_out_Float:")] + static float Test_StaticFloat_out_Float (out float foo) + { + foo = 3.19f; + return 3.19f; + } + } + + + [Register ("FloatingPointStretTrampolines")] + [Preserve (AllMembers = true)] + public class FloatingPointStretTrampolines : NSObject + { + const float pi = 3.14159f; + public NSString StringObj = new NSString ("3.14159"); + + static float ParseString (string str) + { + return float.Parse (str, new CultureInfo ("en-US").NumberFormat); + } + + [Export ("testRectangleF")] + public RectangleF Test_RectangleF () + { + return new RectangleF (1.2f, 2.3f, 3.4f, 4.5f); + } + + [Export ("staticTestRectangleF")] + static public RectangleF StaticTest_RectangleF () + { + return new RectangleF (1.2f, 2.3f, 3.4f, 4.5f); + } + + [Export ("testRectangleF_int:")] + public RectangleF Test_RectangleF_int (int a) + { + return new RectangleF (a + 0.1f, a + 0.2f, a + 0.3f, a + 0.4f); + } + + [Export ("testRectangleF_IntPtr:")] + public RectangleF Test_RectangleF_IntPtr (NSString str) + { + float pi = ParseString (str.ToString ()); + if ((object) StringObj != (object) str) + return RectangleF.Empty; + return new RectangleF (pi + 0.4f, pi + 0.3f, pi + 0.2f, pi + 0.1f); + } + +#if !__TVOS__ + [Export ("testRectangleF_MCCoordinateRegion_IntPtr:str:")] + public RectangleF Test_RectangleF_MKCoordinateRegion_IntPtr (MKCoordinateRegion a, NSString str) + { + float pi = ParseString (str.ToString ()); + if ((object) StringObj != (object) str) + return RectangleF.Empty; +#if __UNIFIED__ + return new RectangleF ((double)(float)a.Center.Latitude+pi, (double)(float)a.Center.Longitude-pi, (double)(float)a.Span.LatitudeDelta*pi, (double)(float)a.Span.LongitudeDelta/pi); +#else + return new RectangleF ((float)a.Center.Latitude+pi, (float)a.Center.Longitude-pi, (float)a.Span.LatitudeDelta*pi, (float)a.Span.LongitudeDelta/pi); +#endif + } + + [Export ("testRectangleF_MKMapRect:")] + public RectangleF Test_RectangleF_MKMapRect (MKMapRect a) + { + return new RectangleF ((float) a.Origin.X, (float) a.Origin.Y, (float) a.Width, (float) a.Height); + } +#endif // !__TVOS__ + + [Export ("testRectangleF_RectangleF:")] + public RectangleF Test_RectangleF_RectangleF (RectangleF a) + { + return new RectangleF (a.X, a.Y, a.Width, a.Height); + } + + [Export ("testRectangleF_RectangleF_int:i:")] + public RectangleF Test_RectangleF_RectangleF_int (RectangleF a, int i) + { + return new RectangleF (a.X*i, a.Y+i, a.Width-i, a.Height/i); + } + + [Export ("testRectangleF_RectangleF_IntPtr:str:")] + public RectangleF Test_RectangleF_RectangleF_IntPtr (RectangleF a, NSString str) + { + float pi = ParseString (str.ToString ()); + if ((object) StringObj != (object) str) + return RectangleF.Empty; + return new RectangleF (a.X*pi, a.Y+pi, a.Width-pi, a.Height/pi); + } + + [Export ("testRectangleF_RectangleF_RectangleF_float:b:c:")] + public RectangleF Test_RectangleF_RectangleF_RectangleF_float (RectangleF a, RectangleF b, float c) + { + return new RectangleF (a.X*b.X*c, a.Y*b.Y*c, a.Width*b.Width*c, a.Height*b.Height*c); + } + + + [Export ("testRectangleF_RectangleF_RectangleF_RectangleF:b:c:")] + public RectangleF Test_RectangleF_RectangleF_RectangleF_RectangleF (RectangleF a, RectangleF b, RectangleF c) + { + return new RectangleF (a.X+b.X+c.X, a.Y+b.Y+c.Y, a.Width+b.Width+c.Width, a.Height+b.Height+c.Height); + } + + [Export ("testRectangleF_string_string_RectangleF:b:c:")] + public RectangleF Test_RectangleF_string_string_RectangleF (NSString a, NSString b, RectangleF c) + { + Assert.That (Is.Equals (a.ToString (), "a"), "#a"); + Assert.That (Is.Equals (b.ToString (), "b"), "#b"); + return new RectangleF (c.X * pi, c.Y * pi, c.Width * pi, c.Height * pi); + } + +#if !__WATCHOS__ + [Export ("testMatrix3")] + public Matrix3 Test_Matrix3 () + { + return new Matrix3 (1, 2, 3, 4, 5, 6, 7, 8, 9); + } + + [Export ("testMatrix4")] + public Matrix4 Test_Matrix4 () + { + return new Matrix4 (9, 8, 7, 6, 5, 4, 3, 2, 1, 9, 8, 7, 6, 5, 4, 3); + } + + [Export ("testCATransform3D")] + public CATransform3D Test_CATransform3D () + { + CATransform3D res = new CATransform3D (); + res.m11 = 11.1f; + res.m22 = 22.2f; + res.m33 = 33.3f; + res.m44 = 44.4f; + return res; + } +#endif // !__WATCHOS__ + + [Export ("testPointF")] + public PointF Test_PointF () + { + return new PointF (pi*2, pi*20); + } + + [Export ("testSizeF")] + public SizeF Test_SizeF () + { + return new SizeF (pi*3, pi*30); + } + + [Export ("Test_PointF_out_Double:")] + PointF Test_PointF_out_Double (out double foo) + { + foo = 3.18f; + return new PointF (1, 2); + } + + [Export ("Test_StaticPointF_out_Float:")] + static PointF Test_StaticPointF_out_Float (out float foo) + { + foo = 3.20f; + return new PointF (10, 20); + } + } +} diff --git a/tests/monotouch-test/Pacifico.ttf b/tests/monotouch-test/Pacifico.ttf new file mode 100755 index 000000000000..6d47cdc9acee Binary files /dev/null and b/tests/monotouch-test/Pacifico.ttf differ diff --git a/tests/monotouch-test/PassKit/AddPassesViewControllerTest.cs b/tests/monotouch-test/PassKit/AddPassesViewControllerTest.cs new file mode 100644 index 000000000000..2da48e9e1129 --- /dev/null +++ b/tests/monotouch-test/PassKit/AddPassesViewControllerTest.cs @@ -0,0 +1,67 @@ +// +// Unit tests for PKAddPassesViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using PassKit; +#else +using MonoTouch.Foundation; +using MonoTouch.PassKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.PassKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AddPassesViewControllerTest { + + [Test] + public void BoardingPass () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Phone) + Assert.Inconclusive ("PassKit does not work on iPads"); + + using (var pass = PassTest.GetBoardingPass ()) + using (var ctrl = new PKAddPassesViewController (pass)) { + ctrl.Finished += delegate { }; + // not available on iPad... + Assert.True ((ctrl.Delegate != null) == PKPassLibrary.IsAvailable, "Delegate"); + Assert.True ((ctrl.WeakDelegate != null) == PKPassLibrary.IsAvailable, "WeakDelegate"); + } + } + + [Test] + public void InitWithNibNameTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("initWithNibName:bundle: returns nil in iOS 6"); + + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Phone) + Assert.Inconclusive ("PassKit does not work on iPads"); + + PKAddPassesViewController ctrl = new PKAddPassesViewController (null, null); + Assert.NotNull (ctrl, "PKAddPassesViewController ctor(String, NSBundle)"); + + ctrl.Finished += delegate { }; + Assert.True ((ctrl.Delegate != null) == PKPassLibrary.IsAvailable, "Delegate"); + Assert.True ((ctrl.WeakDelegate != null) == PKPassLibrary.IsAvailable, "WeakDelegate"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/PassKit/ObjectTest.cs b/tests/monotouch-test/PassKit/ObjectTest.cs new file mode 100644 index 000000000000..f76f2a8a8165 --- /dev/null +++ b/tests/monotouch-test/PassKit/ObjectTest.cs @@ -0,0 +1,44 @@ +// +// Unit tests for PKObject +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using PassKit; +#else +using MonoTouch.Foundation; +using MonoTouch.PassKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.PassKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ObjectTest { + [Test] + public void Constructor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6, 0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + if (TestRuntime.CheckSystemAndSDKVersion (8, 0)) { + Assert.DoesNotThrow (() => new PKObject ()); + } else { + Assert.Throws (() => new PKObject ()); + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/PassKit/PassLibraryTest.cs b/tests/monotouch-test/PassKit/PassLibraryTest.cs new file mode 100644 index 000000000000..c7dd93932340 --- /dev/null +++ b/tests/monotouch-test/PassKit/PassLibraryTest.cs @@ -0,0 +1,81 @@ +// +// Unit tests for PKPassLibrary +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using PassKit; +#else +using MonoTouch.Foundation; +using MonoTouch.PassKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.PassKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PassLibraryTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + // this is yet another case where Apples plays ping-ping with different versions + // + // newsflash: iOS 8.1 says it's available but won't let you create a PKPassLibrary instance #24747 + // but iOS 8.2 (first beta) on an iPad let's you do it + // and final iOS 8.2 does not seems to return true anymore #28711 while 8.3 beta works !?! + if (!PKPassLibrary.IsAvailable) + Assert.Inconclusive ("PassKit is not available"); + + var library = new PKPassLibrary (); + // not null (but empty by default) and there's no API to add them + Assert.NotNull (library.GetPasses (), "GetPasses"); + + // and we can't trick the OS to do it for us + using (NSUrl url = new NSUrl (NSBundle.MainBundle.BundleUrl + "/BoardingPass.pkpass")) { +#if !__WATCHOS__ + Assert.False (UIApplication.SharedApplication.OpenUrl (url), "OpenUrl"); +#endif + } + + Assert.Null (library.GetPass (String.Empty, String.Empty), "GetPass"); + + using (var pass = PassTest.GetBoardingPass ()) { + Assert.False (library.Contains (pass), "Contains"); + Assert.False (library.Replace (pass), "Replace"); + library.Remove (pass); + } + } + + [Test] + public void Fields () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + Assert.That (PKPassLibraryUserInfoKey.AddedPasses.ToString (), Is.EqualTo ("PKPassLibraryAddedPassesUserInfo"), "AddedPassesUserInfoKey"); + Assert.That (PKPassLibraryUserInfoKey.RemovedPassInfos.ToString (), Is.EqualTo ("PKPassLibraryRemovedPassInfosUserInfo"), "RemovedPassInfosUserInfoKey"); + Assert.That (PKPassLibraryUserInfoKey.ReplacementPasses.ToString (), Is.EqualTo ("PKPassLibraryReplacementPassesUserInfo"), "ReplacementPassesUserInfoKey"); + Assert.That (PKPassLibrary.DidChangeNotification.ToString (), Is.EqualTo ("PKPassLibraryDidChangeNotification"), "DidChangeNotification"); + Assert.That (PKPassLibraryUserInfoKey.PassTypeIdentifier.ToString (), Is.EqualTo ("PKPassLibraryPassTypeIdentifierUserInfo"), "PassTypeIdentifierUserInfoKey"); + Assert.That (PKPassLibraryUserInfoKey.SerialNumber.ToString (), Is.EqualTo ("PKPassLibrarySerialNumberUserInfo"), "SerialNumberUserInfoKey"); + } + } +} + +#endif // !__TVOS__ + diff --git a/tests/monotouch-test/PassKit/PassTest.cs b/tests/monotouch-test/PassKit/PassTest.cs new file mode 100644 index 000000000000..e543ffcb141b --- /dev/null +++ b/tests/monotouch-test/PassKit/PassTest.cs @@ -0,0 +1,103 @@ +// +// Unit tests for PKPass +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using PassKit; +#else +using MonoTouch.Foundation; +using MonoTouch.PassKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.PassKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PassTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + using (PKPass pass = new PKPass ()) { + Assert.Null (pass.AuthenticationToken, "AuthenticationToken"); +#if !__WATCHOS__ + Assert.NotNull (pass.Icon, "Icon"); +#endif + Assert.Null (pass.LocalizedDescription, "LocalizedDescription"); + Assert.That (pass.LocalizedName, Is.EqualTo ("Coupon"), "LocalizedName"); + Assert.Null (pass.OrganizationName, "OrganizationName"); + Assert.Null (pass.PassTypeIdentifier, "PassTypeIdentifier"); + Assert.Null (pass.PassUrl, "PassUrl"); + Assert.Null (pass.RelevantDate, "RelevantDate"); + Assert.Null (pass.SerialNumber, "SerialNumber"); + Assert.Null (pass.WebServiceUrl, "WebServiceUrl"); + } + } + + static public PKPass GetBoardingPass () + { + using (NSUrl url = new NSUrl (NSBundle.MainBundle.BundleUrl + "/BoardingPass.pkpass")) + using (NSData data = NSData.FromUrl (url)) { + NSError error; + PKPass pass = new PKPass (data, out error); + Assert.Null (error, "error"); + return pass; + } + } + + [Test] + public void BoardingPass () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + using (var pass = GetBoardingPass ()) { + Assert.That (pass.AuthenticationToken, Is.EqualTo ("vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzFdc"), "AuthenticationToken"); +#if !__WATCHOS__ + Assert.NotNull (pass.Icon, "Icon"); +#endif + + // need to ensure it's english locale + Assert.That (pass.LocalizedDescription, Is.EqualTo ("Skyport Boarding Pass"), "LocalizedDescription"); + Assert.That (pass.LocalizedName, Is.EqualTo ("Boarding Pass"), "LocalizedName"); + + Assert.That (pass.OrganizationName, Is.EqualTo ("Skyport Airways"), "OrganizationName"); + Assert.That (pass.PassTypeIdentifier, Is.EqualTo ("pass.com.apple.devpubs.example"), "PassTypeIdentifier"); + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.That (pass.PassUrl.AbsoluteString, Is.EqualTo ("shoebox://card/1UuiGnfwxHgd0G0bIuPYPNpeRX8="), "PassUrl"); + else + Assert.Null (pass.PassUrl, "PassUrl"); + Assert.That (pass.RelevantDate.SecondsSinceReferenceDate, Is.EqualTo (364688700), "RelevantDate"); + Assert.That (pass.SerialNumber, Is.EqualTo ("gT6zrHkaW"), "SerialNumber"); + Assert.That (pass.WebServiceUrl.AbsoluteString, Is.EqualTo ("https://example.com/passes/"), "WebServiceUrl"); + } + } + + [Test] + public void Fields () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("PassKit is new in 6.0"); + + Assert.That (PKPass.ErrorDomain.ToString (), Is.EqualTo ("PKPassKitErrorDomain"), "ErrorDomain"); + } + } +} + +#endif // !__TVOS__ + diff --git a/tests/monotouch-test/Photos/FetchResultTest.cs b/tests/monotouch-test/Photos/FetchResultTest.cs new file mode 100644 index 000000000000..af3d1c91a448 --- /dev/null +++ b/tests/monotouch-test/Photos/FetchResultTest.cs @@ -0,0 +1,158 @@ +// +// Unit tests for FetchResult +// +// Authors: +// Alex Soto +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Linq; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +using Photos; +using CoreGraphics; +using AssetsLibrary; +using RectangleF = CoreGraphics.CGRect; +using SizeF = CoreGraphics.CGSize; +using PointF = CoreGraphics.CGPoint; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouch.Photos; +using System.Drawing; +using MonoTouch.AssetsLibrary; +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Photos { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FetchResultTest { + + [Test] + public void FetchResultToArray () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8 or later"); + + if (ALAssetsLibrary.AuthorizationStatus != ALAuthorizationStatus.Authorized) + Assert.Inconclusive ("Requires access to the photo library"); + + var collection = PHAsset.FetchAssets (PHAssetMediaType.Image, null); + if (collection.Count == 0) { + XamagramImage.Image.SaveToPhotosAlbum (null); + collection = PHAsset.FetchAssets (PHAssetMediaType.Image, null); + } + + // Actual Test + var array = collection.ToArray (); + Assert.That (array != null && array.Count() > 0); + } + + [Test] + public void FetchResultIndex () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8 or later"); + + if (ALAssetsLibrary.AuthorizationStatus != ALAuthorizationStatus.Authorized) + Assert.Inconclusive ("Requires access to the photo library"); + + var collection = PHAsset.FetchAssets (PHAssetMediaType.Image, null); + if (collection.Count == 0) { + XamagramImage.Image.SaveToPhotosAlbum (null); + collection = PHAsset.FetchAssets (PHAssetMediaType.Image, null); + } + + // Actual Test + var obj = collection [0]; + Assert.IsNotNull (obj); + } + + [Test] + public void FetchResultObjectsAt () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8 or later"); + + if (ALAssetsLibrary.AuthorizationStatus != ALAuthorizationStatus.Authorized) + Assert.Inconclusive ("Requires access to the photo library"); + + var collection = PHAsset.FetchAssets (PHAssetMediaType.Image, null); + if (collection.Count == 0) { + XamagramImage.Image.SaveToPhotosAlbum (null); + collection = PHAsset.FetchAssets (PHAssetMediaType.Image, null); + } + + // Actual Test + var obj = collection.ObjectsAt (NSIndexSet.FromNSRange (new NSRange (0, 1))); + Assert.That (obj != null && obj.Count() > 0); + } + } + + // This class is only used in case the Photo Library is Empty, + // this will create a blue Xamagram logo + static class XamagramImage + { + static UIImage imageOfXamagram; + + static void DrawXamagram() + { + var context = UIGraphics.GetCurrentContext (); + var color = UIColor.FromRGBA (0.204f, 0.600f, 0.863f, 1.000f); + + context.SaveState (); + context.TranslateCTM (257.0f, 257.0f); + context.RotateCTM (90.0f * (nfloat)Math.PI / 180.0f); + + var polygonPath = new UIBezierPath(); + polygonPath.MoveTo (new PointF (0.0f, -250.0f)); + polygonPath.AddLineTo (new PointF (216.51f, -125.0f)); + polygonPath.AddLineTo (new PointF (216.51f, 125.0f)); + polygonPath.AddLineTo (new PointF (0.0f, 250.0f)); + polygonPath.AddLineTo (new PointF (-216.51f, 125.0f)); + polygonPath.AddLineTo (new PointF (-216.51f, -125.0f)); + polygonPath.ClosePath (); + color.SetFill (); + polygonPath.Fill (); + + context.RestoreState(); + + var textRect = new RectangleF (0.0f, 0.0f, 512.0f, 512.0f); + var textContent = "X"; + UIColor.White.SetFill (); + var textFont = UIFont.FromName ("Helvetica", 350.0f); + textRect.Offset (0.0f, (textRect.Height - new NSString (textContent).StringSize (textFont, textRect.Size).Height) / 2.0f); + new NSString (textContent).DrawString (textRect, textFont, UILineBreakMode.WordWrap, UITextAlignment.Center); + } + + public static UIImage Image + { + get + { + if (imageOfXamagram != null) + return imageOfXamagram; + + UIGraphics.BeginImageContextWithOptions (new SizeF (512.0f, 512.0f), false, 0); + DrawXamagram (); + imageOfXamagram = UIGraphics.GetImageFromCurrentImageContext (); + UIGraphics.EndImageContext (); + + return imageOfXamagram; + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/Photos/PhotoLibraryTest.cs b/tests/monotouch-test/Photos/PhotoLibraryTest.cs new file mode 100644 index 000000000000..f9eb9c7a5e61 --- /dev/null +++ b/tests/monotouch-test/Photos/PhotoLibraryTest.cs @@ -0,0 +1,11 @@ +using System; +namespace monotouchtest +{ + public class PhotoLibraryTest + { + public PhotoLibraryTest () + { + } + } +} + diff --git a/tests/monotouch-test/PushKit/PushRegistryTest.cs b/tests/monotouch-test/PushKit/PushRegistryTest.cs new file mode 100644 index 000000000000..58de5c1737cc --- /dev/null +++ b/tests/monotouch-test/PushKit/PushRegistryTest.cs @@ -0,0 +1,48 @@ +// Copyright 2015 Xamarin Inc. + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreFoundation; +using Foundation; +using PushKit; +using UIKit; +#else +using MonoTouch.CoreFoundation; +using MonoTouch.Foundation; +using MonoTouch.PushKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.PushKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PushRegistryTest { + + [Test] + public void CtorDispatchQueue () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) + Assert.Inconclusive ("Requires iOS8 or later"); + + if (!UIDevice.CurrentDevice.CheckSystemVersion (8, 2) && IntPtr.Size == 4) + Assert.Inconclusive ("Requires iOS 8.2 or later in 32-bit mode."); + + using (var dq = new DispatchQueue ("pk-test-queue")) + using (var pr = new PKPushRegistry (dq)) { + Assert.Null (pr.Delegate, "Delegate"); + Assert.Null (pr.DesiredPushTypes, "DesiredPushTypes"); + Assert.Null (pr.WeakDelegate, "WeakDelegate"); + + // it's nullable (setting a value needs more app setup or ObjC exceptions will occurs later) + pr.DesiredPushTypes = null; + Assert.Null (pr.DesiredPushTypes, "DesiredPushTypes-2"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/QuickLook/PreviewControllerTest.cs b/tests/monotouch-test/QuickLook/PreviewControllerTest.cs new file mode 100644 index 000000000000..eece63371f41 --- /dev/null +++ b/tests/monotouch-test/QuickLook/PreviewControllerTest.cs @@ -0,0 +1,85 @@ +// +// Unit tests for QLPreviewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using QuickLook; +#else +using MonoTouch.Foundation; +using MonoTouch.QuickLook; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.QuickLook { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PreviewControllerTest { + + [Test] + public void Defaults () + { + using (QLPreviewController pc = new QLPreviewController ()) { + Assert.Null (pc.CurrentPreviewItem, "CurrentPreviewItem"); + nint index = UIDevice.CurrentDevice.CheckSystemVersion (7, 1) ? -1 : 0; + Assert.That (pc.CurrentPreviewItemIndex, Is.EqualTo (index), "CurrentPreviewItemIndex"); + + Assert.Null (pc.Delegate, "Delegate"); + Assert.Null (pc.WeakDelegate, "WeakDelegate"); + + Assert.Null (pc.DataSource, "DataSource"); + Assert.Null (pc.WeakDataSource, "WeakDataSource"); + + pc.RefreshCurrentPreviewItem (); + pc.ReloadData (); + } + } + + [Test] + public void DelegateEvents () + { + using (QLPreviewController pc = new QLPreviewController ()) { +#if XAMCORE_2_0 + pc.ShouldOpenUrl += delegate (QLPreviewController controller, NSUrl url, IQLPreviewItem item) { +#else + pc.ShouldOpenUrl += delegate (QLPreviewController controller, NSUrl url, QLPreviewItem item) { +#endif + return false; + }; + pc.FrameForPreviewItem += delegate { + return new RectangleF (1, 2, 3, 4); + }; + pc.TransitionImageForPreviewItem += delegate { + return new UIImage (); + }; + + Assert.NotNull (pc.Delegate, "Delegate"); + Assert.NotNull (pc.WeakDelegate, "WeakDelegate"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/Resources/xamarin0.png b/tests/monotouch-test/Resources/xamarin0.png new file mode 100644 index 000000000000..9cbe189939a5 Binary files /dev/null and b/tests/monotouch-test/Resources/xamarin0.png differ diff --git a/tests/monotouch-test/Resources/xamarin1.png b/tests/monotouch-test/Resources/xamarin1.png new file mode 100644 index 000000000000..9874955dd098 Binary files /dev/null and b/tests/monotouch-test/Resources/xamarin1.png differ diff --git a/tests/monotouch-test/Resources/xamarin2.png b/tests/monotouch-test/Resources/xamarin2.png new file mode 100644 index 000000000000..1a51d34f6f33 Binary files /dev/null and b/tests/monotouch-test/Resources/xamarin2.png differ diff --git a/tests/monotouch-test/SafariServices/ReadingListTest.cs b/tests/monotouch-test/SafariServices/ReadingListTest.cs new file mode 100644 index 000000000000..c0313d8f0f02 --- /dev/null +++ b/tests/monotouch-test/SafariServices/ReadingListTest.cs @@ -0,0 +1,82 @@ +// +// Unit tests for SSReadingList +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using SafariServices; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SafariServices; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SafariServices { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ReadingListTest { + + string local_file = Path.Combine (NSBundle.MainBundle.ResourcePath, "Hand.wav"); + + [Test] + public void DefaultReadingList () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + NSError error; + using (var http = new NSUrl ("http://www.xamarin.com")) + using (var local = new NSUrl (local_file, false)) + using (var rl = SSReadingList.DefaultReadingList) { + Assert.True (rl.Add (http, "title", "preview text", out error), "Add-1"); + Assert.Null (error, "error-1"); + + Assert.True (rl.Add (http, null, null, out error), "Add-2"); + Assert.Null (error, "error-2"); + + Assert.False (rl.Add (local, null, null, out error), "Add-3"); + Assert.That (error.Domain, Is.EqualTo ((string) SSReadingList.ErrorDomain), "Domain"); + Assert.That (error.Code, Is.EqualTo ((nint) (int) SSReadingListError.UrlSchemeNotAllowed), "Code"); + } + } + + [Test] + public void SupportsUrl () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + Assert.False (SSReadingList.SupportsUrl (null), "null"); + + using (var http = new NSUrl ("http://www.xamarin.com")) + Assert.True (SSReadingList.SupportsUrl (http), "http"); + + using (var local = new NSUrl (local_file, false)) + Assert.False (SSReadingList.SupportsUrl (local), "local"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/SceneKit/GeometrySourceTest.cs b/tests/monotouch-test/SceneKit/GeometrySourceTest.cs new file mode 100644 index 000000000000..2e27ec983142 --- /dev/null +++ b/tests/monotouch-test/SceneKit/GeometrySourceTest.cs @@ -0,0 +1,60 @@ +// Copyright 2015 Xamarin Inc. All rights reserved. + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using Metal; +using ObjCRuntime; +using SceneKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.Metal; +using MonoTouch.ObjCRuntime; +using MonoTouch.SceneKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SceneKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GeometrySourceTest { + + [Test] + public void FromMetalBuffer () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.Inconclusive ("iOS 9+ required"); + if (Runtime.Arch != Arch.DEVICE) + Assert.Inconclusive ("Metal tests only works on device so far"); + + var device = MTLDevice.SystemDefault; + if (device == null) + Assert.Inconclusive ("Device does not support Metal"); + + using (var buffer = device.CreateBuffer (1024, MTLResourceOptions.CpuCacheModeDefault)) { + using (var source = SCNGeometrySource.FromMetalBuffer (buffer, MTLVertexFormat.Char2, SCNGeometrySourceSemantic.Vertex, 36, 0, 0)) { + // the fact that it works means the lack of respondToSelector (in introspection tests) is no + // big deal and that the API really exists + Assert.NotNull (source); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SceneKit/NodeTest.cs b/tests/monotouch-test/SceneKit/NodeTest.cs new file mode 100644 index 000000000000..290566829036 --- /dev/null +++ b/tests/monotouch-test/SceneKit/NodeTest.cs @@ -0,0 +1,61 @@ +// +// Unit tests for SCNNode +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreAnimation; +using Foundation; +using SceneKit; +using UIKit; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +using MonoTouch.SceneKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SceneKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NodeTest { + + [Test] + public void AddAnimation () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Ignore ("Requires iOS8"); + + using (var a = CAAnimation.CreateAnimation ()) + using (var n = SCNNode.Create ()) { + n.AddAnimation (a, (NSString) null); + n.AddAnimation (a, (string) null); + string key = "key"; + n.AddAnimation (a, key); + using (var s = new NSString (key)) + n.AddAnimation (a, key); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SceneKit/StructTest.cs b/tests/monotouch-test/SceneKit/StructTest.cs new file mode 100644 index 000000000000..94b45ea64f9c --- /dev/null +++ b/tests/monotouch-test/SceneKit/StructTest.cs @@ -0,0 +1,123 @@ +// +// Unit tests for SCN* structures +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreAnimation; +using Foundation; +using SceneKit; +using UIKit; +#else +using MonoTouch.CoreAnimation; +using MonoTouch.Foundation; +using MonoTouch.SceneKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SceneKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class StructTest { + + [Test] + public void Matrix () + { + var id = SCNMatrix4.Identity; +#if !XAMCORE_2_0 + var m = new SCNMatrix4 (); + // that was possible in classic - but will now trigger a CS0198 + SCNMatrix4.Identity = m; +#else + id.M11 = 2; +#endif + Assert.That (SCNMatrix4.Identity, Is.Not.EqualTo (id), "Identity"); + } + + [Test] + public void Quaternion () + { + var id = SCNQuaternion.Identity; +#if !XAMCORE_2_0 + var q = new SCNQuaternion (); + // that was possible in classic - but will now trigger a CS0198 + SCNQuaternion.Identity = q; +#else + id.W = 2; +#endif + Assert.That (SCNQuaternion.Identity, Is.Not.EqualTo (id), "Identity"); + } + + [Test] + public void Vector () + { + var v = new SCNVector4 (); + var u = SCNVector4.UnitX; +#if !XAMCORE_2_0 + // that was possible in classic - but will now trigger a CS0198 + SCNVector4.UnitX = v; +#else + u.X = 2; +#endif + Assert.That (SCNVector4.UnitX, Is.Not.EqualTo (u), "UnitX"); + + u = SCNVector4.UnitY; +#if !XAMCORE_2_0 + // that was possible in classic - but will now trigger a CS0198 + SCNVector4.UnitY = v; +#else + u.Y = 2; +#endif + Assert.That (SCNVector4.UnitY, Is.Not.EqualTo (u), "UnitY"); + + u = SCNVector4.UnitZ; +#if !XAMCORE_2_0 + // that was possible in classic - but will now trigger a CS0198 + SCNVector4.UnitZ = v; +#else + u.Z = 2; +#endif + Assert.That (SCNVector4.UnitZ, Is.Not.EqualTo (u), "UnitZ"); + + u = SCNVector4.UnitW; +#if !XAMCORE_2_0 + // that was possible in classic - but will now trigger a CS0198 + SCNVector4.UnitW = v; +#else + u.W = 2; +#endif + Assert.That (SCNVector4.UnitW, Is.Not.EqualTo (u), "UnitW"); + + u = SCNVector4.Zero; +#if !XAMCORE_2_0 + // that was possible in classic - but will now trigger a CS0198 + SCNVector4.Zero = v; + Assert.That (SCNVector4.Zero, Is.EqualTo (u), "Zero"); +#else + u.W = 2; + Assert.That (SCNVector4.Zero, Is.Not.EqualTo (u), "Zero"); +#endif + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/Security/CertificateTest.cs b/tests/monotouch-test/Security/CertificateTest.cs new file mode 100644 index 000000000000..9c9db62ff54f --- /dev/null +++ b/tests/monotouch-test/Security/CertificateTest.cs @@ -0,0 +1,573 @@ +// +// SecCertificate Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. +// + +using System; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +#if XAMCORE_2_0 +using Foundation; +using Security; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class CertificateTest { + + // CN=mail.google.com, O=Google Inc, L=Mountain View, S=California, C=US + static public byte[] mail_google_com = { + 0x30, 0x82, 0x03, 0x22, 0x30, 0x82, 0x02, 0x8b, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x10, 0x2b, 0x9f, 0x7e, 0xe5, 0xca, 0x25, 0xa6, 0x25, 0x14, + 0x20, 0x47, 0x82, 0x75, 0x3a, 0x9b, 0xb9, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, + 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, + 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, + 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, + 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, + 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x33, 0x30, 0x39, 0x33, 0x30, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, + 0x30, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x14, 0x0d, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x0a, 0x47, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x0f, 0x6d, 0x61, 0x69, 0x6c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, + 0x02, 0x81, 0x81, 0x00, 0xaf, 0x39, 0x15, 0x98, 0x68, 0xe4, 0x92, 0xfe, + 0x4f, 0x4f, 0xf1, 0xbb, 0xff, 0x0d, 0x2e, 0xb0, 0xfe, 0x25, 0xaa, 0xbd, + 0x68, 0x04, 0x67, 0x27, 0xea, 0x6c, 0x43, 0x4c, 0xa7, 0x6d, 0xcb, 0xc8, + 0x8f, 0x7e, 0x81, 0xee, 0x87, 0x26, 0x25, 0x10, 0x12, 0x54, 0x33, 0x9e, + 0xaa, 0x3d, 0x9b, 0x8f, 0x8e, 0x92, 0xb3, 0x4b, 0x01, 0xe3, 0xf9, 0x4a, + 0x29, 0xc3, 0x0f, 0xfd, 0xac, 0xb7, 0xd3, 0x4c, 0x97, 0x29, 0x3f, 0x69, + 0x55, 0xcf, 0x70, 0x83, 0x04, 0xaf, 0x2e, 0x04, 0x6e, 0x74, 0xd6, 0x0f, + 0x17, 0x09, 0xfe, 0x9e, 0x20, 0x24, 0x24, 0xe3, 0xc7, 0x68, 0x9c, 0xac, + 0x11, 0xbd, 0x92, 0xe4, 0xb2, 0x1b, 0x09, 0xf2, 0x02, 0x32, 0xbb, 0x55, + 0x1b, 0x2d, 0x16, 0x5f, 0x30, 0x12, 0x23, 0xe2, 0x4c, 0x4a, 0x8d, 0xc2, + 0xda, 0x3f, 0xe1, 0xb8, 0xbf, 0xf7, 0x3a, 0xb1, 0x86, 0xbe, 0xf0, 0xc5, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, + 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x28, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x04, 0x01, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30, 0x22, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, + 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x68, 0x61, 0x77, + 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x5f, 0x53, 0x47, 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x35, 0x80, 0x11, 0xcd, 0x52, 0x3e, + 0x84, 0x29, 0xfb, 0xc1, 0x28, 0xe1, 0x20, 0xe5, 0x02, 0x8f, 0x5f, 0x71, + 0x65, 0x58, 0x1d, 0x62, 0x72, 0x57, 0x3c, 0xe6, 0x5e, 0x25, 0x61, 0xd3, + 0xcb, 0xad, 0x22, 0xf8, 0xd8, 0x81, 0xa4, 0xe7, 0xf4, 0xae, 0x7c, 0xd9, + 0xc1, 0x6d, 0xaa, 0x93, 0x0d, 0x62, 0x07, 0x9f, 0xf2, 0x67, 0x47, 0x99, + 0x34, 0x33, 0x4f, 0x3d, 0x02, 0x74, 0xf4, 0x81, 0xd6, 0x38, 0x08, 0x21, + 0xe8, 0xe2, 0xa1, 0xfa, 0x05, 0x41, 0x9c, 0x9c, 0xc9, 0xf9, 0xf3, 0xc8, + 0xa3, 0xee, 0x0d, 0xa5, 0xd7, 0x50, 0x54, 0x5e, 0x2f, 0x7d, 0x79, 0xb7, + 0x7e, 0x0a, 0x7c, 0xb6, 0xe2, 0x2c, 0xa8, 0xae, 0xfe, 0x94, 0xd7, 0xcd, + 0x16, 0x30, 0x71, 0x04, 0xaa, 0x9e, 0x79, 0xc3, 0xd2, 0xb6, 0x24, 0xa7, + 0x25, 0xab, 0xf0, 0x48, 0x8e, 0x2f, 0xc3, 0xa7, 0xbb, 0x50, 0xdd, 0x0f, + 0xcf, 0xb0, }; + + // CN=Thawte SGC CA, O=Thawte Consulting (Pty) Ltd., C=ZA + static public byte[] thawte_sgc_ca = { + 0x30, 0x82, 0x03, 0x23, 0x30, 0x82, 0x02, 0x8c, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x04, 0x30, 0x00, 0x00, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, + 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, + 0x1e, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x35, 0x31, 0x33, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x31, 0x32, + 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x4c, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54, 0x68, 0x61, + 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, + 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, + 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, 0x43, 0x20, 0x43, + 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, + 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xd3, 0x67, 0xd0, 0x8d, 0x15, + 0x7f, 0xae, 0xcd, 0x31, 0xfe, 0x7d, 0x1d, 0x91, 0xa1, 0x3f, 0x0b, 0x71, + 0x3c, 0xac, 0xcc, 0xc8, 0x64, 0xfb, 0x63, 0xfc, 0x32, 0x4b, 0x07, 0x94, + 0xbd, 0x6f, 0x80, 0xba, 0x2f, 0xe1, 0x04, 0x93, 0xc0, 0x33, 0xfc, 0x09, + 0x33, 0x23, 0xe9, 0x0b, 0x74, 0x2b, 0x71, 0xc4, 0x03, 0xc6, 0xd2, 0xcd, + 0xe2, 0x2f, 0xf5, 0x09, 0x63, 0xcd, 0xff, 0x48, 0xa5, 0x00, 0xbf, 0xe0, + 0xe7, 0xf3, 0x88, 0xb7, 0x2d, 0x32, 0xde, 0x98, 0x36, 0xe6, 0x0a, 0xad, + 0x00, 0x7b, 0xc4, 0x64, 0x4a, 0x3b, 0x84, 0x75, 0x03, 0xf2, 0x70, 0x92, + 0x7d, 0x0e, 0x62, 0xf5, 0x21, 0xab, 0x69, 0x36, 0x84, 0x31, 0x75, 0x90, + 0xf8, 0xbf, 0xc7, 0x6c, 0x88, 0x1b, 0x06, 0x95, 0x7c, 0xc9, 0xe5, 0xa8, + 0xde, 0x75, 0xa1, 0x2c, 0x7a, 0x68, 0xdf, 0xd5, 0xca, 0x1c, 0x87, 0x58, + 0x60, 0x19, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, + 0xfb, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x11, + 0x04, 0x21, 0x30, 0x1f, 0xa4, 0x1d, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x50, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x33, 0x2d, 0x31, 0x35, 0x30, + 0x31, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2a, 0x30, 0x28, 0x30, 0x26, + 0xa0, 0x24, 0xa0, 0x22, 0x86, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, 0x61, 0x33, 0x2e, 0x63, + 0x72, 0x6c, 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77, + 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x34, 0x06, 0x03, 0x55, 0x1d, + 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, + 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01, + 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, 0x01, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x55, 0xac, 0x63, 0xea, 0xde, + 0xa1, 0xdd, 0xd2, 0x90, 0x5f, 0x9f, 0x0b, 0xce, 0x76, 0xbe, 0x13, 0x51, + 0x8f, 0x93, 0xd9, 0x05, 0x2b, 0xc8, 0x1b, 0x77, 0x4b, 0xad, 0x69, 0x50, + 0xa1, 0xee, 0xde, 0xdc, 0xfd, 0xdb, 0x07, 0xe9, 0xe8, 0x39, 0x94, 0xdc, + 0xab, 0x72, 0x79, 0x2f, 0x06, 0xbf, 0xab, 0x81, 0x70, 0xc4, 0xa8, 0xed, + 0xea, 0x53, 0x34, 0xed, 0xef, 0x1e, 0x53, 0xd9, 0x06, 0xc7, 0x56, 0x2b, + 0xd1, 0x5c, 0xf4, 0xd1, 0x8a, 0x8e, 0xb4, 0x2b, 0xb1, 0x37, 0x90, 0x48, + 0x08, 0x42, 0x25, 0xc5, 0x3e, 0x8a, 0xcb, 0x7f, 0xeb, 0x6f, 0x04, 0xd1, + 0x6d, 0xc5, 0x74, 0xa2, 0xf7, 0xa2, 0x7c, 0x7b, 0x60, 0x3c, 0x77, 0xcd, + 0x0e, 0xce, 0x48, 0x02, 0x7f, 0x01, 0x2f, 0xb6, 0x9b, 0x37, 0xe0, 0x2a, + 0x2a, 0x36, 0xdc, 0xd5, 0x85, 0xd6, 0xac, 0xe5, 0x3f, 0x54, 0x6f, 0x96, + 0x1e, 0x05, 0xaf, }; + + // OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C + static public byte[] verisign_class3_root = { + 0x30, 0x82, 0x02, 0x3c, 0x30, 0x82, 0x01, 0xa5, 0x02, 0x10, 0x3c, 0x91, + 0x31, 0xcb, 0x1f, 0xf6, 0xd0, 0x1b, 0x0e, 0x9a, 0xb8, 0xd0, 0x44, 0xbf, + 0x12, 0xbe, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, + 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37, 0x30, + 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x33, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, + 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x36, + 0x30, 0x31, 0x32, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, + 0x0d, 0x32, 0x38, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, + 0x39, 0x5a, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, + 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x5c, 0x59, 0x9e, + 0xf2, 0x1b, 0x8a, 0x01, 0x14, 0xb4, 0x10, 0xdf, 0x04, 0x40, 0xdb, 0xe3, + 0x57, 0xaf, 0x6a, 0x45, 0x40, 0x8f, 0x84, 0x0c, 0x0b, 0xd1, 0x33, 0xd9, + 0xd9, 0x11, 0xcf, 0xee, 0x02, 0x58, 0x1f, 0x25, 0xf7, 0x2a, 0xa8, 0x44, + 0x05, 0xaa, 0xec, 0x03, 0x1f, 0x78, 0x7f, 0x9e, 0x93, 0xb9, 0x9a, 0x00, + 0xaa, 0x23, 0x7d, 0xd6, 0xac, 0x85, 0xa2, 0x63, 0x45, 0xc7, 0x72, 0x27, + 0xcc, 0xf4, 0x4c, 0xc6, 0x75, 0x71, 0xd2, 0x39, 0xef, 0x4f, 0x42, 0xf0, + 0x75, 0xdf, 0x0a, 0x90, 0xc6, 0x8e, 0x20, 0x6f, 0x98, 0x0f, 0xf8, 0xac, + 0x23, 0x5f, 0x70, 0x29, 0x36, 0xa4, 0xc9, 0x86, 0xe7, 0xb1, 0x9a, 0x20, + 0xcb, 0x53, 0xa5, 0x85, 0xe7, 0x3d, 0xbe, 0x7d, 0x9a, 0xfe, 0x24, 0x45, + 0x33, 0xdc, 0x76, 0x15, 0xed, 0x0f, 0xa2, 0x71, 0x64, 0x4c, 0x65, 0x2e, + 0x81, 0x68, 0x45, 0xa7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x10, 0x72, 0x52, 0xa9, 0x05, 0x14, 0x19, 0x32, + 0x08, 0x41, 0xf0, 0xc5, 0x6b, 0x0a, 0xcc, 0x7e, 0x0f, 0x21, 0x19, 0xcd, + 0xe4, 0x67, 0xdc, 0x5f, 0xa9, 0x1b, 0xe6, 0xca, 0xe8, 0x73, 0x9d, 0x22, + 0xd8, 0x98, 0x6e, 0x73, 0x03, 0x61, 0x91, 0xc5, 0x7c, 0xb0, 0x45, 0x40, + 0x6e, 0x44, 0x9d, 0x8d, 0xb0, 0xb1, 0x96, 0x74, 0x61, 0x2d, 0x0d, 0xa9, + 0x45, 0xd2, 0xa4, 0x92, 0x2a, 0xd6, 0x9a, 0x75, 0x97, 0x6e, 0x3f, 0x53, + 0xfd, 0x45, 0x99, 0x60, 0x1d, 0xa8, 0x2b, 0x4c, 0xf9, 0x5e, 0xa7, 0x09, + 0xd8, 0x75, 0x30, 0xd7, 0xd2, 0x65, 0x60, 0x3d, 0x67, 0xd6, 0x48, 0x55, + 0x75, 0x69, 0x3f, 0x91, 0xf5, 0x48, 0x0b, 0x47, 0x69, 0x22, 0x69, 0x82, + 0x96, 0xbe, 0xc9, 0xc8, 0x38, 0x86, 0x4a, 0x7a, 0x2c, 0x73, 0x19, 0x48, + 0x69, 0x4e, 0x6b, 0x7c, 0x65, 0xbf, 0x0f, 0xfc, 0x70, 0xce, 0x88, 0x90, }; + + // CN=api.imgur.com, OU=Domain Control Validated - QuickSSL(R) Premium, OU=See www.geotrust.com/resources/cps (c)11, OU=GT13382594, O=api.imgur.com, C=US, SERIALNUMBER=Jj-6wNiUyc1j1w-dsJtowuRbij10QwfE + public static byte[] api_imgur_com = { + 0x30, 0x82, 0x04, 0xf1, 0x30, 0x82, 0x03, 0xd9, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x03, 0x02, 0x5d, 0x8d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x61, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, + 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x14, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x20, 0x53, 0x53, 0x4c, 0x31, 0x1b, 0x30, 0x19, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x44, 0x56, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x38, 0x30, 0x32, 0x30, 0x32, + 0x31, 0x33, 0x32, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x38, 0x30, + 0x33, 0x31, 0x30, 0x33, 0x39, 0x34, 0x31, 0x5a, 0x30, 0x81, 0xe9, 0x31, + 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x20, 0x4a, 0x6a, + 0x2d, 0x36, 0x77, 0x4e, 0x69, 0x55, 0x79, 0x63, 0x31, 0x6a, 0x31, 0x77, + 0x2d, 0x64, 0x73, 0x4a, 0x74, 0x6f, 0x77, 0x75, 0x52, 0x62, 0x69, 0x6a, + 0x31, 0x30, 0x51, 0x77, 0x66, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x61, 0x70, 0x69, 0x2e, 0x69, 0x6d, + 0x67, 0x75, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x54, 0x31, 0x33, 0x33, 0x38, + 0x32, 0x35, 0x39, 0x34, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x67, + 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x70, + 0x73, 0x20, 0x28, 0x63, 0x29, 0x31, 0x31, 0x31, 0x37, 0x30, 0x35, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, + 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x20, 0x2d, 0x20, 0x51, 0x75, 0x69, + 0x63, 0x6b, 0x53, 0x53, 0x4c, 0x28, 0x52, 0x29, 0x20, 0x50, 0x72, 0x65, + 0x6d, 0x69, 0x75, 0x6d, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0d, 0x61, 0x70, 0x69, 0x2e, 0x69, 0x6d, 0x67, 0x75, 0x72, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xa1, 0xc7, 0x69, 0xcd, 0xdb, 0xe1, 0x97, 0xbc, 0xba, 0xae, 0x21, + 0x8c, 0x08, 0x67, 0x4c, 0xce, 0xfa, 0x51, 0xbe, 0x67, 0xe6, 0x7e, 0xca, + 0xa8, 0xc4, 0x0f, 0xc9, 0x39, 0x42, 0xa7, 0xa8, 0x99, 0x32, 0xab, 0x24, + 0x50, 0x15, 0xdc, 0xec, 0xdc, 0xa5, 0xbb, 0xc3, 0x08, 0xf8, 0x5d, 0x16, + 0x8c, 0x3a, 0x17, 0x04, 0x90, 0xfb, 0xdf, 0xd4, 0x13, 0x88, 0x63, 0x7b, + 0xfd, 0x54, 0x2f, 0x69, 0xf3, 0x42, 0x00, 0xf9, 0x11, 0x8b, 0x9c, 0x31, + 0x3c, 0xb9, 0xb7, 0x9a, 0xc4, 0xa9, 0xf8, 0xc4, 0x45, 0x02, 0x73, 0x31, + 0xe8, 0x0a, 0x59, 0xbc, 0x58, 0x65, 0x51, 0x64, 0x65, 0x8e, 0xc0, 0xa8, + 0xa8, 0xaa, 0xd1, 0x35, 0x3f, 0x33, 0x05, 0x85, 0xb3, 0x8b, 0x30, 0x92, + 0x3d, 0x24, 0x2c, 0x7c, 0x5c, 0x65, 0x54, 0x57, 0xdf, 0xf2, 0x1b, 0x93, + 0xc0, 0xd8, 0x09, 0xfb, 0x36, 0xdb, 0xfd, 0x27, 0x6c, 0x51, 0xad, 0x44, + 0xa3, 0xb7, 0xd9, 0xa0, 0x68, 0x31, 0xd3, 0x03, 0xc9, 0x91, 0x4f, 0x55, + 0x1e, 0x77, 0x27, 0xec, 0x2d, 0xe3, 0x66, 0x1e, 0xc2, 0x28, 0x37, 0x80, + 0x17, 0xfa, 0xf4, 0xbb, 0xaa, 0x19, 0x91, 0x9f, 0x06, 0xd7, 0xcf, 0x68, + 0xba, 0x8e, 0x22, 0x0e, 0x99, 0x56, 0xe7, 0xf0, 0x72, 0x0d, 0xaa, 0xeb, + 0x4b, 0xae, 0xf6, 0xd4, 0x27, 0x35, 0x5c, 0x08, 0xfa, 0xef, 0x7e, 0xa3, + 0xd9, 0x4d, 0xb6, 0x85, 0x47, 0x1f, 0x3e, 0x14, 0xaa, 0x6a, 0x14, 0xc9, + 0xec, 0x4a, 0x2d, 0x0a, 0x45, 0xd8, 0xc2, 0x54, 0x2e, 0x2d, 0xf2, 0xf1, + 0x38, 0x65, 0x5e, 0x94, 0x29, 0x65, 0x4a, 0xbd, 0x85, 0xc1, 0x65, 0x28, + 0xcb, 0x2a, 0xd2, 0x39, 0xc9, 0xd6, 0xb7, 0x79, 0x3a, 0x10, 0x50, 0xf0, + 0xf6, 0xe2, 0x01, 0xd0, 0x84, 0xdf, 0xd2, 0x32, 0x24, 0x7b, 0x33, 0x3d, + 0xbd, 0x09, 0x42, 0x70, 0xa9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, + 0x01, 0x27, 0x30, 0x82, 0x01, 0x23, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x8c, 0xf4, 0xd9, 0x93, 0x0a, + 0x47, 0xbc, 0x00, 0xa0, 0x4a, 0xce, 0x4b, 0x75, 0x6e, 0xa0, 0xb6, 0xb0, + 0xb2, 0x7e, 0xfc, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x03, 0x02, 0x30, 0x18, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x11, 0x30, + 0x0f, 0x82, 0x0d, 0x61, 0x70, 0x69, 0x2e, 0x69, 0x6d, 0x67, 0x75, 0x72, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x41, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, + 0x3a, 0x30, 0x38, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, 0x86, 0x30, 0x68, + 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x74, 0x73, 0x73, 0x6c, 0x64, + 0x76, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, + 0x67, 0x74, 0x73, 0x73, 0x6c, 0x64, 0x76, 0x2e, 0x63, 0x72, 0x6c, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf1, 0xb4, + 0x71, 0x46, 0x19, 0x12, 0x11, 0x01, 0x1c, 0x78, 0x63, 0xb2, 0x42, 0x24, + 0xa0, 0xe1, 0x10, 0xfa, 0x10, 0xf3, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x47, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x3b, 0x30, 0x39, + 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, + 0x86, 0x2b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x74, 0x73, + 0x73, 0x6c, 0x64, 0x76, 0x2d, 0x61, 0x69, 0x61, 0x2e, 0x67, 0x65, 0x6f, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x74, + 0x73, 0x73, 0x6c, 0x64, 0x76, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x58, 0x0d, 0x3c, 0xe2, 0xf0, 0x9b, 0xaf, + 0x64, 0x4b, 0xac, 0xd3, 0xa3, 0xb4, 0x25, 0x6d, 0xbf, 0xd6, 0x11, 0x1c, + 0xe4, 0x2d, 0x12, 0x69, 0x63, 0x56, 0x5b, 0x4a, 0xb3, 0x2d, 0xa1, 0x5a, + 0xd1, 0xf4, 0x71, 0x87, 0xde, 0x08, 0x16, 0x11, 0xa1, 0xc3, 0x70, 0x26, + 0x71, 0xc4, 0x18, 0x3f, 0xb5, 0xd0, 0x12, 0xb2, 0x27, 0xce, 0x7f, 0x51, + 0x0d, 0x5c, 0xe3, 0xfc, 0x83, 0x3b, 0x64, 0x13, 0xcb, 0xd5, 0xd5, 0x40, + 0x3c, 0x21, 0x67, 0x4a, 0xa6, 0xfb, 0xd7, 0x72, 0xcf, 0x04, 0x29, 0x50, + 0xf9, 0xaa, 0xae, 0xe1, 0x80, 0x31, 0x7e, 0x79, 0xd2, 0x9d, 0x8b, 0xe9, + 0xf5, 0xb6, 0xcb, 0xc9, 0xe6, 0xcc, 0x75, 0x66, 0x15, 0xd3, 0x8a, 0x69, + 0x9d, 0xee, 0x13, 0x21, 0x3b, 0x73, 0x68, 0xaf, 0xee, 0xa2, 0x91, 0x70, + 0x77, 0x02, 0xee, 0x36, 0x56, 0x28, 0x00, 0x17, 0xef, 0x9e, 0x4b, 0x8b, + 0x6c, 0x5d, 0xf5, 0xf6, 0x3d, 0xbb, 0xbb, 0x6b, 0xdc, 0x98, 0x51, 0xbf, + 0xbd, 0x0d, 0x51, 0xf4, 0x1d, 0x4b, 0x2e, 0x3d, 0xe3, 0x07, 0xdb, 0x81, + 0x14, 0x54, 0x67, 0x6e, 0xfc, 0x44, 0x34, 0xf6, 0x9e, 0x9f, 0x0d, 0xfb, + 0xdd, 0x11, 0x24, 0x02, 0x13, 0x6c, 0x66, 0xf2, 0x39, 0x6c, 0x9a, 0x5a, + 0x07, 0xb9, 0x61, 0xc5, 0xb8, 0xda, 0x62, 0x53, 0x23, 0x66, 0x56, 0xdc, + 0x36, 0x57, 0x4e, 0xbf, 0xe8, 0xcd, 0x73, 0xce, 0x91, 0x36, 0xff, 0x28, + 0xc6, 0x0f, 0x20, 0xe9, 0x89, 0xf2, 0xb2, 0x51, 0x4e, 0x8b, 0x3b, 0x8c, + 0xd6, 0x7d, 0x95, 0x03, 0x0c, 0x45, 0x7f, 0xa8, 0xa0, 0x45, 0xf5, 0xa9, + 0x90, 0x30, 0xec, 0xc9, 0xcb, 0x3f, 0xd1, 0x5d, 0x99, 0x8d, 0xe6, 0x61, + 0xcd, 0xbc, 0xe2, 0xd8, 0x9d, 0x7f, 0xa1, 0xbe, 0xca, 0x56, 0x9f, 0x1b, + 0x79, 0xd9, 0x07, 0xe8, 0xec, 0x99, 0x44, 0xa3, 0x8c, }; + + // CN=GeoTrust DV SSL CA, OU=Domain Validated SSL, O=GeoTrust Inc., C=US + public static byte[] geotrust_dv_ssl_ca = { + 0x30, 0x82, 0x03, 0xfa, 0x30, 0x82, 0x02, 0xe2, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x03, 0x02, 0x36, 0xd2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, + 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, + 0x32, 0x32, 0x36, 0x32, 0x31, 0x33, 0x32, 0x33, 0x31, 0x5a, 0x17, 0x0d, + 0x32, 0x30, 0x30, 0x32, 0x32, 0x35, 0x32, 0x31, 0x33, 0x32, 0x33, 0x31, + 0x5a, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x14, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x20, 0x53, 0x53, 0x4c, 0x31, + 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, + 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x44, 0x56, 0x20, 0x53, 0x53, + 0x4c, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xa6, 0xbb, 0x8e, 0x7a, 0xcd, 0xa4, 0x9c, 0x62, 0x57, 0xd4, 0x51, + 0x30, 0x42, 0x7b, 0x8b, 0x1a, 0xb2, 0xd2, 0x88, 0x06, 0xad, 0x3b, 0x3c, + 0x29, 0x13, 0x0c, 0x31, 0xbc, 0x69, 0xf9, 0x9f, 0x5a, 0x94, 0xda, 0x06, + 0xba, 0xac, 0x24, 0x04, 0x9e, 0xce, 0xd4, 0xaa, 0xc4, 0x48, 0x60, 0x00, + 0xf8, 0x34, 0xae, 0xa1, 0x93, 0xaf, 0xde, 0x04, 0x7e, 0xcd, 0xf8, 0x5c, + 0x22, 0x52, 0x0d, 0x56, 0x53, 0xeb, 0xa9, 0x94, 0xcf, 0xfb, 0x74, 0x44, + 0xeb, 0x43, 0x94, 0xa4, 0x97, 0x7a, 0x40, 0x57, 0x35, 0xb6, 0xa4, 0x62, + 0xda, 0xd5, 0x48, 0xf8, 0x7a, 0xf1, 0xec, 0x90, 0xb5, 0x5f, 0x39, 0xfe, + 0x63, 0x72, 0x70, 0xc8, 0x12, 0x85, 0xd0, 0xa5, 0x2e, 0x86, 0x13, 0x40, + 0x6c, 0xeb, 0x6c, 0x4d, 0xd2, 0x54, 0xfd, 0x5f, 0x3e, 0x26, 0x1f, 0x66, + 0x71, 0xa8, 0xc0, 0xb8, 0x85, 0x9e, 0xf5, 0xf5, 0x75, 0x8f, 0xda, 0x91, + 0x4e, 0x89, 0xe3, 0xca, 0x78, 0x74, 0x30, 0x5f, 0x15, 0x0a, 0x99, 0xa7, + 0xca, 0x83, 0x3a, 0x76, 0x35, 0x48, 0xd0, 0xdc, 0x8b, 0x1a, 0x22, 0x4e, + 0x85, 0xa4, 0x4e, 0xfa, 0x49, 0x6d, 0x2b, 0x70, 0xbe, 0x8e, 0x0c, 0x21, + 0xc3, 0x62, 0xcc, 0xa4, 0xd1, 0xad, 0x16, 0x6b, 0x9a, 0x7b, 0xcb, 0x64, + 0xff, 0x8d, 0xba, 0x42, 0xc3, 0x26, 0xaa, 0x15, 0x78, 0x68, 0x9c, 0xec, + 0xf6, 0x6b, 0xc8, 0x0c, 0x57, 0x0d, 0xe5, 0x38, 0x07, 0xd3, 0x6a, 0x57, + 0x03, 0x9d, 0x20, 0x0e, 0x4b, 0xc4, 0x7b, 0x81, 0xb0, 0x2a, 0x1c, 0xf5, + 0x4a, 0xea, 0x4a, 0x98, 0x49, 0xfe, 0x02, 0x5b, 0x3d, 0x03, 0x14, 0x90, + 0x28, 0x7e, 0x9a, 0xf4, 0x78, 0xd0, 0x31, 0x84, 0x57, 0xe5, 0x4c, 0x38, + 0x7a, 0x42, 0x11, 0xe2, 0xf5, 0x28, 0x51, 0x03, 0x4b, 0x20, 0x15, 0xbb, + 0x22, 0x1a, 0xb6, 0xf0, 0x15, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, + 0xd9, 0x30, 0x81, 0xd6, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x8c, 0xf4, 0xd9, 0x93, 0x0a, + 0x47, 0xbc, 0x00, 0xa0, 0x4a, 0xce, 0x4b, 0x75, 0x6e, 0xa0, 0xb6, 0xb0, + 0xb2, 0x7e, 0xfc, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, + 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x3a, 0x06, 0x03, + 0x55, 0x1d, 0x1f, 0x04, 0x33, 0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, + 0x2b, 0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, + 0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x34, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x28, 0x30, 0x26, + 0x30, 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, + 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, + 0x70, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, + 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x33, 0x91, + 0x37, 0x11, 0xdb, 0x40, 0xf9, 0xde, 0x8c, 0xb2, 0x02, 0x88, 0x77, 0xaf, + 0x63, 0x21, 0xc1, 0xad, 0xb0, 0x0d, 0xfa, 0xa0, 0x78, 0x56, 0xa3, 0x82, + 0xfd, 0xbb, 0x49, 0x5f, 0x14, 0x6d, 0xc8, 0xdc, 0x5f, 0x94, 0xda, 0x11, + 0x66, 0x7c, 0x1e, 0x91, 0xc5, 0xb6, 0xd8, 0x6d, 0x4f, 0xaa, 0xf2, 0xbf, + 0x21, 0x28, 0x7e, 0x52, 0xa2, 0x92, 0x78, 0x08, 0x61, 0x69, 0x21, 0xfe, + 0x2d, 0xec, 0x82, 0x18, 0x84, 0xf4, 0xd3, 0x8d, 0xc5, 0x8a, 0xbb, 0x8a, + 0xcc, 0x5d, 0xe6, 0xa3, 0xb6, 0xcc, 0x6e, 0xad, 0x6f, 0xb3, 0x0e, 0x61, + 0xee, 0x89, 0xce, 0x13, 0x34, 0x4f, 0x49, 0x55, 0xf5, 0x39, 0xbb, 0x99, + 0x96, 0xf0, 0xf5, 0xea, 0x5a, 0x3c, 0x9c, 0x16, 0xbd, 0x02, 0x53, 0xf0, + 0x2a, 0x0e, 0x41, 0x6e, 0xeb, 0xef, 0x9e, 0xf7, 0x70, 0x36, 0xcd, 0x80, + 0x2a, 0x76, 0xc8, 0x87, 0xe3, 0xeb, 0x23, 0xb3, 0x96, 0x2c, 0xe6, 0x1d, + 0x94, 0x5f, 0x1c, 0xa4, 0xe2, 0xcd, 0x24, 0x31, 0x2b, 0x06, 0x38, 0x32, + 0x61, 0x61, 0x39, 0x5c, 0x89, 0x4c, 0x48, 0x1d, 0x42, 0xc9, 0x67, 0x9e, + 0xd2, 0xbf, 0x58, 0xf7, 0xf9, 0x37, 0x31, 0xb0, 0x67, 0xdd, 0x8d, 0x26, + 0x36, 0x1a, 0x78, 0x1a, 0x09, 0x19, 0x3c, 0x93, 0x07, 0x70, 0x2a, 0xe1, + 0x7c, 0x29, 0xf5, 0xde, 0x66, 0x57, 0x0b, 0x12, 0x5e, 0x16, 0xed, 0x5e, + 0xbd, 0x37, 0xb3, 0x30, 0x69, 0xc6, 0x92, 0xa5, 0xf6, 0x19, 0xd8, 0x1d, + 0xf8, 0x36, 0x12, 0xb9, 0x4b, 0x95, 0x95, 0x9c, 0xd0, 0xce, 0x6c, 0x30, + 0xa7, 0x16, 0xfb, 0xf6, 0x4d, 0x64, 0xb6, 0x5f, 0x2a, 0x14, 0x9c, 0xa6, + 0xc8, 0x55, 0x8e, 0x20, 0xf9, 0x65, 0x07, 0x24, 0xcc, 0x38, 0x05, 0x4c, + 0x20, 0x88, 0xb4, 0xb5, 0x67, 0x94, 0xcf, 0x5d, 0x8e, 0x62, 0x37, 0xfe, + 0xc4, 0xb4, }; + + // CN=GeoTrust Global CA, O=GeoTrust Inc., C=US + public static byte[] geotrust_global_root = { + 0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02, 0x3c, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x03, 0x02, 0x34, 0x56, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, + 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x32, 0x30, + 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, + 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xda, 0xcc, 0x18, 0x63, 0x30, 0xfd, + 0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b, 0xdf, 0x3c, 0x6c, 0x38, 0xe4, + 0x71, 0xb7, 0x78, 0x91, 0xd4, 0xbc, 0xa1, 0xd8, 0x4c, 0xf8, 0xa8, 0x43, + 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08, 0x88, 0xda, 0x58, 0x2f, 0x66, + 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d, 0x38, 0xe8, 0x05, 0xb7, 0x6a, + 0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6, 0xb0, 0xef, 0x80, 0xe4, 0x89, + 0x28, 0x0f, 0x9e, 0x25, 0xd6, 0xed, 0x83, 0xf3, 0xad, 0xa6, 0x91, 0xc7, + 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d, 0xad, 0x98, 0x46, 0x92, 0x2e, + 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16, 0x95, 0x57, 0x2d, 0x50, 0xef, + 0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2, 0xee, 0x5f, 0x6b, 0xd2, 0x00, + 0x8d, 0xb9, 0x14, 0xf8, 0x14, 0x15, 0x35, 0xd9, 0xc0, 0x46, 0xa3, 0x7b, + 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b, 0xcd, 0xd0, 0x97, 0x3e, 0x9c, + 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19, 0x71, 0xca, 0x4e, 0xe6, 0xd4, + 0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde, 0xc8, 0xec, 0xd2, 0x5e, 0x38, + 0x53, 0xe5, 0x5c, 0x4f, 0x8c, 0x2d, 0xfe, 0x50, 0x23, 0x36, 0xfc, 0x66, + 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00, 0xb7, 0x95, 0x02, 0x39, 0x91, + 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d, 0x05, 0x9a, 0xf6, 0x4d, 0x3e, + 0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e, 0x8f, 0x60, 0x39, 0xe2, 0xfa, + 0x36, 0x53, 0x13, 0x39, 0xd4, 0x5e, 0x26, 0x2b, 0xdb, 0x3d, 0xa8, 0x14, + 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52, 0x04, 0x71, 0xe5, 0xab, 0x33, + 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84, 0x62, 0x9c, 0x79, 0xea, 0x16, + 0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71, 0x6b, 0xe4, 0xf9, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc0, + 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, 0x7d, + 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc0, 0x7a, 0x98, 0x68, + 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, + 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d, 0x54, 0x8e, 0x29, 0x50, 0x94, + 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78, 0x2a, 0x62, 0x94, 0xa2, 0x27, + 0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47, 0xe9, 0xc1, 0xb2, 0xa4, 0xcf, + 0xdd, 0x41, 0x1a, 0x05, 0x4e, 0x9b, 0x4b, 0xee, 0x4a, 0x6f, 0x55, 0x52, + 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64, 0x76, 0x2a, 0x2e, 0x2c, 0xf3, + 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71, 0xd8, 0xc7, 0x3d, 0x37, 0xd2, + 0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde, 0x89, 0x3d, 0x36, 0x7b, 0x38, + 0x77, 0x48, 0x97, 0xac, 0xa6, 0x20, 0x8f, 0x2e, 0xa6, 0xc9, 0x0c, 0xc2, + 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11, 0x51, 0x22, 0x22, 0xe0, 0xa5, + 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea, 0x5e, 0x4f, 0x74, 0xf7, 0x05, + 0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15, 0xb4, 0xbd, 0x6d, 0x9b, 0xe5, + 0xc6, 0xb1, 0x54, 0x68, 0xa9, 0xe3, 0x69, 0x90, 0xb6, 0x9a, 0xa5, 0x0f, + 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a, 0xb5, 0xb8, 0x9c, 0xe4, 0x1d, + 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7, 0x83, 0xad, 0xdb, 0xf5, 0x27, + 0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd, 0xa0, 0x5d, 0xed, 0x87, 0x52, + 0xb7, 0x2b, 0x15, 0x02, 0xae, 0x39, 0xa6, 0x6a, 0x74, 0xe9, 0xda, 0xc4, + 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c, 0x4d, 0x33, 0x5f, 0x92, 0x09, + 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7, 0x1d, 0x76, 0x13, 0xa9, 0xd5, + 0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5, 0xac, 0xdb, 0x24, 0x71, 0x70, + 0x2c, 0x98, 0x56, 0x0b, 0xd9, 0x17, 0xb4, 0xd1, 0xe3, 0x51, 0x2b, 0x5e, + 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34, 0xed, 0xc2, 0x05, 0x66, 0x80, + 0xa1, 0xcb, 0xe6, 0x33, }; + + [DllImport (Constants.CoreFoundationLibrary)] + extern static nint CFGetRetainCount (IntPtr handle); + + void CheckMailGoogleCom (SecCertificate cert, int expectedRetainCount) + { + Assert.That (cert.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (cert.Handle), Is.EqualTo (expectedRetainCount), "RetainCount"); + Assert.That (cert.SubjectSummary, Is.EqualTo ("mail.google.com"), "SubjectSummary"); + Assert.That ((nuint) (uint) mail_google_com.Length, Is.EqualTo (cert.DerData.Length), "DerData"); + } + + [Test] + public void MailNSData() + { + using (var data = NSData.FromArray (mail_google_com)) + using (var sc = new SecCertificate (data)) { + CheckMailGoogleCom (sc, 1); + } + } + + [Test] + public void MailRaw () + { + using (var sc = new SecCertificate (mail_google_com)) { + CheckMailGoogleCom (sc, 1); + } + } + + [Test] + public void MailX1 () + { + using (var cert = new X509Certificate (mail_google_com)) { + /* + * This X509Certificate constructor will use SecCertificateCreateWithData() and + * store the SecCertificateRef in its Handle. + */ + Assert.That (cert.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (cert.Handle), Is.EqualTo (1), "RetainCount"); + using (var sc = new SecCertificate (cert)) { + Assert.That (sc.Handle, Is.EqualTo (cert.Handle), "Same Handle"); + CheckMailGoogleCom (sc, 2); + Assert.That (cert.ToString (true), Is.EqualTo (sc.ToX509Certificate ().ToString (true)), "X509Certificate"); + } + } + } + + [Test] + [Ignore ("https://bugzilla.xamarin.com/show_bug.cgi?id=39952")] + public void MailX2 () + { + using (var cert = new X509Certificate2 (mail_google_com)) { + /* + * FIXME: This X509Certificate2 constructor will use Mono.Security to parse the + * certificate, but also call the base class'es .ctor with the byte array. + */ + Assert.That (cert.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (cert.Handle), Is.EqualTo (1), "RetainCount"); + using (var sc = new SecCertificate (cert)) { + Assert.That (sc.Handle, Is.EqualTo (cert.Handle), "Same Handle"); + CheckMailGoogleCom (sc, 2); + Assert.That (cert.ToString (), Is.EqualTo (sc.ToX509Certificate2 ().ToString ()), "X509Certificate2"); + } + } + } + } +} diff --git a/tests/monotouch-test/Security/IdentityTest.cs b/tests/monotouch-test/Security/IdentityTest.cs new file mode 100644 index 000000000000..a2d7991cf713 --- /dev/null +++ b/tests/monotouch-test/Security/IdentityTest.cs @@ -0,0 +1,46 @@ +// +// SecIdentity Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using Security; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class IdentityTest { + + static public SecIdentity GetIdentity () + { + using (var options = NSDictionary.FromObjectAndKey (new NSString ("farscape"), SecImportExport.Passphrase)) { + NSDictionary[] array; + if (SecImportExport.ImportPkcs12 (ImportExportTest.farscape_pfx, options, out array) != SecStatusCode.Success) + Assert.Fail ("ImportPkcs12"); + return new SecIdentity (array [0].LowlevelObjectForKey (SecImportExport.Identity.Handle)); + } + } + + [Test] + public void Identity () + { + using (SecIdentity id = GetIdentity ()) { + Assert.NotNull (id.PrivateKey, "PrivateKey"); + Assert.NotNull (id.Certificate, "Certificate"); + } + } + } +} diff --git a/tests/monotouch-test/Security/ImportExportTest.cs b/tests/monotouch-test/Security/ImportExportTest.cs new file mode 100644 index 000000000000..17ad041bcd2f --- /dev/null +++ b/tests/monotouch-test/Security/ImportExportTest.cs @@ -0,0 +1,87 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +using System; +#if XAMCORE_2_0 +using Foundation; +using Security; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Security { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImportExportTest { + + // copy-pasted from mono/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509Cert20Test.cs + static public byte[] farscape_pfx = { 0x30, 0x82, 0x06, 0xA3, 0x02, 0x01, 0x03, 0x30, 0x82, 0x06, 0x63, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x06, 0x54, 0x04, 0x82, 0x06, 0x50, 0x30, 0x82, 0x06, 0x4C, 0x30, 0x82, 0x03, 0x8D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x7E, 0x04, 0x82, 0x03, 0x7A, 0x30, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02, 0xA0, 0x82, 0x02, 0xB6, 0x30, 0x82, 0x02, 0xB2, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, + 0x0E, 0x04, 0x08, 0x67, 0xFE, 0x3A, 0x52, 0x75, 0xF3, 0x82, 0x1F, 0x02, 0x02, 0x07, 0xD0, 0x04, 0x82, 0x02, 0x90, 0x31, 0x6B, 0x00, 0xFA, 0x73, 0xE6, 0x8D, 0x3D, 0x62, 0x93, 0x41, 0xA1, 0x44, 0x04, 0x17, 0x8D, 0x66, 0x7A, 0x75, 0x14, 0x89, 0xA8, 0xD1, 0x4D, 0x2A, 0xD7, 0x20, 0x27, 0x71, 0x58, 0x81, 0x16, 0xB5, 0xA6, 0x41, 0x75, 0x92, 0xB2, 0xF4, 0x0C, 0xAA, 0x9B, 0x00, 0x46, 0x85, 0x85, 0x3B, 0x09, 0x2A, 0x62, 0x33, 0x3F, 0x3D, 0x06, 0xC7, 0xE7, 0x16, 0x0C, 0xA7, 0x1D, 0x9C, 0xDA, 0x9D, 0xD3, 0xC9, 0x05, 0x60, 0xA5, 0xBE, 0xF0, 0x07, 0xD5, 0xA9, 0x4F, 0x8A, 0x80, 0xF8, 0x55, 0x7B, 0x7B, 0x3C, + 0xA0, 0x7C, 0x29, 0x29, 0xAB, 0xB1, 0xE1, 0x5A, 0x25, 0xE3, 0x23, 0x6A, 0x56, 0x98, 0x37, 0x68, 0xAF, 0x9C, 0x87, 0xBB, 0x21, 0x6E, 0x68, 0xBE, 0xAE, 0x65, 0x0C, 0x41, 0x8F, 0x5C, 0x3A, 0xB8, 0xB1, 0x9D, 0x42, 0x37, 0xE4, 0xA0, 0x37, 0xA6, 0xB8, 0xAC, 0x85, 0xD7, 0x85, 0x27, 0x68, 0xD0, 0xB6, 0x3D, 0xC7, 0x39, 0x92, 0x41, 0x46, 0x24, 0xDD, 0x08, 0x57, 0x22, 0x6A, 0xC0, 0xB7, 0xAD, 0x52, 0xC6, 0x7F, 0xE5, 0x74, 0x6A, 0x5E, 0x28, 0xA3, 0x85, 0xBD, 0xE8, 0xAD, 0x5D, 0xA3, 0x55, 0xE6, 0x63, 0x15, 0x56, 0x7B, 0x01, 0x26, 0x68, 0x5F, 0x11, 0xA3, 0x12, 0x37, 0x02, 0xA5, 0xD0, 0xB7, 0x73, 0x0C, 0x7C, + 0x97, 0xE1, 0xC6, 0x2F, 0x98, 0x82, 0x67, 0x2F, 0x5F, 0x3F, 0xBE, 0x32, 0x16, 0x25, 0x9D, 0x51, 0x48, 0x32, 0xCB, 0x42, 0xD1, 0x31, 0x07, 0xBE, 0x5D, 0xF8, 0xCD, 0x2C, 0x38, 0x0A, 0x33, 0x3B, 0x7B, 0x04, 0x84, 0xAE, 0x9C, 0xA7, 0x6B, 0x36, 0x39, 0x12, 0x87, 0x9D, 0x5B, 0x56, 0x00, 0x44, 0x11, 0xB1, 0xE2, 0x78, 0x14, 0x60, 0xF3, 0xE4, 0x1A, 0x08, 0x14, 0xC0, 0x9E, 0x49, 0x9F, 0xE0, 0x4C, 0xEC, 0x95, 0x15, 0x18, 0x48, 0x0E, 0xB9, 0x0B, 0x3A, 0xFE, 0x45, 0xB0, 0x2D, 0x0D, 0x4F, 0x94, 0x5A, 0x3C, 0x43, 0xB7, 0x40, 0x8E, 0x7B, 0xA2, 0x8E, 0x23, 0x9F, 0x75, 0x97, 0xE7, 0x21, 0x0D, 0xEB, 0xA3, 0x9D, + 0x6C, 0xC0, 0xDC, 0x73, 0xED, 0x15, 0x98, 0xE3, 0xE8, 0x32, 0x2C, 0x12, 0x92, 0x45, 0x25, 0x45, 0x76, 0x18, 0xF5, 0x97, 0x7F, 0xAC, 0xCE, 0xCF, 0x23, 0xF7, 0xD1, 0xCF, 0x06, 0xAB, 0x82, 0x96, 0x1F, 0xF8, 0x68, 0x4F, 0x5D, 0xE1, 0x09, 0xAA, 0xCB, 0xB3, 0x50, 0x85, 0x46, 0x72, 0x14, 0x6C, 0x49, 0x84, 0x57, 0x55, 0x00, 0x78, 0x3E, 0xD9, 0xAA, 0xBD, 0xCC, 0xE2, 0x7B, 0x18, 0xAA, 0x2E, 0x5D, 0xB9, 0x28, 0xEA, 0x8F, 0x8C, 0xFA, 0xB7, 0x06, 0x27, 0x07, 0x89, 0x41, 0x3F, 0x66, 0x1A, 0x91, 0xCA, 0xE9, 0xEC, 0x09, 0x12, 0x1C, 0x67, 0xB2, 0x2A, 0x8B, 0x4A, 0xF0, 0x97, 0x17, 0xDC, 0x3E, 0xCD, 0x9F, 0x03, + 0x15, 0xEF, 0x03, 0x84, 0x08, 0x4A, 0x73, 0xAE, 0xE4, 0x07, 0x30, 0x27, 0xF7, 0x25, 0x69, 0x9D, 0x6C, 0x7D, 0x81, 0x88, 0xCC, 0xFA, 0xD4, 0xC7, 0x64, 0x11, 0xC0, 0xC8, 0x2C, 0x23, 0xF6, 0xFF, 0x9B, 0xE3, 0xC8, 0x89, 0x85, 0x0B, 0x3E, 0x81, 0xD8, 0x9C, 0xBD, 0xD0, 0x2D, 0xCD, 0x15, 0xA9, 0x30, 0x84, 0xF7, 0x6D, 0xEF, 0x62, 0x3B, 0xA7, 0x8C, 0xC2, 0x93, 0x90, 0x6F, 0x91, 0xB4, 0x8A, 0x71, 0x4E, 0x41, 0x4E, 0x5C, 0x67, 0xB5, 0x49, 0xF8, 0x56, 0x3A, 0x83, 0x03, 0x4F, 0xB1, 0xF6, 0xB7, 0x31, 0x5B, 0x68, 0x26, 0x70, 0x89, 0xB1, 0x1E, 0x67, 0x4F, 0xBA, 0xE7, 0xD9, 0xDF, 0x91, 0xD8, 0xFB, 0x8A, 0xDD, + 0xB2, 0xD3, 0x4B, 0xBB, 0x9F, 0x5C, 0xA3, 0x04, 0x2C, 0x87, 0xBC, 0xD5, 0xBE, 0x8C, 0xD7, 0xCF, 0x9B, 0x72, 0x82, 0xA6, 0x99, 0xDA, 0xD7, 0x66, 0x48, 0xE7, 0x8F, 0xE9, 0x48, 0x56, 0x9D, 0xD2, 0xB9, 0x28, 0x84, 0x4F, 0x6A, 0x83, 0xB2, 0xB9, 0x4D, 0x91, 0x10, 0x58, 0x22, 0x4C, 0xE7, 0x9D, 0xC6, 0x0C, 0x74, 0xF4, 0x16, 0x58, 0x30, 0xB7, 0xB7, 0x96, 0x39, 0x6C, 0x5D, 0xFA, 0xB2, 0x03, 0x8C, 0x98, 0xD2, 0xC0, 0x64, 0xB8, 0x05, 0x29, 0x4F, 0xF0, 0x4C, 0x43, 0x48, 0xD3, 0xD8, 0xBD, 0xC7, 0xC1, 0xEA, 0x39, 0x2A, 0xDF, 0xD4, 0xDA, 0x79, 0x7C, 0xB9, 0x06, 0xC7, 0x10, 0x8D, 0x8B, 0xF1, 0xA8, 0x8E, 0x44, + 0x9E, 0x99, 0xFF, 0x81, 0x84, 0x8F, 0xD0, 0x38, 0xE1, 0xF0, 0x5A, 0x12, 0x5F, 0xC5, 0xA6, 0xED, 0x6D, 0xEE, 0xE7, 0x69, 0xC0, 0xA2, 0xB4, 0x13, 0xCA, 0x7A, 0x5D, 0xDE, 0x88, 0x75, 0xE7, 0xE2, 0x6D, 0x8A, 0xEC, 0x0F, 0x88, 0x3F, 0xE2, 0xCB, 0x60, 0xF0, 0x6A, 0xEC, 0xD0, 0xF4, 0x0D, 0x11, 0xC2, 0x84, 0x19, 0x67, 0x52, 0xAD, 0xC0, 0xC0, 0x20, 0x84, 0x6D, 0x7D, 0xEA, 0xD2, 0xF9, 0x3F, 0xE5, 0x58, 0x00, 0xED, 0x24, 0xD6, 0x50, 0x9B, 0x80, 0x80, 0x0A, 0x31, 0x81, 0xA8, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x02, 0x31, 0x00, 0x30, 0x13, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x17, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x14, 0x31, 0x0A, 0x1E, 0x08, 0x00, 0x4D, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x6F, 0x30, 0x69, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x5C, 0x1E, 0x5A, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x52, 0x00, 0x53, 0x00, 0x41, 0x00, 0x20, 0x00, 0x53, 0x00, 0x43, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x6C, + 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x30, 0x82, 0x02, 0xB7, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06, 0xA0, 0x82, 0x02, 0xA8, 0x30, 0x82, 0x02, 0xA4, 0x02, 0x01, 0x00, 0x30, 0x82, 0x02, 0x9D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, + 0x06, 0x30, 0x0E, 0x04, 0x08, 0xB8, 0x22, 0xEA, 0x3C, 0x70, 0x6A, 0xFC, 0x39, 0x02, 0x02, 0x07, 0xD0, 0x80, 0x82, 0x02, 0x70, 0x76, 0xBE, 0x5B, 0xD5, 0x3D, 0x05, 0xC1, 0xDB, 0x10, 0xA3, 0x02, 0xBB, 0x7F, 0x0A, 0x8B, 0x54, 0xC1, 0x7D, 0x19, 0xDA, 0x7E, 0x82, 0xDF, 0xAD, 0x6B, 0x42, 0xC2, 0x95, 0x95, 0x00, 0x6E, 0x82, 0x77, 0xD5, 0x42, 0x6E, 0x21, 0xA2, 0x95, 0xB4, 0x98, 0xF5, 0xDD, 0x18, 0x6F, 0xC4, 0xF3, 0xB6, 0x93, 0xA0, 0x6C, 0xF4, 0x34, 0x7A, 0x48, 0x72, 0x08, 0xB1, 0x28, 0x51, 0x54, 0x10, 0x7F, 0x35, 0xB2, 0xE5, 0x89, 0x5C, 0x0A, 0x14, 0x31, 0x1C, 0x9D, 0xA9, 0xE4, 0x94, 0x91, 0x28, 0x65, + 0xC4, 0xE7, 0x5E, 0xA9, 0x37, 0x08, 0x3D, 0xB1, 0x16, 0x61, 0x9D, 0xA9, 0x44, 0x6F, 0x20, 0x0C, 0x55, 0xD7, 0xCC, 0x48, 0x82, 0x13, 0x5D, 0xE1, 0xBD, 0x9D, 0xCE, 0x64, 0x28, 0x6D, 0x69, 0x4E, 0x08, 0x53, 0x09, 0xE0, 0xCC, 0xA8, 0x79, 0x04, 0xCF, 0xFA, 0x35, 0x1C, 0xA6, 0x70, 0x37, 0x64, 0x70, 0x74, 0xF8, 0xD0, 0xC4, 0x34, 0x0F, 0x71, 0xEF, 0x57, 0xC2, 0x43, 0x7D, 0xFA, 0xE5, 0x1B, 0x8C, 0x15, 0xA5, 0x08, 0x60, 0x78, 0xAF, 0xDA, 0x36, 0xDF, 0x79, 0x2D, 0xD7, 0x54, 0x35, 0xD7, 0x8D, 0x99, 0xD5, 0x81, 0xEC, 0x6D, 0x9F, 0x2D, 0x5E, 0xF8, 0x48, 0x85, 0x50, 0x20, 0x7D, 0xBB, 0x16, 0x4E, 0x39, 0x64, + 0xB7, 0xBC, 0xED, 0xA9, 0x6A, 0x7A, 0x06, 0x09, 0x6B, 0xBC, 0x2C, 0x5A, 0xE1, 0x4F, 0xD4, 0xA9, 0x82, 0x83, 0x5B, 0xBD, 0xCE, 0x14, 0x31, 0x89, 0x66, 0xB3, 0x9C, 0x31, 0x23, 0x00, 0x4B, 0x02, 0x34, 0x85, 0x30, 0x39, 0x77, 0x80, 0x5D, 0x72, 0x0A, 0xCE, 0x43, 0x2A, 0x1F, 0x02, 0x09, 0xAB, 0x2D, 0x46, 0x3A, 0x1C, 0xD2, 0x7B, 0xF6, 0x02, 0x92, 0xCA, 0xDA, 0x26, 0x0C, 0xF8, 0xE2, 0x67, 0x7E, 0xE2, 0x55, 0xB1, 0x3F, 0x6A, 0x06, 0x65, 0x6D, 0x74, 0x98, 0x59, 0xE2, 0x8A, 0x1E, 0x61, 0x03, 0x4D, 0xFC, 0x68, 0x31, 0x6A, 0xE7, 0xCF, 0x52, 0x88, 0x8E, 0x06, 0x97, 0x77, 0xB3, 0x20, 0x7E, 0x09, 0x5D, 0x3B, + 0xAF, 0x56, 0xF4, 0xE8, 0x4C, 0x69, 0x09, 0xB9, 0x80, 0x38, 0xDC, 0x66, 0x2E, 0x06, 0xF6, 0xCB, 0x1F, 0x1B, 0xAD, 0x51, 0xFF, 0xFD, 0x38, 0x8D, 0x03, 0x90, 0xCF, 0x31, 0x01, 0x30, 0xEA, 0x48, 0x4C, 0xBB, 0x40, 0x87, 0x1D, 0x97, 0x6A, 0x56, 0x4C, 0xED, 0x07, 0x23, 0x45, 0x50, 0x2F, 0x56, 0xC9, 0x90, 0x79, 0x09, 0xC5, 0x45, 0xB9, 0xAD, 0x58, 0x2B, 0x4C, 0xA3, 0x01, 0xE0, 0x2D, 0xE5, 0x30, 0xBC, 0x54, 0xEC, 0x65, 0xB4, 0x79, 0x22, 0x7D, 0x15, 0xF6, 0x28, 0xCD, 0x84, 0x7E, 0x27, 0x95, 0xA1, 0xC7, 0x82, 0x6D, 0xFB, 0xDF, 0x03, 0xD9, 0x14, 0xFE, 0x0A, 0x06, 0x6F, 0x14, 0xFF, 0x8A, 0x27, 0x80, 0x36, + 0xDC, 0xBA, 0xAE, 0xDD, 0x44, 0x15, 0xA5, 0x6E, 0x64, 0x73, 0xBD, 0xFB, 0xAE, 0x6D, 0x6F, 0x42, 0x96, 0xDF, 0x90, 0xE5, 0x6A, 0x9B, 0x05, 0xAE, 0xD5, 0x0A, 0x22, 0x88, 0xD6, 0x5D, 0x4C, 0x7B, 0xB1, 0x3A, 0xFC, 0x0C, 0x32, 0x02, 0xB1, 0x18, 0x0D, 0xAF, 0xE0, 0xFE, 0x7E, 0x07, 0x96, 0x85, 0xBB, 0xC8, 0x21, 0x68, 0x12, 0xD4, 0xC8, 0xBF, 0x91, 0x47, 0xE2, 0xF3, 0xA5, 0xA3, 0x86, 0xE6, 0x30, 0x42, 0xF5, 0xA9, 0xB9, 0x48, 0xCB, 0x18, 0xE6, 0x64, 0x3B, 0xE0, 0x8E, 0xC3, 0x03, 0x45, 0xA0, 0xED, 0x1A, 0x09, 0xFF, 0xB3, 0x99, 0x14, 0x5F, 0xDA, 0x90, 0x58, 0x61, 0x8E, 0xF7, 0x0A, 0x00, 0xC7, 0x44, 0xE7, + 0x73, 0x78, 0xC4, 0x8B, 0x39, 0xCE, 0x70, 0x0E, 0x24, 0x03, 0x95, 0x94, 0x73, 0x76, 0x10, 0x7E, 0x4C, 0xFF, 0xCA, 0x49, 0x93, 0x89, 0xD4, 0x3E, 0x1A, 0x88, 0xCC, 0x48, 0xA7, 0x78, 0x2F, 0x83, 0x4F, 0x6C, 0x33, 0x55, 0xDD, 0x7F, 0x7D, 0x4D, 0xE5, 0xCD, 0x9C, 0x3D, 0x04, 0x1E, 0xC1, 0x9B, 0x6D, 0x7E, 0x7A, 0xAC, 0x93, 0x5E, 0x2B, 0xC3, 0x85, 0x36, 0x07, 0x66, 0xE8, 0xC9, 0xC0, 0xD1, 0x54, 0xF4, 0x4C, 0x6A, 0x02, 0x24, 0x9A, 0x7D, 0x10, 0xD9, 0x79, 0x94, 0x00, 0x64, 0x63, 0x36, 0xDC, 0x35, 0x0C, 0x8F, 0x79, 0xBA, 0xC7, 0x10, 0x76, 0xF8, 0x4A, 0xD3, 0x69, 0x95, 0x23, 0x89, 0x66, 0xC4, 0x5A, 0xE7, + 0xCE, 0x21, 0xBC, 0xCB, 0xF2, 0x4F, 0x92, 0x33, 0xE7, 0x89, 0xD6, 0x23, 0xF7, 0x67, 0x5B, 0x20, 0xD9, 0xDA, 0x1A, 0xD1, 0xF6, 0x9E, 0x01, 0x83, 0x51, 0xAF, 0x35, 0x43, 0xDD, 0x3A, 0xAB, 0xCA, 0x0E, 0xED, 0x2E, 0x4D, 0x1E, 0x91, 0xCF, 0x2E, 0xA9, 0x4D, 0x08, 0xD9, 0x48, 0x30, 0x37, 0x30, 0x1F, 0x30, 0x07, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x04, 0x14, 0xA2, 0xED, 0x05, 0x50, 0x89, 0x91, 0x1D, 0xEB, 0xF6, 0x57, 0x66, 0xAF, 0x70, 0x15, 0xDD, 0x1A, 0xA1, 0x94, 0xB7, 0xB2, 0x04, 0x14, 0x09, 0xE4, 0x0B, 0xEC, 0x1D, 0x93, 0x3E, 0x32, 0x94, 0x6A, 0x95, 0x36, 0xDD, 0xBA, 0x93, 0x9D, 0x75, 0xB6, + 0x3E, 0xF5 }; + + [Test] + public void P12_Success () + { + NSDictionary[] array; + using (NSMutableDictionary options = new NSMutableDictionary ()) { + options [SecImportExport.Passphrase] = new NSString ("farscape"); + Assert.That (SecImportExport.ImportPkcs12 (farscape_pfx, options, out array), Is.EqualTo (SecStatusCode.Success), "Success"); + } + Assert.That (array.Length, Is.EqualTo (1), "1"); + NSDictionary dict = array [0]; + foreach (var x in dict) { + switch (x.Key.ToString ()) { + case "trust": + case "identity": + Assert.That (x.Value, Is.TypeOf (typeof (NSObject)), "NSObject"); + break; + case "chain": + Assert.True (x.Value is NSArray, "NSArray"); + NSArray a = (x.Value as NSArray); + Assert.That (a.Count, Is.EqualTo ((nuint) 1), "Count"); + break; + default: + Assert.Fail ("Unexpected {0}", x.Key); + break; + } + } + } + + [Test] + public void P12_AuthFailed () + { + using (NSMutableDictionary options = new NSMutableDictionary ()) { + options [SecImportExport.Passphrase] = new NSString ("b5"); + NSDictionary[] array; + Assert.That (SecImportExport.ImportPkcs12 (farscape_pfx, options, out array), Is.EqualTo (SecStatusCode.AuthFailed), "AuthFailed"); + } + } + } +} diff --git a/tests/monotouch-test/Security/KeyChainTest.cs b/tests/monotouch-test/Security/KeyChainTest.cs new file mode 100644 index 000000000000..90a49173b002 --- /dev/null +++ b/tests/monotouch-test/Security/KeyChainTest.cs @@ -0,0 +1,139 @@ +// Copyright 2011, 2013 Xamarin Inc. All rights reserved + +using System; +using System.Runtime.InteropServices; +using System.IO; +using System.Reflection; + + +#if XAMCORE_2_0 +using Foundation; +using Security; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.Security; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Security { + + [TestFixture] + [Preserve (AllMembers = true)] + public class KeyChainTest { + + [DllImport (Constants.CoreFoundationLibrary)] + extern static int CFGetRetainCount (IntPtr handle); + + [Test] + public void Add_Certificate () + { + Stream certStream = typeof(KeyChainTest).Assembly.GetManifestResourceStream ("monotouchtest.Security.openssl_crt.der"); + NSData data = NSData.FromStream (certStream); + + var rec = new SecRecord (SecKind.Certificate) { + Label = "MyCert" + }; + rec.SetValueRef (new SecCertificate (data)); + + var rc = SecKeyChain.Add (rec); + Assert.IsTrue (rc == SecStatusCode.Success || rc == SecStatusCode.DuplicateItem, "Add_Certificate"); + } + + [Test] + public void AddQueryRemove_Identity () + { + using (SecRecord rec = new SecRecord (SecKind.Identity)) + using (var id = IdentityTest.GetIdentity ()) { + rec.SetValueRef (id); + SecStatusCode code = SecKeyChain.Add (rec); + Assert.True (code == SecStatusCode.DuplicateItem || code == SecStatusCode.Success); + } + + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("QueryAsConcreteType does not work before iOS7"); + + using (SecRecord rec = new SecRecord (SecKind.Identity)) { + SecStatusCode code; + var match = SecKeyChain.QueryAsConcreteType (rec, out code); + if ((match == null) && (code == SecStatusCode.ItemNotFound)) + Assert.Inconclusive ("Test randomly fails (race condition between addtion/commit/query?"); + + Assert.That (code, Is.EqualTo (SecStatusCode.Success), "QueryAsRecord-2"); + Assert.NotNull (match, "match-2"); + + code = SecKeyChain.Remove (rec); + Assert.That (code, Is.EqualTo (SecStatusCode.Success), "Remove"); + + match = SecKeyChain.QueryAsConcreteType (rec, out code); + Assert.That (code, Is.EqualTo (SecStatusCode.ItemNotFound), "QueryAsRecord-3"); + Assert.Null (match, "match-3"); + } + } + + [DllImport ("/System/Library/Frameworks/Security.framework/Security")] + internal extern static SecStatusCode SecItemAdd (IntPtr cfDictRef, IntPtr result); + + [Test] + // same as Add_Identity but directly p/invoking - shows that the type MUST NOT be included for Identity + public void SecItemAdd_Identity () + { + using (NSString valueref = new NSString ("v_Ref")) + using (NSMutableDictionary data = new NSMutableDictionary ()) + using (var id = IdentityTest.GetIdentity ()) { + data.LowlevelSetObject (id.Handle, valueref.Handle); + SecStatusCode code = SecItemAdd (data.Handle, IntPtr.Zero); + Assert.True (code == SecStatusCode.DuplicateItem || code == SecStatusCode.Success); + } + } + + static Guid GetID() + { + Guid returnGuid = Guid.Empty; + SecStatusCode code; + SecRecord queryRec = new SecRecord (SecKind.GenericPassword) { + Service = "KEYCHAIN_SERVICE", + Label = "KEYCHAIN_SERVICE", + Account = "KEYCHAIN_ACCOUNT" + }; + queryRec = SecKeyChain.QueryAsRecord (queryRec, out code); + + if (code == SecStatusCode.Success && queryRec != null && queryRec.Generic != null ) + { + returnGuid = new Guid(NSString.FromData(queryRec.Generic, NSStringEncoding.UTF8)); + } + + return returnGuid; + } + + static SecStatusCode SetID (Guid setID) + { + var queryRec = new SecRecord (SecKind.GenericPassword) { + Service = "KEYCHAIN_SERVICE", + Label = "KEYCHAIN_SERVICE", + Account = "KEYCHAIN_ACCOUNT" + }; + var record = queryRec.Clone (); + record.Generic = NSData.FromString (Convert.ToString (setID), NSStringEncoding.UTF8); + record.Accessible = SecAccessible.Always; + SecStatusCode code = SecKeyChain.Add (record); + if (code == SecStatusCode.DuplicateItem) { + code = SecKeyChain.Remove (queryRec); + if (code == SecStatusCode.Success) + code = SecKeyChain.Add (record); + } + return code; + } + + [Test] + public void CheckId () + { + // test case from http://stackoverflow.com/questions/9481860/monotouch-cant-get-value-of-existing-keychain-item + // not a bug (no class lib fix) just a misuse of the API wrt status codes + Guid g = Guid.NewGuid (); + SetID (g); + Assert.That (g, Is.EqualTo (GetID ()), "same guid"); + } + } +} diff --git a/tests/monotouch-test/Security/KeyTest.cs b/tests/monotouch-test/Security/KeyTest.cs new file mode 100644 index 000000000000..5799e5be93d5 --- /dev/null +++ b/tests/monotouch-test/Security/KeyTest.cs @@ -0,0 +1,304 @@ +// +// SecKey Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2015 Xamarin Inc. +// + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +#if XAMCORE_2_0 +using Foundation; +using Security; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class KeyTest { + + static X509Certificate2 _c; + static X509Certificate2 c { + get { + if (_c == null) + _c = new X509Certificate2 (ImportExportTest.farscape_pfx, "farscape"); + return _c; + } + } + + [Test] + public void Encrypt_Old () + { + // the old API was not working but the crash was fixed, still you need to provide an adequatly sized buffer + using (SecPolicy p = SecPolicy.CreateBasicX509Policy ()) + using (SecTrust t = new SecTrust (c, p)) { + // getting the public key won't (always) work if evaluate was not called + t.Evaluate (); + using (SecKey pubkey = t.GetPublicKey ()) { + byte[] plain = new byte [20]; + byte[] cipher = new byte [pubkey.BlockSize]; + Assert.That (pubkey.Encrypt (SecPadding.PKCS1, plain, cipher), Is.EqualTo (SecStatusCode.Success), "Encrypt"); + } + } + } + + [Test] + public void Encrypt_Empty () + { + using (SecPolicy p = SecPolicy.CreateBasicX509Policy ()) + using (SecTrust t = new SecTrust (c, p)) { + // getting the public key won't (always) work if evaluate was not called + t.Evaluate (); + using (SecKey pubkey = t.GetPublicKey ()) { + byte[] plain = new byte [0]; + byte[] secret; + Assert.That (pubkey.Encrypt (SecPadding.PKCS1, plain, out secret), Is.EqualTo (SecStatusCode.Success), "Encrypt"); + Assert.That (secret.Length, Is.EqualTo (128), "secret.Length"); + } + } + } + + [Test] + public void Encrypt_New () + { + using (SecPolicy p = SecPolicy.CreateBasicX509Policy ()) + using (SecTrust t = new SecTrust (c, p)) { + // getting the public key won't (always) work if evaluate was not called + t.Evaluate (); + using (SecKey pubkey = t.GetPublicKey ()) { + byte[] plain = new byte [20]; + byte[] secret; + Assert.That (pubkey.Encrypt (SecPadding.PKCS1, plain, out secret), Is.EqualTo (SecStatusCode.Success), "Encrypt"); + Assert.That (secret.Length, Is.EqualTo (128), "secret.Length"); + } + } + } + + [Test] + public void RoundtripRSA512PKCS1 () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 512; // it's not a performance test :) + + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "GenerateKeyPair"); + + byte [] plain = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + byte [] cipher; + Assert.That (public_key.Encrypt (SecPadding.PKCS1, plain, out cipher), Is.EqualTo (SecStatusCode.Success), "Encrypt"); + public_key.Dispose (); + + byte[] result; + Assert.That (private_key.Decrypt (SecPadding.PKCS1, cipher, out result), Is.EqualTo (SecStatusCode.Success), "Decrypt"); + Assert.That (plain, Is.EqualTo (result), "match"); + private_key.Dispose (); + } + } + + [Test] + public void EncryptTooLarge () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 512; // it's not a performance test :) + + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "GenerateKeyPair"); + + byte [] plain = new byte [64]; // 64 * 8 == 512 - but there's the padding to consider + byte [] cipher; + Assert.That (public_key.Encrypt (SecPadding.PKCS1, plain, out cipher), Is.EqualTo (SecStatusCode.Param), "Encrypt"); + + public_key.Dispose (); + private_key.Dispose (); + } + } + + [Test] + public void RoundtripRSA1024OAEP () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 1024; // it's not a performance test :) + + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "GenerateKeyPair"); + + byte [] plain = new byte [0]; + byte [] cipher; + Assert.That (public_key.Encrypt (SecPadding.OAEP, plain, out cipher), Is.EqualTo (SecStatusCode.Success), "Encrypt"); + public_key.Dispose (); + + byte[] result; + Assert.That (private_key.Decrypt (SecPadding.OAEP, cipher, out result), Is.EqualTo (SecStatusCode.Success), "Decrypt"); + Assert.That (plain, Is.EqualTo (result), "match"); + private_key.Dispose (); + } + } + + [Test] + public void SignVerifyRSA512PKCS1SHA1 () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 512; // it's not a performance test :) + + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "GenerateKeyPair"); + + byte [] hash = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + byte [] sign; + Assert.That (private_key.RawSign (SecPadding.PKCS1SHA1, hash, out sign), Is.EqualTo (SecStatusCode.Success), "RawSign"); + Assert.That (public_key.RawVerify (SecPadding.PKCS1SHA1, hash, sign), Is.EqualTo (SecStatusCode.Success), "RawVerify"); + + var empty = new byte [0]; + Assert.That (private_key.RawSign (SecPadding.PKCS1SHA1, empty, out sign), Is.EqualTo (SecStatusCode.Param), "RawSign-empty"); + Assert.That (public_key.RawVerify (SecPadding.PKCS1SHA1, empty, empty), Is.EqualTo (SecStatusCode.Param), "RawVerify-empty"); + + private_key.Dispose (); + public_key.Dispose (); + } + } + + [Test] + public void SignVerifyECSHA1 () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.EC; + record.KeySizeInBits = 256; // it's not a performance test :) + + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "GenerateKeyPair"); + + byte [] hash = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + byte [] sign; + // PKCS1SHA1 implies RSA (oid) + Assert.That (private_key.RawSign (SecPadding.PKCS1, hash, out sign), Is.EqualTo (SecStatusCode.Success), "RawSign"); + Assert.That (public_key.RawVerify (SecPadding.PKCS1, hash, sign), Is.EqualTo (SecStatusCode.Success), "RawVerify"); + + var empty = new byte [0]; + // there does not seem to be a length-check on PKCS1, likely because not knowning the hash algorithm makes it harder + Assert.That (private_key.RawSign (SecPadding.PKCS1, empty, out sign), Is.EqualTo (SecStatusCode.Success), "RawSign-empty"); + // but that does not work at verification time + Assert.That (public_key.RawVerify (SecPadding.PKCS1, empty, empty), Is.EqualTo ((SecStatusCode)(-9809)), "RawVerify-empty"); + + private_key.Dispose (); + public_key.Dispose (); + } + } + + [Test] + public void GenerateKeyPairTooLargeRSA () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + // maximum documented as 2048, .NET maximum is 16384 + record.KeySizeInBits = 16384; + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Param), "16384"); + record.KeySizeInBits = 8192; + if (TestRuntime.CheckiOSSystemVersion (9, 0)) { + // It seems iOS 9 supports 8192, but it takes a long time to generate (~40 seconds on my iPad Air 2), so skip it. +// Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "8192"); + } else { + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Param), "8192"); + } + } + /* On iOS 7.1 the device console logs will show: + * + * Mar 18 08:27:30 Mercure monotouchtest[1397] : SecRSAPrivateKeyInit Invalid or missing key size in: { + * bsiz = 16384; + * class = keys; + * type = 42; + * } + * Mar 18 08:27:30 Mercure monotouchtest[1397] : SecKeyCreate init RSAPrivateKey key: -50 + */ + } + + [Test] + [Ignore ("Just to compare performance with BenchmarkNative4096")] + public void BenchmarkManaged4096 () + { + var chrono = new Stopwatch (); + chrono.Start (); + var rsa = new RSACryptoServiceProvider (4096); + Assert.IsNotNull (rsa.ExportParameters (true), "ExportParameters"); // that will provoke the key generation + Console.WriteLine ("Key generation {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + byte [] hash = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + var result = rsa.Encrypt (hash, true); + Console.WriteLine ("Encrypt {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + rsa.Decrypt (result, true); + Console.WriteLine ("Decrypt {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + result = rsa.SignHash (hash, null /* SHA1 */); + Console.WriteLine ("Sign {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + rsa.VerifyHash (hash, null, result); + Console.WriteLine ("Verify {0} ms", chrono.ElapsedMilliseconds); + } + + [Test] + [Ignore ("Just to compare performance with BenchmarkManaged4096")] + public void BenchmarkNative4096 () + { + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 4096; + + var chrono = new Stopwatch (); + chrono.Start (); + Assert.That (SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key), Is.EqualTo (SecStatusCode.Success), "GenerateKeyPair"); + Console.WriteLine ("Key generation {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + byte [] hash = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + byte[] result; + public_key.Encrypt (SecPadding.OAEP, hash, out result); + Console.WriteLine ("Encrypt {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + private_key.Decrypt (SecPadding.OAEP, result, out result); + Console.WriteLine ("Decrypt {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + private_key.RawSign (SecPadding.PKCS1SHA1, hash, out result); + Console.WriteLine ("Sign {0} ms", chrono.ElapsedMilliseconds); + chrono.Restart (); + + public_key.RawVerify (SecPadding.PKCS1SHA1, hash, result); + Console.WriteLine ("Verify {0} ms", chrono.ElapsedMilliseconds); + + private_key.Dispose (); + public_key.Dispose (); + } + } + } +} diff --git a/tests/monotouch-test/Security/PolicyTest.cs b/tests/monotouch-test/Security/PolicyTest.cs new file mode 100644 index 000000000000..e6d1d610c972 --- /dev/null +++ b/tests/monotouch-test/Security/PolicyTest.cs @@ -0,0 +1,181 @@ +// +// SecPolicy Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. +// + +using System; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using Security; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class SecPolicyTest { + + [DllImport (Constants.CoreFoundationLibrary)] + extern static nint CFGetRetainCount (IntPtr handle); + + [Test] + public void SslServerNoHost () + { + using (var policy = SecPolicy.CreateSslPolicy (true, null)) { + Assert.That (policy.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 1), "RetainCount"); + + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + using (var properties = policy.GetProperties ()) { + Assert.That (properties.Handle, Is.Not.EqualTo (IntPtr.Zero), "Properties.Handle"); + Assert.That (CFGetRetainCount (properties.Handle), Is.EqualTo ((nint) 1), "Properties.RetainCount"); + Assert.That (properties.Count, Is.EqualTo ((nuint) 1), "Count"); + Assert.That (properties [SecPolicyPropertyKey.Oid].ToString (), Is.EqualTo ("1.2.840.113635.100.1.3"), "SecPolicyOid"); + } + } + } + } + + [Test] + public void SslServer () + { + using (var policy = SecPolicy.CreateSslPolicy (true, "google.com")) { + Assert.That (policy.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 1), "RetainCount"); + + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + using (var properties = policy.GetProperties ()) { + Assert.That (properties.Handle, Is.Not.EqualTo (IntPtr.Zero), "Properties.Handle"); + Assert.That (CFGetRetainCount (properties.Handle), Is.EqualTo ((nint) 1), "Properties.RetainCount"); + Assert.That (properties.Count, Is.EqualTo ((nuint) 2), "Count"); + Assert.That (properties [SecPolicyPropertyKey.Oid].ToString (), Is.EqualTo ("1.2.840.113635.100.1.3"), "SecPolicyOid"); + Assert.That (properties [SecPolicyPropertyKey.Name].ToString (), Is.EqualTo ("google.com"), "SecPolicyName"); + } + } + } + } + + [Test] + public void SslClient () + { + using (var policy = SecPolicy.CreateSslPolicy (false, null)) { + Assert.That (policy.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 1), "RetainCount"); + + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + using (var properties = policy.GetProperties ()) { + Assert.That (properties.Handle, Is.Not.EqualTo (IntPtr.Zero), "Properties.Handle"); + Assert.That (CFGetRetainCount (properties.Handle), Is.EqualTo ((nint) 1), "Properties.RetainCount"); + Assert.That (properties.Count, Is.EqualTo ((nuint) 2), "Count"); + Assert.That (properties [SecPolicyPropertyKey.Oid].ToString (), Is.EqualTo ("1.2.840.113635.100.1.3"), "SecPolicyOid"); + Assert.That (properties [SecPolicyPropertyKey.Client].ToString (), Is.EqualTo ("1"), "SecPolicyClient"); + } + } + } + } + + [Test] + public void BasicX509Policy () + { + using (var policy = SecPolicy.CreateBasicX509Policy ()) { + Assert.That (policy.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 1), "RetainCount"); + + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + using (var properties = policy.GetProperties ()) { + Assert.That (properties.Handle, Is.Not.EqualTo (IntPtr.Zero), "Properties.Handle"); + Assert.That (CFGetRetainCount (properties.Handle), Is.EqualTo ((nint) 1), "Properties.RetainCount"); + Assert.That (properties.Count, Is.EqualTo ((nuint) 1), "Count"); + Assert.That (properties [SecPolicyPropertyKey.Oid].ToString (), Is.EqualTo ("1.2.840.113635.100.1.2"), "SecPolicyOid"); + } + } + } + } + + [Test] + public void RevocationPolicy () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + using (var policy = SecPolicy.CreateRevocationPolicy (SecRevocation.UseAnyAvailableMethod | SecRevocation.RequirePositiveResponse)) { + Assert.That (policy.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 1), "RetainCount"); + + using (var properties = policy.GetProperties ()) { + Assert.That (properties.Handle, Is.Not.EqualTo (IntPtr.Zero), "Properties.Handle"); + Assert.That (CFGetRetainCount (properties.Handle), Is.EqualTo ((nint) 1), "Properties.RetainCount"); + Assert.That (properties.Count, Is.EqualTo ((nuint) 1), "Count"); + Assert.That (properties [SecPolicyPropertyKey.Oid].ToString (), Is.EqualTo ("1.2.840.113635.100.1.21"), "SecPolicyOid"); + } + } + } + + void CreatePolicy (NSString oid) + { + string name = oid + "."; + using (var policy = SecPolicy.CreatePolicy (oid, null)) { + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 1), name + "RetainCount"); + Assert.That (policy.GetProperties ().Values [0], Is.EqualTo (oid), name + "SecPolicyOid"); + } + } + + [Test] + public void CreatWellKnownPolicies () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + CreatePolicy (SecPolicyIdentifier.AppleX509Basic); + CreatePolicy (SecPolicyIdentifier.AppleSSL); + CreatePolicy (SecPolicyIdentifier.AppleSMIME); + // crash + // CreatePolicy (SecPolicyIdentifier.AppleEAP); + CreatePolicy (SecPolicyIdentifier.AppleIPsec); + CreatePolicy (SecPolicyIdentifier.AppleCodeSigning); + CreatePolicy (SecPolicyIdentifier.AppleIDValidation); + // invalid handle ? not yet supported ?!? + // CreatePolicy (SecPolicyIdentifier.AppleTimeStamping); + CreatePolicy (SecPolicyIdentifier.AppleRevocation); + } + + [Test] + public void CreateUnknownPolicy () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7"); + + using (var oid = new NSString ("1.2.3.4")) { + Assert.Throws (delegate { + SecPolicy.CreatePolicy (oid, null); + }); + } + } + } +} diff --git a/tests/monotouch-test/Security/RecordTest.cs b/tests/monotouch-test/Security/RecordTest.cs new file mode 100644 index 000000000000..ca4f5d792baa --- /dev/null +++ b/tests/monotouch-test/Security/RecordTest.cs @@ -0,0 +1,278 @@ +// Copyright 2014-2015 Xamarin Inc. All rights reserved + +using System; +#if XAMCORE_2_0 +using Foundation; +using Security; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using NUnit.Framework.Internal; + +namespace MonoTouchFixtures.Security { + + [TestFixture] + [Preserve (AllMembers = true)] + public class RecordTest { + + [Test] + public void Identity () + { + var rec = new SecRecord (SecKind.Identity) { + Account = "Username", + ValueData = NSData.FromString ("Password"), + }; + + // prior to iOS7 you had to deal without the class + using (var dict = rec.ToDictionary ()) { + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.That (dict ["class"].ToString (), Is.EqualTo ("idnt"), "idnt"); + else + Assert.Null (dict ["class"], "idnt"); + } + } + + void Accessible (SecAccessible access) + { + var rec = new SecRecord (SecKind.GenericPassword) { + Account = "Username" + }; + SecKeyChain.Remove (rec); // it might already exists (or not) + + rec = new SecRecord (SecKind.GenericPassword) { + Account = "Username", + ValueData = NSData.FromString ("Password"), + Accessible = access + }; + + Assert.That (SecKeyChain.Add (rec), Is.EqualTo (SecStatusCode.Success), "Add"); + + SecStatusCode code; + var match = SecKeyChain.QueryAsRecord (rec, out code); + Assert.That (code, Is.EqualTo (SecStatusCode.Success), "QueryAsRecord"); + + Assert.That (match.Accessible, Is.EqualTo (access), "Accessible"); + } + + [Test] + public void Match () + { + var rec = new SecRecord (SecKind.GenericPassword) { + Account = "Username", + }; + Assert.Null (rec.MatchIssuers, "MatchIssuers"); + // we do not have a way (except the getter) to craete SecKeyChain instances + Assert.Null (rec.MatchItemList, "MatchItemList"); + + using (var data = new NSData ()) { + rec.MatchIssuers = new NSData[] { data }; + Assert.AreSame (rec.MatchIssuers [0], data, "MatchIssuers [0]"); + } + + if (!TestRuntime.CheckiOSSystemVersion (9,0)) + return; + Assert.That (rec.AuthenticationUI, Is.EqualTo (SecAuthenticationUI.NotSet), "AuthenticationUI-get"); + rec.AuthenticationUI = SecAuthenticationUI.Allow; + Assert.That (rec.AuthenticationUI, Is.EqualTo (SecAuthenticationUI.Allow), "AuthenticationUI-set"); + } + + [Test] + public void Accessible_17579 () + { + Accessible (SecAccessible.AfterFirstUnlock); + Accessible (SecAccessible.AfterFirstUnlockThisDeviceOnly); + Accessible (SecAccessible.Always); + Accessible (SecAccessible.AlwaysThisDeviceOnly); + Accessible (SecAccessible.WhenUnlocked); + Accessible (SecAccessible.WhenUnlockedThisDeviceOnly); + } + + void Protocol (SecProtocol protocol) + { + var rec = new SecRecord (SecKind.InternetPassword) { + Account = "Protocol" + }; + SecKeyChain.Remove (rec); // it might already exists (or not) + + rec = new SecRecord (SecKind.InternetPassword) { + Account = "Protocol", + ValueData = NSData.FromString ("Password"), + Protocol = protocol, + Server = "www.xamarin.com" + }; + + Assert.That (SecKeyChain.Add (rec), Is.EqualTo (SecStatusCode.Success), "Add"); + + SecStatusCode code; + var match = SecKeyChain.QueryAsRecord (rec, out code); + Assert.That (code, Is.EqualTo (SecStatusCode.Success), "QueryAsRecord"); + + Assert.That (match.Protocol, Is.EqualTo (protocol), "Protocol"); + } + + [Test] + public void Protocol_17579 () + { + Protocol (SecProtocol.Afp); + Protocol (SecProtocol.AppleTalk); + Protocol (SecProtocol.Daap); + Protocol (SecProtocol.Eppc); + Protocol (SecProtocol.Ftp); + Protocol (SecProtocol.FtpAccount); + Protocol (SecProtocol.FtpProxy); + Protocol (SecProtocol.Ftps); + Protocol (SecProtocol.Http); + Protocol (SecProtocol.HttpProxy); + Protocol (SecProtocol.Https); + Protocol (SecProtocol.HttpsProxy); + Protocol (SecProtocol.Imap); + Protocol (SecProtocol.Imaps); + Protocol (SecProtocol.Ipp); + Protocol (SecProtocol.Irc); + Protocol (SecProtocol.Ircs); + Protocol (SecProtocol.Ldap); + Protocol (SecProtocol.Ldaps); + Protocol (SecProtocol.Nntp); + Protocol (SecProtocol.Nntps); + Protocol (SecProtocol.Pop3); + Protocol (SecProtocol.Pop3s); + Protocol (SecProtocol.Rtsp); + Protocol (SecProtocol.RtspProxy); + Protocol (SecProtocol.Smb); + Protocol (SecProtocol.Smtp); + Protocol (SecProtocol.Socks); + Protocol (SecProtocol.Ssh); + Protocol (SecProtocol.Telnet); + Protocol (SecProtocol.Telnets); + } + + void AuthenticationType (SecAuthenticationType type) + { + var rec = new SecRecord (SecKind.InternetPassword) { + Account = "AuthenticationType" + }; + SecKeyChain.Remove (rec); // it might already exists (or not) + + rec = new SecRecord (SecKind.InternetPassword) { + Account = "AuthenticationType", + ValueData = NSData.FromString ("Password"), + AuthenticationType = type, + Server = "www.xamarin.com" + }; + + Assert.That (SecKeyChain.Add (rec), Is.EqualTo (SecStatusCode.Success), "Add"); + + SecStatusCode code; + var match = SecKeyChain.QueryAsRecord (rec, out code); + Assert.That (code, Is.EqualTo (SecStatusCode.Success), "QueryAsRecord"); + + Assert.That (match.AuthenticationType, Is.EqualTo (type), "AuthenticationType"); + } + + [Test] + public void AuthenticationType_17579 () + { + AuthenticationType (SecAuthenticationType.Default); + AuthenticationType (SecAuthenticationType.Dpa); + AuthenticationType (SecAuthenticationType.HtmlForm); + AuthenticationType (SecAuthenticationType.HttpBasic); + AuthenticationType (SecAuthenticationType.HttpDigest); + AuthenticationType (SecAuthenticationType.Msn); + AuthenticationType (SecAuthenticationType.Ntlm); + AuthenticationType (SecAuthenticationType.Rpa); + } + + // Test Case provided by user + // This test case scenario used to fail under iOS 6 or lower + [Test] + public void DeskCase_83099_InmutableDictionary () + { + var testUsername = "testusername"; + + //TEST 1: Save a keychain value + var test1 = SaveUserPassword (testUsername, "testValue1"); + Assert.IsTrue (test1, "Password could not be saved to keychain"); + + //TEST 2: Get the saved keychain value + var test2 = GetUserPassword (testUsername); + Assert.IsTrue (StringUtil.StringsEqual (test2, "testValue1", false)); + + //TEST 3: Update the keychain value + var test3 = SaveUserPassword (testUsername, "testValue2"); + Assert.IsTrue (test3, "Password could not be saved to keychain"); + + //TEST 4: Get the updated keychain value + var test4 = GetUserPassword (testUsername); + Assert.IsTrue (StringUtil.StringsEqual (test4, "testValue2", false)); + + //TEST 5: Clear the keychain values + var test5 = ClearUserPassword (testUsername); + Assert.IsTrue (test5, "Password could not be cleared from keychain"); + + //TEST 6: Verify no keychain value + var test6 = GetUserPassword (testUsername); + Assert.IsNull (test6, "No password should exist here"); + } + + public static string GetUserPassword (string username) + { + string password = null; + var searchRecord = new SecRecord (SecKind.InternetPassword) { + Server = "Test1", + Account = username.ToLower() + }; + SecStatusCode code; + var record = SecKeyChain.QueryAsRecord(searchRecord, out code); + if (code == SecStatusCode.Success && record != null) + password = NSString.FromData (record.ValueData, NSStringEncoding.UTF8); + return password; + } + + public static bool SaveUserPassword (string username, string password) + { + var success = false; + var searchRecord = new SecRecord (SecKind.InternetPassword) { + Server = "Test1", + Account = username.ToLower () + }; + SecStatusCode queryCode; + var record = SecKeyChain.QueryAsRecord (searchRecord, out queryCode); + if (queryCode == SecStatusCode.ItemNotFound) { + record = new SecRecord (SecKind.InternetPassword) { + Server = "Test1", + Account = username.ToLower (), + ValueData = NSData.FromString (password) + }; + var addCode = SecKeyChain.Add (record); + success = (addCode == SecStatusCode.Success); + } + if (queryCode == SecStatusCode.Success && record != null) { + record.ValueData = NSData.FromString (password); + var updateCode = SecKeyChain.Update (searchRecord, record); + success = (updateCode == SecStatusCode.Success); + } + return success; + } + + public static bool ClearUserPassword (string username) + { + var success = false; + var searchRecord = new SecRecord (SecKind.InternetPassword) { + Server = "Test1", + Account = username.ToLower () + }; + SecStatusCode queryCode; + var record = SecKeyChain.QueryAsRecord (searchRecord, out queryCode); + + if (queryCode == SecStatusCode.Success && record != null) { + var removeCode = SecKeyChain.Remove (searchRecord); + success = (removeCode == SecStatusCode.Success); + } + return success; + } + } +} diff --git a/tests/monotouch-test/Security/SecSharedCredentialTest.cs b/tests/monotouch-test/Security/SecSharedCredentialTest.cs new file mode 100644 index 000000000000..b995126c5108 --- /dev/null +++ b/tests/monotouch-test/Security/SecSharedCredentialTest.cs @@ -0,0 +1,142 @@ +#if !__WATCHOS__ +using System; +using System.Threading; + +#if XAMCORE_2_0 +using Foundation; +using Security; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.Security; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class SecSharedCredentialTest { + + string domainName; + string account; + string password; + AutoResetEvent waitEvent; + + [SetUp] + public void SetUp () + { + domainName = "com.xamarin.monotouch-test"; + account = "twitter"; + password = "12345678"; + waitEvent = new AutoResetEvent (false); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void AddSharedWebCredentialNullDomain () + { + domainName = null; + Action handler = (NSError e) => { + Assert.IsNull (e); + waitEvent.Set (); + }; + SecSharedCredential.AddSharedWebCredential (domainName, account, password, handler); + waitEvent.WaitOne (); + Assert.Pass ("Block was correctly executed."); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void AddSharedWebCredentialNullAccount () + { + account = null; + Action handler = (NSError e) => { + Assert.IsNull (e); + waitEvent.Set (); + }; + SecSharedCredential.AddSharedWebCredential (domainName, account, password, handler); + waitEvent.WaitOne (); + Assert.Pass ("Block was correctly executed."); + } + + [Test] + // We do not want to block for a long period of time if the event is not set. + // We are testing the fact that the trampoline works. + [Timeout (5000)] + public void AddSharedWebCredentialNotNullPassword () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring AddSharedWebCredentialNotNullPassword test: Requires iOS8+"); + + Action handler = (NSError e) => { + // we do nothing, if we did block the test should be interactive because a dialog is shown. + }; + SecSharedCredential.AddSharedWebCredential (domainName, account, password, handler); + } + + [Test] + // We do not want to block for a long period of time if the event is not set. + // We are testing the fact that the trampoline works. + [Timeout (5000)] + public void AddSharedWebCredentialNullPassword () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring AddSharedWebCredentialNullPassword test: Requires iOS8+"); + + password = null; + Action handler = (NSError e) => { + // we do nothing, if we did block the test should be interactive because a dialog is shown. + }; + SecSharedCredential.AddSharedWebCredential (domainName, account, password, handler); + } + + [Test] + // We do not want to block for a long period of time if the event is not set. + // We are testing the fact that the trampoline works. + [Timeout (5000)] + public void RequestSharedWebCredentialNullDomain () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring RequestSharedWebCredentialNullDomain test: Requires iOS8+"); + + Action getHandler = (string [] pwds, NSError e) => { + waitEvent.Set (); + }; + SecSharedCredential.RequestSharedWebCredential (null, account, getHandler); + waitEvent.WaitOne (); + Assert.Pass ("Block was correctly executed."); + } + + [Test] + // We do not want to block for a long period of time if the event is not set. + // We are testing the fact that the trampoline works. + [Timeout (5000)] + public void RequestSharedWebCredentialNullAccount () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring RequestSharedWebCredentialNullAccount test: Requires iOS8+"); + + Action getHandler = (string [] pwds, NSError e) => { + waitEvent.Set (); + }; + SecSharedCredential.RequestSharedWebCredential (null, null, getHandler); + waitEvent.WaitOne (); + Assert.Pass ("Block was correctly executed."); + } + + [Test] + public void CreateSharedWebCredentialPassword () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring CreateSharedWebCredentialPassword test: Requires iOS8+"); + + var pwd = SecSharedCredential.CreateSharedWebCredentialPassword (); + Assert.IsNotNull (pwd); + } + + } +} +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/Security/SecureTransportTest.cs b/tests/monotouch-test/Security/SecureTransportTest.cs new file mode 100644 index 000000000000..a0d75234cb52 --- /dev/null +++ b/tests/monotouch-test/Security/SecureTransportTest.cs @@ -0,0 +1,196 @@ +// +// SecureTransport Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. +// + +using System; +using System.Net.Sockets; +using System.Text; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using Security; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class SecureTransportTest { + + const int errSecParam = -50; + const int errSecAllocate = -108; + + [Test] + public void StreamDefaults () + { + using (var ssl = new SslContext (SslProtocolSide.Client, SslConnectionType.Stream)) { + Assert.That (ssl.BufferedReadSize, Is.EqualTo ((nint) 0), "BufferedReadSize"); + Assert.That (ssl.ClientCertificateState, Is.EqualTo (SslClientCertificateState.None), "ClientCertificateState"); + Assert.Null (ssl.Connection, "Connection"); + Assert.That (ssl.DatagramWriteSize, Is.EqualTo ((nint) 0), "DatagramWriteSize"); + Assert.That (ssl.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (ssl.MaxDatagramRecordSize, Is.EqualTo ((nint) 0), "MaxDatagramRecordSize"); + Assert.That (ssl.MaxProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "MaxProtocol"); + Assert.That (ssl.MinProtocol, Is.EqualTo (SslProtocol.Ssl_3_0), "MinProtocol"); + Assert.That (ssl.NegotiatedCipher, Is.EqualTo (SslCipherSuite.SSL_NULL_WITH_NULL_NULL), "NegotiatedCipher"); + Assert.That (ssl.NegotiatedProtocol, Is.EqualTo (SslProtocol.Unknown), "NegotiatedProtocol"); + + Assert.That (ssl.PeerDomainName, Is.Empty, "PeerDomainName"); + ssl.PeerDomainName = "google.ca"; + Assert.That (ssl.PeerDomainName, Is.EqualTo ("google.ca"), "PeerDomainName-2"); + ssl.PeerDomainName = null; + Assert.That (ssl.PeerDomainName, Is.Empty, "PeerDomainName"); + + Assert.Null (ssl.PeerId, "PeerId"); + ssl.PeerId = new byte [] { 0xff }; + Assert.That (ssl.PeerId.Length, Is.EqualTo (1), "1a"); + + // note: SSLSetPeerID (see Apple open source code) does not accept a null/zero-length value + ssl.PeerId = new byte [0]; + Assert.That ((int) ssl.GetLastStatus (), Is.EqualTo (errSecParam), "set_PeerId/empty"); + Assert.That (ssl.PeerId.Length, Is.EqualTo (1), "1b"); + + ssl.PeerId = new byte [] { 0x01, 0x02 }; + Assert.That (ssl.PeerId.Length, Is.EqualTo (2), "2"); + + Assert.Null (ssl.PeerTrust, "PeerTrust"); + Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Idle), "SessionState"); + + Assert.That ((int)ssl.SetDatagramHelloCookie (new byte [32]), Is.EqualTo (-50), "no cookie in stream"); + + // Assert.Null (ssl.GetDistinguishedNames (), "GetDistinguishedNames"); + } + } + + [Test] + public void DatagramDefaults () + { + nint dsize = TestRuntime.CheckSystemAndSDKVersion (8, 0) ? 1327 : 1387; + using (var ssl = new SslContext (SslProtocolSide.Client, SslConnectionType.Datagram)) { + Assert.That (ssl.BufferedReadSize, Is.EqualTo ((nint) 0), "BufferedReadSize"); + Assert.Null (ssl.Connection, "Connection"); + Assert.That (ssl.DatagramWriteSize, Is.EqualTo (dsize), "DatagramWriteSize"); + Assert.That (ssl.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (ssl.MaxDatagramRecordSize, Is.EqualTo ((nint) 1400), "MaxDatagramRecordSize"); + Assert.That (ssl.MaxProtocol, Is.EqualTo (SslProtocol.Dtls_1_0), "MaxProtocol"); + Assert.That (ssl.MinProtocol, Is.EqualTo (SslProtocol.Dtls_1_0), "MinProtocol"); + Assert.That (ssl.NegotiatedCipher, Is.EqualTo (SslCipherSuite.SSL_NULL_WITH_NULL_NULL), "NegotiatedCipher"); + Assert.That (ssl.NegotiatedProtocol, Is.EqualTo (SslProtocol.Unknown), "NegotiatedProtocol"); + Assert.Null (ssl.PeerId, "PeerId"); + Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Idle), "SessionState"); + + ssl.PeerId = new byte [] { 0xff }; + Assert.That (ssl.PeerId.Length, Is.EqualTo (1), "1"); + // note: SSLSetPeerID (see Apple open source code) does not accept a null/zero-length value + ssl.PeerId = null; + Assert.That ((int) ssl.GetLastStatus (), Is.EqualTo (errSecParam), "set_PeerId/null"); + + Assert.That ((int)ssl.SetDatagramHelloCookie (new byte [33]), Is.EqualTo (-50), "cookie to long"); + Assert.That (ssl.SetDatagramHelloCookie (new byte [32]), Is.EqualTo (SslStatus.Success), "tasty cookie");; + Assert.That (ssl.SetDatagramHelloCookie (new byte [1]), Is.EqualTo (SslStatus.Success), "fat free cookie"); + Assert.That (ssl.SetDatagramHelloCookie (null), Is.EqualTo (SslStatus.Success), "no more cookies"); + } + } + + [Test] + public void SslSupportedCiphers () + { + int ssl_client_ciphers = -1; + using (var client = new SslContext (SslProtocolSide.Client, SslConnectionType.Stream)) { + // maximum downgrade + client.MaxProtocol = client.MinProtocol; + var ciphers = client.GetSupportedCiphers (); + ssl_client_ciphers = ciphers.Count; + Assert.That (ssl_client_ciphers, Is.AtLeast (1), "GetSupportedCiphers"); + // we can't really scan for SSL_* since (some of) the values are identical to TLS_ + // useful the other way around + } + int ssl_server_ciphers = -1; + using (var server = new SslContext (SslProtocolSide.Server, SslConnectionType.Stream)) { + // no downgrade, shows that the ciphers are not really restriced + var ciphers = server.GetSupportedCiphers (); + ssl_server_ciphers = ciphers.Count; + Assert.That (ssl_server_ciphers, Is.AtLeast (1), "GetSupportedCiphers"); + // we can't really scan for SSL_* since (some of) the values are identical to TLS_ + // useful the other way around + + // make sure we have names for all ciphers - except old export ones (that we do not want to promote) + // e.g. iOS 5.1 still supports them + foreach (var cipher in ciphers) { + string s = cipher.ToString (); + if (s.Length < 8) + Console.WriteLine (s); + Assert.True (s.StartsWith ("SSL_", StringComparison.Ordinal) || s.StartsWith ("TLS_", StringComparison.Ordinal), s); + } + } + Assert.That (ssl_client_ciphers, Is.EqualTo (ssl_server_ciphers), "same"); + } + + [Test] + public void Tls12 () + { + var client = new TcpClient ("google.ca", 443); + using (NetworkStream ns = client.GetStream ()) + using (var ssl = new SslContext (SslProtocolSide.Client, SslConnectionType.Stream)) { + + ssl.MinProtocol = SslProtocol.Tls_1_2; + Assert.That (ssl.MinProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "MinProtocol"); + + ssl.Connection = new SslStreamConnection (ns); + + var result = ssl.Handshake (); + while (result == SslStatus.WouldBlock || result == (SslStatus) (-108)) { + // we need to ask again - but if we're too fast we'll get -108 (errSecAllocate) + Thread.Sleep (100); + // during the above call SessionState is Handshake + Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Handshake), "Handshake/in progress"); + result = ssl.Handshake (); + } + Assert.That (result, Is.EqualTo (SslStatus.Success), "Handshake/done"); + + // FIXME: iOS 8 beta 1 bug ?!? the state is not updated (maybe delayed?) but the code still works + //Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Connected), "Connected"); + Assert.That (ssl.NegotiatedCipher, Is.Not.EqualTo (SslCipherSuite.SSL_NULL_WITH_NULL_NULL), "NegotiatedCipher"); + Assert.That (ssl.NegotiatedProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "NegotiatedProtocol"); + + nint processed; + var data = Encoding.UTF8.GetBytes ("GET / HTTP/1.0" + Environment.NewLine + Environment.NewLine); + result = ssl.Write (data, out processed); + Assert.That (processed, Is.EqualTo ((nint) data.Length), "small buffer"); + Assert.That (result, Is.EqualTo (SslStatus.Success), "Write"); + + data = new byte [1024]; + result = ssl.Read (data, out processed); + while (result == SslStatus.WouldBlock) + result = ssl.Read (data, out processed); + Assert.That (result, Is.EqualTo (SslStatus.Success), "Read"); + + string s = Encoding.UTF8.GetString (data, 0, (int) processed); + // The result apparently depends on where you are: I get a 302, the bots get a 200. + Assert.That (s, Is.StringStarting ("HTTP/1.0 302 Found").Or.StringStarting ("HTTP/1.0 200 OK"), "response"); + } + } + } +} \ No newline at end of file diff --git a/tests/monotouch-test/Security/TrustTest.cs b/tests/monotouch-test/Security/TrustTest.cs new file mode 100644 index 000000000000..7604892d4557 --- /dev/null +++ b/tests/monotouch-test/Security/TrustTest.cs @@ -0,0 +1,335 @@ +// +// SecTrust Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using Security; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.Security { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class TrustTest { + + [DllImport (Constants.CoreFoundationLibrary)] + extern static nint CFGetRetainCount (IntPtr handle); + + // SecTrustResult.Unspecified == "Use System Defaults" (valid) + + // some days it seems iOS timeout just a bit too fast and we get a lot of false positives + // this will try again a few times (giving the network request a chance to get back) + static SecTrustResult Evaluate (SecTrust trust, bool expect_recoverable = false) + { + SecTrustResult result = SecTrustResult.Deny; + for (int i = 0; i < 8; i++) { + result = trust.Evaluate (); + if (result != SecTrustResult.RecoverableTrustFailure || expect_recoverable) + return result; + NSRunLoop.Main.RunUntil (NSDate.Now.AddSeconds (i)); + } + return result; + } + + [Test] + public void Trust_Leaf_Only () + { + X509Certificate x = new X509Certificate (CertificateTest.mail_google_com); + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.google.com")) + using (var trust = new SecTrust (x, policy)) { + Assert.That (CFGetRetainCount (trust.Handle), Is.EqualTo ((nint) 1), "RetainCount(trust)"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 2), "RetainCount(policy)"); + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + // the system was able to construct the chain based on the single certificate + Assert.That (Evaluate (trust, true), Is.EqualTo (SecTrustResult.RecoverableTrustFailure), "Evaluate"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + Assert.True (trust.NetworkFetchAllowed, "NetworkFetchAllowed-1"); + trust.NetworkFetchAllowed = false; + Assert.False (trust.NetworkFetchAllowed, "NetworkFetchAllowed-2"); + + trust.SetPolicy (policy); + + var policies = trust.GetPolicies (); + Assert.That (policies.Length, Is.EqualTo (1), "Policies.Length"); + Assert.That (policies [0].Handle, Is.EqualTo (policy.Handle), "Handle"); + } + } + } + + [Test] + public void HostName_Leaf_Only () + { + X509Certificate x = new X509Certificate (CertificateTest.mail_google_com); + // a bad hostname (mismatched) is recoverable (e.g. if you change policy) + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.xamarin.com")) + using (var trust = new SecTrust (x, policy)) { + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + Assert.That (Evaluate (trust, true), Is.EqualTo (SecTrustResult.RecoverableTrustFailure), "Evaluate"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + Assert.That (trust.GetTrustResult (), Is.EqualTo (SecTrustResult.RecoverableTrustFailure), "GetTrustResult"); + + using (var a = NSArray.FromNSObjects (policy)) + trust.SetPolicies (a); + + var policies = trust.GetPolicies (); + Assert.That (policies.Length, Is.EqualTo (1), "Policies.Length"); + Assert.That (policies [0].Handle, Is.EqualTo (policy.Handle), "Handle"); + + // since we modified the `trust` instance it's result was invalidated + Assert.That (trust.GetTrustResult (), Is.EqualTo (SecTrustResult.Invalid), "GetTrustResult-2"); + } + } + } + + [Test] + public void NoHostName () + { + X509Certificate x = new X509Certificate (CertificateTest.mail_google_com); + // a null host name means "*" (accept any name) which is not stated in Apple documentation + using (var policy = SecPolicy.CreateSslPolicy (true, null)) + using (var trust = new SecTrust (x, policy)) { + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + Assert.That (Evaluate (trust, true), Is.EqualTo (SecTrustResult.RecoverableTrustFailure), "Evaluate"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + using (var rev = SecPolicy.CreateRevocationPolicy (SecRevocation.UseAnyAvailableMethod)) { + List list = new List () { policy, rev }; + trust.SetPolicies (list); + + var policies = trust.GetPolicies (); + Assert.That (policies.Length, Is.EqualTo (2), "Policies.Length"); + } + } + } + } + + [Test] + public void Client_Leaf_Only () + { + X509Certificate x = new X509Certificate (CertificateTest.mail_google_com); + using (var policy = SecPolicy.CreateSslPolicy (false, null)) + using (var trust = new SecTrust (x, policy)) { + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + // a host name is not meaningful for client certificates + Assert.That (Evaluate (trust, true), Is.EqualTo (SecTrustResult.RecoverableTrustFailure), "Evaluate"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + // by default there's no *custom* anchors + Assert.Null (trust.GetCustomAnchorCertificates (), "GetCustomAnchorCertificates"); + + using (var results = trust.GetResult ()) { + Assert.That (CFGetRetainCount (results.Handle), Is.EqualTo ((nint) 1), "RetainCount"); + + SecTrustResult value = (SecTrustResult) (int) (NSNumber) results [SecTrustResultKey.ResultValue]; + Assert.That (value, Is.EqualTo (SecTrustResult.RecoverableTrustFailure), "ResultValue"); + } + } + } + } + + [Test] + public void Basic_Leaf_Only () + { + X509Certificate x = new X509Certificate (CertificateTest.mail_google_com); + using (var policy = SecPolicy.CreateBasicX509Policy ()) + using (var trust = new SecTrust (x, policy)) { + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + // SSL certs are a superset of the basic X509 profile + SecTrustResult result = SecTrustResult.RecoverableTrustFailure; + Assert.That (Evaluate (trust, result == SecTrustResult.RecoverableTrustFailure), Is.EqualTo (result), "Evaluate"); + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + // call GetPolicies without a SetPolicy / SetPolicies + var policies = trust.GetPolicies (); + Assert.That (policies.Length, Is.EqualTo (1), "Policies.Length"); + + using (var data = new NSData ()) { + // we do not have an easy way to get the response but the API accepts an empty NSData + trust.SetOCSPResponse (data); + } + } + } + } + + [Test] + public void Trust_NoRoot () + { + X509CertificateCollection certs = new X509CertificateCollection (); + certs.Add (new X509Certificate (CertificateTest.mail_google_com)); + certs.Add (new X509Certificate (CertificateTest.thawte_sgc_ca)); + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.google.com")) + using (var trust = new SecTrust (certs, policy)) { + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + // iOS9 is not fully happy with the basic constraints: `SecTrustEvaluate [root AnchorTrusted BasicContraints]` + // so it returns RecoverableTrustFailure and that affects the Count of trust later (it does not add to what we provided) + var ios9 = TestRuntime.CheckiOSSystemVersion (9,0); + var result = Evaluate (trust, ios9); + Assert.That (result, Is.EqualTo (ios9 ? SecTrustResult.RecoverableTrustFailure : SecTrustResult.Unspecified), "Evaluate"); + // Evalute must be called prior to Count (Apple documentation) + Assert.That (trust.Count, Is.EqualTo (ios9 ? 2 : 3), "Count"); + + using (SecKey pkey = trust.GetPublicKey ()) { + Assert.That (CFGetRetainCount (pkey.Handle), Is.EqualTo ((nint) 2), "RetainCount(pkey)"); + } + } + } + + [Test] + public void Trust_FullChain () + { + X509CertificateCollection certs = new X509CertificateCollection (); + certs.Add (new X509Certificate (CertificateTest.mail_google_com)); + certs.Add (new X509Certificate (CertificateTest.thawte_sgc_ca)); + certs.Add (new X509Certificate (CertificateTest.verisign_class3_root)); + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.google.com")) + using (var trust = new SecTrust (certs, policy)) { + // that certificate stopped being valid on September 30th, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + // iOS9 is not fully happy with the basic constraints: `SecTrustEvaluate [root AnchorTrusted BasicContraints]` + var ios9 = TestRuntime.CheckiOSSystemVersion (9,0); + var result = Evaluate (trust, ios9); + Assert.That (result, Is.EqualTo (ios9 ? SecTrustResult.RecoverableTrustFailure : SecTrustResult.Unspecified), "Evaluate"); + + // Evalute must be called prior to Count (Apple documentation) + Assert.That (trust.Count, Is.EqualTo (3), "Count"); + + using (SecCertificate sc1 = trust [0]) { + // seems the leaf gets an extra one + Assert.That (CFGetRetainCount (sc1.Handle), Is.GreaterThanOrEqualTo ((nint) 2), "RetainCount(sc1)"); + Assert.That (sc1.SubjectSummary, Is.EqualTo ("mail.google.com"), "SubjectSummary(sc1)"); + } + using (SecCertificate sc2 = trust [1]) { + Assert.That (CFGetRetainCount (sc2.Handle), Is.GreaterThanOrEqualTo ((nint) 2), "RetainCount(sc2)"); + Assert.That (sc2.SubjectSummary, Is.EqualTo ("Thawte SGC CA"), "SubjectSummary(sc2)"); + } + using (SecCertificate sc3 = trust [2]) { + Assert.That (CFGetRetainCount (sc3.Handle), Is.GreaterThanOrEqualTo ((nint) 2), "RetainCount(sc3)"); + Assert.That (sc3.SubjectSummary, Is.EqualTo ("Class 3 Public Primary Certification Authority"), "SubjectSummary(sc3)"); + } + + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + Assert.That (trust.GetTrustResult (), Is.EqualTo (ios9 ? SecTrustResult.RecoverableTrustFailure : SecTrustResult.Unspecified), "GetTrustResult"); + + trust.SetAnchorCertificates (certs); + Assert.That (trust.GetCustomAnchorCertificates ().Length, Is.EqualTo (certs.Count), "GetCustomAnchorCertificates"); + + // since we modified the `trust` instance it's result was invalidated + Assert.That (trust.GetTrustResult (), Is.EqualTo (SecTrustResult.Invalid), "GetTrustResult"); + } + } + } + + [Test] + public void Trust2_Leaf_Only () + { + X509Certificate2 x = new X509Certificate2 (CertificateTest.api_imgur_com); + using (var policy = SecPolicy.CreateSslPolicy (true, "api.imgur.com")) + using (var trust = new SecTrust (x, policy)) { + // that certificate stopped being valid on August 3rd, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + Assert.That (CFGetRetainCount (trust.Handle), Is.EqualTo ((nint) 1), "RetainCount(trust)"); + Assert.That (CFGetRetainCount (policy.Handle), Is.EqualTo ((nint) 2), "RetainCount(policy)"); + // the system was able to construct the chain based on the single certificate + Assert.That (Evaluate (trust), Is.EqualTo (SecTrustResult.Unspecified), "Evaluate"); + // Evalute must be called prior to Count (Apple documentation) + Assert.That (trust.Count, Is.EqualTo (3), "Count"); + + using (NSData data = trust.GetExceptions ()) { + Assert.That (CFGetRetainCount (data.Handle), Is.EqualTo ((nint) 1), "RetainCount(data)"); + Assert.False (trust.SetExceptions (null), "SetExceptions(null)"); + Assert.True (trust.SetExceptions (data), "SetExceptions"); + } + } + } + + [Test] + public void Trust2_NoRoot () + { + X509Certificate2Collection certs = new X509Certificate2Collection (); + certs.Add (new X509Certificate2 (CertificateTest.api_imgur_com)); + certs.Add (new X509Certificate2 (CertificateTest.geotrust_dv_ssl_ca)); + using (var policy = SecPolicy.CreateSslPolicy (true, "api.imgur.com")) + using (var trust = new SecTrust (certs, policy)) { + // that certificate stopped being valid on August 3rd, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + Assert.That (Evaluate (trust), Is.EqualTo (SecTrustResult.Unspecified), "Evaluate"); + // Evalute must be called prior to Count (Apple documentation) + Assert.That (trust.Count, Is.EqualTo (3), "Count"); + + using (SecKey pkey = trust.GetPublicKey ()) { + Assert.That (CFGetRetainCount (pkey.Handle), Is.EqualTo ((nint) 2), "RetainCount(pkey)"); + } + } + } + + [Test] + public void Trust2_FullChain () + { + X509Certificate2Collection certs = new X509Certificate2Collection (); + certs.Add (new X509Certificate2 (CertificateTest.api_imgur_com)); + certs.Add (new X509Certificate2 (CertificateTest.geotrust_dv_ssl_ca)); + certs.Add (new X509Certificate2 (CertificateTest.geotrust_global_root)); + using (var policy = SecPolicy.CreateSslPolicy (true, "api.imgur.com")) + using (var trust = new SecTrust (certs, policy)) { + // that certificate stopped being valid on August 3rd, 2013 so we validate it with a date earlier than that + trust.SetVerifyDate (new DateTime (635108745218945450, DateTimeKind.Utc)); + Assert.That (Evaluate (trust), Is.EqualTo (SecTrustResult.Unspecified), "Evaluate"); + // Evalute must be called prior to Count (Apple documentation) + Assert.That (trust.Count, Is.EqualTo (3), "Count"); + + using (SecCertificate sc1 = trust [0]) { + // seems the leaf gets an extra one + Assert.That (CFGetRetainCount (sc1.Handle), Is.GreaterThanOrEqualTo ((nint) 2), "RetainCount(sc1)"); + Assert.That (sc1.SubjectSummary, Is.EqualTo ("api.imgur.com"), "SubjectSummary(sc1)"); + } + using (SecCertificate sc2 = trust [1]) { + Assert.That (CFGetRetainCount (sc2.Handle), Is.GreaterThanOrEqualTo ((nint) 2), "RetainCount(sc2)"); + Assert.That (sc2.SubjectSummary, Is.EqualTo ("GeoTrust DV SSL CA"), "SubjectSummary(sc2)"); + } + using (SecCertificate sc3 = trust [2]) { + Assert.That (CFGetRetainCount (sc3.Handle), Is.GreaterThanOrEqualTo ((nint) 2), "RetainCount(sc3)"); + Assert.That (sc3.SubjectSummary, Is.EqualTo ("GeoTrust Global CA"), "SubjectSummary(sc3)"); + } + } + } + } +} diff --git a/tests/monotouch-test/Security/openssl_crt.der b/tests/monotouch-test/Security/openssl_crt.der new file mode 100644 index 000000000000..d6fb34d0a7af Binary files /dev/null and b/tests/monotouch-test/Security/openssl_crt.der differ diff --git a/tests/monotouch-test/SpriteKit/FieldNodeTest.cs b/tests/monotouch-test/SpriteKit/FieldNodeTest.cs new file mode 100644 index 000000000000..5b60a1fc382b --- /dev/null +++ b/tests/monotouch-test/SpriteKit/FieldNodeTest.cs @@ -0,0 +1,95 @@ + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using OpenTK; +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FieldNodeTest { + [SetUp] + public void VersionCheck () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("requires iOS8+"); + } + + [Test] + public void CreateRadialGravityField () + { + using (SKFieldNode node = SKFieldNode.CreateRadialGravityField ()) { + + var v = new Vector4 (1, 2, 3, 4); + node.Direction = v; + Assert.AreEqual (node.Direction.X, 1, "#x1"); + Assert.AreEqual (node.Direction.Y, 2, "#y1"); + Assert.AreEqual (node.Direction.Z, 3, "#z1"); + Assert.AreEqual (node.Direction.W, 0, "#w1"); + + v = node.Direction; + Assert.AreEqual (v.X, 1, "#x2"); + Assert.AreEqual (v.Y, 2, "#y2"); + Assert.AreEqual (v.Z, 3, "#z2"); + Assert.AreEqual (v.W, 0, "#w2"); + } + } + + [Test] + public void CreateLinearGravityField () + { + using (var node = SKFieldNode.CreateLinearGravityField (new Vector4 (1, 2, 3, 4))) { + + Assert.AreEqual (0.00457763672f, node.MinimumRadius, "#minimum radius"); + } + } + + [Test] + public void CreateVelocityField () + { + using (var node = SKFieldNode.CreateVelocityField (new Vector4 (1, 2, 3, 4))) { + + Assert.AreEqual (0.00457763672f, node.MinimumRadius, "#minimum radius"); + } + } + + [Test] + public void CreateCustomField () + { + using (var node = SKFieldNode.CreateCustomField ((Vector4 position, Vector4 velocity, float mass, float charge, double time) => { + return new Vector3 (3, 1, 4); + })) { + + // FIXME: the code below doesn't end up calling the anonymous delegate above. + var v = node.Direction; + Assert.AreEqual (0, v.X, "#x2"); + Assert.AreEqual (0, v.Y, "#y2"); + Assert.AreEqual (0, v.Z, "#z2"); + Assert.AreEqual (0, v.W, "#w2"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/KeyframeSequenceTest.cs b/tests/monotouch-test/SpriteKit/KeyframeSequenceTest.cs new file mode 100644 index 000000000000..3b91c00037c0 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/KeyframeSequenceTest.cs @@ -0,0 +1,113 @@ +// +// Unit tests for SKKeyframeSequence +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class KeyframeSequenceTest { + + [Test] + public void Ctor_Capacity () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS7"); + + using (var s = new SKKeyframeSequence (0)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 0), "Count-0"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-0"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-0"); + } + + using (var s = new SKKeyframeSequence (1)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 0), "Count-1"); + } + } + + [Test] + public void Ctor_Arrays_Null () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS7"); + + using (var s = new SKKeyframeSequence (null, (NSNumber []) null)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 0), "Count-1"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-1"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-1"); + } + + using (var s = new SKKeyframeSequence (null, (float []) null)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 0), "Count-2"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-2"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-2"); + } + + using (var s = new SKKeyframeSequence (null, (double []) null)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 0), "Count-3"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-3"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-3"); + } + } + + [Test] + public void Ctor_Arrays () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Ignore ("Requires iOS7"); + + NSNumber[] keys = new NSNumber[] { 1.0f, 2.0f, 3.0f }; + NSNumber[] values = new NSNumber[] { 1.0f, 2.0f, 3.0f }; + using (var s = new SKKeyframeSequence (keys, values)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 3), "Count-1"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-1"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-1"); + } + + float[] values_f = new [] { 4.0f, 5.0f, 6.0f }; + using (var s = new SKKeyframeSequence (keys, values_f)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 3), "Count-2"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-2"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-2"); + } + + double[] values_d = new [] { 7.0d, 8.0d, 9.0d }; + using (var s = new SKKeyframeSequence (keys, values_d)) { + Assert.That (s.Count, Is.EqualTo ((nuint) 3), "Count-3"); + Assert.That (s.InterpolationMode, Is.EqualTo (SKInterpolationMode.Linear), "SKInterpolationMode-3"); + Assert.That (s.RepeatMode, Is.EqualTo (SKRepeatMode.Clamp), "RepeatMode-3"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/PhysicsBodyTest.cs b/tests/monotouch-test/SpriteKit/PhysicsBodyTest.cs new file mode 100644 index 000000000000..607a0de019bd --- /dev/null +++ b/tests/monotouch-test/SpriteKit/PhysicsBodyTest.cs @@ -0,0 +1,73 @@ +// +// Unit tests for SKPhysicsBody +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PhysicsBodyTest { + + [Test] + public void BodyWithEdgeLoopFromRect () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + // bug 13772 - that call actually return a PKPhysicsBody (private PhysicKit framework) + SizeF size = new SizeF (3, 2); + using (var body = SKPhysicsBody.CreateRectangularBody (size)) { + Assert.That (body, Is.TypeOf (), "SKPhysicsBody"); + } + } + +#if false + // reminder that the default ctor is bad (uncomment to try again in future iOS release) + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=14502 + + [Test] + public void DefaultCtor () + { + using (var Scene = new SKScene(UIScreen.MainScreen.Bounds.Size)) + using (var b = new SKSpriteNode (UIColor.Red, new SizeF (10, 10))) { + b.PhysicsBody = new SKPhysicsBody (); + Scene.AddChild (b); //BOOM + } + } +#endif + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/PhysicsJointFixedTest.cs b/tests/monotouch-test/SpriteKit/PhysicsJointFixedTest.cs new file mode 100644 index 000000000000..0218ec90d303 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/PhysicsJointFixedTest.cs @@ -0,0 +1,74 @@ +// +// Unit tests for SKPhysicsJointFixed +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PhysicsJointFixedTest { + + [Test] + public void Create () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var s = new SKScene (new SizeF (320, 240))) + using (var b1 = SKPhysicsBody.CreateCircularBody (1.0f)) + using (var b2 = SKPhysicsBody.CreateCircularBody (2.0f)) { + // according to Apple docs we should not create this joint before adding it to a scene + // The body must be connected to a node that is already part of the scene’s node tree. + // Note that doing the same for a `SKPhysicsJointLimit` does crash + using (var j = SKPhysicsJointFixed.Create (b1, b2, new PointF (10, 20))) { + Assert.That (j.BodyA, Is.SameAs (b1), "BodyA"); + Assert.That (j.BodyB, Is.SameAs (b2), "BodyB"); + + SKNode n1 = new SKNode (); + n1.PhysicsBody = b1; + s.AddChild (n1); + + SKNode n2 = new SKNode (); + n2.PhysicsBody = b2; + s.AddChild (n2); + + // using the default ctor (for `j`) would crash (and no way to set the PointF argument) + // https://bugzilla.xamarin.com/show_bug.cgi?id=14511 + s.PhysicsWorld.AddJoint (j); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/PhysicsJointLimitTest.cs b/tests/monotouch-test/SpriteKit/PhysicsJointLimitTest.cs new file mode 100644 index 000000000000..da6ce0d53ec2 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/PhysicsJointLimitTest.cs @@ -0,0 +1,72 @@ +// +// Unit tests for SKPhysicsJointLimit +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PhysicsJointLimitTest { + + [Test] + public void Create () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var s = new SKScene (new SizeF (320, 240))) + using (var b1 = SKPhysicsBody.CreateCircularBody (1.0f)) + using (var b2 = SKPhysicsBody.CreateCircularBody (2.0f)) { + // The body must be connected to a node that is already part of the scene’s node tree. + SKNode n1 = new SKNode (); + n1.PhysicsBody = b1; + s.AddChild (n1); + + SKNode n2 = new SKNode (); + n2.PhysicsBody = b2; + s.AddChild (n2); + + // if you create the SKPhysicsJointLimit *before* adding the nodes + // to a scene then you'll crash and burn. ref: bug #14793 + using (var j = SKPhysicsJointLimit.Create (b1, b2, PointF.Empty, new PointF (10, 20))) { + Assert.That (j.BodyA, Is.SameAs (b1), "BodyA"); + Assert.That (j.BodyB, Is.SameAs (b2), "BodyB"); + + s.PhysicsWorld.AddJoint (j); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/PhysicsWorldTest.cs b/tests/monotouch-test/SpriteKit/PhysicsWorldTest.cs new file mode 100644 index 000000000000..ee32d134e252 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/PhysicsWorldTest.cs @@ -0,0 +1,54 @@ + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using OpenTK; +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PhysicsWorldTest { + [SetUp] + public void VersionCheck () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("requires iOS8+"); + } + + [Test] + public void SampleFields () + { + using (var scene = new SKScene ()) { + using (var world = scene.PhysicsWorld) { + var v = world.SampleFields (new Vector3 (1, 2, 3)); + Assert.AreEqual (0, v.X, "#x1"); + Assert.AreEqual (0, v.Y, "#y1"); + Assert.AreEqual (0, v.Z, "#z1"); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/SK3DNodeTest.cs b/tests/monotouch-test/SpriteKit/SK3DNodeTest.cs new file mode 100644 index 000000000000..73c8f2c53746 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/SK3DNodeTest.cs @@ -0,0 +1,88 @@ + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +using ObjCRuntime; +using SceneKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +using MonoTouch.SceneKit; +#endif +using OpenTK; +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SK3DNodeTest { + [SetUp] + public void VersionCheck () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Inconclusive ("requires iOS8+"); + } + + [Test] + public void ProjectPoint () + { + if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("This doesn't seem to work properly in the iOS 9"); + + // SK3Node loads SCNRenderer dynamically, so make sure it's actually loaded. + GC.KeepAlive (Class.GetHandle (typeof(SCNRenderer))); + + using (var node = new SK3DNode ()) { + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // 32-bit simulator returns 0,0,0 the first time + // this is executed for some reason, so just + // ignore that. + node.ProjectPoint (new Vector3 (4, 5, 6)); + } + var v = node.ProjectPoint (new Vector3 (1, 2, 3)); + Assert.AreEqual (1, v.X, "#x1"); + Assert.AreEqual (2, v.Y, "#y1"); + Assert.AreEqual (3, v.Z, "#z1"); + } + } + + [Test] + public void UnprojectPoint () + { + if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + Assert.Ignore ("This doesn't seem to work properly in the iOS 9"); + + using (var node = new SK3DNode ()) { + if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4) { + // 32-bit simulator returns 0,0,0 the first time + // this is executed for some reason, so just + // ignore that. + node.UnprojectPoint (new Vector3 (4, 5, 6)); + } + var v = node.UnprojectPoint (new Vector3 (1, 2, 3)); + Assert.AreEqual (1, v.X, "#x1"); + Assert.AreEqual (2, v.Y, "#y1"); + Assert.AreEqual (3, v.Z, "#z1"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/SKShapeNodeTest.cs b/tests/monotouch-test/SpriteKit/SKShapeNodeTest.cs new file mode 100644 index 000000000000..d592421ecdb9 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/SKShapeNodeTest.cs @@ -0,0 +1,107 @@ +// +// Unit tests for SKShapeNodeTest +// +// Authors: +// Alex Soto +// +// Copyright 2016 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat = global::System.Single; +using nint = global::System.Int32; +using nuint = global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class SKShapeNodeTest { + + [Test] + public void FromPointsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("requires iOS8+"); + + var pts = new[] { + new PointF (0, 0), + new PointF (320, 568) + }; + + var result = SKShapeNode.FromPoints (pts); + Assert.IsNotNull (result, "result should not be null"); + } + + [Test] + public void FromPointsOffsetTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("requires iOS8+"); + + var pts = new [] { + new PointF (0, 0), + new PointF (320, 568) + }; + + var result = SKShapeNode.FromPoints (pts, 1, 1); + Assert.IsNotNull (result, "result should not be null"); + + Assert.Throws (() => SKShapeNode.FromPoints (pts, 1, 2)); + } + + [Test] + public void FromSplinePointsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("requires iOS8+"); + + var pts = new[] { + new PointF (0, 0), + new PointF (320, 568) + }; + + var result = SKShapeNode.FromSplinePoints (pts); + Assert.IsNotNull (result, "result should not be null"); + } + + [Test] + public void FromSplinePointsOffsetTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("requires iOS8+"); + + var pts = new [] { + new PointF (0, 0), + new PointF (320, 568) + }; + + var result = SKShapeNode.FromSplinePoints (pts, 1, 1); + Assert.IsNotNull (result, "result should not be null"); + + Assert.Throws (() => SKShapeNode.FromSplinePoints (pts, 1, 2)); + } + } +} + +#endif // !__WATCHOS__ + diff --git a/tests/monotouch-test/SpriteKit/SpriteNodeTest.cs b/tests/monotouch-test/SpriteKit/SpriteNodeTest.cs new file mode 100644 index 000000000000..7ebf8a44be80 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/SpriteNodeTest.cs @@ -0,0 +1,117 @@ +// +// Unit tests for SKSpriteNode +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SpriteNodeTest { + + void CheckEmpty (SKSpriteNode n) + { + Assert.IsNotNull (n.Color, "Color"); + Assert.Null (n.Name, "Name"); + Assert.True (n.Size.IsEmpty, "Size"); + Assert.Null (n.Texture, "Texture"); + } + + [SetUp] + public void VersionCheck () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS7+"); + } + + [Test] + public void Ctor () + { + using (var n = new SKSpriteNode ()) { + CheckEmpty (n); + } + } + + [Test] + public void CtorColor () + { + using (var n = new SKSpriteNode ((UIColor) null, SizeF.Empty)) { + CheckEmpty (n); + } + } + + [Test] + public void CtorName () + { + Assert.Throws (delegate { new SKSpriteNode ((string) null); }, "string"); + } + + [Test] + public void CtorTexture () + { + using (var n = new SKSpriteNode ((SKTexture) null)) { + CheckEmpty (n); + } + } + + [Test] + public void CtorTextureColor () + { + using (var n = new SKSpriteNode (null, null, SizeF.Empty)) { + CheckEmpty (n); + } + } + + [Test] + public void Color () + { + using (var n = new SKSpriteNode (UIColor.Blue, SizeF.Empty)) { + Assert.That (n.Color.ToString (), Is.EqualTo ("UIColor [A=255, R=0, G=0, B=255]"), "Color-1"); + n.Color = null; + Assert.That (n.Color.ToString (), Is.EqualTo ("UIColor [A=0, R=0, G=0, B=0]"), "Color-2"); + } + } + + [Test] + public void Texture () + { + using (var t = SKTexture.FromImageNamed ("basn3p08.png")) + using (var n = new SKSpriteNode (t)) { + Assert.AreSame (n.Texture, t, "Texture-1"); + n.Texture = null; + Assert.IsNull (n.Texture, "Texture-2"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/TextureAtlasTest.cs b/tests/monotouch-test/SpriteKit/TextureAtlasTest.cs new file mode 100644 index 000000000000..3b1d0724454e --- /dev/null +++ b/tests/monotouch-test/SpriteKit/TextureAtlasTest.cs @@ -0,0 +1,54 @@ +// +// Unit tests for SKTextureAtlas +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TextureAtlasTest { + + [Test] + public void Empty () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var atlas = new SKTextureAtlas ()) { + Assert.That (atlas.TextureNames, Is.Empty, "TextureNames"); + + // completionHandler is optional + SKTextureAtlas.PreloadTextures (new [] { atlas }, null); + + // completionHandler is optional + atlas.Preload (null); + + // that returns a texture, calling 'MissingResource.png' (128 x 128) + using (var texture = atlas.TextureNamed ("ship")) { + Assert.That (texture.Handle, Is.Not.EqualTo (IntPtr.Zero), "valid"); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SpriteKit/TextureTest.cs b/tests/monotouch-test/SpriteKit/TextureTest.cs new file mode 100644 index 000000000000..bc63cfbe1858 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/TextureTest.cs @@ -0,0 +1,76 @@ +// +// Unit tests for SKTexture +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using SpriteKit; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TextureTest { + + // Apple bug ? + void CrashAvoider () + { + } + + [Test] + public void Atlas_MissingResource () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("Requires iOS7"); + + using (var atlas = new SKTextureAtlas ()) { + // that returns a texture, calling 'MissingResource.png' (128 x 128) + using (var texture = atlas.TextureNamed ("ship")) { + + // this completionHandler is *NOT* optional -> crash if null + SKTexture.PreloadTextures (new [] { texture }, CrashAvoider); + + // this completionHandler is *NOT* optional -> crash if null + texture.Preload (CrashAvoider); + + Assert.That (texture.FilteringMode, Is.EqualTo (SKTextureFilteringMode.Linear), "FilteringMode"); + + // FIXME: bug in iOS9 - it will randomly return 0,0 (but almost always on the first try) + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.That (texture.Size, Is.EqualTo (new SizeF (128, 128)), "Size"); + + Assert.That (texture.TextureRect, Is.EqualTo (new RectangleF (0, 0, 1, 1)), "TextureRect"); + Assert.False (texture.UsesMipmaps, "UsesMipmaps"); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/StoreKit/ReceiptRefreshRequestTest.cs b/tests/monotouch-test/StoreKit/ReceiptRefreshRequestTest.cs new file mode 100644 index 000000000000..2db99cc25170 --- /dev/null +++ b/tests/monotouch-test/StoreKit/ReceiptRefreshRequestTest.cs @@ -0,0 +1,50 @@ +// +// Unit tests for SKReceiptRefreshRequest +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using StoreKit; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.StoreKit; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.StoreKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ReceiptRefreshRequestTest { + + [Test] + public void TerminateForInvalidReceipt () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 1)) + Assert.Inconclusive ("requires iOS 7.1+"); + + // not yet documented - seems to kill the app on purpose ?!? on both sim and devices + //SKReceiptRefreshRequest.TerminateForInvalidReceipt (); + + IntPtr sk = Dlfcn.dlopen ("/System/Library/Frameworks/StoreKit.framework/StoreKit", 1); + IntPtr fp = Dlfcn.dlsym (sk, "SKTerminateForInvalidReceipt"); + Assert.That (fp, Is.Not.EqualTo (IntPtr.Zero), "pointer"); + Dlfcn.dlclose (sk); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SystemConfiguration/CaptiveNetworkTest.cs b/tests/monotouch-test/SystemConfiguration/CaptiveNetworkTest.cs new file mode 100644 index 000000000000..9c87f71cd175 --- /dev/null +++ b/tests/monotouch-test/SystemConfiguration/CaptiveNetworkTest.cs @@ -0,0 +1,160 @@ +// +// Unit tests for CaptiveNetwork +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using SystemConfiguration; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.SystemConfiguration; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.SystemConfiguration { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CaptiveNetworkTest { + + static bool RunningOnSnowLeopard { + get { + return !File.Exists ("/usr/lib/system/libsystem_kernel.dylib"); + } + } + + [Test] + public void Fields () + { + if (Runtime.Arch == Arch.SIMULATOR) { + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("Fails (NullReferenceException) on iOS6 simulator"); + } + + Assert.That (CaptiveNetwork.NetworkInfoKeyBSSID.ToString (), Is.EqualTo ("BSSID"), "kCNNetworkInfoKeyBSSID"); + Assert.That (CaptiveNetwork.NetworkInfoKeySSID.ToString (), Is.EqualTo ("SSID"), "kCNNetworkInfoKeySSID"); + Assert.That (CaptiveNetwork.NetworkInfoKeySSIDData.ToString (), Is.EqualTo ("SSIDDATA"), "kCNNetworkInfoKeySSIDData"); + } + +#if !XAMCORE_2_0 + [Test] + public void GetSupportedInterfaces () + { + if (Runtime.Arch == Arch.SIMULATOR) { + if (RunningOnSnowLeopard) + Assert.Inconclusive ("This test crash on the simulator with Snow Leopard"); + + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("This test crash on the iOS 6 simulator with Lion"); + } + + string [] interfaces = CaptiveNetwork.GetSupportedInterfaces (); + if (Runtime.Arch == Arch.SIMULATOR) { + // we can't assume much about the computer running the simulator + Assert.NotNull (interfaces, "GetSupportedInterfaces"); + } else { + Assert.That (interfaces.Length, Is.EqualTo (1), "1"); + Assert.That (interfaces [0], Is.EqualTo ("en0"), "en0"); + } + } +#endif + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void TryCopyCurrentNetworkInfo_Null () + { + NSDictionary dict; + CaptiveNetwork.TryCopyCurrentNetworkInfo (null, out dict); + } + + [Test] + public void TryCopyCurrentNetworkInfo () + { + if (Runtime.Arch == Arch.SIMULATOR) { + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("This test throws EntryPointNotFoundException on the iOS 6 simulator with Lion"); + } + + NSDictionary dict; + var status = CaptiveNetwork.TryCopyCurrentNetworkInfo ("en0", out dict); + + // No network, ignore test + if (status == StatusCode.NoKey) + return; + + Assert.AreEqual (StatusCode.OK, status, "Status"); + + if ((dict == null) && (Runtime.Arch == Arch.DEVICE) && UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.Ignore ("null on iOS9 devices - CaptiveNetwork is being deprecated ?!?"); + + if (dict.Count == 3) { + Assert.NotNull (dict [CaptiveNetwork.NetworkInfoKeyBSSID], "NetworkInfoKeyBSSID"); + Assert.NotNull (dict [CaptiveNetwork.NetworkInfoKeySSID], "NetworkInfoKeySSID"); + Assert.NotNull (dict [CaptiveNetwork.NetworkInfoKeySSIDData], "NetworkInfoKeySSIDData"); + } else { + Assert.Fail ("Unexpected dictionary result with {0} items", dict.Count); + } + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void MarkPortalOnline_Null () + { + CaptiveNetwork.MarkPortalOnline (null); + } + + [Test] + public void MarkPortalOnline () + { + Assert.False (CaptiveNetwork.MarkPortalOnline ("xamxam")); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void MarkPortalOffline_Null () + { + CaptiveNetwork.MarkPortalOffline (null); + } + + [Test] + public void MarkPortalOffline () + { + Assert.False (CaptiveNetwork.MarkPortalOffline ("xamxam")); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void SetSupportedSSIDs_Null () + { + CaptiveNetwork.SetSupportedSSIDs (null); + } + + [Test] + public void SetSupportedSSIDs () + { + if (Runtime.Arch == Arch.SIMULATOR) { + if (RunningOnSnowLeopard) + Assert.Inconclusive ("This test crash on the simulator with Snow Leopard"); + } + + // that API is deprecated in iOS9 - and it might be why it returns false (or not) + bool supported = !UIDevice.CurrentDevice.CheckSystemVersion (9,0); + Assert.That (CaptiveNetwork.SetSupportedSSIDs (new string [2] { "one", "two" } ), Is.EqualTo (supported), "set"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs b/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs new file mode 100644 index 000000000000..313ad942c121 --- /dev/null +++ b/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs @@ -0,0 +1,145 @@ +// +// Unit tests for NetworkReachability +// +// Authors: +// Marek Safar +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +using SystemConfiguration; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.SystemConfiguration; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; +using System.Net; + +namespace MonoTouchFixtures.SystemConfiguration { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NetworkReachabilityTest + { + [Test] + public void CtorNameAddress () + { + using (var nr = new NetworkReachability ("apple.com")) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags)); + Assert.That (flags, Is.EqualTo (NetworkReachabilityFlags.Reachable), "Reachable"); + } + } + + [Test] + public void CtorIPAddress () + { + using (var nr = new NetworkReachability (IPAddress.Loopback)) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#1"); + var expected = NetworkReachabilityFlags.Reachable | NetworkReachabilityFlags.IsLocalAddress; + if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) + expected |= NetworkReachabilityFlags.IsDirect; // make sense + Assert.That (flags, Is.EqualTo (expected), "#1 Reachable"); + } + + using (var nr = new NetworkReachability (new IPAddress (new byte[] { 10, 99, 99, 99 }))) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#2"); + //Assert.That (flags, Is.EqualTo (NetworkReachabilityFlags.Reachable), "#2 Reachable"); + } + + using (var nr = new NetworkReachability (IPAddress.IPv6Loopback)) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#3"); + //Assert.That (flags, Is.EqualTo ( + // NetworkReachabilityFlags.TransientConnection | NetworkReachabilityFlags.Reachable | NetworkReachabilityFlags.ConnectionRequired), "#3 Reachable"); + } + + using (var nr = new NetworkReachability (IPAddress.Parse ("2001:4860:4860::8844"))) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#4"); + + // TODO: Will probably change when IPv6 is enabled locally + //Assert.That (flags, Is.EqualTo ( + // NetworkReachabilityFlags.TransientConnection | NetworkReachabilityFlags.Reachable | NetworkReachabilityFlags.ConnectionRequired), "#4 Reachable"); + } + + } + + [Test] + public void CtorIPAddressPair () + { + var address = Dns.GetHostAddresses ("apple.com")[0]; + using (var nr = new NetworkReachability (IPAddress.Loopback, address)) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#1"); + Assert.That (flags, Is.EqualTo (NetworkReachabilityFlags.Reachable), "#1 Reachable"); + } + + using (var nr = new NetworkReachability (null, address)) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#2"); + Assert.That (flags, Is.EqualTo (NetworkReachabilityFlags.Reachable), "#2 Reachable"); + } + + using (var nr = new NetworkReachability (IPAddress.Loopback, null)) + { + NetworkReachabilityFlags flags; + + Assert.IsTrue (nr.TryGetFlags (out flags), "#3"); + var expected = NetworkReachabilityFlags.Reachable; + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + expected |= NetworkReachabilityFlags.IsLocalAddress; + Assert.That (flags, Is.EqualTo (expected), "#3 Reachable"); + } + } + + [Test] + public void Ctor_Invalid () + { + try { + new NetworkReachability ((string) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException) { + } + + try { + new NetworkReachability ((IPAddress) null); + Assert.Fail ("#2"); + } catch (ArgumentNullException) { + } + + try { + new NetworkReachability (null, null); + Assert.Fail ("#3"); + } catch (ArgumentException) { + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/SystemConfiguration/StatusCodeErrorTest.cs b/tests/monotouch-test/SystemConfiguration/StatusCodeErrorTest.cs new file mode 100644 index 000000000000..650e2d5ca5c1 --- /dev/null +++ b/tests/monotouch-test/SystemConfiguration/StatusCodeErrorTest.cs @@ -0,0 +1,40 @@ +// +// Unit tests for StatusCodeError +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using SystemConfiguration; +#else +using MonoTouch.Foundation; +using MonoTouch.SystemConfiguration; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.SystemConfiguration { + + [TestFixture] + [Preserve (AllMembers = true)] + public class StatusCodeErrorTest { + + [Test] + public void InvalidStatusCode () + { + var s = StatusCodeError.GetErrorDescription ((StatusCode) 1); + // "Operation not permitted" (might be localized so we just check non-null) + Assert.NotNull (s, "1"); + s = StatusCodeError.GetErrorDescription ((StatusCode) Int32.MinValue); + Assert.Null (s, "MinValue"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/Tamarin.pdf b/tests/monotouch-test/Tamarin.pdf new file mode 100644 index 000000000000..7117d37538fa Binary files /dev/null and b/tests/monotouch-test/Tamarin.pdf differ diff --git a/tests/monotouch-test/UIKit/AccessibilityTest.cs b/tests/monotouch-test/UIKit/AccessibilityTest.cs new file mode 100644 index 000000000000..61301fa529dd --- /dev/null +++ b/tests/monotouch-test/UIKit/AccessibilityTest.cs @@ -0,0 +1,45 @@ +// +// Unit tests for UIAccessibility +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AccessibilityTest { + + [Test] + public void RequestGuidedAccessSession () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + // should not affect execution since it needs to be a "supervised" device (and allowed in MDM) + // UIAccessibility.RequestGuidedAccessSession (true, delegate (bool didSuccess) { + // Assert.Fail ("should not be reached"); + //}); + UIAccessibility.RequestGuidedAccessSession (false, null); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ActionSheetTest.cs b/tests/monotouch-test/UIKit/ActionSheetTest.cs new file mode 100644 index 000000000000..05d57013b8ef --- /dev/null +++ b/tests/monotouch-test/UIKit/ActionSheetTest.cs @@ -0,0 +1,96 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ActionSheetTest { + + void CheckDefault (UIActionSheet a) + { + Assert.That (a.ButtonCount, Is.EqualTo ((nint) 0), "ButtonCount"); + Assert.That (a.CancelButtonIndex, Is.EqualTo ((nint) (-1)), "CancelButtonIndex"); + Assert.Null (a.Delegate, "Delegate"); + Assert.That (a.DestructiveButtonIndex, Is.EqualTo ((nint) (-1)), "DestructiveButtonIndex"); + Assert.That (a.FirstOtherButtonIndex, Is.EqualTo ((nint) (-1)), "FirstOtherButtonIndex"); + + var style = TestRuntime.CheckSystemAndSDKVersion (8, 0) ? UIActionSheetStyle.Default : UIActionSheetStyle.Automatic; + Assert.That (a.Style, Is.EqualTo (style), "Style"); + + Assert.Null (a.Title, "Title"); + + Assert.False (a.Visible, "Visible"); + + Assert.Null (a.WeakDelegate, "WeakDelegate"); + } + + [Test] + public void CtorDefault () + { + using (UIActionSheet a = new UIActionSheet ()) { + CheckDefault (a); + } + } + + [Test] + public void CtorAllNulls () + { + // http://bugzilla.xamarin.com/show_bug.cgi?id=3081 + using (UIActionSheet a = new UIActionSheet (null, null, null, null)) { + CheckDefault (a); + } + } + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIActionSheet a = new UIActionSheet (frame)) { + Assert.That (a.Frame, Is.EqualTo (frame), "Frame"); + CheckDefault (a); + } + } + + class MyActionSheetDelegate : UIActionSheetDelegate { + } + + [Test] + public void CtorDelegate () + { + using (var del = new MyActionSheetDelegate ()) + using (var a = new UIActionSheet ("title", del, null, null, null)) { + Assert.That (a.Title, Is.EqualTo ("title"), "Title"); + Assert.NotNull (typeof (UIActionSheet).GetField ("__mt_WeakDelegate_var", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (a), "backing field"); + // check properties after the field (so we're not setting it only when calling the properties) + Assert.NotNull (a.Delegate, "Delegate"); + Assert.NotNull (a.WeakDelegate, "WeakDelegate"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ActivityIndicatorViewTest.cs b/tests/monotouch-test/UIKit/ActivityIndicatorViewTest.cs new file mode 100644 index 000000000000..9390f748f9ef --- /dev/null +++ b/tests/monotouch-test/UIKit/ActivityIndicatorViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ActivityIndicatorViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIActivityIndicatorView aiv = new UIActivityIndicatorView (frame)) { + Assert.That (aiv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/AlertViewDelegateTest.cs b/tests/monotouch-test/UIKit/AlertViewDelegateTest.cs new file mode 100644 index 000000000000..e9cf2a1e0a85 --- /dev/null +++ b/tests/monotouch-test/UIKit/AlertViewDelegateTest.cs @@ -0,0 +1,45 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AlertViewDelegateTest { + +#if false + // this occurs only on the simulator where we use a different code path to register classes + [Test] + public void Default () + { + using (var d = new UIAlertViewDelegate ()) { + Assert.That (d.Handle, Is.EqualTo (IntPtr.Zero), "Handle"); + } + } +#endif + + class MyAlertViewDelegate2 : UIAlertViewDelegate { + } + + [Test] + public void MyDefault () + { + using (var d = new MyAlertViewDelegate2 ()) { + Assert.That (d.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/AlertViewTest.cs b/tests/monotouch-test/UIKit/AlertViewTest.cs new file mode 100644 index 000000000000..c67fae0497bf --- /dev/null +++ b/tests/monotouch-test/UIKit/AlertViewTest.cs @@ -0,0 +1,86 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AlertViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIAlertView av = new UIAlertView (frame)) { + Assert.That (av.Frame, Is.EqualTo (frame), "Frame"); + } + } + + class MyAlertViewDelegate : UIAlertViewDelegate { + } + + [Test] + public void CtorNull () + { + // null title + using (var a = new UIAlertView (null, "message", null, null, null)) { + Assert.That (a.Handle, Is.Not.EqualTo (IntPtr.Zero), "1"); + } + // null message + using (var a = new UIAlertView ("title", null, null, null, null)) { + Assert.That (a.Handle, Is.Not.EqualTo (IntPtr.Zero), "2"); + } + // all null + using (var a = new UIAlertView (null, null, null, null, null)) { + Assert.That (a.Handle, Is.Not.EqualTo (IntPtr.Zero), "3"); + } + } + + [Test] + public void CtorDelegate () + { + using (var del = new MyAlertViewDelegate ()) + using (var a = new UIAlertView ("title", "message", del, null, null)) { + Assert.That (a.Title, Is.EqualTo ("title"), "Title"); + Assert.That (a.Message, Is.EqualTo ("message"), "Message"); + Assert.NotNull (typeof (UIAlertView).GetField ("__mt_WeakDelegate_var", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (a), "backing field"); + // check properties after the field (so we're not setting it only when calling the properties) + Assert.NotNull (a.Delegate, "Delegate"); + Assert.NotNull (a.WeakDelegate, "WeakDelegate"); + } + } + + [Test] + public void FirstOtherButtonIndex () + { + using (var a = new UIAlertView ("title", "message", null, "cancel", "other")) { + Assert.That (a.FirstOtherButtonIndex, Is.EqualTo ((nint) 1), "#other button index"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/AppearanceTest.cs b/tests/monotouch-test/UIKit/AppearanceTest.cs new file mode 100644 index 000000000000..944a1b8050bd --- /dev/null +++ b/tests/monotouch-test/UIKit/AppearanceTest.cs @@ -0,0 +1,231 @@ +// +// UIAppearance Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AppearanceTest { + + [Test] + public void Equality () + { + using (var a = UITableView.Appearance) + using (var b = UITableView.Appearance) + using (var c = UILabel.Appearance) { + Assert.True (a == b, "1"); + Assert.False (a == c, "2"); + } + } + + [Test] + public void Inequality () + { + using (var a = UITableView.Appearance) + using (var b = UITableView.Appearance) + using (var c = UILabel.Appearance) { + Assert.False (a != b, "1"); + Assert.True (a != c, "2"); + } + } + + [Test] + public void Appearance () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("UITraitCollection requires iOS 8.0"); + + using (var traits = new UITraitCollection ()) { + nfloat r, g, b, a; + + // Appearance + // it can be set + Assert.IsNull (UILabel.Appearance.TextColor, "null 1"); + UILabel.Appearance.TextColor = UIColor.Red; + UILabel.Appearance.TextColor.GetRGBA (out r, out g, out b, out a); + Assert.AreEqual (1, a, "a1"); + Assert.AreEqual (1, r, "r1"); + Assert.AreEqual (0, g, "g1"); + Assert.AreEqual (0, b, "b1"); + + // check that other appearance instances didn't change + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "other null 2"); + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "other null 3"); + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "other null 4"); + + // it can be cleared + UILabel.Appearance.TextColor = null; + Assert.IsNull (UILabel.Appearance.TextColor, "null 2"); + } + } + + [Test] + public void AppearanceWhenContainedIn () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("UITraitCollection requires iOS 8.0"); + + using (var traits = new UITraitCollection ()) { + nfloat r, g, b, a; + + // it can be set + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "null 1"); + UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor = UIColor.Blue; + UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor.GetRGBA (out r, out g, out b, out a); + Assert.AreEqual (1, a, "a1"); + Assert.AreEqual (0, r, "r1"); + Assert.AreEqual (0, g, "g1"); + Assert.AreEqual (1, b, "b1"); + + // check that other appearance instances didn't change (bug 26353) + Assert.IsNull (UILabel.Appearance.TextColor, "other null 1"); + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "other null 2"); + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "other null 3"); + + // it can be cleared + UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor = null; + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "null 2"); + } + } + + + [Test] + public void AppearanceWhenContainedIn_UITraitCollection () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("UITraitCollection requires iOS 8.0"); + + using (var traits = new UITraitCollection ()) { + nfloat r, g, b, a; + + // it can be set + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "null 1"); + UILabel.GetAppearance (traits, typeof (UITextField)).TextColor = UIColor.Blue; + UILabel.GetAppearance (traits, typeof (UITextField)).TextColor.GetRGBA (out r, out g, out b, out a); + Assert.AreEqual (1, a, "a1"); + Assert.AreEqual (0, r, "r1"); + Assert.AreEqual (0, g, "g1"); + Assert.AreEqual (1, b, "b1"); + + // check that other appearance instances didn't change + Assert.IsNull (UILabel.Appearance.TextColor, "other null 1"); + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "other null 2"); + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "other null 4"); + + // it can be cleared + UILabel.GetAppearance (traits, typeof (UITextField)).TextColor = null; + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "null 2"); + } + + using (var traits = new UITraitCollection ()) { + nfloat r, g, b, a; + + // it can be set + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "g null 1"); + UILabel.GetAppearance (traits, typeof (UITextField)).TextColor = UIColor.Blue; + UILabel.GetAppearance (traits, typeof (UITextField)).TextColor.GetRGBA (out r, out g, out b, out a); + Assert.AreEqual (1, a, "g a1"); + Assert.AreEqual (0, r, "g r1"); + Assert.AreEqual (0, g, "g g1"); + Assert.AreEqual (1, b, "g b1"); + + // check that other appearance instances didn't change + Assert.IsNull (UILabel.Appearance.TextColor, "g other null 1"); + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "g other null 2"); + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "g other null 4"); + + // it can be cleared + UILabel.GetAppearance (traits, typeof (UITextField)).TextColor = null; + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "g null 2"); + } + } + + [Test] + public void Appearance_UITraitCollection () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("UITraitCollection requires iOS 8.0"); + + using (var traits = new UITraitCollection ()) { + nfloat r, g, b, a; + + // it can be set + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "null 1"); + UILabel.GetAppearance (traits).TextColor = UIColor.Blue; + UILabel.GetAppearance (traits).TextColor.GetRGBA (out r, out g, out b, out a); + Assert.AreEqual (1, a, "a1"); + Assert.AreEqual (0, r, "r1"); + Assert.AreEqual (0, g, "g1"); + Assert.AreEqual (1, b, "b1"); + + // check that other appearance instances didn't change + Assert.IsNull (UILabel.Appearance.TextColor, "other null 1"); + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "other null 3"); + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "other null 4"); + + // it can be cleared + UILabel.GetAppearance (traits).TextColor = null; + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "null 2"); + } + + // generic version + using (var traits = new UITraitCollection ()) { + nfloat r, g, b, a; + + // it can be set + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "g null 1"); + UILabel.GetAppearance (traits).TextColor = UIColor.Blue; + UILabel.GetAppearance (traits).TextColor.GetRGBA (out r, out g, out b, out a); + Assert.AreEqual (1, a, "g a1"); + Assert.AreEqual (0, r, "g r1"); + Assert.AreEqual (0, g, "g g1"); + Assert.AreEqual (1, b, "g b1"); + + // check that other appearance instances didn't change + Assert.IsNull (UILabel.Appearance.TextColor, "g other null 1"); + Assert.IsNull (UILabel.GetAppearance (traits, typeof (UITextField)).TextColor, "g other null 3"); + Assert.IsNull (UILabel.AppearanceWhenContainedIn (typeof (UITextField)).TextColor, "g other null 4"); + + // it can be cleared + UILabel.GetAppearance (traits).TextColor = null; + Assert.IsNull (UILabel.GetAppearance (traits).TextColor, "g null 2"); + } + } + + class CustomLabel : UILabel {} + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ApplicationTest.cs b/tests/monotouch-test/UIKit/ApplicationTest.cs new file mode 100644 index 000000000000..39c392e0543c --- /dev/null +++ b/tests/monotouch-test/UIKit/ApplicationTest.cs @@ -0,0 +1,62 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ApplicationTest { + + [Test] + public void BackgroundTaskInvalid () + { + Assert.That (UIApplication.BackgroundTaskInvalid.ToString () == "0", "#1"); + Assert.That (UIApplication.BackgroundTaskInvalid == 0, "#2"); + } + +#if !__TVOS__ + [Test] + public void SetKeepAliveTimeout_Null () + { + Assert.False (UIApplication.SharedApplication.SetKeepAliveTimeout (600, null), "SetKeepAliveTimeout"); + } +#endif + + [Test] + public void BeginBackgroundTask_Null () + { + var taskid = UIApplication.SharedApplication.BeginBackgroundTask (null); + Assert.That (taskid, Is.Not.EqualTo (UIApplication.BackgroundTaskInvalid), "BeginBackgroundTask"); + UIApplication.SharedApplication.EndBackgroundTask (taskid); + } + + [Test] + public void MinimumKeepAliveTimeout () + { + // NSTimeInternal (double) not NSString + Assert.That (UIApplication.MinimumKeepAliveTimeout, Is.EqualTo (600.0), "MinimumKeepAliveTimeout"); + } + + [Test] + public void SendAction_Null () + { + UIApplication.SharedApplication.SendAction (new Selector ("someSelector"), null, null, null); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/BarButtonItemTest.cs b/tests/monotouch-test/UIKit/BarButtonItemTest.cs new file mode 100644 index 000000000000..fb396fbcfd24 --- /dev/null +++ b/tests/monotouch-test/UIKit/BarButtonItemTest.cs @@ -0,0 +1,145 @@ +// Copyright 2011-2013 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + class MyView : UIView { + + public MyView (string note) + { + Annotation = note; + } + + public string Annotation { get; private set; } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class ButtonBarItemTest { + + [Test] + public void InitWithImage () + { + using (var img = new UIImage ()) + using (var btn = new UIBarButtonItem (img, UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.Target, "Target"); + Assert.AreSame (img, btn.Image, "Image"); + btn.Image = null; // nullable + } + + using (var btn = new UIBarButtonItem ((UIImage) null, UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.Image, "Image-null"); + } + } + + [Test] + public void InitWithImage2 () + { + using (var img = new UIImage ()) + using (var btn = new UIBarButtonItem (img, img, UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.Target, "Target"); + Assert.AreSame (img, btn.Image, "Image"); + btn.Image = null; // nullable + } + + using (var btn = new UIBarButtonItem (null, null, UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.Image, "Image-null"); + } + } + + [Test] + public void InitWithText () + { + using (var btn = new UIBarButtonItem ("title", UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.Target, "Target"); + Assert.That (btn.Title, Is.EqualTo ("title"), "Title"); + btn.Title = null; // nullable + } + + using (var btn = new UIBarButtonItem ((string) null, UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.Title, "Title-null"); + } + } + + [Test] + public void CustomView_Null () + { + using (var btn = new UIBarButtonItem ("title", UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.CustomView, "default"); + btn.CustomView = null; // nullable + } + } + + [Test] + public void TintColor_Null () + { + using (var btn = new UIBarButtonItem ("title", UIBarButtonItemStyle.Bordered, null, null)) { + Assert.Null (btn.TintColor, "default"); + btn.TintColor = UIColor.Blue; + Assert.That (btn.TintColor == UIColor.Blue, "blue"); + btn.TintColor = null; + Assert.Null (btn.TintColor, "null"); + } + } + + [Test] + public void Action_Set () + { + using (UIBarButtonItem btn = new UIBarButtonItem ()) { + btn.Action = null; + // that caller the getter, which is not a valid selector if null and was throwing, ref: #10876 + btn.Action = btn.Action; + } + } + + [Test] + public void BackgroundImage () + { + using (UIBarButtonItem btn = new UIBarButtonItem ()) { + Assert.Null (btn.GetBackgroundImage (UIControlState.Highlighted, UIBarMetrics.Default), "Get"); + btn.SetBackgroundImage (null, UIControlState.Highlighted, UIBarMetrics.Default); + + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + Assert.Null (btn.GetBackgroundImage (UIControlState.Highlighted, UIBarButtonItemStyle.Plain, UIBarMetrics.Default), "Get2"); + btn.SetBackgroundImage (null, UIControlState.Highlighted, UIBarButtonItemStyle.Plain, UIBarMetrics.Default); + } + } + } + + [Test] + public void BackButtonBackgroundImage () + { + using (UIBarButtonItem btn = new UIBarButtonItem ()) { +#if !__TVOS__ + Assert.Null (btn.GetBackButtonBackgroundImage (UIControlState.Highlighted, UIBarMetrics.Default), "Get"); + btn.SetBackButtonBackgroundImage (null, UIControlState.Highlighted, UIBarMetrics.Default); +#endif + } + } + +#if !__TVOS__ + [Test] + public void SetTitleTextAttributes_Null () + { + using (MyView v = new MyView ("note")) + using (var b = new UIBarButtonItem (v)) { + b.SetTitleTextAttributes (null, UIControlState.Disabled); + } + } +#endif + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ButtonTest.cs b/tests/monotouch-test/UIKit/ButtonTest.cs new file mode 100644 index 000000000000..75b3a86ad782 --- /dev/null +++ b/tests/monotouch-test/UIKit/ButtonTest.cs @@ -0,0 +1,75 @@ +// Copyright 2011, 2013 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ButtonTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIButton b = new UIButton (frame)) { + Assert.That (b.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void NullAllowed () + { + using (var b = new UIButton ()) { + b.SetTitle (null, UIControlState.Normal); + Assert.IsNull (b.Title (UIControlState.Normal), "title"); + + b.SetTitleColor (null, UIControlState.Normal); + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.That (b.TitleColor (UIControlState.Normal), Is.EqualTo (UIColor.White), "titlecolor"); + else + Assert.IsNull (b.TitleColor (UIControlState.Normal), "titlecolor"); + + b.SetTitleShadowColor (null, UIControlState.Normal); + Assert.IsNull (b.TitleShadowColor (UIControlState.Normal), "titleshadowcolor"); + } + } + + [Test] + public void Tag_12557 () + { + using (UIButton b = new UIButton ()) { + Assert.That (b.Tag, Is.EqualTo ((nint) 0), "default"); + b.Tag = nint.MaxValue; + Assert.That (b.Tag, Is.EqualTo (nint.MaxValue), "nint.MaxValue"); + b.Tag = nint.MinValue; + Assert.That (b.Tag, Is.EqualTo (nint.MinValue), "nint.MinValue"); + b.Tag = 0; + Assert.That (b.Tag, Is.EqualTo ((nint) 0), "0"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/CollectionViewControllerTest.cs b/tests/monotouch-test/UIKit/CollectionViewControllerTest.cs new file mode 100644 index 000000000000..798cfab309c7 --- /dev/null +++ b/tests/monotouch-test/UIKit/CollectionViewControllerTest.cs @@ -0,0 +1,38 @@ +// Copyright 2014 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CollectionViewControllerTest { + + [Test] + public void Ctor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6, 0)) + Assert.Inconclusive ("requires iOS 6.0+"); + + using (var l = new UICollectionViewLayout ()) + // interesting ctor for the linker: a [PostSnippet] directly on the backing field is needed + using (var c = new UICollectionViewController (l)) { + // that's because Apple did not expose the init* argument as a property until 7.0 + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.AreSame (l, c.Layout, "Layout"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/CollectionViewTransitionLayoutTest.cs b/tests/monotouch-test/UIKit/CollectionViewTransitionLayoutTest.cs new file mode 100644 index 000000000000..58faa54f86a6 --- /dev/null +++ b/tests/monotouch-test/UIKit/CollectionViewTransitionLayoutTest.cs @@ -0,0 +1,38 @@ +// Copyright 2014 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class CollectionViewTransitionLayoutTest { + + [Test] + public void Ctor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("requires iOS 7.0+"); + + using (var l1 = new UICollectionViewLayout ()) + using (var l2 = new UICollectionViewLayout ()) + using (var tl = new UICollectionViewTransitionLayout (l1, l2)) { + // interesting ctor for the linker (two [PostGet]) + Assert.AreSame (tl.CurrentLayout, l1, "CurrentLayout"); + Assert.AreSame (tl.NextLayout, l2, "NextLayout"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ColorTest.cs b/tests/monotouch-test/UIKit/ColorTest.cs new file mode 100644 index 000000000000..7d004aa33d1c --- /dev/null +++ b/tests/monotouch-test/UIKit/ColorTest.cs @@ -0,0 +1,310 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +using System; +#if !__WATCHOS__ +using System.Drawing; +#endif +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ColorTest { + + [Test] + public void ToString_ () + { + Assert.That ("UIColor [A=255, R=0, G=0, B=0]", + Is.EqualTo (UIColor.Black.ToString ()), "Black"); + Assert.That ("UIColor [A=255, R=0, G=0, B=255]", + Is.EqualTo (UIColor.Blue.ToString ()), "Blue"); + Assert.That ("UIColor [A=255, R=153, G=102, B=51]", + Is.EqualTo (UIColor.Brown.ToString ()), "Brown"); + Assert.That ("UIColor [A=0, R=0, G=0, B=0]", + Is.EqualTo (UIColor.Clear.ToString ()), "Clear"); + Assert.That ("UIColor [A=255, R=0, G=255, B=255]", + Is.EqualTo (UIColor.Cyan.ToString ()), "Cyan"); + Assert.That ("UIColor [A=255, R=85, G=85, B=85]", + Is.EqualTo (UIColor.DarkGray.ToString ()), "DarkGray"); + Assert.That ("UIColor [A=255, R=127, G=127, B=127]", + Is.EqualTo (UIColor.Gray.ToString ()), "Gray"); + Assert.That ("UIColor [A=255, R=0, G=255, B=0]", + Is.EqualTo (UIColor.Green.ToString ()), "Green"); + Assert.That ("UIColor [A=255, R=170, G=170, B=170]", + Is.EqualTo (UIColor.LightGray.ToString ()), "LightGray"); + Assert.That ("UIColor [A=255, R=255, G=0, B=255]", + Is.EqualTo (UIColor.Magenta.ToString ()), "Magenta"); + Assert.That ("UIColor [A=255, R=255, G=127, B=0]", + Is.EqualTo (UIColor.Orange.ToString ()), "Orange"); + Assert.That ("UIColor [A=255, R=127, G=0, B=127]", + Is.EqualTo (UIColor.Purple.ToString ()), "Purple"); + Assert.That ("UIColor [A=255, R=255, G=0, B=0]", + Is.EqualTo (UIColor.Red.ToString ()), "Red"); + Assert.That ("UIColor [A=255, R=255, G=255, B=255]", + Is.EqualTo (UIColor.White.ToString ()), "White"); + Assert.That ("UIColor [A=255, R=255, G=255, B=0]", + Is.EqualTo (UIColor.Yellow.ToString ()), "Yellow"); + } + + void RoundtripHSBA (UIColor c, bool supported = true) + { + try { + nfloat h, s, b, a; + /*bool result =*/ c.GetHSBA (out h, out s, out b, out a); + UIColor r = UIColor.FromHSBA (h, s, b, a); +#if true + Assert.That (r.ToString (), Is.EqualTo (c.ToString ()), c.ToString ()); +#else + if (result) { + string cs = c.ToString (); + float h2, s2, b2, a2; + c.GetHSBA2 (out h2, out s2, out b2, out a2); + Assert.That (h, Is.EqualTo (h2), cs); + Assert.That (s, Is.EqualTo (s2), cs); + Assert.That (b, Is.EqualTo (b2), cs); + Assert.That (a, Is.EqualTo (a2), cs); + } +#endif + } + catch (Exception) { + if (supported) + Assert.Fail (c.ToString ()); + } + } + + [Test] + public void HSBA () + { + GlobalSettings.DefaultFloatingPointTolerance = 0.00001; + RoundtripHSBA (UIColor.Black); + RoundtripHSBA (UIColor.Blue); + RoundtripHSBA (UIColor.Brown); + RoundtripHSBA (UIColor.Clear); + RoundtripHSBA (UIColor.Cyan); + RoundtripHSBA (UIColor.DarkGray); + RoundtripHSBA (UIColor.Gray); + RoundtripHSBA (UIColor.Green); + RoundtripHSBA (UIColor.LightGray); + RoundtripHSBA (UIColor.Magenta); + RoundtripHSBA (UIColor.Orange); + RoundtripHSBA (UIColor.Purple); + RoundtripHSBA (UIColor.Red); + RoundtripHSBA (UIColor.White); + RoundtripHSBA (UIColor.Yellow); +#if !__TVOS__ && !__WATCHOS__ + RoundtripHSBA (UIColor.DarkTextColor); + RoundtripHSBA (UIColor.GroupTableViewBackgroundColor, false); // unsupported color space + RoundtripHSBA (UIColor.LightTextColor); + RoundtripHSBA (UIColor.ScrollViewTexturedBackgroundColor, false); // unsupported color space + RoundtripHSBA (UIColor.UnderPageBackgroundColor, false); // unsupported color space + RoundtripHSBA (UIColor.ViewFlipsideBackgroundColor, false); // unsupported color space +#endif +#if false + for (int r = 0; r < 256; r++) { + for (int g = 0; g < 256; g++) { + for (int b = 0; b < 256; b++) { + RoundtripHSBA (UIColor.FromRGBA (r, g, b, b)); + } + Console.WriteLine ("\tg {0}", g); + } + Console.WriteLine ("\t\tr {0}", r); + } +#endif + } + + [Test] + public void HSBA_No_Saturation () + { + nfloat h = 0.0f; + nfloat s = 0.0f; + nfloat b = 0.0f; + nfloat a = 0.0f; + UIColor c = UIColor.FromHSBA (h, s, b, a); + c.GetHSBA (out h, out s, out b, out a); + Assert.That (h, Is.EqualTo ((nfloat) 0f), "h"); + Assert.That (s, Is.EqualTo ((nfloat) 0f), "s"); + Assert.That (b, Is.EqualTo ((nfloat) 0f), "b"); + Assert.That (a, Is.EqualTo ((nfloat) 0f), "a"); + } + + // note: MonoTouch addition - not fully compatible with "getHue:saturation:brightness:alpha:" wrt alpha + void RoundtripHSB (UIColor c) + { + nfloat h, s, b, a; + c.GetHSBA (out h, out s, out b, out a); + UIColor r = UIColor.FromHSB (h, s, b); + Assert.That (r.ToString (), Is.EqualTo (c.ToString ()), c.ToString ()); + } + + [Test] + public void HSB () + { + RoundtripHSB (UIColor.Black); + RoundtripHSB (UIColor.Blue); + RoundtripHSB (UIColor.Brown); + //RoundtripHSB (UIColor.Clear); // alpha is 0 + RoundtripHSB (UIColor.Cyan); + RoundtripHSB (UIColor.DarkGray); +#if !__TVOS__ && !__WATCHOS__ + RoundtripHSB (UIColor.DarkTextColor); +#endif + RoundtripHSB (UIColor.Gray); + RoundtripHSB (UIColor.Green); + //RoundtripHSB (UIColor.GroupTableViewBackgroundColor); // unsupported color space + RoundtripHSB (UIColor.LightGray); + //RoundtripHSB (UIColor.LightTextColor); // alpha is 153 + RoundtripHSB (UIColor.Magenta); + RoundtripHSB (UIColor.Orange); + RoundtripHSB (UIColor.Purple); + RoundtripHSB (UIColor.Red); + //RoundtripHSB (UIColor.ScrollViewTexturedBackgroundColor); // unsupported color space + //RoundtripHSB (UIColor.UnderPageBackgroundColor); // unsupported color space + //RoundtripHSB (UIColor.ViewFlipsideBackgroundColor); // unsupported color space + RoundtripHSB (UIColor.White); + RoundtripHSB (UIColor.Yellow); + } + + void RoundtripRGBA (UIColor c) + { + nfloat r, g, b, a; + c.GetRGBA (out r, out g, out b, out a); + UIColor k = UIColor.FromRGBA (r, g, b, a); + Assert.That (k.ToString (), Is.EqualTo (c.ToString ()), c.ToString ()); + } + + [Test] + public void RGBA () + { + RoundtripRGBA (UIColor.Black); + RoundtripRGBA (UIColor.Blue); + RoundtripRGBA (UIColor.Brown); + RoundtripRGBA (UIColor.Clear); + RoundtripRGBA (UIColor.Cyan); + RoundtripRGBA (UIColor.DarkGray); +#if !__TVOS__ && !__WATCHOS__ + RoundtripRGBA (UIColor.DarkTextColor); +#endif + RoundtripRGBA (UIColor.Gray); + RoundtripRGBA (UIColor.Green); + //RoundtripRGBA (UIColor.GroupTableViewBackgroundColor); + RoundtripRGBA (UIColor.LightGray); + //RoundtripRGBA (UIColor.LightTextColor); + RoundtripRGBA (UIColor.Magenta); + RoundtripRGBA (UIColor.Orange); + RoundtripRGBA (UIColor.Purple); + RoundtripRGBA (UIColor.Red); + //RoundtripRGBA (UIColor.ScrollViewTexturedBackgroundColor); // unsupported color space + //RoundtripRGBA (UIColor.UnderPageBackgroundColor); // unsupported color space + //RoundtripRGBA (UIColor.ViewFlipsideBackgroundColor); // unsupported color space + RoundtripRGBA (UIColor.White); + RoundtripRGBA (UIColor.Yellow); + } + + // note: MonoTouch addition - not fully compatible with "getRed:green:blue:alpha:" wrt alpha + void RoundtripRGB (UIColor c) + { + nfloat r, g, b, a; + c.GetRGBA (out r, out g, out b, out a); + UIColor k = UIColor.FromRGB (r, g, b); + Assert.That (k.ToString (), Is.EqualTo (c.ToString ()), c.ToString ()); + } + + [Test] + public void RGB () + { + RoundtripRGB (UIColor.Black); + RoundtripRGB (UIColor.Blue); + RoundtripRGB (UIColor.Brown); + // RoundtripRGB (UIColor.Clear); // alpha is 0 + RoundtripRGB (UIColor.Cyan); + RoundtripRGB (UIColor.DarkGray); +#if !__TVOS__ && !__WATCHOS__ + RoundtripRGB (UIColor.DarkTextColor); +#endif + RoundtripRGB (UIColor.Gray); + RoundtripRGB (UIColor.Green); + //RoundtripRGB (UIColor.GroupTableViewBackgroundColor); // unsupported color space + RoundtripRGB (UIColor.LightGray); + //RoundtripRGB (UIColor.LightTextColor); // alpha is 153 + RoundtripRGB (UIColor.Magenta); + RoundtripRGB (UIColor.Orange); + RoundtripRGB (UIColor.Purple); + RoundtripRGB (UIColor.Red); + //RoundtripRGB (UIColor.ScrollViewTexturedBackgroundColor); // unsupported color space + //RoundtripRGB (UIColor.UnderPageBackgroundColor); // unsupported color space + //RoundtripRGB (UIColor.ViewFlipsideBackgroundColor); // unsupported color space + RoundtripRGB (UIColor.White); + RoundtripRGB (UIColor.Yellow); + } + + [Test] + public void Pattern_7362 () + { + using (var img = UIImage.FromFile ("basn3p08.png")) + using (var color = UIColor.FromPatternImage (img)) { + Assert.That (color.ToString (), Is.EqualTo (color.Description), "not an RGBA color"); + } + } + + void RoundtripConstructorRGB (UIColor c) + { + nfloat r, g, b, a; + c.GetRGBA (out r, out g, out b, out a); + var k = new UIColor (r, g, b, a); + Assert.That (k.ToString (), Is.EqualTo (c.ToString ()), c.ToString ()); + } + + [Test] + public void RGBAConstructor () + { + RoundtripConstructorRGB (UIColor.Black); + RoundtripConstructorRGB (UIColor.Blue); + RoundtripConstructorRGB (UIColor.Brown); + RoundtripConstructorRGB (UIColor.Cyan); + RoundtripConstructorRGB (UIColor.DarkGray); +#if !__TVOS__ && !__WATCHOS__ + RoundtripConstructorRGB (UIColor.DarkTextColor); +#endif + RoundtripConstructorRGB (UIColor.Gray); + RoundtripConstructorRGB (UIColor.Green); + RoundtripConstructorRGB (UIColor.LightGray); + RoundtripConstructorRGB (UIColor.Magenta); + RoundtripConstructorRGB (UIColor.Orange); + RoundtripConstructorRGB (UIColor.Purple); + RoundtripConstructorRGB (UIColor.Red); + RoundtripConstructorRGB (UIColor.White); + RoundtripConstructorRGB (UIColor.Yellow); + } + + [TestCase (0.2, 0.4)] + [TestCase (0.3, 0.5)] + [TestCase (0.4, 0.6)] + [TestCase (0.5, 0.7)] + public void WAConstructor (double w, double a) + { + var nw = (nfloat)w; + var na = (nfloat)a; + var c = UIColor.FromWhiteAlpha (nw, na); + var r = new UIColor (nw, na); + Assert.That (r.ToString (), Is.EqualTo (c.ToString ()), c.ToString ()); + } + } +} diff --git a/tests/monotouch-test/UIKit/ControlTest.cs b/tests/monotouch-test/UIKit/ControlTest.cs new file mode 100644 index 000000000000..39fa89863188 --- /dev/null +++ b/tests/monotouch-test/UIKit/ControlTest.cs @@ -0,0 +1,97 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ControlTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIControl c = new UIControl (frame)) { + Assert.That (c.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void CancelTrackingTest () + { + using (var c = new UIControl ()) { + c.CancelTracking (null); + c.CancelTracking (new UIEvent ()); + } + } + + [Test] + public void AddTargetTable () + { + const int items = 100; + var handles = new GCHandle [items]; + var handler = new EventHandler (delegate(object sender, EventArgs e) { + + }); + for (int i = 0; i < items; i++) { + var ctrl = new UIControl (); + ctrl.AddTarget (handler, UIControlEvent.EditingChanged); + handles [i] = GCHandle.Alloc (ctrl, GCHandleType.Weak); + } + GC.Collect (); + + // If at least one object was collected, then we know the static ConditionalWeakTable + // of object -> event handlers doesn't keep strong references. + var any_collected = false; + for (int i = 0; i < items; i++) { + if (handles [i].Target == null) + any_collected = true; + handles [i].Free (); + } + Assert.IsTrue (any_collected, "Nothing collected"); + } + + [Test] + public void AddTargetMakeDirty () + { + using (var ctrl = new UIControl ()) { + ctrl.AddTarget ((a, b) => { }, UIControlEvent.EditingDidBegin); + Assert.IsTrue ((GetFlags (ctrl) & 0x8) /* RegisteredToggleRef */ == 0x8, "RegisteredToggleRef"); + } + } + + + byte GetFlags (NSObject obj) + { + return (byte) typeof (NSObject).GetField ("flags", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); + } + + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/DatePickerTest.cs b/tests/monotouch-test/UIKit/DatePickerTest.cs new file mode 100644 index 000000000000..dd48619eeef0 --- /dev/null +++ b/tests/monotouch-test/UIKit/DatePickerTest.cs @@ -0,0 +1,91 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DatePickerTest { + + [Test] + public void Defaults () + { + using (UIDatePicker dp = new UIDatePicker ()) { + Assert.Null (dp.MinimumDate, "MinimumDate"); + Assert.Null (dp.MaximumDate, "MaximumDate"); + Assert.Null (dp.TimeZone, "TimeZone"); + + Assert.NotNull (dp.Calendar, "Calendar"); + Assert.NotNull (dp.Date, "Date"); + } + } + + [Test] + public void Locale () + { + using (UIDatePicker dp = new UIDatePicker ()) { + // this is documented as deprecated in 5.1 but not in 6.0 (reversal or misdocumentation ?) + // default value also differs + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.NotNull (dp.Locale, "Locale"); + else + Assert.Null (dp.Locale, "Locale"); + } + } + [Test] + public void Nulls () + { + using (UIDatePicker dp = new UIDatePicker ()) { + dp.Calendar = null; + dp.Locale = null; + dp.MinimumDate = null; + dp.MaximumDate = null; + dp.TimeZone = null; + + // some null checks are done, otherwise we end up with + // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Invalid parameter not satisfying: date + Assert.Throws (delegate { + dp.Date = null; + }); + Assert.Throws (delegate { + dp.SetDate (null, true); + }); + } + } + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIDatePicker dp = new UIDatePicker (frame)) { + Assert.That (dp.Frame.X, Is.EqualTo (frame.X), "X"); + Assert.That (dp.Frame.Y, Is.EqualTo (frame.Y), "Y"); + // Width and Height are set by the DatePicker (e.g. 320 x 216 for the iPhone) + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/DeviceTest.cs b/tests/monotouch-test/UIKit/DeviceTest.cs new file mode 100644 index 000000000000..b8bb7de53af8 --- /dev/null +++ b/tests/monotouch-test/UIKit/DeviceTest.cs @@ -0,0 +1,65 @@ +// +// Unit tests for UIDevice +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.IO; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DeviceTest { + +#if !XAMCORE_2_0 + [Test] + public void CurrentDevice () + { + UIDevice device = UIDevice.CurrentDevice; + // under iOS 5.1 some API (mobileDevice on client) stopped reporting the identifier + // this will warn us then this API "fails" too + Assert.NotNull (device.UniqueIdentifier, "UniqueIdentifier"); + } +#endif + +#if !__TVOS__ && !__WATCHOS__ + [Test] + public void Battery () + { + UIDevice device = UIDevice.CurrentDevice; + Assert.False (device.BatteryMonitoringEnabled, "false"); + Assert.That (device.BatteryState, Is.EqualTo (UIDeviceBatteryState.Unknown), "false/Unknown"); + Assert.That (device.BatteryLevel, Is.EqualTo (-1), "false/-1"); + + device.BatteryMonitoringEnabled = true; + try { + if (Runtime.Arch == Arch.SIMULATOR) { + Assert.That (device.BatteryState, Is.EqualTo (UIDeviceBatteryState.Unknown), "true/Unknown"); + Assert.That (device.BatteryLevel, Is.EqualTo (-1), "true/-1"); + } else { + Assert.That (device.BatteryState, Is.Not.EqualTo (UIDeviceBatteryState.Unknown), "true/Unknown"); + Assert.That (device.BatteryLevel, Is.Not.EqualTo (-1), "true/-1"); + } + } + finally { + device.BatteryMonitoringEnabled = false; + } + } +#endif // !__TVOS__ && !__WATCHOS__ + } +} diff --git a/tests/monotouch-test/UIKit/DictationPhrase.cs b/tests/monotouch-test/UIKit/DictationPhrase.cs new file mode 100644 index 000000000000..3fdbf0e6caab --- /dev/null +++ b/tests/monotouch-test/UIKit/DictationPhrase.cs @@ -0,0 +1,36 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class DictationPhraseTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (5, 1)) + return; + + using (UIDictationPhrase dp = new UIDictationPhrase ()) { + Assert.Null (dp.AlternativeInterpretations, "AlternativeInterpretations"); + Assert.Null (dp.Text, "Text"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/EdgeInsetsTest.cs b/tests/monotouch-test/UIKit/EdgeInsetsTest.cs new file mode 100644 index 000000000000..e4dec3db7639 --- /dev/null +++ b/tests/monotouch-test/UIKit/EdgeInsetsTest.cs @@ -0,0 +1,74 @@ +// +// Unit tests for UIEdgeInsets +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class EdgeInsetsTest { + + [Test] + public void FromString_Null () + { + var e = UIEdgeInsets.FromString (null); + Assert.That (e, Is.EqualTo (UIEdgeInsets.Zero), "roundtrip"); + } + + [Test] + public void ToFromString_Zero () + { + string s = UIEdgeInsets.Zero.ToString (); + var e = UIEdgeInsets.FromString (s); + Assert.That (e, Is.EqualTo (UIEdgeInsets.Zero), "roundtrip"); + } + + [Test] + public void InsetRect_Zero () + { + var r = UIEdgeInsets.Zero.InsetRect (RectangleF.Empty); + Assert.That (r, Is.EqualTo (RectangleF.Empty), "InsetRect"); + } + + [Test] + public void InsetRect () + { + var i = new UIEdgeInsets (10, 20, 30, 40); + var r = new RectangleF (1, 2, 3, 4); + r = i.InsetRect (r); + Assert.That (r.X, Is.EqualTo ((nfloat) 21f), "X"); + Assert.That (r.Y, Is.EqualTo ((nfloat) 12f), "Y"); + Assert.That (r.Width, Is.EqualTo ((nfloat) (-57f)), "Width"); + Assert.That (r.Height, Is.EqualTo ((nfloat) (-36f)), "Height"); + + Assert.False (i.Equals (UIEdgeInsets.Zero), "Equals(UIEdgeInsets)"); + Assert.False (UIEdgeInsets.Zero.Equals ((object) i), "Equals(object)"); + } + } +} diff --git a/tests/monotouch-test/UIKit/FloatRangeTest.cs b/tests/monotouch-test/UIKit/FloatRangeTest.cs new file mode 100644 index 000000000000..bd2f028d6a1c --- /dev/null +++ b/tests/monotouch-test/UIKit/FloatRangeTest.cs @@ -0,0 +1,87 @@ +// Authors: +// Sebastien Pouliot +// +// Copyright 2013, 2016 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FloatRangeTest { + + [Test] + public void ManagedVersusNative () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.Ignore ("Requires iOS 9+"); + var uikit = Dlfcn.dlopen (Constants.UIKitLibrary, 0); + try { + var zero = Dlfcn.dlsym (uikit, "UIFloatRangeZero"); + var Zero = (UIFloatRange)Marshal.PtrToStructure (zero, typeof (UIFloatRange)); + Assert.True (UIFloatRange.Zero.Equals (Zero), "Zero"); + + var infinite = Dlfcn.dlsym (uikit, "UIFloatRangeInfinite"); + var Infinite = (UIFloatRange)Marshal.PtrToStructure (infinite, typeof (UIFloatRange)); + Assert.True (Infinite.IsInfinite, "IsInfinite"); + Assert.False (UIFloatRange.Infinite.Equals (Infinite), "Infinite"); + } finally { + Dlfcn.dlclose (uikit); + } + } + + [Test] + public void IsInfinite () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.Ignore ("Requires iOS 9+"); + Assert.True (UIFloatRange.Infinite.IsInfinite, "Infinite"); + Assert.False (UIFloatRange.Zero.IsInfinite, "Zero"); + } + + [Test] + public void Equals () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (9,0)) + Assert.Ignore ("Requires iOS 9+"); + Assert.True (UIFloatRange.Zero.Equals (UIFloatRange.Zero), "Zero-Zero"); + var one = new UIFloatRange (1f, 1f); + Assert.False (one.Equals (UIFloatRange.Zero), "one-Zero"); + Assert.False (UIFloatRange.Zero.Equals ((object) one), "Zero-one"); + Assert.True (one.Equals (one), "one-one"); + + Assert.False (UIFloatRange.Infinite.Equals (UIFloatRange.Infinite), "Infinite-Infinite"); + Assert.False (UIFloatRange.Infinite.Equals (UIFloatRange.Zero), "Infinite-Zero"); + Assert.False (UIFloatRange.Zero.Equals (UIFloatRange.Infinite), "Zero-Infinite"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/FontTest.cs b/tests/monotouch-test/UIKit/FontTest.cs new file mode 100644 index 000000000000..d43a7ea6c7c8 --- /dev/null +++ b/tests/monotouch-test/UIKit/FontTest.cs @@ -0,0 +1,180 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class FontTest { + + [Test] + public void WithSize () + { + var f1 = UIFont.SystemFontOfSize (10).WithSize (20); + Assert.AreEqual (f1.PointSize, (nfloat) 20, "#size"); + } + + [Test] + public void TestDescriptors () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + var font = UIFont.BoldSystemFontOfSize (80); + var descriptor = font.FontDescriptor; + + // Ensure that Apple does not break things behind us, they documented + // the size property as being a string, but it is a number (makes sense) + // but make sure we dont regress if they fix it. + + var size = descriptor.FontAttributes.Size; + Assert.AreEqual (true, size.HasValue); + Assert.AreEqual (80.0f, size.Value); + } + + // ref: https://trello.com/c/wKZyugio/437-many-managed-peers-on-a-single-native-instance + + void SemiFactory_25511 (UIFont f1, UIFont f2, string api) + { + using (f1) { + // the same instance will be returned (from an iOS cache) + Assert.That (f1.Handle, Is.EqualTo (f2.Handle), "{0} Handle", api); + // using means f1 will be disposed and it's handle will be zero'ed + // but f2 is the same (managed) instance and _normally_ would become unusable + // to fix this we now return a different instance - but we must still match the existing behavior + Assert.True (f1 == f2, "{0} ==", api); + Assert.True (f1.Equals ((object) f2), "{0} Equals(object)", api); + // IEquatable is only in unified - otherwise it would be the same call as above + Assert.True (f1.Equals (f2), "{0} Equals", api); + } + Assert.That (f1.Handle, Is.EqualTo (IntPtr.Zero), "{0} 1", api); + // without our "fix" that would be the same managed instance (as f1) and the handle would be nil + Assert.That (f2.Handle, Is.Not.EqualTo (IntPtr.Zero), "{0} 2", api); + } + + [Test] + public void Methods () + { + var f1 = UIFont.FromName ("Helvetica", 20.0f); + // the same instance will be returned (from an iOS cache) + var f2 = UIFont.FromName ("Helvetica", 20.0f); + // first instance will be disposed and the 2nd one needs to stay valid + SemiFactory_25511 (f1, f2, "FromName"); + + f1 = UIFont.SystemFontOfSize (12); + f2 = UIFont.SystemFontOfSize (12); + SemiFactory_25511 (f1, f2, "SystemFontOfSize"); + + f1 = UIFont.BoldSystemFontOfSize (12); + f2 = UIFont.BoldSystemFontOfSize (12); + SemiFactory_25511 (f1, f2, "BoldSystemFontOfSize"); + + f1 = UIFont.ItalicSystemFontOfSize (12); + f2 = UIFont.ItalicSystemFontOfSize (12); + SemiFactory_25511 (f1, f2, "ItalicSystemFontOfSize"); + + f1 = UIFont.SystemFontOfSize (12); + f2 = UIFont.SystemFontOfSize (12); + SemiFactory_25511 (f1, f2, "SystemFontOfSize"); + + // instance + f1 = f2.WithSize (12); + f2 = f2.WithSize (12); + SemiFactory_25511 (f1, f2, "WithSize"); + + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + return; + + using (var name = new NSString ("UICTFontTextStyleBody")) { + f1 = UIFont.GetPreferredFontForTextStyle (name); + f2 = UIFont.GetPreferredFontForTextStyle (name); + SemiFactory_25511 (f1, f2, "GetPreferredFontForTextStyle"); + } + + var d = f2.FontDescriptor; + f1 = UIFont.FromDescriptor (d, 12); + f2 = UIFont.FromDescriptor (d, 12); + SemiFactory_25511 (f1, f2, "FromDescriptor"); + } + + [Test] + public void Properties () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + var f1 = UIFont.PreferredBody; + // the same instance will be returned (from an iOS cache) + var f2 = UIFont.PreferredBody; + // first instance will be disposed and the 2nd one needs to stay valid + SemiFactory_25511 (f1, f2, "PreferredBody"); + + f1 = UIFont.PreferredCaption1; + f2 = UIFont.PreferredCaption1; + SemiFactory_25511 (f1, f2, "PreferredCaption1"); + + f1 = UIFont.PreferredCaption2; + f2 = UIFont.PreferredCaption2; + SemiFactory_25511 (f1, f2, "PreferredCaption2"); + + f1 = UIFont.PreferredFootnote; + f2 = UIFont.PreferredFootnote; + SemiFactory_25511 (f1, f2, "PreferredFootnote"); + + f1 = UIFont.PreferredHeadline; + f2 = UIFont.PreferredHeadline; + SemiFactory_25511 (f1, f2, "PreferredHeadline"); + + f1 = UIFont.PreferredSubheadline; + f2 = UIFont.PreferredSubheadline; + SemiFactory_25511 (f1, f2, "PreferredSubheadline"); + } + + [Test] + public void NullFonts () + { + var invalidFontName = new NSString ("Invalid Font Name"); + if (TestRuntime.CheckiOSSystemVersion (7, 0)) { + Assert.IsNotNull (UIFont.GetPreferredFontForTextStyle (invalidFontName), "GetPreferredFontForTextStyle"); + Assert.IsNotNull (UIFont.FromDescriptor (new UIFontDescriptor (), -2), "FromDescriptor (,)"); + } + + Assert.IsNull (UIFont.FromName (invalidFontName, 1), "FromName"); + + Assert.IsNotNull (UIFont.SystemFontOfSize (-3), "SystemFontOfSize()"); + + if (TestRuntime.CheckiOSSystemVersion (8, 2)) { + Assert.IsNotNull (UIFont.SystemFontOfSize (0, UIFontWeight.Regular), "SystemFontOfSize (nfloat, UIFontWeight)"); + Assert.IsNotNull (UIFont.SystemFontOfSize (0, (nfloat) 0), "SystemFontOfSize (nfloat, nfloat)"); + } + + Assert.IsNotNull (UIFont.BoldSystemFontOfSize (-4), "BoldSystemFontOfSize"); + Assert.IsNotNull (UIFont.ItalicSystemFontOfSize (-5), "ItalicSystemFontOfSize"); + + using (var font = UIFont.SystemFontOfSize (12)) { + Assert.IsNotNull (font.WithSize (-6), "WithSize"); + } + } + } +} diff --git a/tests/monotouch-test/UIKit/GestureRecognizerTest.cs b/tests/monotouch-test/UIKit/GestureRecognizerTest.cs new file mode 100644 index 000000000000..35f73f685d17 --- /dev/null +++ b/tests/monotouch-test/UIKit/GestureRecognizerTest.cs @@ -0,0 +1,43 @@ +// +// UIGestureRecognizer Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class GestureRecognizerTest { + + [Test] + public void Null () + { + using (var gr = new UIGestureRecognizer (Null)) { + // ensure documented null-friendly methods actually are before releasing them in the wild + gr.LocationInView (null); + // can't call LocationOfTouch, 0 is not valid if there's no touch event + // gr.LocationOfTouch (0, null); + gr.RemoveTarget (null, null); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/GuidedAccessRestrictionTest.cs b/tests/monotouch-test/UIKit/GuidedAccessRestrictionTest.cs new file mode 100644 index 000000000000..03869e1dcdaf --- /dev/null +++ b/tests/monotouch-test/UIKit/GuidedAccessRestrictionTest.cs @@ -0,0 +1,41 @@ +// +// Unit tests for UIGuidedAccessRestriction +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class GuidedAccessRestrictionTest { + + [Test] + public void GetState () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + Assert.That (UIGuidedAccessRestriction.GetState (null), Is.EqualTo (UIGuidedAccessRestrictionState.Allow), "null"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ImageTest.cs b/tests/monotouch-test/UIKit/ImageTest.cs new file mode 100644 index 000000000000..27c30b407d83 --- /dev/null +++ b/tests/monotouch-test/UIKit/ImageTest.cs @@ -0,0 +1,105 @@ +// Copyright 2011, 2013 Xamarin Inc. All rights reserved + +using System; +using System.Drawing; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageTest { + + [Test] + public void TestAutorelease () + { + int iWidth = 2500; + int iHeight = 2500; + int r = 0; + + try { + for (r = 0; r < 1000; r++) { + using (CGColorSpace oColorSpace = CGColorSpace.CreateDeviceRGB ()) { + using (CGBitmapContext oContext = new CGBitmapContext (null, iWidth, iHeight, 8, iWidth * 4, oColorSpace, CGImageAlphaInfo.PremultipliedFirst)) { + using (CGImage oImage = oContext.ToImage ()) { + using (var img = UIImage.FromImage (oImage)) { + Assert.That (img.Size.Width, Is.GreaterThan ((nfloat) 0), "w" + r.ToString ()); + Assert.That (img.Size.Height, Is.GreaterThan ((nfloat) 0), "h" + r.ToString ()); + } + } + } + } + } + } catch (AssertionException) { + throw; + } catch (Exception ex) { + throw new Exception (string.Format ("Test failed after {0} iterations: {1}", r, ex.Message), ex); + } + } + + [Test] + public void CGImageBackend () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var original = UIImage.FromFile (file)) { + Assert.That (original.CGImage.Width, Is.EqualTo ((nint) 32), "Width-a"); + Assert.That (original.CGImage.Height, Is.EqualTo ((nint) 32), "Height-a"); + SizeF half = new SizeF (16f, 16f); + IntPtr handle = original.CGImage.Handle; + using (var resized = original.Scale (half)) { + Assert.That (resized.CGImage.Height, Is.EqualTo (resized.CGImage.Width), "Width-Height-identical"); + // caching of the backing CGImage occurs on devices (but not always) + if (Runtime.Arch == Arch.SIMULATOR) { + Assert.That ((nint) 16, Is.EqualTo (resized.CGImage.Width), "half"); + } else { + var h = resized.CGImage.Height; + Assert.True (h == 16 || h == 32, "mostly"); + } + Assert.That (handle, Is.Not.EqualTo (resized.CGImage.Handle), "Handle"); + } + } + } + + [Test] + public void CreateAnimatedImage () + { + using (var i = UIImage.CreateAnimatedImage ("xamarin", UIEdgeInsets.Zero, 1d)) { + Assert.That (i.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + Assert.That (i.Images.Length, Is.EqualTo (3), "3 images"); + Assert.True (i.Description.Contains ("UIAnimatedImage"), "UIAnimatedImage"); + } +#if !XAMCORE_2_0 + Assert.Null (UIImage.CreateAnimatedImage (new UIImage[0], UIEdgeInsets.Zero, 1d), "bad binding"); +#endif + } + + [Test] + public void FromImage_Null () + { + Assert.Throws (() => UIImage.FromImage ((CGImage)null), "CGImage"); + } + } +} diff --git a/tests/monotouch-test/UIKit/ImageViewTest.cs b/tests/monotouch-test/UIKit/ImageViewTest.cs new file mode 100644 index 000000000000..f34b9a65f89a --- /dev/null +++ b/tests/monotouch-test/UIKit/ImageViewTest.cs @@ -0,0 +1,69 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class ImageViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIImageView iv = new UIImageView (frame)) { + Assert.That (iv.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void AnimationImages () + { + using (var i1 = new UIImage ()) + using (var i2 = new UIImage ()) + using (var v = new UIImageView ()) { + v.AnimationImages = new UIImage[] { i1, i2 }; + // no need for [PostGet] since it does not change other properties + Assert.Null (v.Image, "Image"); + Assert.Null (v.HighlightedImage); + } + } + + [Test] + public void HighlightedAnimationImages_BackingFields () + { + using (var i1 = new UIImage ()) + using (var i2 = new UIImage ()) + using (var v = new UIImageView ()) { + v.HighlightedAnimationImages = new UIImage[] { i1, i2 }; + // no need for [PostGet] since it does not change other properties + Assert.Null (v.Image, "Image"); + Assert.Null (v.HighlightedImage); + } + } + } +} + +#endif // !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/UIKit/LabelTest.cs b/tests/monotouch-test/UIKit/LabelTest.cs new file mode 100644 index 000000000000..1dfd5cbbd624 --- /dev/null +++ b/tests/monotouch-test/UIKit/LabelTest.cs @@ -0,0 +1,54 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LabelTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UILabel l = new UILabel (frame)) { + Assert.That (l.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void HighlightedTextColor () + { + UILabel label = new UILabel (); + Assert.Null (label.HighlightedTextColor, "HighlightedTextColor/default"); + label.HighlightedTextColor = UIColor.Blue; + Assert.That (label.HighlightedTextColor, Is.EqualTo (UIColor.Blue), "HighlightedTextColor/blue"); + label.HighlightedTextColor = null; + Assert.Null (label.HighlightedTextColor, "HighlightedTextColor/null"); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/LayoutConstraintTest.cs b/tests/monotouch-test/UIKit/LayoutConstraintTest.cs new file mode 100644 index 000000000000..2b4315f5a8c9 --- /dev/null +++ b/tests/monotouch-test/UIKit/LayoutConstraintTest.cs @@ -0,0 +1,68 @@ +// Copyright 2012-2013 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LayoutConstraintTest { + + [Test] + public void Create () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("requires iOS 6"); + + using (var view = new UIView ()) { + NSLayoutConstraint.Create (view, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 5).Dispose (); + } + } + + [Test] + public void FromVisualFormat_NullMetrics () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("requires iOS 6"); + + using (var dict = new NSMutableDictionary ()) + using (var b0 = UIButton.FromType (UIButtonType.InfoDark)) + using (var b1 = UIButton.FromType (UIButtonType.InfoLight)) { + dict ["button0"] = b0; + dict ["button1"] = b1; + var constaints = NSLayoutConstraint.FromVisualFormat ("[button0]-20-[button1]", NSLayoutFormatOptions.AlignAllBaseline, null, dict); + Assert.That (constaints.Length, Is.EqualTo (2), "constaints"); + } + } + + [Test] + public void FromVisualFormat () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("requires iOS 6"); + + using (var metrics = new NSMutableDictionary ()) + using (var dict = new NSMutableDictionary ()) + using (var b0 = UIButton.FromType (UIButtonType.InfoDark)) + using (var b1 = UIButton.FromType (UIButtonType.InfoLight)) { + dict ["button0"] = b0; + dict ["button1"] = b1; + var constaints = NSLayoutConstraint.FromVisualFormat ("[button0]-20-[button1]", NSLayoutFormatOptions.AlignAllBaseline, metrics, dict); + Assert.NotNull (constaints); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/LayoutManagerTest.cs b/tests/monotouch-test/UIKit/LayoutManagerTest.cs new file mode 100644 index 000000000000..bf1ac2c02e00 --- /dev/null +++ b/tests/monotouch-test/UIKit/LayoutManagerTest.cs @@ -0,0 +1,101 @@ +// +// NSLayoutManager Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LayoutManagerTest { + + [Test] + public void Defaults () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var lm = new NSLayoutManager ()) { + Assert.False (lm.AllowsNonContiguousLayout, "AllowsNonContiguousLayout"); + Assert.True (lm.ExtraLineFragmentRect.IsEmpty, "ExtraLineFragmentRect"); + Assert.Null (lm.ExtraLineFragmentTextContainer, "ExtraLineFragmentTextContainer"); + Assert.True (lm.ExtraLineFragmentUsedRect.IsEmpty, "ExtraLineFragmentUsedRect"); + Assert.That (lm.FirstUnlaidCharacterIndex, Is.EqualTo ((nuint) 0), "FirstUnlaidCharacterIndex"); + Assert.That (lm.FirstUnlaidGlyphIndex, Is.EqualTo ((nuint) 0), "FirstUnlaidGlyphIndex"); + Assert.False (lm.HasNonContiguousLayout, "HasNonContiguousLayout"); + Assert.That (lm.HyphenationFactor, Is.EqualTo ((nfloat) 0), "HyphenationFactor"); + Assert.That (lm.NumberOfGlyphs, Is.EqualTo ((nuint) 0), "NumberOfGlyphs"); + Assert.False (lm.ShowsControlCharacters, "ShowsControlCharacters"); + Assert.False (lm.ShowsInvisibleCharacters, "ShowsInvisibleCharacters"); + Assert.Null (lm.TextStorage, "TextStorage"); + Assert.True (lm.UsesFontLeading, "UsesFontLeading"); + } + } + + [Test] + public void GetGlyphsTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var txt = new NSTextStorage ()) { + var str = "hello world\n\t"; + txt.SetString (new NSAttributedString (str)); + using (var lm = new NSLayoutManager ()) { + lm.TextStorage = txt; + var glyphs = new short[str.Length]; + var props = new NSGlyphProperty [glyphs.Length]; + var charIndexBuffer = new nuint [glyphs.Length]; + var bidiLevelBuffer = new byte [glyphs.Length]; + lm.GetGlyphs (new NSRange (0, str.Length), glyphs, props, charIndexBuffer, bidiLevelBuffer); + Assert.That (glyphs, Is.EqualTo (new short [] { 75, 72, 79, 79, 82, 3, 90, 82, 85, 79, 71, -1, -1 }), "glyphs"); + Assert.That (props, Is.EqualTo (new NSGlyphProperty [] { + 0, + 0, + 0, + 0, + 0, + NSGlyphProperty.Elastic, + 0, + 0, + 0, + 0, + 0, + NSGlyphProperty.ControlCharacter, + NSGlyphProperty.ControlCharacter + }), "props"); + Assert.That (charIndexBuffer, Is.EqualTo (new nuint [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }), "charIndexBuffer"); + Assert.That (bidiLevelBuffer, Is.EqualTo (new byte [str.Length]), "bidiLevelBuffer"); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/LocalNotificationTest.cs b/tests/monotouch-test/UIKit/LocalNotificationTest.cs new file mode 100644 index 000000000000..658abfbfea36 --- /dev/null +++ b/tests/monotouch-test/UIKit/LocalNotificationTest.cs @@ -0,0 +1,119 @@ +// +// Unit tests for UILocalNotification +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class LocalNotificationTest { + + [Test] + public void DefaultValues () + { + using (var def = new UILocalNotification ()) { + Assert.IsNull (def.FireDate, "FireDate"); + Assert.IsNull (def.TimeZone, "TimeZone"); + Assert.That ((nuint) (ulong) def.RepeatInterval, Is.EqualTo ((nuint) 0), "RepeatInterval"); // documented to be 0, which is not in the enum. + Assert.IsNull (def.RepeatCalendar, "RepeatCalendar"); + Assert.IsNull (def.AlertBody, "AlertBody"); + Assert.IsTrue (def.HasAction, "HasAction"); + Assert.IsNull (def.AlertAction, "AlertAction"); + Assert.IsNull (def.AlertLaunchImage, "AlertLaunchImage"); + Assert.IsNull (def.SoundName, "SoundName"); + Assert.That (def.ApplicationIconBadgeNumber, Is.EqualTo ((nint)0), "ApplicationIconBadgeNumber"); + Assert.IsNull (def.UserInfo, "UserInfo"); + } + } + + [Test] + public void NullValues () + { + using (var def = new UILocalNotification ()) { + def.FireDate = null; + def.FireDate = new NSDate (); + Assert.IsNotNull (def.FireDate, "FireDate NN"); + def.FireDate = null; + Assert.IsNull (def.FireDate, "FireDate N"); + + def.TimeZone = null; + def.TimeZone = new NSTimeZone ("GMT"); + Assert.IsNotNull (def.TimeZone, "TimeZone NN"); + def.TimeZone = null; + Assert.IsNull (def.TimeZone, "TimeZone N"); + + def.RepeatInterval = NSCalendarUnit.Calendar; + Assert.That (def.RepeatInterval, Is.EqualTo (NSCalendarUnit.Calendar), "RepeatInterval 1"); + def.RepeatInterval = (NSCalendarUnit)0; + Assert.That (def.RepeatInterval, Is.EqualTo ((NSCalendarUnit)0), "RepeatInterval 2"); + + def.RepeatCalendar = null; + def.RepeatCalendar = new NSCalendar (NSCalendarType.Hebrew); + Assert.IsNotNull (def.RepeatCalendar, "RepeatCalendar NN"); + def.RepeatCalendar = null; + Assert.IsNull (def.RepeatCalendar, "RepeatCalendar N"); + + def.AlertBody = null; + def.AlertBody = "body"; + Assert.AreEqual ("body", def.AlertBody, "AlertBody NN"); + def.AlertBody = null; + Assert.IsNull (def.AlertBody, "AlertBody N"); + + def.AlertAction = null; + def.AlertAction = "action"; + Assert.AreEqual ("action", def.AlertAction, "AlertAction NN"); + def.AlertAction = null; + Assert.IsNull (def.AlertAction, "AlertAction N"); + + def.AlertLaunchImage = null; + def.AlertLaunchImage = "image"; + Assert.AreEqual ("image", def.AlertLaunchImage, "AlertLaunchImage NN"); + def.AlertLaunchImage = null; + Assert.IsNull (def.AlertLaunchImage, "AlertLaunchImage N"); + + def.SoundName = null; + def.SoundName = "sound"; + Assert.AreEqual ("sound", def.SoundName, "SoundName NN"); + def.SoundName = null; + Assert.IsNull (def.SoundName, "SoundName N"); + + def.UserInfo = null; + def.UserInfo = new NSDictionary (); + Assert.IsNotNull (def.UserInfo, "UserInfo NN"); + def.UserInfo = null; + Assert.IsNull (def.UserInfo, "UserInfo N"); + } + } + } +} + +#endif // !__TVOS__ diff --git a/tests/monotouch-test/UIKit/NavigationBarTest.cs b/tests/monotouch-test/UIKit/NavigationBarTest.cs new file mode 100644 index 000000000000..4820da03a7db --- /dev/null +++ b/tests/monotouch-test/UIKit/NavigationBarTest.cs @@ -0,0 +1,53 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class NavigationBarTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UINavigationBar nb = new UINavigationBar (frame)) { + Assert.That (nb.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void BackgroundImage () + { + // http://stackoverflow.com/q/10504966/220643 + using (UINavigationBar nb = new UINavigationBar ()) { + Assert.Null (nb.GetBackgroundImage (UIBarMetrics.Default), "Get"); + nb.SetBackgroundImage (null, UIBarMetrics.Default); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/NavigationControllerTest.cs b/tests/monotouch-test/UIKit/NavigationControllerTest.cs new file mode 100644 index 000000000000..8648ec6c9fef --- /dev/null +++ b/tests/monotouch-test/UIKit/NavigationControllerTest.cs @@ -0,0 +1,49 @@ +// +// Unit tests for UINavigationController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + class NavigationControllerPoker : UINavigationController { + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class NavigationControllerTest { + [Test] + public void ViewControllers_EmptyNull () + { + using (UIViewController vc = new UIViewController ()) + using (var nc = new NavigationControllerPoker ()) { + Assert.That (nc.ViewControllers, Is.Empty, "Empty"); + nc.SetViewControllers (new UIViewController[] { vc }, false); + Assert.That (nc.ViewControllers, Is.Not.Empty, "!Empty"); + nc.SetViewControllers (null, false); + Assert.That (nc.ViewControllers, Is.Empty, "null->Empty/SetMethod"); + nc.ViewControllers = null; + Assert.That (nc.ViewControllers, Is.Empty, "null->Empty/Property"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/NavigationItemTest.cs b/tests/monotouch-test/UIKit/NavigationItemTest.cs new file mode 100644 index 000000000000..192efbcfa0d4 --- /dev/null +++ b/tests/monotouch-test/UIKit/NavigationItemTest.cs @@ -0,0 +1,32 @@ +// +// Unit tests for UINavigationItem +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NavigationItemTest { + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/NibTest.cs b/tests/monotouch-test/UIKit/NibTest.cs new file mode 100644 index 000000000000..69ed5b58061c --- /dev/null +++ b/tests/monotouch-test/UIKit/NibTest.cs @@ -0,0 +1,77 @@ +// +// UINib Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NibTest { + + [Test] + public void FromName_DoesNotExists () + { + using (UINib n = UINib.FromName ("does-not-exists", null)) { + // note: it's not really loaded until `instantiateWithOwner:options:` is called + // so the result is not null + Assert.NotNull (n, "created with null options"); + } + } + + [Test] + public void FromName () + { + using (UINib n = UINib.FromName ("EmptyNib", null)) { + Assert.NotNull (n, "created with null options"); +#if !XAMCORE_2_0 + // obsolete name (too long and case typo) + var result = n.InstantiateWithOwneroptions (null, null); + Assert.That (result.Length, Is.EqualTo (0), "InstantiateWithOwneroptions"); +#endif + // newer version (same selector) + var result2 = n.Instantiate (null, null); + Assert.That (result2.Length, Is.EqualTo (0), "Instantiate"); + } + } + + [Test] + public void FromData () + { + using (NSData data = NSData.FromFile ("EmptyNib.nib")) + using (UINib n = UINib.FromData (data, null)) { + Assert.NotNull (n, "created with null options"); +#if !XAMCORE_2_0 + // obsolete name (too long and case typo) + var result = n.InstantiateWithOwneroptions (null, null); + Assert.That (result.Length, Is.EqualTo (0), "InstantiateWithOwneroptions"); +#endif + // newer version (same selector) + var result2 = n.Instantiate (null, null); + Assert.That (result2.Length, Is.EqualTo (0), "Instantiate"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PageControlTest.cs b/tests/monotouch-test/UIKit/PageControlTest.cs new file mode 100644 index 000000000000..9dc4e00f1075 --- /dev/null +++ b/tests/monotouch-test/UIKit/PageControlTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PageControlTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIPageControl pc = new UIPageControl (frame)) { + Assert.That (pc.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PageViewControllerTest.cs b/tests/monotouch-test/UIKit/PageViewControllerTest.cs new file mode 100644 index 000000000000..0f4e179a7c16 --- /dev/null +++ b/tests/monotouch-test/UIKit/PageViewControllerTest.cs @@ -0,0 +1,66 @@ +// +// Unit tests for UIPageViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class PageViewControllerTest { + + [Test] + public void Defaults () + { + UIPageViewController pvc = new UIPageViewController (); + Assert.Null (pvc.DataSource, "DataSource"); + Assert.Null (pvc.Delegate, "Delegate"); + Assert.False (pvc.DoubleSided, "DoubleSided"); + Assert.That (pvc.GestureRecognizers.Length, Is.EqualTo (2), "GestureRecognizers"); + Assert.Null (pvc.GetNextViewController, "GetNextViewController"); + Assert.Null (pvc.GetPreviousViewController, "GetPreviousViewController"); +#if !__TVOS__ + Assert.Null (pvc.GetSpineLocation, "GetSpineLocation"); +#endif + Assert.That (pvc.NavigationOrientation, Is.EqualTo (UIPageViewControllerNavigationOrientation.Horizontal), "NavigationOrientation"); + Assert.That (pvc.SpineLocation, Is.EqualTo (UIPageViewControllerSpineLocation.Min), "SpineLocation"); + Assert.That (pvc.TransitionStyle, Is.EqualTo (UIPageViewControllerTransitionStyle.PageCurl), "TransitionStyle"); + Assert.That (pvc.ViewControllers.Length, Is.EqualTo (0), "ViewControllers"); + } + + UIPageViewController pvc; + + [Test] + public void SetViewControllers () + { + pvc = new UIPageViewController (); + // note: Complete is called synchronously + pvc.SetViewControllers (pvc.ViewControllers, UIPageViewControllerNavigationDirection.Forward, false, Complete); + Assert.Null (pvc, "pvc"); + } + + void Complete (bool finished) + { + Assert.True (finished, "finished"); + pvc = null; + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PanGestureRecognizerTest.cs b/tests/monotouch-test/UIKit/PanGestureRecognizerTest.cs new file mode 100644 index 000000000000..0f00fcad5f4a --- /dev/null +++ b/tests/monotouch-test/UIKit/PanGestureRecognizerTest.cs @@ -0,0 +1,56 @@ +// +// UIPanGestureRecognizer Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + public class PanGestureRecognizerTest { + + [Test] + public void Null () + { + using (var pgr = new UIPanGestureRecognizer (Null)) { + pgr.SetTranslation (PointF.Empty, null); + + var pt = pgr.TranslationInView (null); + Assert.That (pt, Is.EqualTo (PointF.Empty), "TranslationInView"); + + pt = pgr.VelocityInView (null); + Assert.That (pt, Is.EqualTo (PointF.Empty), "VelocityInView"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PasteboardTest.cs b/tests/monotouch-test/UIKit/PasteboardTest.cs new file mode 100644 index 000000000000..efe7156e5872 --- /dev/null +++ b/tests/monotouch-test/UIKit/PasteboardTest.cs @@ -0,0 +1,48 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.IO; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using CoreGraphics; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.CoreGraphics; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PasteboardTest { + + [Test] + public void ImagesTest () + { + string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); + using (var dp = new CGDataProvider (file)) { + using (var cgimg = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) { + using (var img = new UIImage (cgimg)) { + UIPasteboard.General.Images = new UIImage[] { img }; + Assert.AreEqual (1, UIPasteboard.General.Images.Length, "a - length"); + + UIPasteboard.General.Images = new UIImage[] { img, img }; + Assert.AreEqual (2, UIPasteboard.General.Images.Length, "b - length"); + Assert.IsNotNull (UIPasteboard.General.Images [0], "b - nonnull[0]"); + Assert.IsNotNull (UIPasteboard.General.Images [1], "b - nonnull[0]"); + } + } + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PickerViewTest.cs b/tests/monotouch-test/UIKit/PickerViewTest.cs new file mode 100644 index 000000000000..a8b737a581b0 --- /dev/null +++ b/tests/monotouch-test/UIKit/PickerViewTest.cs @@ -0,0 +1,56 @@ +// Copyright 2011,2015 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PickerViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIPickerView pv = new UIPickerView (frame)) { + Assert.That (pv.Frame.X, Is.EqualTo (frame.X), "X"); + Assert.That (pv.Frame.Y, Is.EqualTo (frame.Y), "Y"); + Assert.That (pv.Frame.Width, Is.EqualTo (frame.Width), "Width"); + // Height is set by Picker (e.g. 162 for the iPhone) + } + } + + [Test] + public void ConformsTo () + { + using (UIPickerView pv = new UIPickerView ()) { + Assert.True (pv.ConformsToProtocol (Protocol.GetHandle ("UITableViewDataSource")), "UITableViewDataSource"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PopoverBackgroundViewTest.cs b/tests/monotouch-test/UIKit/PopoverBackgroundViewTest.cs new file mode 100644 index 000000000000..36e8a83b3963 --- /dev/null +++ b/tests/monotouch-test/UIKit/PopoverBackgroundViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PopoverBackgroundViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIPopoverBackgroundView pbv = new UIPopoverBackgroundView (frame)) { + Assert.That (pbv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PopoverControllerTest.cs b/tests/monotouch-test/UIKit/PopoverControllerTest.cs new file mode 100644 index 000000000000..6977e2a3d953 --- /dev/null +++ b/tests/monotouch-test/UIKit/PopoverControllerTest.cs @@ -0,0 +1,133 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +using MonoTouchException=Foundation.MonoTouchException; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouchException=MonoTouch.Foundation.MonoTouchException; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PopoverControllerTest { + [Test] + public void Defaults () + { + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Pad) + return; + + bool ios8 = TestRuntime.CheckSystemAndSDKVersion (8, 0); + + using (var vc = new UIViewController ()) + using (var pc = new UIPopoverController (vc)) { + Assert.That (pc.ContentViewController, Is.SameAs (vc), "ContentViewController"); + Assert.Null (pc.PassthroughViews, "PassthroughViews"); + Assert.That (pc.PopoverArrowDirection, Is.EqualTo (UIPopoverArrowDirection.Unknown), "PopoverArrowDirection"); + Assert.That (pc.PopoverContentSize.IsEmpty, Is.EqualTo (ios8), "PopoverContentSize"); + Assert.That (pc.PopoverLayoutMargins.ToString (), Is.EqualTo (ios8 ? "{0, 0, 0, 0}" : "{30, 10, 10, 10}"), "PopoverLayoutMargins"); + Assert.False (pc.PopoverVisible, "PopoverVisible"); + Assert.Null (pc.ShouldDismiss, "ShouldDismiss"); + } + } + + [Test] + [ExpectedException (typeof (MonoTouchException))] + public void PresentFromBarButtonItem_BadButton () + { + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Pad) + Assert.Inconclusive ("Requires iPad"); + + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("ObjectiveC exception crash on devices - bug #3980"); + + using (var vc = new UIViewController ()) + using (var bbi = new UIBarButtonItem (UIBarButtonSystemItem.Action)) + using (var pc = new UIPopoverController (vc)) { + // UIBarButtonItem is itself 'ok' but it's not assigned to a view + pc.PresentFromBarButtonItem (bbi, UIPopoverArrowDirection.Down, true); + // fails with: + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[UIPopoverController presentPopoverFromBarButtonItem:permittedArrowDirections:animated:]: Popovers cannot be presented from a view which does not have a window. + } + } + + [Test] + public void PresentFromRect () + { + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Pad) + return; + + using (var vc = new UIViewController ()) + using (var bbi = new UIBarButtonItem (UIBarButtonSystemItem.Action)) + using (var pc = new UIPopoverController (vc)) { + var view = UIApplication.SharedApplication.KeyWindow; + pc.PresentFromRect (new RectangleF (10, 10, 100, 100), view, UIPopoverArrowDirection.Down, true); + pc.Dismiss (true); + // works (as long as we dismiss the popover before disposing) + } + } + + [Test] + [ExpectedException (typeof (MonoTouchException))] + public void PresentFromRect_BadView () + { + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Pad) + Assert.Inconclusive ("Requires iPad"); + + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("ObjectiveC exception crash on devices - bug #3980"); + + using (var vc = new UIViewController ()) + using (var bbi = new UIBarButtonItem (UIBarButtonSystemItem.Action)) + using (var pc = new UIPopoverController (vc)) { + // 'vc' has never been shown + pc.PresentFromRect (new RectangleF (10, 10, 100, 100), vc.View, UIPopoverArrowDirection.Down, true); + // fails with: + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[UIPopoverController presentPopoverFromRect:inView:permittedArrowDirections:animated:]: Popovers cannot be presented from a view which does not have a window. + } + } + + // note: not complete (won't work) - but enough for testing the property + // full sample at http://stackoverflow.com/a/9312939/220643 + class MyPopoverBackgroundView : UIPopoverBackgroundView { + } + + [Test] + public void PopoverBackgroundViewType () + { + if (UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Pad) + return; + + using (var vc = new UIViewController ()) + using (var pc = new UIPopoverController (vc)) { + Assert.Null (pc.PopoverBackgroundViewType, "PopoverBackgroundViewType"); + Type my = typeof (MyPopoverBackgroundView); + pc.PopoverBackgroundViewType = my; + Assert.That (pc.PopoverBackgroundViewType, Is.SameAs (my), "MyPopoverBackgroundView"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/PopoverPresentationControllerTest.cs b/tests/monotouch-test/UIKit/PopoverPresentationControllerTest.cs new file mode 100644 index 000000000000..dc787fb698b1 --- /dev/null +++ b/tests/monotouch-test/UIKit/PopoverPresentationControllerTest.cs @@ -0,0 +1,51 @@ +// Copyright 2014 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class PopoverPresentationControllerTest { + + class MyPopoverBackgroundView : UIPopoverBackgroundView { + } + + [Test] + public void PopoverBackgroundViewType () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("Requires iOS8+"); + + using (var vc = new UIViewController ()) + using (var pc = new UIPopoverPresentationController (vc, null)) { + Assert.Null (pc.PopoverBackgroundViewType, "PopoverBackgroundViewType"); + Type my = typeof (MyPopoverBackgroundView); + pc.PopoverBackgroundViewType = my; + Assert.That (pc.PopoverBackgroundViewType, Is.SameAs (my), "MyPopoverBackgroundView"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ProgressViewTest.cs b/tests/monotouch-test/UIKit/ProgressViewTest.cs new file mode 100644 index 000000000000..0fc8fc9a7cb2 --- /dev/null +++ b/tests/monotouch-test/UIKit/ProgressViewTest.cs @@ -0,0 +1,46 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ProgressViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIProgressView pv = new UIProgressView (frame)) { + Assert.That (pv.Frame.X, Is.EqualTo (frame.X), "X"); + Assert.That (pv.Frame.Y, Is.EqualTo (frame.Y), "Y"); + Assert.That (pv.Frame.Width, Is.EqualTo (frame.Width), "Width"); + // Height is set by the ProgressView (e.g. 9 for the iPhone) + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ReferenceLibraryViewControllerTest.cs b/tests/monotouch-test/UIKit/ReferenceLibraryViewControllerTest.cs new file mode 100644 index 000000000000..3e8df8334a46 --- /dev/null +++ b/tests/monotouch-test/UIKit/ReferenceLibraryViewControllerTest.cs @@ -0,0 +1,44 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ReferenceLibraryViewControllerTest { + + [Test] + public void InitWithTerm () + { + if (Runtime.Arch == Arch.DEVICE && TestRuntime.CheckiOSSystemVersion (9, 0)) + Assert.Ignore ("crash on iOS9 devices"); + using (UIReferenceLibraryViewController rlvc = new UIReferenceLibraryViewController ("Mono")) { + } + } + + [Test] + [Ignore ("ios6 beta issues")] + public void DictionaryHasDefinitionForTerm () + { + // note: iOS 6 beta 3 fails with: +[_UIDictionaryWrapper _availableDictionaryAssets] returned failed - retrying. Error: Error Domain=ASError Code=4 "The operation couldn’t be completed. (ASError error 4 - Unable to copy asset information)" UserInfo=0x16ac81a0 {NSDescription=Unable to copy asset information} + // beta 3 always return true, beta 4 false ... + Assert.True (UIReferenceLibraryViewController.DictionaryHasDefinitionForTerm ("Mono"), "Mono"); + Assert.False (UIReferenceLibraryViewController.DictionaryHasDefinitionForTerm ("zozo"), "zozo"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ScrollViewTest.cs b/tests/monotouch-test/UIKit/ScrollViewTest.cs new file mode 100644 index 000000000000..89f02f4bce70 --- /dev/null +++ b/tests/monotouch-test/UIKit/ScrollViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ScrollViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIScrollView sv = new UIScrollView (frame)) { + Assert.That (sv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/SearchBarTest.cs b/tests/monotouch-test/UIKit/SearchBarTest.cs new file mode 100644 index 000000000000..1a9a7b0a9469 --- /dev/null +++ b/tests/monotouch-test/UIKit/SearchBarTest.cs @@ -0,0 +1,66 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SearchBarTest { + +#if !__TVOS__ + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UISearchBar sb = new UISearchBar (frame)) { + Assert.That (sb.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void TextInput () + { + // in iOS 7.1 the "Text Input Properties" stopped responsind in the introspection tests + using (UISearchBar sb = new UISearchBar ()) { + // that's a check that the feature still works + Assert.That (sb.AutocapitalizationType, Is.EqualTo (UITextAutocapitalizationType.Sentences), "AutocapitalizationType"); + sb.AutocapitalizationType = UITextAutocapitalizationType.AllCharacters; + + // looks like 7.1 was alone to select 'default' over 'no' since iOS8 returned to old default + var act = UIDevice.CurrentDevice.SystemVersion.StartsWith ("7.1") ? UITextAutocorrectionType.Default : UITextAutocorrectionType.No; + Assert.That (sb.AutocorrectionType, Is.EqualTo (act), "AutocorrectionType"); + + sb.AutocorrectionType = UITextAutocorrectionType.Yes; + Assert.That (sb.KeyboardType, Is.EqualTo (UIKeyboardType.Default), "KeyboardType"); + sb.KeyboardType = UIKeyboardType.EmailAddress; + Assert.That (sb.SpellCheckingType, Is.EqualTo (UITextSpellCheckingType.Default), "SpellCheckingType"); + sb.SpellCheckingType = UITextSpellCheckingType.Default; + } + } +#endif + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/SearchDisplayControllerTest.cs b/tests/monotouch-test/UIKit/SearchDisplayControllerTest.cs new file mode 100644 index 000000000000..3e0b999a09cd --- /dev/null +++ b/tests/monotouch-test/UIKit/SearchDisplayControllerTest.cs @@ -0,0 +1,125 @@ +// +// Unit tests for UISearchDisplayController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + class SearchDisplayControllerPoker : UISearchDisplayController { + + static FieldInfo bkSearchBar; + static FieldInfo bkSearchContentsController; + static FieldInfo bkSearchResultsTableView; + + static SearchDisplayControllerPoker () + { + var t = typeof (UISearchDisplayController); + bkSearchBar = t.GetField ("__mt_SearchBar_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkSearchContentsController = t.GetField ("__mt_SearchContentsController_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkSearchResultsTableView = t.GetField ("__mt_SearchResultsTableView_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public SearchDisplayControllerPoker () + { + } + + public SearchDisplayControllerPoker (UISearchBar searchBar, UIViewController viewController) : base (searchBar, viewController) + { + } + + public UISearchBar SearchBarBackingField { + get { + return (UISearchBar) bkSearchBar.GetValue (this); + } + } + + public UIViewController SearchContentsControllerBackingField { + get { + return (UIViewController) bkSearchContentsController.GetValue (this); + } + } + + public UITableView SearchResultsTableViewBackingField { + get { + return (UITableView) bkSearchResultsTableView.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class SearchDisplayControllerTest { + + [Test] + public void Ctor_Default_BackingFields () + { + if (SearchDisplayControllerPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var sc = new SearchDisplayControllerPoker ()) { + // default constructor does not set any UIViewController so the backing fields are null + Assert.Null (sc.SearchBarBackingField, "1a"); + Assert.Null (sc.SearchContentsControllerBackingField, "2a"); + Assert.Null (sc.SearchResultsTableViewBackingField, "3a"); + + Assert.Null (sc.SearchBar, "1b"); + Assert.Null (sc.SearchContentsController, "2b"); + // not an issue (backing field being null before calling the getter) + // since it's not something we supplied to the instance + Assert.NotNull (sc.SearchResultsTableView, "3b"); + // the backing field will be set afterward + Assert.NotNull (sc.SearchResultsTableViewBackingField, "3c"); + } + } + + [Test] + public void Ctor_BackingFields () + { + if (SearchDisplayControllerPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var sb = new UISearchBar ()) + using (var vc = new UIViewController ()) + using (var sc = new SearchDisplayControllerPoker (sb, vc)) { + // default constructor does not set any UIViewController so the backing fields are null + Assert.AreSame (sb, sc.SearchBarBackingField, "1a"); + Assert.AreSame (vc, sc.SearchContentsControllerBackingField, "2a"); + Assert.Null (sc.SearchResultsTableViewBackingField, "3a"); + + Assert.AreSame (sb, sc.SearchBar, "1b"); + Assert.AreSame (vc, sc.SearchContentsController, "2b"); + // not an issue (backing field being null before calling the getter) + // since it's not something we supplied to the instance + Assert.NotNull (sc.SearchResultsTableView, "3b"); + // the backing field will be set afterward + Assert.NotNull (sc.SearchResultsTableViewBackingField, "3c"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ + diff --git a/tests/monotouch-test/UIKit/SegmentedControlTest.cs b/tests/monotouch-test/UIKit/SegmentedControlTest.cs new file mode 100644 index 000000000000..d2dedc8a4480 --- /dev/null +++ b/tests/monotouch-test/UIKit/SegmentedControlTest.cs @@ -0,0 +1,60 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SegmentedControlTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UISegmentedControl sc = new UISegmentedControl (frame)) { + Assert.That (sc.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void BackgroundImage () + { + using (UISegmentedControl sc = new UISegmentedControl ()) { + Assert.Null (sc.GetBackgroundImage (UIControlState.Application, UIBarMetrics.Default), "Get"); + sc.SetBackgroundImage (null, UIControlState.Application, UIBarMetrics.Default); + } + } + + [Test] + public void Appearance_7 () + { + // iOS 7 beta 3 throws "-setTintColor: is not allowed for use with the appearance proxy." + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=13286 + UISegmentedControl.Appearance.TintColor = UIColor.Blue; + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/SimpleTextPrintFormatterTest.cs b/tests/monotouch-test/UIKit/SimpleTextPrintFormatterTest.cs new file mode 100644 index 000000000000..9972bd8fa343 --- /dev/null +++ b/tests/monotouch-test/UIKit/SimpleTextPrintFormatterTest.cs @@ -0,0 +1,68 @@ +// +// Unit tests for UISimpleTextPrintFormatter +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.IO; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SimpleTextPrintFormatterTest { + + [Test] + public void DefaultCtor () + { + using (var stpf = new UISimpleTextPrintFormatter ()) { + Assert.That (stpf.Handle, Is.Not.EqualTo (IntPtr.Zero), "Handle"); + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) { + Assert.Null (stpf.Color, "Color"); + Assert.Null (stpf.Font, "Font"); + Assert.That (stpf.TextAlignment, Is.EqualTo (UITextAlignment.Natural), "TextAlignment"); + } else { + Assert.That (stpf.Color, Is.EqualTo (UIColor.Black), "Color"); + Assert.NotNull (stpf.Font, "Font"); + Assert.That (stpf.TextAlignment, Is.EqualTo (UITextAlignment.Left), "TextAlignment"); + } + Assert.That (stpf.Text, Is.Empty, "Text"); + } + } + + [Test] + public void StringCtor () + { + using (var stpf = new UISimpleTextPrintFormatter ("Xamarin")) { + if (TestRuntime.CheckSystemAndSDKVersion (7, 0)) { + Assert.Null (stpf.Color, "Color"); + Assert.That (stpf.TextAlignment, Is.EqualTo (UITextAlignment.Natural), "TextAlignment"); + } else { + Assert.That (stpf.Color, Is.EqualTo (UIColor.Black), "Color"); + Assert.That (stpf.TextAlignment, Is.EqualTo (UITextAlignment.Left), "TextAlignment"); + } + Assert.NotNull (stpf.Font, "Font"); + Assert.That (stpf.Text, Is.EqualTo ("Xamarin"), "Text"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/SliderTest.cs b/tests/monotouch-test/UIKit/SliderTest.cs new file mode 100644 index 000000000000..4e064d15f7b4 --- /dev/null +++ b/tests/monotouch-test/UIKit/SliderTest.cs @@ -0,0 +1,178 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + class SliderPoker : UISlider { + + static FieldInfo bkCurrentThumbImage; + static FieldInfo bkCurrentMinTrackImage; + static FieldInfo bkCurrentMaxTrackImage; + static FieldInfo bkMinValueImage; + static FieldInfo bkMaxValueImage; + + static SliderPoker () + { + var t = typeof (UISlider); + bkCurrentThumbImage = t.GetField ("__mt_CurrentThumbImage_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkCurrentMinTrackImage = t.GetField ("__mt_CurrentMinTrackImage_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkCurrentMaxTrackImage = t.GetField ("__mt_CurrentMaxTrackImage_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkMinValueImage = t.GetField ("__mt_MinValueImage_var", BindingFlags.Instance | BindingFlags.NonPublic); + bkMaxValueImage = t.GetField ("__mt_MaxValueImage_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public SliderPoker () + { + } + + public UIImage CurrentThumbImageBackingField { + get { + return (UIImage) bkCurrentThumbImage.GetValue (this); + } + } + + public UIImage CurrentMinTrackImageBackingField { + get { + return (UIImage) bkCurrentMinTrackImage.GetValue (this); + } + } + + public UIImage CurrentMaxTrackImageBackingField { + get { + return (UIImage) bkCurrentMaxTrackImage.GetValue (this); + } + } + + public UIImage MinValueImageBackingField { + get { + return (UIImage) bkMinValueImage.GetValue (this); + } + } + + public UIImage MaxValueImageBackingField { + get { + return (UIImage) bkMaxValueImage.GetValue (this); + } + } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class SliderTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UISlider s = new UISlider (frame)) { + Assert.That (s.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void Ctor_Default_BackingFields () + { + if (SliderPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var s = new SliderPoker ()) { + // default constructor does not set any UIViewController so the backing fields are null + Assert.Null (s.CurrentThumbImageBackingField, "1a"); + Assert.Null (s.CurrentMinTrackImageBackingField, "2a"); + Assert.Null (s.CurrentMaxTrackImageBackingField, "3a"); + Assert.Null (s.MinValueImageBackingField, "4a"); + Assert.Null (s.MaxValueImageBackingField, "5a"); + + Assert.Null (s.CurrentThumbImage, "1b"); + Assert.Null (s.CurrentMinTrackImage, "2b"); + Assert.Null (s.CurrentMaxTrackImage, "3b"); + Assert.Null (s.MinValueImage, "4b"); + Assert.Null (s.MaxValueImage, "5b"); + } + } + + [Test] + public void CurrentThumbImage_BackingFields () + { + if (SliderPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var i = new UIImage ()) + using (var s = new SliderPoker ()) { + // default constructor does not set any UIViewController so the backing fields are null + Assert.Null (s.CurrentThumbImageBackingField, "1a"); + Assert.Null (s.CurrentThumbImage, "1b"); + + s.SetThumbImage (i, UIControlState.Normal); + Assert.NotNull (s.CurrentThumbImageBackingField, "1c"); + Assert.NotNull (s.CurrentThumbImage, "1d"); + } + } + + [Test] + public void CurrentMinTrackImage_BackingFields () + { + if (SliderPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var i = new UIImage ()) + using (var s = new SliderPoker ()) { + // default constructor does not set any UIViewController so the backing fields are null + Assert.Null (s.CurrentMinTrackImageBackingField, "1a"); + Assert.Null (s.CurrentMinTrackImage, "1b"); + + s.SetMinTrackImage (i, UIControlState.Normal); + Assert.NotNull (s.CurrentMinTrackImageBackingField, "1c"); + Assert.NotNull (s.CurrentMinTrackImage, "1d"); + } + } + + [Test] + public void CurrentMaxTrackImage_BackingFields () + { + if (SliderPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + using (var i = new UIImage ()) + using (var s = new SliderPoker ()) { + // default constructor does not set any UIViewController so the backing fields are null + Assert.Null (s.CurrentMaxTrackImageBackingField, "1a"); + Assert.Null (s.CurrentMaxTrackImage, "1b"); + + s.SetMaxTrackImage (i, UIControlState.Normal); + Assert.NotNull (s.CurrentMaxTrackImageBackingField, "1c"); + Assert.NotNull (s.CurrentMaxTrackImage, "1d"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/SplitViewControllerTest.cs b/tests/monotouch-test/UIKit/SplitViewControllerTest.cs new file mode 100644 index 000000000000..5417f9f9ee2b --- /dev/null +++ b/tests/monotouch-test/UIKit/SplitViewControllerTest.cs @@ -0,0 +1,65 @@ +// Copyright 2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class SplitViewControllerTest { + + [Test] + public void Defaults () + { + // UISplitViewController feature is only available on iPads + // and we (presently) crash on devices when an objective-c exception is thrown + if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) + return; + + using (UIViewController v1 = new UIViewController ()) + using (UIViewController v2 = new UIViewController ()) + using (UISplitViewController svc = new UISplitViewController ()) { + Assert.That (svc.ViewControllers, Is.Empty, "ViewControllers"); // not null, empty + + svc.ViewControllers = new UIViewController[] { v1, v2 }; + + Assert.AreSame (v1, svc.ViewControllers [0], "vc0"); + Assert.AreSame (v2, svc.ViewControllers [1], "vc1"); + + Assert.AreSame (v1, svc.ChildViewControllers [0], "cvc0"); + Assert.AreSame (v2, svc.ChildViewControllers [1], "cvc1"); + } + } + + [Test] + public void PresentsWithGesture () + { + // UISplitViewController feature is only available on iPads + // and we (presently) crash on devices when an objective-c exception is thrown + if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) + return; + + if (!TestRuntime.CheckSystemAndSDKVersion (5, 1)) + return; + + TestRuntime.IgnoreOnTVOS (); + + using (UISplitViewController svc = new UISplitViewController ()) { + Assert.True (svc.PresentsWithGesture, "PresentsWithGesture/default"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/StepperTest.cs b/tests/monotouch-test/UIKit/StepperTest.cs new file mode 100644 index 000000000000..8f2919418c71 --- /dev/null +++ b/tests/monotouch-test/UIKit/StepperTest.cs @@ -0,0 +1,56 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class StepperTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIStepper s = new UIStepper (frame)) { + Assert.That (s.Frame.X, Is.EqualTo (frame.X), "X"); + Assert.That (s.Frame.Y, Is.EqualTo (frame.Y), "Y"); + // Width and Height are set by the Slider (e.g. 94 x 27 for the iPhone) + } + } + + [Test] + public void BackgroundImage () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("requires iOS 6"); + + using (var s = new UIStepper ()) { + s.SetBackgroundImage (null, UIControlState.Application); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/StringAttributesTest.cs b/tests/monotouch-test/UIKit/StringAttributesTest.cs new file mode 100644 index 000000000000..c34f126d86b1 --- /dev/null +++ b/tests/monotouch-test/UIKit/StringAttributesTest.cs @@ -0,0 +1,162 @@ +// +// UIStringAttributes Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + // we want the test to be availble if we use the linker + [Preserve (AllMembers = true)] + [TestFixture] + public class StringAttributesTest { + + [Test] + public void RetainCount () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.Inconclusive ("Requires iOS 6+"); + + var sa = new UIStringAttributes (); + + var bc = UIColor.FromRGBA (0.1f, 0.2f, 0.3f, 0.4f); + Assert.That (bc.RetainCount, Is.EqualTo ((nint) 2), "BackgroundColor-new"); // bug + sa.BackgroundColor = bc; + Assert.That (bc.RetainCount, Is.EqualTo ((nint) 3), "BackgroundColor-set"); + + sa.BaselineOffset = 0.0f; + + var fc = UIColor.FromRGBA (0.5f, 0.6f, 0.7f, 0.8f); + Assert.That (fc.RetainCount, Is.EqualTo ((nint) 2), "ForegroundColor-new"); // bug + sa.ForegroundColor = fc; + Assert.That (fc.RetainCount, Is.EqualTo ((nint) 3), "ForegroundColor-set"); + + var f = UIFont.FromName ("Helvetica", 12); + var f_count = f.RetainCount; // lots of owner + sa.Font = f; + Assert.That (f.RetainCount, Is.EqualTo (++f_count), "Font-set"); + + var ps = new NSParagraphStyle (); + Assert.That (ps.RetainCount, Is.EqualTo ((nint) 1), "ParagraphStyle-new"); + sa.ParagraphStyle = ps; + Assert.That (ps.RetainCount, Is.EqualTo ((nint) 2), "ParagraphStyle-set"); + + for (int i=0; i < 16; i++) { + Assert.NotNull (sa.BackgroundColor, "BackgroundColor-get"); + Assert.NotNull (sa.ForegroundColor, "ForegroundColor-get"); + Assert.NotNull (sa.Font, "Font-get"); + Assert.NotNull (sa.ParagraphStyle, "ParagraphStyle-get"); + } + + Assert.That (sa.BackgroundColor.RetainCount, Is.EqualTo ((nint) 3), "BackgroundColor"); + Assert.That (sa.ForegroundColor.RetainCount, Is.EqualTo ((nint) 3), "ForegroundColor"); + Assert.That (sa.Font.RetainCount, Is.EqualTo (f_count), "Font"); + Assert.That (sa.ParagraphStyle.RetainCount, Is.EqualTo ((nint) 2), "ParagraphStyle"); + + GC.KeepAlive (bc); + GC.KeepAlive (fc); + GC.KeepAlive (f); + GC.KeepAlive (ps); + } + + [Test] + public void RetainCount_7 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS 7+"); + + var sa = new UIStringAttributes (); + sa.Expansion = 0.0f; + + var uc = UIColor.FromRGBA (0.1f, 0.2f, 0.3f, 0.4f); + Assert.That (uc.RetainCount, Is.EqualTo ((nint) 2), "UnderlineColor-new"); + sa.UnderlineColor = uc; + Assert.That (uc.RetainCount, Is.EqualTo ((nint) 3), "UnderlineColor-set"); + + var sc = UIColor.FromRGBA (0.5f, 0.6f, 0.7f, 0.8f); + Assert.That (sc.RetainCount, Is.EqualTo ((nint) 2), "StrikethroughColor-new"); + sa.StrikethroughColor = sc; + Assert.That (sc.RetainCount, Is.EqualTo ((nint) 3), "StrikethroughColor-set"); + + var u = new NSUrl ("http://xamarin.com"); + Assert.That (u.RetainCount, Is.EqualTo ((nint) 1), "Link-new"); + sa.Link = u; + Assert.That (u.RetainCount, Is.EqualTo ((nint) 2), "Link-set"); + +#if !__WATCHOS__ + var ta = new NSTextAttachment (); + Assert.That (ta.RetainCount, Is.EqualTo ((nint) 1), "TextAttachment-new"); + sa.TextAttachment = ta; + Assert.That (ta.RetainCount, Is.EqualTo ((nint) 2), "TextAttachment-set"); +#endif // !__WATCHOS__ + + for (int i=0; i < 16; i++) { + Assert.NotNull (sa.UnderlineColor, "UnderlineColor-get"); + Assert.NotNull (sa.StrikethroughColor, "StrikethroughColor-get"); + Assert.NotNull (sa.Link, "Link-get"); +#if !__WATCHOS__ + Assert.NotNull (sa.TextAttachment, "TextAttachment-get"); +#endif + } + + Assert.That (sa.UnderlineColor.RetainCount, Is.EqualTo ((nint) 3), "UnderlineColor"); + Assert.That (sa.StrikethroughColor.RetainCount, Is.EqualTo ((nint) 3), "StrikethroughColor"); + Assert.That (sa.Link.RetainCount, Is.EqualTo ((nint) 2), "Link"); +#if !__WATCHOS__ + Assert.That (sa.TextAttachment.RetainCount, Is.EqualTo ((nint) 2), "TextAttachment"); +#endif + + GC.KeepAlive (uc); + GC.KeepAlive (sc); + GC.KeepAlive (u); +#if !__WATCHOS__ + GC.KeepAlive (ta); +#endif + } + +#if !__WATCHOS__ + [Test] + public void MutableStringAttributesTest () + { + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=28158 + // issue: Properties of type UIStringAttributes produce immutable objects that crash when you try to modify them + // This test proves that the bug is fixed + + using (var nb = new UINavigationBar ()) { + Assert.Null (nb.TitleTextAttributes, "TitleTextAttributes should be null"); + nb.TitleTextAttributes = new UIStringAttributes { ForegroundColor = UIColor.Green }; + Assert.AreSame (UIColor.Green, nb.TitleTextAttributes.ForegroundColor, "TitleTextAttributes.ForegroundColor should match"); + + var titleAttribtues = nb.TitleTextAttributes; // we now get a mutable dictionary for this DictionaryContainer + titleAttribtues.ForegroundColor = UIColor.Red; // this used to throw unrecognized selector before fixing bug 28158 + nb.TitleTextAttributes = titleAttribtues; + Assert.AreSame (UIColor.Red, nb.TitleTextAttributes.ForegroundColor, "TitleTextAttributes.ForegroundColor should match"); + } + } +#endif // !__WATCHOS__ + } +} diff --git a/tests/monotouch-test/UIKit/SwitchTest.cs b/tests/monotouch-test/UIKit/SwitchTest.cs new file mode 100644 index 000000000000..0240540e08d0 --- /dev/null +++ b/tests/monotouch-test/UIKit/SwitchTest.cs @@ -0,0 +1,45 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SwitchTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UISwitch s = new UISwitch (frame)) { + Assert.That (s.Frame.X, Is.EqualTo (frame.X), "X"); + Assert.That (s.Frame.Y, Is.EqualTo (frame.Y), "Y"); + // Width and Height are set by the Switch (e.g. 79 x 27 for the iPhone) + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TabBarControllerTest.cs b/tests/monotouch-test/UIKit/TabBarControllerTest.cs new file mode 100644 index 000000000000..ac2fea9d5382 --- /dev/null +++ b/tests/monotouch-test/UIKit/TabBarControllerTest.cs @@ -0,0 +1,72 @@ +// +// Unit tests for UITabBarController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class TabBarControllerTest { + + void CheckDefault (UITabBarController c) + { +#if !__TVOS__ + Assert.Null (c.CustomizableViewControllers, "CustomizableViewControllers"); + Assert.NotNull (c.MoreNavigationController, "MoreNavigationController"); +#endif + Assert.That (c.SelectedIndex, Is.EqualTo (nint.MaxValue), "SelectedIndex"); + Assert.Null (c.SelectedViewController, "SelectedViewController"); + Assert.Null (c.ShouldSelectViewController, "ShouldSelectViewController"); + Assert.NotNull (c.TabBar, "TabBar"); + Assert.Null (c.ViewControllers, "ViewControllers"); + } + + [Test] + public void Ctor_Defaults () + { + using (UITabBarController c = new UITabBarController ()) { + CheckDefault (c); + } + } + + [Test] + public void Ctor_Nib () + { + using (UITabBarController c = new UITabBarController ("EmptyNib", null)) { + // `initWithNibName:bundle:` is defined on a base class so it does not + // affect the fields from UITabBarController + CheckDefault (c); + } + } + } +} + +#endif // !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/UIKit/TabBarTest.cs b/tests/monotouch-test/UIKit/TabBarTest.cs new file mode 100644 index 000000000000..aedb03082cb0 --- /dev/null +++ b/tests/monotouch-test/UIKit/TabBarTest.cs @@ -0,0 +1,180 @@ +// Copyright 2011-2012 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class TabBarTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UITabBar tb = new UITabBar (frame)) { + Assert.That (tb.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void SelectedItem () + { + using (UITabBarItem item = new UITabBarItem ()) + using (UITabBar tb = new UITabBar ()) { + Assert.Null (tb.SelectedItem, "1a"); + + tb.SelectedItem = item; + // setter did not work because 'item' is not in Items + Assert.Null (tb.SelectedItem, "2a"); + Assert.Null (tb.Items, "2b"); + + tb.SelectedItem = null; + Assert.Null (tb.SelectedItem, "3a"); + } + } + + [Test] + public void Items () + { + using (UITabBarItem item = new UITabBarItem ()) + using (UITabBar tb = new UITabBar ()) { + Assert.Null (tb.Items, "1a"); + Assert.Null (tb.SelectedItem, "1b"); + + tb.Items = new UITabBarItem[] { item }; + Assert.NotNull (tb.Items, "2a"); + tb.SelectedItem = item; + Assert.NotNull (tb.SelectedItem, "2b"); + + tb.Items = null; + Assert.Null (tb.Items, "3a"); + // Interaction between Items and SelectedItems -> backing fields! + Assert.Null (tb.SelectedItem, "3b"); + } + } + +#if !__TVOS__ + [Test] + public void Customizing () + { + using (UITabBarItem item = new UITabBarItem ()) + using (UITabBar tb = new UITabBar ()) { + Assert.False (tb.IsCustomizing, "IsCustomizing-1"); + + tb.BeginCustomizingItems (new UITabBarItem[] { item }); + Assert.True (tb.IsCustomizing, "IsCustomizing-2"); +#if XAMCORE_2_0 + Assert.False (tb.EndCustomizing (false), "End-1"); +#else + Assert.False (tb.EndCustomizingAnimated (false), "End-1"); +#endif + + tb.BeginCustomizingItems (null); +#if XAMCORE_2_0 + Assert.False (tb.EndCustomizing (false), "End-2"); +#else + Assert.False (tb.EndCustomizingAnimated (false), "End-2"); +#endif + + Assert.False (tb.IsCustomizing, "IsCustomizing-3"); + } + } +#endif + + [Test] + public void BackgroundImage () + { + using (UIImage i = new UIImage ()) + using (UITabBar tb = new UITabBar ()) { + Assert.Null (tb.BackgroundImage, "1"); + + tb.BackgroundImage = i; + Assert.NotNull (tb.BackgroundImage, "2"); + + tb.BackgroundImage = null; + Assert.Null (tb.BackgroundImage, "3"); + } + } + + [Test] + public void SelectionIndicatorImage () + { + using (UIImage i = new UIImage ()) + using (UITabBar tb = new UITabBar ()) { + Assert.Null (tb.SelectionIndicatorImage, "1"); + + tb.SelectionIndicatorImage = i; + Assert.NotNull (tb.SelectionIndicatorImage, "2"); + + tb.SelectionIndicatorImage = null; + Assert.Null (tb.SelectionIndicatorImage, "3"); + } + } + + [Test] + public void TintColor () + { + using (UITabBar tb = new UITabBar ()) { + // TintColor is inherited in iOS7 so it won't be null by default + if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.NotNull (tb.TintColor, "1"); + else + Assert.Null (tb.TintColor, "1"); + + tb.TintColor = UIColor.White; + Assert.That (tb.TintColor, Is.EqualTo (UIColor.White), "2"); + + tb.TintColor = null; + if (TestRuntime.IsTVOS) + Assert.That (tb.TintColor, Is.EqualTo (UIColor.White), "3"); + else if (TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.That (tb.TintColor, Is.Not.EqualTo (UIColor.White), "3"); + else + Assert.Null (tb.TintColor, "3"); + } + } + +#if !__TVOS__ + [Test] + public void SelectedImageTintColor () + { + using (UITabBar tb = new UITabBar ()) { + Assert.Null (tb.SelectedImageTintColor, "1"); + + tb.SelectedImageTintColor = UIColor.Black; + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 1)) { + // before 7.1 the tintColor would have been accepted + Assert.NotNull (tb.SelectedImageTintColor, "2"); + + tb.SelectedImageTintColor = null; + } + Assert.Null (tb.SelectedImageTintColor, "3"); + } + } +#endif + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TableViewCellTest.cs b/tests/monotouch-test/UIKit/TableViewCellTest.cs new file mode 100644 index 000000000000..7254a12a54b7 --- /dev/null +++ b/tests/monotouch-test/UIKit/TableViewCellTest.cs @@ -0,0 +1,46 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TableViewCellTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UITableViewCell tvc = new UITableViewCell (frame)) { + Assert.That (tvc.Frame.X, Is.EqualTo ((nfloat) 0.0f), "X"); + Assert.That (tvc.Frame.Y, Is.EqualTo ((nfloat) 0.0f), "Y"); + // whatever supplied value X and Y are set to 0.0 by the cell + // Width and Height are set by the cell (e.g. 320 x 44 for the iPhone) + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TableViewControllerTest.cs b/tests/monotouch-test/UIKit/TableViewControllerTest.cs new file mode 100644 index 000000000000..100cf3f1a9ec --- /dev/null +++ b/tests/monotouch-test/UIKit/TableViewControllerTest.cs @@ -0,0 +1,49 @@ +// +// Unit tests for UITableViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TableViewControllerTest { + +#if !__TVOS__ + [Test] + public void RefreshControl_18744 () + { + if (!TestRuntime.CheckSystemAndSDKVersion (6, 0)) + Assert.Ignore ("requires 6.0+"); + + using (var rc = new UIRefreshControl ()) + using (var tvc = new UITableViewController ()) { + Assert.Null (tvc.RefreshControl, "default"); + tvc.RefreshControl = rc; + Assert.AreSame (tvc.RefreshControl, rc, "same"); + tvc.RefreshControl = null; + Assert.Null (tvc.RefreshControl, "nullable"); + } + } +#endif // !__TVOS__ + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TableViewTest.cs b/tests/monotouch-test/UIKit/TableViewTest.cs new file mode 100644 index 000000000000..442e69820d91 --- /dev/null +++ b/tests/monotouch-test/UIKit/TableViewTest.cs @@ -0,0 +1,43 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TableViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UITableView tv = new UITableView (frame)) { + Assert.That (tv.Frame, Is.EqualTo (frame), "Frame"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TarBarItemTest.cs b/tests/monotouch-test/UIKit/TarBarItemTest.cs new file mode 100644 index 000000000000..de335e770a79 --- /dev/null +++ b/tests/monotouch-test/UIKit/TarBarItemTest.cs @@ -0,0 +1,203 @@ +// +// Unit tests for UITabBarItem +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class TabBarItemTest { + [Test] + public void Ctor_Defaults () + { + using (UITabBarItem tbi = new UITabBarItem ()) { + Assert.Null (tbi.BadgeValue, "BadgeValue"); + Assert.True (tbi.Enabled, "Enabled"); +#if !__TVOS__ + Assert.Null (tbi.FinishedSelectedImage, "FinishedSelectedImage"); + Assert.Null (tbi.FinishedUnselectedImage, "FinishedUnselectedImage"); +#endif + Assert.Null (tbi.Image, "Image"); + Assert.That (tbi.ImageInsets, Is.EqualTo (UIEdgeInsets.Zero), "ImageInsets"); + Assert.That (tbi.Tag, Is.EqualTo ((nint) 0), "Tag"); + Assert.Null (tbi.Title, "Title"); + Assert.That (tbi.TitlePositionAdjustment.Horizontal, Is.EqualTo ((nfloat) 0f), "TitlePositionAdjustment.Horizontal"); + Assert.That (tbi.TitlePositionAdjustment.Vertical, Is.EqualTo ((nfloat) 0f), "TitlePositionAdjustment.Vertical"); + } + } + + [Test] + public void Ctor_2 () + { + using (UITabBarItem tbi = new UITabBarItem (UITabBarSystemItem.Bookmarks, nint.MaxValue)) { + Assert.Null (tbi.BadgeValue, "BadgeValue"); + Assert.True (tbi.Enabled, "Enabled"); +#if !__TVOS__ + Assert.Null (tbi.FinishedSelectedImage, "FinishedSelectedImage"); + Assert.Null (tbi.FinishedUnselectedImage, "FinishedUnselectedImage"); +#endif + Assert.Null (tbi.Image, "Image"); + Assert.That (tbi.ImageInsets, Is.EqualTo (UIEdgeInsets.Zero), "ImageInsets"); + Assert.That (tbi.Tag, Is.EqualTo (nint.MaxValue), "Tag"); + Assert.Null (tbi.Title, "Title"); + Assert.That (tbi.TitlePositionAdjustment.Horizontal, Is.EqualTo ((nfloat) 0f), "TitlePositionAdjustment.Horizontal"); + Assert.That (tbi.TitlePositionAdjustment.Vertical, Is.EqualTo ((nfloat) 0f), "TitlePositionAdjustment.Vertical"); + } + } + + [Test] + public void Ctor_3 () + { + using (UIImage img = new UIImage ()) + using (UITabBarItem tbi = new UITabBarItem ("title", img, nint.MinValue)) { + Assert.Null (tbi.BadgeValue, "BadgeValue"); + Assert.True (tbi.Enabled, "Enabled"); +#if !__TVOS__ + Assert.Null (tbi.FinishedSelectedImage, "FinishedSelectedImage"); + Assert.Null (tbi.FinishedUnselectedImage, "FinishedUnselectedImage"); +#endif + Assert.AreSame (tbi.Image, img, "Image"); + Assert.That (tbi.ImageInsets, Is.EqualTo (UIEdgeInsets.Zero), "ImageInsets"); + Assert.That (tbi.Tag, Is.EqualTo (nint.MinValue), "Tag"); + Assert.That (tbi.Title, Is.EqualTo ("title"), "Title"); + Assert.That (tbi.TitlePositionAdjustment.Horizontal, Is.EqualTo ((nfloat) 0f), "TitlePositionAdjustment.Horizontal"); + Assert.That (tbi.TitlePositionAdjustment.Vertical, Is.EqualTo ((nfloat) 0f), "TitlePositionAdjustment.Vertical"); + } + } + + [Test] + public void Ctor_3a_Null () + { + using (UIImage img = new UIImage ()) { + using (UITabBarItem tbi1 = new UITabBarItem (null, img, nint.MinValue)) { + Assert.Null (tbi1.Title, "Title-1a"); + Assert.AreSame (tbi1.Image, img, "Image-1a"); + tbi1.Title = "title"; + tbi1.Image = null; + Assert.That (tbi1.Title, Is.EqualTo ("title"), "Title-1b"); + Assert.IsNull (tbi1.Image, "Image-1b"); + } + using (UITabBarItem tbi2 = new UITabBarItem ("title", null, nint.MaxValue)) { + Assert.That (tbi2.Title, Is.EqualTo ("title"), "Title-2a"); + Assert.Null (tbi2.Image, "Image-2a"); + tbi2.Title = null; + tbi2.Image = img; + Assert.Null (tbi2.Title, "Title-2b"); + Assert.AreSame (tbi2.Image, img, "Image-2b"); + } + using (UITabBarItem tbi3 = new UITabBarItem (null, null, 0)) { + Assert.Null (tbi3.Title, "Title-3a"); + Assert.Null (tbi3.Image, "Image-3a"); + tbi3.Title = "title"; + tbi3.Image = img; + Assert.That (tbi3.Title, Is.EqualTo ("title"), "Title-3b"); + Assert.AreSame (tbi3.Image, img, "Image-3b"); + } + } + } + + [Test] + public void Ctor_3b_Null () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + using (UIImage img = new UIImage ()) { + using (UITabBarItem tbi1 = new UITabBarItem (null, null, null)) { + Assert.Null (tbi1.Title, "Title-1a"); + Assert.Null (tbi1.Image, "Image-1a"); + Assert.Null (tbi1.SelectedImage, "SelectedImage-1a"); + } + using (UITabBarItem tbi2 = new UITabBarItem ("title", img, null)) { + Assert.That (tbi2.Title, Is.EqualTo ("title"), "Title-2a"); + Assert.AreSame (tbi2.Image, img, "Image-2a"); + // if not supplied Image is reused + Assert.AreSame (tbi2.SelectedImage, img, "SelectedImage-2a"); + } + using (UITabBarItem tbi3 = new UITabBarItem (null, null, img)) { + Assert.Null (tbi3.Title, "Title-3a"); + Assert.Null (tbi3.Image, "Image-3a"); + // looks like a select-only image is not something allowed on 7.1 + if (UIDevice.CurrentDevice.CheckSystemVersion (7,1)) + Assert.Null (tbi3.SelectedImage, "SelectedImage-3a"); + else + Assert.AreSame (tbi3.SelectedImage, img, "SelectedImage-3a"); + } + } + } + + [Test] + public void SelectedImage_7a () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + using (UIImage i1 = new UIImage ()) + using (UITabBarItem tbi = new UITabBarItem ("title", i1, null)) { + Assert.AreSame (i1, tbi.Image, "Image"); + Assert.AreSame (i1, tbi.SelectedImage, "SelectedImage"); +#if !__TVOS__ + Assert.Null (tbi.FinishedSelectedImage, "FinishedSelectedImage"); + Assert.Null (tbi.FinishedUnselectedImage, "FinishedSelectedImage"); +#endif + // null does a reset, in this case i1 can be reused + tbi.SelectedImage = null; + Assert.AreSame (i1, tbi.SelectedImage, "SelectedImage2"); + } + } + + [Test] + public void SelectedImage_7b () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7 or later"); + + using (UIImage i1 = new UIImage ()) + using (UIImage i2 = new UIImage ()) + using (UITabBarItem tbi = new UITabBarItem ("title", i1, i2)) { + Assert.AreSame (i1, tbi.Image, "Image"); + Assert.AreSame (i2, tbi.SelectedImage, "SelectedImage"); +#if !__TVOS__ + Assert.Null (tbi.FinishedSelectedImage, "FinishedSelectedImage"); + Assert.Null (tbi.FinishedUnselectedImage, "FinishedSelectedImage"); +#endif + tbi.SelectedImage = null; + // null does a reset, in this case i2 is removed and i1 gets used + Assert.AreSame (i1, tbi.SelectedImage, "SelectedImage2"); + } + } + } +} + +#endif // !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/UIKit/TextAttachmentTest.cs b/tests/monotouch-test/UIKit/TextAttachmentTest.cs new file mode 100644 index 000000000000..4748838e887a --- /dev/null +++ b/tests/monotouch-test/UIKit/TextAttachmentTest.cs @@ -0,0 +1,45 @@ +// +// NSTextAttachment Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TextAttachmentTest { + + [Test] + public void CtorNull () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("requires iOS7+"); + + using (var ta = new NSTextAttachment (null, null)) { + Assert.IsTrue (ta.Bounds.IsEmpty, "Bounds"); + Assert.Null (ta.Contents, "Contents"); + Assert.Null (ta.FileType, "FileType"); + Assert.Null (ta.FileWrapper, "FileWrapper"); + Assert.Null (ta.Image, "Image"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TextContainerTest.cs b/tests/monotouch-test/UIKit/TextContainerTest.cs new file mode 100644 index 000000000000..c245a49deb59 --- /dev/null +++ b/tests/monotouch-test/UIKit/TextContainerTest.cs @@ -0,0 +1,41 @@ +// +// NSTextContainer Unit Tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TextContainerTest { + + [Test] + public void Layout () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var tc = new NSTextContainer ()) { + Assert.Null (tc.LayoutManager, "LayoutManager"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TextFieldTest.cs b/tests/monotouch-test/UIKit/TextFieldTest.cs new file mode 100644 index 000000000000..d363bd01516d --- /dev/null +++ b/tests/monotouch-test/UIKit/TextFieldTest.cs @@ -0,0 +1,110 @@ +// Copyright 2011-2013 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TextFieldTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UITextField tf = new UITextField (frame)) { + Assert.That (tf.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void InputAccessoryViewTest () + { + using (var tf = new UITextField ()) { + Assert.That (tf.InputAccessoryView, Is.Null, "1"); + tf.InputAccessoryView = new UIView (); + Assert.That (tf.InputAccessoryView, Is.Not.Null, "2"); + tf.InputAccessoryView = null; + Assert.That (tf.InputAccessoryView, Is.Null, "3"); + } + } + + [Test] + public void EmptySelection () + { + using (var tf = new UITextField ()) { + Assert.IsNull (tf.SelectedTextRange, "SelectedTextRange"); + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + Assert.IsNull (tf.TypingAttributes, "default"); + // ^ calling TypingAttributes does not crash like UITextView does, it simply returns null + tf.TypingAttributes = new NSDictionary (); + Assert.IsNull (tf.TypingAttributes, "empty"); + // and it stays null, even if assigned, since there's not selection + } + } + } + + [Test] + public void LeftRight () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=15004 + using (UITextField tf = new UITextField ()) { + Assert.IsNull (tf.LeftView, "LeftView"); + tf.LeftView = null; + Assert.IsNull (tf.RightView, "RightView"); + tf.RightView = null; + } + } + + [Test] + public void GetCaretRectForPositiont_Null () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=20572 + using (UITextField tf = new UITextField ()) { + var rect = tf.GetCaretRectForPosition (null); + Assert.True (rect.IsEmpty, "IsEmpty"); + } + } + + [Test] + public void TextInputTraits () + { + // UITextInputTraits members are not required but we marked them abstract + // that's even more confusing since they all fails for respondToSelector tests but works in real life + using (UITextField tf = new UITextField ()) { + // this is just to show we can get and set those values (even if respondToSelector returns NO) + tf.AutocapitalizationType = tf.AutocapitalizationType; + tf.AutocorrectionType = tf.AutocorrectionType; + tf.EnablesReturnKeyAutomatically = tf.EnablesReturnKeyAutomatically; + tf.KeyboardAppearance = tf.KeyboardAppearance; + tf.KeyboardType = tf.KeyboardType; + tf.ReturnKeyType = tf.ReturnKeyType; + tf.SecureTextEntry = tf.SecureTextEntry; + tf.SpellCheckingType = tf.SpellCheckingType; + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/TextViewTest.cs b/tests/monotouch-test/UIKit/TextViewTest.cs new file mode 100644 index 000000000000..91868252ca51 --- /dev/null +++ b/tests/monotouch-test/UIKit/TextViewTest.cs @@ -0,0 +1,119 @@ +// Copyright 2011-2013 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TextViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UITextView tv = new UITextView (frame)) { + Assert.That (tv.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void EmptySelection () + { + using (UITextView tv = new UITextView ()) { + Assert.That (tv.SelectedRange.Length, Is.EqualTo ((nint) 0), "SelectedRange"); + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + Assert.IsNull (tv.TypingAttributes, "default"); + // ^ without a [PreSnippet] attribute this would crash like: + // 7 monotouchtest 0x00006340 mono_sigill_signal_handler + 64 + // 8 WebKit 0x06b6afa5 -[WebView(WebPrivate) styleAtSelectionStart] + 53 + // 9 UIKit 0x028daa8a -[UIWebDocumentView typingAttributes] + 50 + // 10 UIKit 0x0285de57 -[UITextView typingAttributes] + 42 + tv.TypingAttributes = new NSDictionary (); + // Assert.IsNotNull (tv.TypingAttributes, "assigned"); + // ^ this would still crash + } + } + } + + [Test] + public void NonEmptySelection () + { + using (UITextView tv = new UITextView ()) { + tv.Text = "Bla bla bla"; + tv.SelectAll (tv); + Assert.That (tv.SelectedRange.Length, Is.Not.EqualTo (0), "SelectedRange"); + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) { + Assert.IsNotNull (tv.TypingAttributes, "TypingAttributes"); + // ^ this does not crash when a selection is made + } + } + } + + [Test] + // if this fails ping lobrien (or doc team) since it means Apple changed the defaults we documented + public void LayoutManager () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (UITextView tv = new UITextView ()) { + var lm = tv.LayoutManager; + Assert.True (lm.AllowsNonContiguousLayout, "AllowsNonContiguousLayout"); + Assert.False (lm.ExtraLineFragmentRect.IsEmpty, "ExtraLineFragmentRect"); + Assert.NotNull (lm.ExtraLineFragmentTextContainer, "ExtraLineFragmentTextContainer"); + Assert.False (lm.ExtraLineFragmentUsedRect.IsEmpty, "ExtraLineFragmentUsedRect"); + Assert.That (lm.FirstUnlaidCharacterIndex, Is.EqualTo ((nuint) 0), "FirstUnlaidCharacterIndex"); + Assert.That (lm.FirstUnlaidGlyphIndex, Is.EqualTo ((nuint) 0), "FirstUnlaidGlyphIndex"); + Assert.False (lm.HasNonContiguousLayout, "HasNonContiguousLayout"); + Assert.That (lm.HyphenationFactor, Is.EqualTo ((nfloat) 0), "HyphenationFactor"); + Assert.That (lm.NumberOfGlyphs, Is.EqualTo ((nuint) 0), "NumberOfGlyphs"); + Assert.False (lm.ShowsControlCharacters, "ShowsControlCharacters"); + Assert.False (lm.ShowsInvisibleCharacters, "ShowsInvisibleCharacters"); + Assert.NotNull (lm.TextStorage, "TextStorage"); + Assert.True (lm.UsesFontLeading, "UsesFontLeading"); + } + } + + [Test] + public void TextInputTraits () + { + // UITextInputTraits members are not required but we marked them abstract + // that's even more confusing since they all fails for respondToSelector tests but works in real life + using (UITextView tv = new UITextView ()) { + // this is just to show we can get and set those values (even if respondToSelector returns NO) + tv.AutocapitalizationType = tv.AutocapitalizationType; + tv.AutocorrectionType = tv.AutocorrectionType; + tv.EnablesReturnKeyAutomatically = tv.EnablesReturnKeyAutomatically; + tv.KeyboardAppearance = tv.KeyboardAppearance; + tv.KeyboardType = tv.KeyboardType; + tv.ReturnKeyType = tv.ReturnKeyType; + tv.SecureTextEntry = tv.SecureTextEntry; + tv.SpellCheckingType = tv.SpellCheckingType; + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ToolbarTest.cs b/tests/monotouch-test/UIKit/ToolbarTest.cs new file mode 100644 index 000000000000..cbac245f0af6 --- /dev/null +++ b/tests/monotouch-test/UIKit/ToolbarTest.cs @@ -0,0 +1,52 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ToolbarTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIToolbar tb = new UIToolbar (frame)) { + Assert.That (tb.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void BackgroundImage () + { + using (UIToolbar tb = new UIToolbar ()) { + Assert.Null (tb.GetBackgroundImage (UIToolbarPosition.Any, UIBarMetrics.Default), "Get"); + tb.SetBackgroundImage (null, UIToolbarPosition.Any, UIBarMetrics.Default); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/UIAlertControllerTest.cs b/tests/monotouch-test/UIKit/UIAlertControllerTest.cs new file mode 100644 index 000000000000..13653bdd9762 --- /dev/null +++ b/tests/monotouch-test/UIKit/UIAlertControllerTest.cs @@ -0,0 +1,55 @@ +// +// Unit tests for UIAlertControllerTest +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class UIAlertControllerTest { + + [Test] + public void InitWithNibNameTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("UIAlertControllerTest is new in 8.0"); + + UIAlertController ctrl = new UIAlertController (null, null); + Assert.NotNull (ctrl, "UIAlertController ctor(String, NSBundle)"); + + ctrl.AddAction (new UIAlertAction ()); + ctrl.AddAction (new UIAlertAction ()); + Assert.That (ctrl.Actions.Length, Is.EqualTo (2), "UIAlertController instance is not usable "); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/UIDocumentTest.cs b/tests/monotouch-test/UIKit/UIDocumentTest.cs new file mode 100644 index 000000000000..dddfcee9cbfd --- /dev/null +++ b/tests/monotouch-test/UIKit/UIDocumentTest.cs @@ -0,0 +1,178 @@ +// +// Unit tests for UIDocument +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.IO; +using System.Reflection; +using System.Threading; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +using MonoTouchException=ObjCRuntime.RuntimeException; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouchException=MonoTouch.RuntimeException; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + class DocumentPoker : UIDocument { + + static FieldInfo bkFileUrl; + + static DocumentPoker () + { + var t = typeof (UIDocument); + bkFileUrl = t.GetField ("__mt_FileUrl_var", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public static bool NewRefcountEnabled () + { + return NSObject.IsNewRefcountEnabled (); + } + + public DocumentPoker (NSUrl url) : base (url) + { + } + + public NSUrl FileUrlBackingField { + get { + return (NSUrl) bkFileUrl.GetValue (this); + } + } + } + + class MyUrl : NSUrl { + + public MyUrl (string url, string annotation) : base (url) + { + Annotation = annotation; + } + + public string Annotation { get; private set; } + } + + [TestFixture] + [Preserve (AllMembers = true)] + public class DocumentTest { + + class MyDocument : UIDocument { + + private string content = "content"; + + public MyDocument (NSUrl url) : base (url) + { + } + + public override NSObject ContentsForType (string typeName, out NSError outError) + { + outError = null; + return NSData.FromString (content); + } + + public override bool LoadFromContents (NSObject contents, string typeName, out NSError outError) + { + outError = null; + content = (contents as NSData).ToString (); + return true; + } + } + + MyDocument doc; + + string GetFileName () + { + string file = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "mydocument.txt"); + if (File.Exists (file)) + File.Delete (file); + return file; + } + + [Test] + public void Save () + { + using (NSUrl url = NSUrl.FromFilename (GetFileName ())) { + doc = new MyDocument (url); + doc.Save (url, UIDocumentSaveOperation.ForCreating, OperationHandler); + } + } + + void OperationHandler (bool success) + { + Assert.True (success); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void PerformAsynchronousFileAccess_Null () + { + using (NSUrl url = NSUrl.FromFilename (GetFileName ())) + using (var doc = new MyDocument (url)) { + // NULL value is not documented by Apple but adding a + // [NullAllowed] would throw an Objective-C exception (bad) + doc.PerformAsynchronousFileAccess (null); + } + } + + [Test] + public void FileUrl_BackingField () + { + if (DocumentPoker.NewRefcountEnabled ()) + Assert.Inconclusive ("backing fields are removed when newrefcount is enabled"); + + string file = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "uidocument.txt"); + if (File.Exists (file)) + File.Delete (file); + + using (NSUrl url = NSUrl.FromFilename (file)) + using (var doc = new DocumentPoker (url)) { + Assert.NotNull (doc.FileUrlBackingField, "1a"); + Assert.AreSame (doc.FileUrl, doc.FileUrlBackingField, "2a"); + // not a big deal in this case since we can't subclass NSUrl + } + } + + [Test] + [Ignore ("crash on the bots, run fines locally on sim")] + public void NSUrl_Subclass () + { + if (Runtime.Arch == Arch.DEVICE) + Assert.Inconclusive ("will crash runner application after test execution"); + + string file = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "uidocument.txt"); + if (File.Exists (file)) + File.Delete (file); + + // interesting limitation + using (MyUrl url2 = new MyUrl (file, "my document")) { + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: must pass a valid file URL to -[UIDocument initWithFileURL:] + Assert.Throws (delegate { + new DocumentPoker (url2); + }); + } + } + + [Test] + public void Fields () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Ignore ("requires iOS8+"); + // just to confirm it's not an NSUrl but an NSString + Assert.That (UIDocument.UserActivityDocumentUrlKey.ToString (), Is.EqualTo ("NSUserActivityDocumentURL"), "NSUserActivityDocumentURLKey"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/UISearchControllerTest.cs b/tests/monotouch-test/UIKit/UISearchControllerTest.cs new file mode 100644 index 000000000000..5af5b0f52e40 --- /dev/null +++ b/tests/monotouch-test/UIKit/UISearchControllerTest.cs @@ -0,0 +1,54 @@ +// +// Unit tests for UISearchControllerTest +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class UISearchControllerTest { + + [Test] + public void InitWithNibNameTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8,0)) + Assert.Inconclusive ("UISearchController is new in 8.0"); + + UISearchController ctrl = new UISearchController (null, null); + Assert.NotNull (ctrl, "UISearchController ctor(String, NSBundle)"); + + ctrl.Delegate = new UISearchControllerDelegate (); + Assert.NotNull (ctrl.Delegate, "UISearchController instance is not usable "); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/UIStackViewTest.cs b/tests/monotouch-test/UIKit/UIStackViewTest.cs new file mode 100644 index 000000000000..8507753f6a3a --- /dev/null +++ b/tests/monotouch-test/UIKit/UIStackViewTest.cs @@ -0,0 +1,56 @@ +// +// Unit tests for UIStackViewTest +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class A_UIStackViewTest { + + [Test] + public void InitWithFrameTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9,0)) + Assert.Inconclusive ("UIStackView is new in 9.0"); + + UIStackView stack = new UIStackView (new RectangleF (0, 0, 10, 10)); + Assert.NotNull (stack, "UIStackView ctor(CGRect)"); + + stack.AddArrangedSubview (new UIImageView ()); + stack.AddArrangedSubview (new UIView ()); + + Assert.That (stack.Subviews.Length, Is.EqualTo (2), "UIStackView instance is not usable "); + } + } +} + +#endif // !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/UIKit/VibrancyEffectTest.cs b/tests/monotouch-test/UIKit/VibrancyEffectTest.cs new file mode 100644 index 000000000000..9e418a290c4a --- /dev/null +++ b/tests/monotouch-test/UIKit/VibrancyEffectTest.cs @@ -0,0 +1,53 @@ +// +// Unit tests for UIVibrancyEffect +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using NotificationCenter; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.NotificationCenter; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VibrancyEffectTest { + +#if !XAMCORE_2_0 + [Test] + public void NotificationCenterVibrancyEffect_Old () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (8,0)) + Assert.Inconclusive ("Requires 8.0+"); + + (null as UIVibrancyEffect).NotificationCenterVibrancyEffect (); + } +#endif + [Test] + public void NotificationCenterVibrancyEffect_New () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (8,0)) + Assert.Inconclusive ("Requires 8.0+"); + + UIVibrancyEffect.CreateForNotificationCenter (); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ \ No newline at end of file diff --git a/tests/monotouch-test/UIKit/ViewControllerTest.cs b/tests/monotouch-test/UIKit/ViewControllerTest.cs new file mode 100644 index 000000000000..60fbfbbfc1dc --- /dev/null +++ b/tests/monotouch-test/UIKit/ViewControllerTest.cs @@ -0,0 +1,214 @@ +// +// Unit tests for UIViewController +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#if !__TVOS__ +using iAd; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.iAd; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.UIKit { + [TestFixture] + [Preserve (AllMembers = true)] + public class ViewControllerTest { + +#if !__TVOS__ + [Test] + public void Bug3489 () + { + using (UIViewController a = new UIViewController ()) + using (UIViewController b = new UIViewController ()) + using (UIViewController c = new UIViewController ()) { + a.PresentModalViewController (b, true); + b.PresentModalViewController (c, true); + +#if XAMCORE_2_0 + b.DismissModalViewController (true); + a.DismissModalViewController (true); //error +#else + b.DismissModalViewControllerAnimated (true); + a.DismissModalViewControllerAnimated (true); //error +#endif + } + } +#endif + +#if !__TVOS__ + [Test] + public void Bug3189 () + { + using (UIViewController a = new UIViewController ()) + using (UIViewController b = new UIViewController ()) + using (UIViewController c = new UIViewController ()) + using (UIViewController wb = new UINavigationController (b)) + using (UIViewController wc = new UINavigationController (c)) + { + a.PresentModalViewController (wb, true); + b.PresentModalViewController (wc, true); + +#if XAMCORE_2_0 + c.DismissModalViewController (true); //error +#else + c.DismissModalViewControllerAnimated (true); //error +#endif + } + } +#endif + + [Test] + public void NonModal () + { + using (UIViewController a = new UIViewController ()) + using (UIViewController b = new UIViewController ()) + using (UIViewController c = new UIViewController ()) + using (UIViewController wb = new UINavigationController (b)) + using (UIViewController wc = new UINavigationController (c)) + { + // interesting [PreSnippet] for the linker (wrt backing field elimitation) + a.PresentViewController (wb, true, null); + b.PresentViewController (wc, true, null); + + // interesting [PostSnippet] for the linker (wrt backing field elimitation) + c.DismissViewController (true, null); + } + } + + [Test] + public void NSAction_Null () + { + using (var vc = new UIViewController ()) + using (var child = new UIViewController ()) { + vc.PresentViewController (child, false, null); + child.DismissViewController (false, null); + } + } + + [Test] + public void Defaults () + { + using (var vc = new UIViewController ()) { + Assert.That (vc.ChildViewControllers, Is.Empty, "ChildViewControllers"); + Assert.False (vc.DefinesPresentationContext, "DefinesPresentationContext"); + Assert.False (vc.DisablesAutomaticKeyboardDismissal, "DisablesAutomaticKeyboardDismissal"); + Assert.False (vc.Editing, "Editing"); + Assert.False (vc.IsBeingDismissed, "IsBeingDismissed"); + Assert.False (vc.IsBeingPresented, "IsBeingPresented"); + Assert.False (vc.IsMovingFromParentViewController, "IsMovingFromParentViewController"); + Assert.False (vc.IsMovingToParentViewController, "IsMovingToParentViewController"); + Assert.False (vc.IsViewLoaded, "IsViewLoaded"); + Assert.False (vc.ModalInPopover, "ModalInPopover"); + Assert.Null (vc.NavigationController, "NavigationController"); + Assert.NotNull (vc.NibBundle, "NibBundle"); + Assert.Null (vc.NibName, "NibName"); + Assert.Null (vc.ParentViewController, "ParentViewController"); + Assert.Null (vc.PresentedViewController, "PresentedViewController"); + Assert.Null (vc.PresentingViewController, "PresentingViewController"); + Assert.False (vc.ProvidesPresentationContextTransitionStyle, "ProvidesPresentationContextTransitionStyle"); +#if !__TVOS__ + Assert.True (vc.AutomaticallyForwardAppearanceAndRotationMethodsToChildViewControllers, "AutomaticallyForwardAppearanceAndRotationMethodsToChildViewControllers"); + Assert.False (vc.HidesBottomBarWhenPushed, "HidesBottomBarWhenPushed"); + Assert.Null (vc.ModalViewController, "ModalViewController"); + Assert.Null (vc.RotatingFooterView, "RotatingFooterView"); + Assert.Null (vc.RotatingHeaderView, "RotatingHeaderView"); + Assert.Null (vc.SearchDisplayController, "SearchDisplayController"); + Assert.False (vc.WantsFullScreenLayout, "WantsFullScreenLayout"); +#endif + Assert.Null (vc.SplitViewController, "SplitViewController"); + Assert.Null (vc.Storyboard, "Storyboard"); + Assert.Null (vc.TabBarController, "TabBarController"); + Assert.NotNull (vc.TabBarItem, "TabBarItem"); + Assert.Null (vc.Title, "Title"); + Assert.Null (vc.ToolbarItems, "ToolbarItems"); + Assert.NotNull (vc.View, "View"); + } + } + + [Test] + public void Toolbars_Null () + { + using (var undo = new UIBarButtonItem (UIBarButtonSystemItem.Undo)) + using (var redo = new UIBarButtonItem (UIBarButtonSystemItem.Redo)) + using (var vc = new UIViewController ()) { + var buttons = new UIBarButtonItem [] { undo, redo }; + vc.ToolbarItems = buttons; + Assert.That (vc.ToolbarItems.Length, Is.EqualTo (2), "1"); + vc.ToolbarItems = null; + Assert.Null (vc.ToolbarItems, "2"); +#if !__TVOS__ + vc.SetToolbarItems (buttons, true); + Assert.That (vc.ToolbarItems.Length, Is.EqualTo (2), "3"); + vc.SetToolbarItems (null, false); + Assert.Null (vc.ToolbarItems, "4"); +#endif + } + } + + [Test] + public void View_Null () + { + using (var vc = new UIViewController ()) { + // even if the default is null The default value of this property is nil. + // we'll never see it as such as it will be loaded (loadView) + Assert.NotNull (vc.View, "View-a"); + // OTOH we can set it to null ourself + // or the controller can do it if iOS runs out of memory + vc.View = null; + // but again, accessing it will load the view + Assert.NotNull (vc.View, "View-b"); + } + } + + [Test] + public void AppearanceTransition () + { + // this was retroactively documented as available in 5.0 (officially added in 6.0) + // but respondToSelector return false + using (var vc = new UIViewController ()) { + vc.BeginAppearanceTransition (true, true); + vc.EndAppearanceTransition (); + } + } + +#if !XAMCORE_2_0 + [Test] + public void InterstitialAds_Old () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) + Assert.Inconclusive ("prepareInterstitialAds is > iOS 7.0"); + + UIViewController vc = null; + vc.PrepareInterstitialAds (); + } +#endif + +#if !__TVOS__ + [Test] + public void InterstitialAds_New () + { + if (!UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) + Assert.Inconclusive ("prepareInterstitialAds is > iOS 7.0"); + + UIViewController.PrepareForInterstitialAds (); + } +#endif // !__TVOS__ + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/ViewTest.cs b/tests/monotouch-test/UIKit/ViewTest.cs new file mode 100644 index 000000000000..646a4b59132c --- /dev/null +++ b/tests/monotouch-test/UIKit/ViewTest.cs @@ -0,0 +1,311 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIView v = new UIView (frame)) { + Assert.That (v.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void HitTest_Null () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIView v = new UIView (frame)) { + UIView result = v.HitTest (new PointF (-10, -10), null); + Assert.Null (result, "outside"); + result = v.HitTest (new PointF (50, 50), null); + Assert.That (result.Handle, Is.EqualTo (v.Handle), "inside"); + } + } + + [Test] + public void PointInside_Null () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIView v = new UIView (frame)) { + Assert.False (v.PointInside (new PointF (-10, -10), null), "outside"); + Assert.True (v.PointInside (new PointF (50, 50), null), "inside"); + } + } + + [Test] + public void SizeThatFits () + { + // same as LinkerTest in 'linksdk' project - but won't be linked here (for simulator) + SizeF empty = SizeF.Empty; + using (UIView v = new UIView ()) { + Assert.True (v.SizeThatFits (empty).IsEmpty, "Empty"); + } + } + + [Test] + public void Convert_Null () + { + using (UIView v = new UIView ()) { + Assert.That (v.ConvertPointFromView (PointF.Empty, null), Is.EqualTo (PointF.Empty), "ConvertPointFromView"); + Assert.That (v.ConvertPointToView (PointF.Empty, null), Is.EqualTo (PointF.Empty), "ConvertPointToView"); + Assert.That (v.ConvertRectFromView (RectangleF.Empty, null), Is.EqualTo (RectangleF.Empty), "ConvertRectFromView"); + Assert.That (v.ConvertRectToView (RectangleF.Empty, null), Is.EqualTo (RectangleF.Empty), "ConvertRectToView"); + } + } + + // Apple does not allow NULL on 'animations' parameters used in animate* and transition* selectors + + void Completion () + { + } + + void CompletionHandler (bool finished) + { + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Animate_Null_a1 () + { + UIView.Animate (1.0, null); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Animate_Null_a2 () + { + UIView.Animate (1.0, null, Completion); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void Animate_Null_a3 () + { + UIView.Animate (1.0, 2.0, UIViewAnimationOptions.Autoreverse, null, Completion); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void AnimateNotify_Null_a1 () + { + UIView.AnimateNotify (1.0, null, CompletionHandler); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void AnimateNotify_Null_a2 () + { + UIView.AnimateNotify (1.0, 2.0, UIViewAnimationOptions.Autoreverse, null, CompletionHandler); + } + + [Test] + public void Transition_Null_a1 () + { + using (UIView v = new UIView ()) { + UIView.Transition (v, 1.0, UIViewAnimationOptions.AllowAnimatedContent, null, Completion); + } + } + + [Test] + public void TransitionNotify_Null_a1 () + { + using (UIView v = new UIView ()) { + UIView.TransitionNotify (v, 1.0, UIViewAnimationOptions.AllowAnimatedContent, null, CompletionHandler); + } + } + + // Apple allows NULL on 'completion' parameters used in animate* and transition* selectors + + void Animations () + { + } + + [Test] + public void Animate_Null_c1 () + { + UIView.Animate (1.0, Animations, null); + } + + [Test] + public void Animate_Null_c2 () + { + UIView.Animate (1.0, 2.0, UIViewAnimationOptions.Autoreverse, Animations, null); + } + + [Test] + public void AnimateNotify_Null_c1 () + { + UIView.AnimateNotify (1.0, Animations, null); + } + + [Test] + public void AnimateNotify_Null_c2 () + { + UIView.AnimateNotify (1.0, 2.0, UIViewAnimationOptions.Autoreverse, Animations, null); + } + + [Test] + public void Transition_Null_c1 () + { + using (UIView v = new UIView ()) { + UIView.Transition (v, 1.0, UIViewAnimationOptions.AllowAnimatedContent, Animations, null); + } + } + + [Test] + public void Transition_Null_c2 () + { + using (UIView v = new UIView ()) { + UIView.Transition (v, v, 1.0, UIViewAnimationOptions.AllowAnimatedContent, null); + } + } + + [Test] + public void TransitionNotify_Null_c1 () + { + using (UIView v = new UIView ()) { + UIView.TransitionNotify (v, 1.0, UIViewAnimationOptions.AllowAnimatedContent, Animations, null); + } + } + + [Test] + public void TransitionNotify_Null_c2 () + { + using (UIView v = new UIView ()) { + UIView.TransitionNotify (v, v, 1.0, UIViewAnimationOptions.AllowAnimatedContent, null); + } + } + + [Test] + public void BackgroundColorTest () + { + using (var color = UIColor.FromRGB (5, 6, 7)) { + using (var view = new ViewWithCustomBackgroundColor ()) { + Messaging.void_objc_msgSend_IntPtr (view.Handle, new Selector ("setBackgroundColor:").Handle, color.Handle); + } + } + } + + [Register ("ViewWithCustomBackgroundColor")] + public class ViewWithCustomBackgroundColor : UIView + { + public override UIColor BackgroundColor { + get { return base.BackgroundColor; } + set { base.BackgroundColor = value; } + } + } + + [Test] + public void TraitTest () + { + using (var view = new UIView ()) { + Assert.AreEqual (UIAccessibilityTrait.None, view.AccessibilityTraits, "a"); + view.AccessibilityTraits = UIAccessibilityTrait.None; + Assert.AreEqual (UIAccessibilityTrait.None, view.AccessibilityTraits, "b"); + view.AccessibilityTraits = UIAccessibilityTrait.Adjustable; + Assert.AreEqual (UIAccessibilityTrait.Adjustable, view.AccessibilityTraits, "c"); + view.AccessibilityTraits = UIAccessibilityTrait.Adjustable | UIAccessibilityTrait.Button; + Assert.AreEqual (UIAccessibilityTrait.Adjustable | UIAccessibilityTrait.Button, view.AccessibilityTraits, "e"); + } + } + + [Test] + public void TraitMatch () + { + Assert.AreEqual ((int) UIAccessibilityTrait.Adjustable, UIView.TraitAdjustable, "Adjustable"); + Assert.AreEqual ((int) UIAccessibilityTrait.AllowsDirectInteraction, UIView.TraitAllowsDirectInteraction, "AllowsDirectInteraction"); + Assert.AreEqual ((int) UIAccessibilityTrait.Button, UIView.TraitButton, "Button"); + Assert.AreEqual ((int) UIAccessibilityTrait.CausesPageTurn, UIView.TraitCausesPageTurn, "CausesPageTurn"); + Assert.AreEqual ((int) UIAccessibilityTrait.Image, UIView.TraitImage, "Image"); + Assert.AreEqual ((int) UIAccessibilityTrait.KeyboardKey, UIView.TraitKeyboardKey, "KeyboardKey"); + Assert.AreEqual ((int) UIAccessibilityTrait.Link, UIView.TraitLink, "Link"); + Assert.AreEqual ((int) UIAccessibilityTrait.None, UIView.TraitNone, "None"); + Assert.AreEqual ((int) UIAccessibilityTrait.NotEnabled, UIView.TraitNotEnabled, "NotEnabled"); + Assert.AreEqual ((int) UIAccessibilityTrait.PlaysSound, UIView.TraitPlaysSound, "PlaysSound"); + Assert.AreEqual ((int) UIAccessibilityTrait.SearchField, UIView.TraitSearchField, "SearchField"); + Assert.AreEqual ((int) UIAccessibilityTrait.Selected, UIView.TraitSelected, "Selected"); + Assert.AreEqual ((int) UIAccessibilityTrait.StartsMediaSession, UIView.TraitStartsMediaSession, "StartsMediaSession"); + Assert.AreEqual ((int) UIAccessibilityTrait.StaticText, UIView.TraitStaticText, "StaticText"); + Assert.AreEqual ((int) UIAccessibilityTrait.SummaryElement, UIView.TraitSummaryElement, "SummaryElement"); + Assert.AreEqual ((int) UIAccessibilityTrait.UpdatesFrequently, UIView.TraitUpdatesFrequently, "UpdatesFrequently"); + + // some [Field] won't return a valid value before iOS 6.0 + if (TestRuntime.CheckSystemAndSDKVersion (6,0)) + Assert.AreEqual ((int) UIAccessibilityTrait.Header, UIView.TraitHeader, "Header"); + } + + [Test] + public void Subviews () + { + using (var v = new UIView ()) { + Assert.That (v.Subviews, Is.Not.Null); + + // even if null we want to ensure we can use UIView.GetEnumarator to iterate subviews + int n = 0; + foreach (var sv in v) + Assert.NotNull (sv, n++.ToString ()); + } + } + + [Test] + public void TintColor () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7, 0)) + Assert.Ignore ("requires iOS7+"); + + using (var v = new UIView ()) { + var tc = v.TintColor; + Assert.NotNull (tc, "TintColor-1"); + v.TintColor = UIColor.Red; + v.TintColor = null; + // setting to null returns to default (i.e. not the last non-null value) + Assert.NotNull (v.TintColor, "TintColor-2"); + } + } + + [Test] + public void Equality () + { + using (var v1 = new UIView ()) + using (var v2 = new UIView ()) { + // two basic/init'ed instances differ only by their handles + Assert.That (v1.Handle, Is.Not.EqualTo (v2.Handle), "Handle"); + // and that's enough to make them totally different (natively in objc for both `hash` and `isEqual:`) + Assert.That (v1.GetHashCode (), Is.Not.EqualTo (v2.GetHashCode ()), "GetHashCode"); + Assert.False (v1.Equals (v2.Handle), "Equals"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/WebViewTest.cs b/tests/monotouch-test/UIKit/WebViewTest.cs new file mode 100644 index 000000000000..c9ac363935f1 --- /dev/null +++ b/tests/monotouch-test/UIKit/WebViewTest.cs @@ -0,0 +1,57 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class WebViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIWebView wv = new UIWebView (frame)) { + Assert.That (wv.Frame, Is.EqualTo (frame), "Frame"); + Assert.Null (wv.Request, "Request"); + } + } + + [Test] + public void InstantiateDerivedClass () + { + using (var derived = new DerivedUIWebView ()) { + // bug #9261 - just instantiating a derived UIWebView class crashes on iOS 5 + } + } + + class DerivedUIWebView : UIWebView + { + } + } + +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/UIKit/WindowTest.cs b/tests/monotouch-test/UIKit/WindowTest.cs new file mode 100644 index 000000000000..fa96384f1bb9 --- /dev/null +++ b/tests/monotouch-test/UIKit/WindowTest.cs @@ -0,0 +1,78 @@ +// Copyright 2011-2013 Xamarin Inc. All rights reserved + +#if !__WATCHOS__ + +using System; +using System.Drawing; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.UIKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class WindowTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (UIWindow w = new UIWindow (frame)) { + Assert.That (w.Frame, Is.EqualTo (frame), "Frame"); + } + } + + [Test] + public void Convert_Null () + { + using (UIWindow w = new UIWindow ()) { + Assert.That (w.ConvertPointFromWindow (PointF.Empty, null), Is.EqualTo (PointF.Empty), "ConvertPointFromWindow"); + Assert.That (w.ConvertPointToWindow (PointF.Empty, null), Is.EqualTo (PointF.Empty), "ConvertPointToWindow"); + Assert.That (w.ConvertRectFromWindow (RectangleF.Empty, null), Is.EqualTo (RectangleF.Empty), "ConvertRectFromWindow"); + Assert.That (w.ConvertRectToWindow (RectangleF.Empty, null), Is.EqualTo (RectangleF.Empty), "ConvertRectToWindow"); + } + } + + [Test] + public void IsKeyWindow_5199 () + { + using (UIWindow w = new UIWindow ()) { + Assert.False (w.IsKeyWindow, "IsKeyWindow"); + } + } + + [Test] + public void Level () + { + using (UIWindow w = new UIWindow ()) { + Assert.That (w.WindowLevel, Is.EqualTo ((nfloat) 0f), "default"); + w.WindowLevel = UIWindowLevel.Normal; + Assert.That (w.WindowLevel, Is.EqualTo ((nfloat) 0f), "Normal"); + w.WindowLevel = UIWindowLevel.Alert; + Assert.That (w.WindowLevel, Is.EqualTo ((nfloat) 2000f), "Alert"); +#if !__TVOS__ + w.WindowLevel = UIWindowLevel.StatusBar; + Assert.That (w.WindowLevel, Is.EqualTo ((nfloat) 1000f), "StatusBar"); +#endif // !__TVOS__ + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/VideoToolbox/VTCompressionSessionTests.cs b/tests/monotouch-test/VideoToolbox/VTCompressionSessionTests.cs new file mode 100644 index 000000000000..4506639204a7 --- /dev/null +++ b/tests/monotouch-test/VideoToolbox/VTCompressionSessionTests.cs @@ -0,0 +1,151 @@ +// +// Unit tests for VTCompressionSession +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using VideoToolbox; +using UIKit; +using CoreMedia; +using AVFoundation; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.VideoToolbox; +using MonoTouch.UIKit; +using MonoTouch.CoreMedia; +using MonoTouch.AVFoundation; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.VideoToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VTCompressionSessionTests + { + [Test] + public void CompressionSessionCreateTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var session = CreateSession ()){ + Assert.IsNotNull (session, "Session should not be null"); + } + } + + [Test] + public void CompressionSessionSetCompressionPropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var session = CreateSession ()){ + + var result = session.SetCompressionProperties (new VTCompressionProperties { + RealTime = true, + AllowFrameReordering = false + }); + + Assert.That (result == VTStatus.Ok, "SetCompressionProperties"); + } + } + + [Test] + public void CompressionSessionSetPropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var session = CreateSession ()){ + + var result = session.SetProperties (new VTPropertyOptions { + ReadWriteStatus = VTReadWriteStatus.ReadWrite, + ShouldBeSerialized = true + }); + + Assert.That (result == VTStatus.Ok, "SetProperties"); + } + } + + [Test] + public void CompressionSessionSetCompressionPropertiesMultiPassStorageTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var session = CreateSession ()) + using (var storage = VTMultiPassStorage.Create ()){ + var result = session.SetCompressionProperties (new VTCompressionProperties { + RealTime = false, + AllowFrameReordering = true, + MultiPassStorage = storage + }); + + Assert.That (result == VTStatus.Ok, "SetCompressionPropertiesMultiPassStorage"); + } + } + + // On iOS 8 all properties in GetSupportedProperties for Compression session return false on ShouldBeSerialized + // with this test we will be able to catch if apple changes its mind about this in the future. + [Test] + public void CompressionSessionGetSupportedPropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var session = CreateSession ()) { + var supportedProps = session.GetSupportedProperties (); + Assert.NotNull (supportedProps, "GetSupportedProperties IsNull"); + + var key = new NSString ("ShouldBeSerialized"); + foreach (var item in supportedProps) { + var dict = (NSDictionary)item.Value; + if (dict == null) continue; + + NSObject value; + if (dict.TryGetValue (key, out value) && value != null ) { + var number = (NSNumber) value; + Assert.IsFalse (number.BoolValue, "CompressionSession GetSupportedPropertiesTest ShouldBeSerialized is True"); + } + } + } + } + + // This test is (kind of) expected to be null due to as of iOS 8 all supported properties are not meant to be serialized + // see CompressionSessionGetSupportedPropertiesTest. + [Test] + public void CompressionSessionGetSerializablePropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var session = CreateSession ()) { + var supportedProps = session.GetSerializableProperties (); + Assert.IsNull (supportedProps, "CompressionSession GetSerializableProperties is not null"); + } + } + + VTCompressionSession CreateSession () + { + var session = VTCompressionSession.Create (1024, 768, CMVideoCodecType.H264, + (sourceFrame, status, flags, buffer) => { }); + return session; + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ + diff --git a/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs b/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs new file mode 100644 index 000000000000..1342f1cd2a0f --- /dev/null +++ b/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs @@ -0,0 +1,115 @@ +// +// Unit tests for VTDecompressionSession +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using VideoToolbox; +using UIKit; +using CoreMedia; +using AVFoundation; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.VideoToolbox; +using MonoTouch.UIKit; +using MonoTouch.CoreMedia; +using MonoTouch.AVFoundation; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.VideoToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VTDecompressionSessionTests + { + [Test] + public void DecompressionSessionCreateTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var asset = AVAsset.FromUrl (NSBundle.MainBundle.GetUrlForResource ("xamvideotest", "mp4"))) + using (var session = CreateSession (asset)){ + Assert.IsNotNull (session, "Session should not be null"); + } + } + + [Test] + public void DecompressionSessionSetDecompressionPropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var asset = AVAsset.FromUrl (NSBundle.MainBundle.GetUrlForResource ("xamvideotest", "mp4"))) + using (var session = CreateSession (asset)){ + + var result = session.SetDecompressionProperties (new VTDecompressionProperties { + RealTime = true, + OnlyTheseFrames = VTOnlyTheseFrames.AllFrames + }); + + Assert.That (result == VTStatus.Ok, "SetDecompressionProperties"); + } + } + + [Test] + public void DecompressionSessionSetPropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var asset = AVAsset.FromUrl (NSBundle.MainBundle.GetUrlForResource ("xamvideotest", "mp4"))) + using (var session = CreateSession (asset)){ + + var result = session.SetProperties (new VTPropertyOptions { + ReadWriteStatus = VTReadWriteStatus.ReadWrite, + ShouldBeSerialized = true + }); + + Assert.That (result == VTStatus.Ok, "SetProperties"); + } + } + + [Test] + public void DecompressionSessionGetSupportedPropertiesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var asset = AVAsset.FromUrl (NSBundle.MainBundle.GetUrlForResource ("xamvideotest", "mp4"))) + using (var session = CreateSession (asset)) { + var supportedProps = session.GetSupportedProperties (); + Assert.NotNull (supportedProps, "GetSupportedProperties"); + Assert.That (supportedProps.Count > 0, "GetSupportedProperties should be more than zero"); + } + } + + VTDecompressionSession CreateSession (AVAsset asset) + { + var videoTracks = asset.TracksWithMediaType (AVMediaType.Video); + var track = videoTracks[0]; + var formatDescriptor = track.FormatDescriptions[0] as CMVideoFormatDescription; + + var session = VTDecompressionSession.Create ( + (sourceFrame, status, flags, buffer, presentationTimeStamp, presentationDuration) => {}, + formatDescriptor); + + return session; + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/VideoToolbox/VTFrameSiloTests.cs b/tests/monotouch-test/VideoToolbox/VTFrameSiloTests.cs new file mode 100644 index 000000000000..cc79de5b6518 --- /dev/null +++ b/tests/monotouch-test/VideoToolbox/VTFrameSiloTests.cs @@ -0,0 +1,88 @@ +// +// Unit tests for VTFrameSilo +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using VideoToolbox; +using UIKit; +using CoreMedia; +using AVFoundation; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.VideoToolbox; +using MonoTouch.UIKit; +using MonoTouch.CoreMedia; +using MonoTouch.AVFoundation; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.VideoToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VTFrameSiloTests + { + [Test] + public void FrameSiloCreateTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var silo = VTFrameSilo.Create ()){ + Assert.IsNotNull (silo, "Silo should not be null"); + } + } + + [Test] + public void SetTimeRangesTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var silo = VTFrameSilo.Create ()){ + var result = silo.SetTimeRangesForNextPass (new CMTimeRange [0]); + Assert.IsTrue (result == VTStatus.FrameSiloInvalidTimeRange, "SetTimeRangesForNextPass"); + } + } + + [Test] + public void ForEachTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var silo = VTFrameSilo.Create ()){ + + var result = silo.ForEach ((arg) => { + return VTStatus.Ok; + }); + Assert.IsTrue (result == VTStatus.Ok, "VTFrameSilo ForEach"); + + result = silo.ForEach ((arg) => { + return VTStatus.Ok; + }); + Assert.IsTrue (result == VTStatus.Ok, "VTFrameSilo ForEach"); + + result = silo.ForEach ((arg) => { + return VTStatus.Ok; + }); + Assert.IsTrue (result == VTStatus.Ok, "VTFrameSilo ForEach"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/VideoToolbox/VTMultiPassStorageTests.cs b/tests/monotouch-test/VideoToolbox/VTMultiPassStorageTests.cs new file mode 100644 index 000000000000..522f1cbc621f --- /dev/null +++ b/tests/monotouch-test/VideoToolbox/VTMultiPassStorageTests.cs @@ -0,0 +1,63 @@ +// +// Unit tests for VTMultiPassStorage +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using VideoToolbox; +using UIKit; +using CoreMedia; +using AVFoundation; +using CoreFoundation; +#else +using MonoTouch.Foundation; +using MonoTouch.VideoToolbox; +using MonoTouch.UIKit; +using MonoTouch.CoreMedia; +using MonoTouch.AVFoundation; +using MonoTouch.CoreFoundation; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.VideoToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VTMultiPassStorageTests + { + [Test] + public void MultiPassStorageCreateTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var storage = VTMultiPassStorage.Create ()){ + Assert.IsNotNull (storage, "Storage should not be null"); + } + } + + [Test] + public void MultiPassStorageCloseTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + using (var storage = VTMultiPassStorage.Create ()){ + var result = storage.Close (); + Assert.IsTrue (result == VTStatus.Ok, "VTMultiPassStorage Close"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/VideoToolbox/VTUtilitiesTests.cs b/tests/monotouch-test/VideoToolbox/VTUtilitiesTests.cs new file mode 100644 index 000000000000..db1754b51b33 --- /dev/null +++ b/tests/monotouch-test/VideoToolbox/VTUtilitiesTests.cs @@ -0,0 +1,97 @@ +// +// Unit tests for VTMultiPassStorage +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using VideoToolbox; +using UIKit; +using CoreMedia; +using AVFoundation; +using CoreFoundation; +using CoreVideo; +using CoreGraphics; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.VideoToolbox; +using MonoTouch.UIKit; +using MonoTouch.CoreMedia; +using MonoTouch.AVFoundation; +using MonoTouch.CoreFoundation; +using MonoTouch.CoreVideo; +using MonoTouch.CoreGraphics; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.VideoToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VTUtilitiesTests { + + [DllImport (Constants.CoreFoundationLibrary)] + extern static int CFGetRetainCount (IntPtr handle); + + [Test] + public void ToCGImageTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (9, 0)) + Assert.Ignore ("Ignoring VideoToolbox.VTUtilitiesTests: Requires iOS9+"); + + var originalImage = UIImage.FromBundle ("CoreImage/Xam.png"); + var originalCGImage = originalImage.CGImage; + + var pxbuffer = new CVPixelBuffer (originalCGImage.Width, originalCGImage.Height, CVPixelFormatType.CV32ARGB, + new CVPixelBufferAttributes { CGImageCompatibility = true, CGBitmapContextCompatibility = true }); + pxbuffer.Lock (CVOptionFlags.None); + + using (var colorSpace = CGColorSpace.CreateDeviceRGB ()) + using (var ctx = new CGBitmapContext (pxbuffer.BaseAddress, originalCGImage.Width, originalCGImage.Height, 8, + 4 * originalCGImage.Width, colorSpace, CGBitmapFlags.NoneSkipLast)) { + ctx.RotateCTM (0); + ctx.DrawImage (new RectangleF (0, 0, originalCGImage.Width, originalCGImage.Height), originalCGImage); + pxbuffer.Unlock (CVOptionFlags.None); + } + + Assert.NotNull (pxbuffer, "VTUtilitiesTests.ToCGImageTest pxbuffer should not be null"); + + CGImage newImage; + var newImageStatus = pxbuffer.ToCGImage (out newImage); + + Assert.That (newImageStatus == VTStatus.Ok, "VTUtilitiesTests.ToCGImageTest must be ok"); + Assert.NotNull (newImage, "VTUtilitiesTests.ToCGImageTest pxbuffer should not be newImage"); + Assert.AreEqual (originalCGImage.Width, newImage.Width, "VTUtilitiesTests.ToCGImageTest"); + Assert.AreEqual (originalCGImage.Height, newImage.Height, "VTUtilitiesTests.ToCGImageTest"); + + var retainCount = CFGetRetainCount (newImage.Handle); + Assert.That (retainCount, Is.EqualTo (1), "RetainCount"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/VideoToolbox/VTVideoEncoderListTests.cs b/tests/monotouch-test/VideoToolbox/VTVideoEncoderListTests.cs new file mode 100644 index 000000000000..ab2154141ac5 --- /dev/null +++ b/tests/monotouch-test/VideoToolbox/VTVideoEncoderListTests.cs @@ -0,0 +1,43 @@ +// +// Unit tests for VTVideoEncoderList +// +// Authors: +// Alex Soto +// +// +// Copyright 2015 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +using VideoToolbox; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.VideoToolbox; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.VideoToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class VTVideoEncoderListTests + { + [Test] + public void VideoEncoderListTest () + { + if (!TestRuntime.CheckSystemAndSDKVersion (8, 0)) + Assert.Ignore ("Ignoring VideoToolbox tests: Requires iOS8+"); + + var encoders = VTVideoEncoder.GetEncoderList (); + Assert.NotNull (encoders, "VTVideoEncoder.GetEncoderList () Should Not be null"); + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/basn3p08.png b/tests/monotouch-test/basn3p08.png new file mode 100644 index 000000000000..0ddad07e5f5d Binary files /dev/null and b/tests/monotouch-test/basn3p08.png differ diff --git a/tests/monotouch-test/drum01.mp3 b/tests/monotouch-test/drum01.mp3 new file mode 100644 index 000000000000..91b6b7a781e3 Binary files /dev/null and b/tests/monotouch-test/drum01.mp3 differ diff --git a/tests/monotouch-test/iAd/BannerViewTest.cs b/tests/monotouch-test/iAd/BannerViewTest.cs new file mode 100644 index 000000000000..06dcdf2c405f --- /dev/null +++ b/tests/monotouch-test/iAd/BannerViewTest.cs @@ -0,0 +1,49 @@ +// Copyright 2011 Xamarin Inc. All rights reserved + +#if !__TVOS__ && !__WATCHOS__ + +using System; +#if !__WATCHOS__ +using System.Drawing; +#endif +#if XAMCORE_2_0 +using Foundation; +#if !__WATCHOS__ +using iAd; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.iAd; +#endif +using NUnit.Framework; + +#if XAMCORE_2_0 +using RectangleF=CoreGraphics.CGRect; +using SizeF=CoreGraphics.CGSize; +using PointF=CoreGraphics.CGPoint; +#else +using nfloat=global::System.Single; +using nint=global::System.Int32; +using nuint=global::System.UInt32; +#endif + +namespace MonoTouchFixtures.iAd { + + [TestFixture] + [Preserve (AllMembers = true)] + public class BannerViewTest { + + [Test] + public void InitWithFrame () + { + RectangleF frame = new RectangleF (10, 10, 100, 100); + using (ADBannerView bv = new ADBannerView (frame)) { + Assert.That (bv.Frame.X, Is.EqualTo (frame.X), "X"); + Assert.That (bv.Frame.Y, Is.EqualTo (frame.Y), "Y"); + // Width and Height are set by the Ad (e.g. 320 x 50 for the iPhone) + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/iAd/ViewControllerExtensionsTest.cs b/tests/monotouch-test/iAd/ViewControllerExtensionsTest.cs new file mode 100644 index 000000000000..6b8eed03d736 --- /dev/null +++ b/tests/monotouch-test/iAd/ViewControllerExtensionsTest.cs @@ -0,0 +1,52 @@ +// +// Unit tests for iAd's UIViewController extensions methods +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +#if !__TVOS__ && !__WATCHOS__ + +using System; + +#if XAMCORE_2_0 +using Foundation; +using UIKit; +using iAd; +#else +using MonoTouch.Foundation; +using MonoTouch.iAd; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures.CoreImage { + + [TestFixture] + [Preserve (AllMembers = true)] + public class ViewControllerExtensionsTest { + + [Test] + [Ignore ("got the original error back, needs more investigation")] + public void PresentationPolicy () + { + if (!TestRuntime.CheckSystemAndSDKVersion (7,0)) + Assert.Inconclusive ("Requires iOS7+"); + + using (var vc = new UIViewController ()) { + // without calling PrepareInterstitialAds we get a *unrecognized selector* native exception + // http://forums.xamarin.com/discussion/9160/setinterstitialpresentationpolicy-gives-me-nsinvalidargumentexception + UIViewController.PrepareForInterstitialAds (); + + Assert.That (vc.GetInterstitialPresentationPolicy (), Is.EqualTo (ADInterstitialPresentationPolicy.None), "default"); + + vc.SetInterstitialPresentationPolicy (ADInterstitialPresentationPolicy.Automatic); + Assert.That (vc.GetInterstitialPresentationPolicy (), Is.EqualTo (ADInterstitialPresentationPolicy.Automatic), "Automatic"); + } + } + } +} + +#endif // !__TVOS__ && !__WATCHOS__ diff --git a/tests/monotouch-test/mono/Symbols.cs b/tests/monotouch-test/mono/Symbols.cs new file mode 100644 index 000000000000..293b5e4c8585 --- /dev/null +++ b/tests/monotouch-test/mono/Symbols.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures { + [TestFixture] + [Preserve (AllMembers = true)] + public partial class Symbols { + string [] symbols; + + [Test] + public void FunctionNames () + { + if (Runtime.Arch != Arch.DEVICE) + Assert.Ignore ("This is a device-only test."); + + Collect (); + Assert.That (symbols [1], Contains.Substring ("MonoTouchFixtures_Symbols_Collect"), "#1"); + } + + void Collect () + { + var array = new IntPtr [50]; + var size = backtrace (array, array.Length); + var symbols = backtrace_symbols (array, size); + + this.symbols = new string [size]; + for (int i = 0; i < size; i++) { + this.symbols [i] = Marshal.PtrToStringAuto (Marshal.ReadIntPtr (symbols, i * IntPtr.Size)); +// Console.WriteLine (" #{0}: {1}", i, this.symbols [i]); + } + + free (symbols); + } + + [DllImport (Constants.libcLibrary)] + static extern int backtrace (IntPtr[] array, int size); + + [DllImport (Constants.libcLibrary)] + static extern IntPtr backtrace_symbols (IntPtr[] array, int size); + + [DllImport (Constants.libcLibrary)] + static extern void free (IntPtr ptr); + } +} + diff --git a/tests/monotouch-test/mono/bug18634.cs b/tests/monotouch-test/mono/bug18634.cs new file mode 100644 index 000000000000..b532f3f38c0f --- /dev/null +++ b/tests/monotouch-test/mono/bug18634.cs @@ -0,0 +1,546 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Threading; + +using System.Collections; +using System.Collections.ObjectModel; +using System.Linq; + +using MonoTouch; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#if !__TVOS__ +using MapKit; +#endif +#if !__WATCHOS__ +using CoreAnimation; +#endif +using CoreGraphics; +using CoreLocation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.MapKit; +using MonoTouch.CoreAnimation; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreLocation; +using MonoTouch.UIKit; +#endif +#if !__WATCHOS__ +using OpenTK; +#endif +using NUnit.Framework; + +namespace MonoTouchFixtures { + [TestFixture] + [Preserve (AllMembers = true)] + public partial class MonoRuntimeTests { + [Test] + public void Bug18632 () + { + var hit = false; + var ret1 = Observable.Return ("1"); + Observable.CombineLatest(ret1, ret1, ret1, (a, b, c) => { + return true; + }).Subscribe(new AnonymousObserver ()); + + var ret2 = Observable.Return (1); + Observable.CombineLatest(ret2, ret2, ret2, (a, b, c) => { + hit = true; + return true; + }).Subscribe(new AnonymousObserver ()); + + Assert.IsTrue (hit, "The second CombineLatest callback wasn't called."); + } + + class QueryLanguage : IQueryLanguage + { + public virtual Producer CombineLatest(Producer source1, Producer source2, Producer source3, Func resultSelector) + { + return new CombineLatest(source1, source2, source3, resultSelector); + } + + public virtual Producer Return(TResult value) + { + return new Return(value); + } + } + + interface IQueryLanguage + { + Producer Return(TResult value); + Producer CombineLatest(Producer source1, Producer source2, Producer source3, Func resultSelector); + } + + static class Observable + { + static IQueryLanguage s_impl = new QueryLanguage(); + public static Producer Return(TResult value) + { + return s_impl.Return(value); + } + public static Producer CombineLatest(Producer source1, Producer source2, Producer source3, Func resultSelector) + { + return s_impl.CombineLatest(source1, source2, source3, resultSelector); + } + } + + class Return : Producer + { + private readonly TResult _value; + + public Return(TResult value) + { + _value = value; + } + + protected override IDisposable Run(IObserver observer) + { + var sink = new _(this, observer); + return sink.Run(); + } + + class _ : Sink + { + private readonly Return _parent; + + public _(Return parent, IObserver observer) + : base(observer) + { + _parent = parent; + } + + public IDisposable Run() + { + Invoke (); + return null; + } + + private void Invoke() + { + base._observer.OnNext(_parent._value); + base._observer.OnCompleted(); + } + } + } + + class CombineLatest : Producer + { + private readonly Producer _source1; + private readonly Producer _source2; + private readonly Producer _source3; + private readonly Func _resultSelector; + + public CombineLatest(Producer source1, Producer source2, Producer source3, Func resultSelector) + { + _source1 = source1; + _source2 = source2; + _source3 = source3; + _resultSelector = resultSelector; + } + + protected override IDisposable Run(IObserver observer) + { + var sink = new _(this, observer); + return sink.Run(); + } + + class _ : CombineLatestSink + { + private readonly CombineLatest _parent; + + public _(CombineLatest parent, IObserver observer) + : base(3, observer) + { + _parent = parent; + } + + private CombineLatestObserver _observer1; + private CombineLatestObserver _observer2; + private CombineLatestObserver _observer3; + + public IDisposable Run() + { + _observer1 = new CombineLatestObserver(_gate, this, 0); + _observer2 = new CombineLatestObserver(_gate, this, 1); + _observer3 = new CombineLatestObserver(_gate, this, 2); + + _parent._source1.Subscribe(_observer1); + _parent._source2.Subscribe(_observer2); + _parent._source3.Subscribe(_observer3); + + return null; + } + + protected override TResult GetResult() + { + return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value); + } + } + } + + interface ICombineLatest + { + void Next(int index); + void Fail(Exception error); + void Done(int index); + } + + abstract class CombineLatestSink : Sink, ICombineLatest + { + protected readonly object _gate; + + private bool _hasValueAll; + private readonly bool[] _hasValue; + private readonly bool[] _isDone; + + public CombineLatestSink(int arity, IObserver observer) + : base(observer) + { + _gate = new object(); + + _hasValue = new bool[arity]; + _isDone = new bool[arity]; + } + + public void Next(int index) + { + if (!_hasValueAll) + { + _hasValue[index] = true; + + var hasValueAll = true; + foreach (var hasValue in _hasValue) + { + if (!hasValue) + { + hasValueAll = false; + break; + } + } + + _hasValueAll = hasValueAll; + } + + if (_hasValueAll) + { + var res = default(TResult); + try + { + res = GetResult(); + } + catch (Exception ex) + { + base._observer.OnError(ex); + return; + } + + base._observer.OnNext(res); + } + else + { + var allOthersDone = true; + for (int i = 0; i < _isDone.Length; i++) + { + if (i != index && !_isDone[i]) + { + allOthersDone = false; + break; + } + } + + if (allOthersDone) + { + base._observer.OnCompleted(); + } + } + } + + protected abstract TResult GetResult(); + + public void Fail(Exception error) + { + base._observer.OnError(error); + + } + + public void Done(int index) + { + _isDone[index] = true; + + var allDone = true; + foreach (var isDone in _isDone) + { + if (!isDone) + { + allDone = false; + break; + } + } + + if (allDone) + { + base._observer.OnCompleted(); + } + } + } + + class CombineLatestObserver : IObserver + { + private readonly object _gate; + private readonly ICombineLatest _parent; + private readonly int _index; + private T _value; + + public CombineLatestObserver(object gate, ICombineLatest parent, int index) + { + _gate = gate; + _parent = parent; + _index = index; + } + + public T Value + { + get { return _value; } + } + + public void OnNext(T value) + { + lock (_gate) + { + _value = value; + _parent.Next(_index); + } + } + + public void OnError(Exception error) + { + lock (_gate) + { + _parent.Fail(error); + } + } + + public void OnCompleted() + { + lock (_gate) + { + _parent.Done(_index); + } + } + } + + class CombineLatest : Producer + { + private readonly IEnumerable> _sources; + private readonly Func, TResult> _resultSelector; + + public CombineLatest(IEnumerable> sources, Func, TResult> resultSelector) + { + _sources = sources; + _resultSelector = resultSelector; + } + + protected override IDisposable Run(IObserver observer) + { + var sink = new _(this, observer); + return sink.Run(); + } + + class _ : Sink + { + private readonly CombineLatest _parent; + + public _(CombineLatest parent, IObserver observer) + : base(observer) + { + _parent = parent; + } + + private object _gate; + private bool[] _hasValue; + private bool _hasValueAll; + private List _values; + private bool[] _isDone; + + public IDisposable Run() + { + var srcs = _parent._sources.ToArray(); + + var N = srcs.Length; + + _hasValue = new bool[N]; + _hasValueAll = false; + + _values = new List(N); + for (int i = 0; i < N; i++) + _values.Add(default(TSource)); + + _isDone = new bool[N]; + + _gate = new object(); + + for (int i = 0; i < N; i++) + { + var j = i; + + var o = new O(this, j); + srcs[j].Subscribe(o); + } + + return null; + } + + private void OnNext(int index, TSource value) + { + lock (_gate) + { + _values[index] = value; + + _hasValue[index] = true; + + if (_hasValueAll || (_hasValueAll = _hasValue.All(__ => __))) + { + var res = default(TResult); + try + { + res = _parent._resultSelector(new ReadOnlyCollection(_values)); + } + catch (Exception ex) + { + base._observer.OnError(ex); + return; + } + + _observer.OnNext(res); + } + else if (_isDone.Where((x, i) => i != index).All(__ => __)) + { + base._observer.OnCompleted(); + return; + } + } + } + + private void OnError(Exception error) + { + lock (_gate) + { + base._observer.OnError(error); + } + } + + private void OnCompleted(int index) + { + lock (_gate) + { + _isDone[index] = true; + + if (_isDone.All(__ => __)) + { + base._observer.OnCompleted(); + return; + } + else + { + + } + } + } + + class O : IObserver + { + private readonly _ _parent; + private readonly int _index; + + public O(_ parent, int index) + { + _parent = parent; + _index = index; + } + + public void OnNext(TSource value) + { + _parent.OnNext(_index, value); + } + + public void OnError(Exception error) + { + _parent.OnError(error); + } + + public void OnCompleted() + { + _parent.OnCompleted(_index); + } + } + } + } + + internal abstract class Sink + { + protected internal volatile IObserver _observer; + + public Sink(IObserver observer) + { + _observer = observer; + } + + class _ : IObserver + { + private readonly Sink _forward; + + public _(Sink forward) + { + _forward = forward; + } + + public void OnNext(TSource value) + { + _forward._observer.OnNext(value); + } + + public void OnError(Exception error) + { + _forward._observer.OnError(error); + } + + public void OnCompleted() + { + _forward._observer.OnCompleted(); + } + } + } + + abstract class Producer : IObservable + { + public IDisposable Subscribe(IObserver observer) + { + this.Run(observer); + + return null; + } + + protected abstract IDisposable Run(IObserver observer); + } + + sealed class AnonymousObserver : IObserver + { + public void OnNext(bool value) + { + } + + public void OnError(Exception error) + { + } + + public void OnCompleted() + { + } + } + } +} diff --git a/tests/monotouch-test/mono/bug26989.cs b/tests/monotouch-test/mono/bug26989.cs new file mode 100644 index 000000000000..a19a114521cd --- /dev/null +++ b/tests/monotouch-test/mono/bug26989.cs @@ -0,0 +1,72 @@ +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +namespace MonoTouchFixtures { + [TestFixture] + [Preserve (AllMembers = true)] + public partial class MonoRuntimeTests { + static string cookie; + + [Test] + public void Bug26989 () + { + strlen ("abc"); + Assert.AreEqual ("ChocolateCookie", cookie); + } + + [DllImport (Constants.libcLibrary)] + static extern int strlen ([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8StringMarshaler), MarshalCookie = "ChocolateCookie")] string str); + + [Preserve(AllMembers = true)] + class UTF8StringMarshaler : ICustomMarshaler + { + static UTF8StringMarshaler singleton; + + IntPtr ICustomMarshaler.MarshalManagedToNative (object managedObject) + { + return Marshal.StringToHGlobalAuto ((string) managedObject); + } + + object ICustomMarshaler.MarshalNativeToManaged (IntPtr nativeDataPtr) + { + if (nativeDataPtr == IntPtr.Zero) + return null; + + return Marshal.PtrToStringAuto (nativeDataPtr); + } + + void ICustomMarshaler.CleanUpNativeData (IntPtr nativeDataPtr) + { + Marshal.FreeHGlobal (nativeDataPtr); + } + + void ICustomMarshaler.CleanUpManagedData (object managedObject) + { + } + + int ICustomMarshaler.GetNativeDataSize() + { + throw new NotImplementedException(); + } + + public static ICustomMarshaler GetInstance(string cookie) + { + MonoRuntimeTests.cookie = cookie; + if (singleton == null) + return singleton = new UTF8StringMarshaler(); + return singleton; + } + } + } +} + diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj new file mode 100644 index 000000000000..e34e11e0ef0b --- /dev/null +++ b/tests/monotouch-test/monotouch-test.csproj @@ -0,0 +1,645 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {AC6D070F-2ED4-4701-B701-81915B931D1D} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + monotouchtest + monotouchtest + True + ..\..\..\xamarin-macios\product.snk + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG; + prompt + 0 + False + True + -v -v -v -v + True + i386 + Entitlements.plist + iPhone Developer + None + + + none + False + bin\iPhoneSimulator\Release + MONOTOUCH; + prompt + 4 + False + None + -v -v -v -v + True + i386 + + + Entitlements.plist + + + True + full + False + bin\iPhone\Debug + DEBUG; + prompt + 0 + False + True + iPhone Developer + -v -v -v -v + ARMv7 + True + + + + + none + False + bin\iPhone\Release + MONOTOUCH; + prompt + 4 + False + iPhone Developer + -v -v -v -v --nosymbolstrip + ARMv7 + + + True + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + System.Drawing\TestPoint.cs + + + System.Drawing\TestPointF.cs + + + System.Drawing\TestRectangle.cs + + + System.Drawing\TestRectangleF.cs + + + System.Drawing\TestSize.cs + + + System.Drawing\TestSizeF.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + shared\ObjCRuntime\RegistrarTest.cs + + + + + + + CoreFoundation\CFNotificationCenterTest.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {676F527D-3352-42EA-9DE2-181C45003568} + EmbeddedResources + + + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA} + bindings-test + + + {C7212169-BA46-413B-91CD-A32C52AD5E0D} + fsharplibrary + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/monotouch-test/xamvideotest.mp4 b/tests/monotouch-test/xamvideotest.mp4 new file mode 100644 index 000000000000..ce6a6378f25c Binary files /dev/null and b/tests/monotouch-test/xamvideotest.mp4 differ diff --git a/tests/msbuild-mac/CustomBuildActions.targets b/tests/msbuild-mac/CustomBuildActions.targets new file mode 100644 index 000000000000..cf10050b28c3 --- /dev/null +++ b/tests/msbuild-mac/CustomBuildActions.targets @@ -0,0 +1,11 @@ + + + + + $(CreateAppBundleDependsOn);CreateNativeLibs + + + + + + diff --git a/tests/msbuild-mac/Info.plist b/tests/msbuild-mac/Info.plist new file mode 100644 index 000000000000..4689b4537d2a --- /dev/null +++ b/tests/msbuild-mac/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleName + msbuild-mac + CFBundleIdentifier + com.hamons.msbuild-mac + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.11 + CFBundleDevelopmentRegion + en + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + NSHumanReadableCopyright + donblas + NSPrincipalClass + NSApplication + + diff --git a/tests/msbuild-mac/msbuild-mac.csproj b/tests/msbuild-mac/msbuild-mac.csproj new file mode 100644 index 000000000000..3cbb065e9b85 --- /dev/null +++ b/tests/msbuild-mac/msbuild-mac.csproj @@ -0,0 +1,86 @@ + + + + Debug + x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + msbuildMac + msbuild-mac + v2.0 + Xamarin.Mac + Resources + + + true + full + false + bin\x86\Debug + __UNIFIED__;DEBUG;XAMCORE_2_0;MONOMAC;MMP_TEST + prompt + 4 + false + false + Mac Developer + false + false + false + true + true + true + x86 + + + true + bin\x86\Release + __UNIFIED__;XAMCORE_2_0;MONOMAC;MMP_TEST + prompt + 4 + false + true + Developer ID Application + true + false + true + true + true + SdkOnly + x86 + + + + + + + + ..\..\..\xamarin-macios\external\guiunit\bin\net_4_5\GuiUnit.exe + + + + + + + + + + + + MacTestMain.cs + + + ProjectTestHelpers.cs + + + Configuration.cs + + + ErrorHelper.cs + + + RuntimeException.cs + + + + + diff --git a/tests/msbuild-mac/src/MSBuild-Smoke.cs b/tests/msbuild-mac/src/MSBuild-Smoke.cs new file mode 100644 index 000000000000..ca3d38686a48 --- /dev/null +++ b/tests/msbuild-mac/src/MSBuild-Smoke.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using NUnit.Framework; + +namespace Xamarin.MMP.Tests +{ + [TestFixture] + public class MMPTests + { + void RunMSBuildTest (Action test) + { + string tmpDir = Path.Combine (Path.GetTempPath (), "msbuild-tests"); + try { + Directory.CreateDirectory (tmpDir); + test (tmpDir); + } + finally { + Directory.Delete (tmpDir, true); + } + } + + [Test] + public void BuildUnifiedMobile_Program_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedExample.csproj" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildUnifiedXM45_Program_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = "XM45Example.csproj" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + void TestBCLCore (string tmpDir, string projectName) + { + File.Copy (Path.Combine (TI.AssemblyDirectory, TI.TestDirectory + "common/mac/System.Collections.Immutable.dll"), Path.Combine (tmpDir, "System.Collections.Immutable.dll")); + string reference = "System.Collections.Immutable.dll"; + string testCode = "var v = System.Collections.Immutable.ImmutableArray.CreateRange (new int [] { 42 });"; + string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = projectName, References = reference, TestCode = testCode }); + TI.BuildProject (projectPath, isUnified : true); + } + + [Test] + public void BuildUnifiedMobile_Program_WithBCL () + { + RunMSBuildTest (tmpDir => { + TestBCLCore (tmpDir, "UnifiedExample.csproj"); + }); + } + + [Test] + public void BuildUnifiedXM45_Program_WithBCL () + { + RunMSBuildTest (tmpDir => { + TestBCLCore (tmpDir, "XM45Example.csproj"); + }); + } + + [Test] + public void BuildFSharpUnifiedMobile_Program_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { FSharp = true, ProjectName = "FSharpUnifiedExample.fsproj" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildFSharpUnifiedXM45_Program_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { FSharp = true, ProjectName = "FSharpXM45Example.fsproj" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildUnifiedMobile_Library_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateUnifiedLibraryProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedLibrary" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildUnifiedXM45_Library_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateUnifiedLibraryProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = "XM45Library" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildFSharpUnifiedMobile_Library_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateUnifiedLibraryProject (new TI.UnifiedTestConfig (tmpDir) { FSharp = true, ProjectName = "FSharpUnifiedLibrary" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildFSharpUnifiedXM45_Library_SmokeTest () + { + RunMSBuildTest (tmpDir => { + string projectPath = TI.GenerateUnifiedLibraryProject (new TI.UnifiedTestConfig (tmpDir) { FSharp = true, ProjectName = "FSharpXM45Library" }); + TI.BuildProject (projectPath, isUnified : true); + }); + } + + [Test] + public void BuildUnifiedProject_WithJustNativeRefNoLinkWith_Builds() + { + RunMSBuildTest (tmpDir => { + string dylibPath = Path.Combine (tmpDir, "dll/"); + Directory.CreateDirectory (dylibPath); + File.Copy (Path.Combine (TI.AssemblyDirectory, TI.TestDirectory + "mac-binding-project/bin/SimpleClassDylib.dylib"), Path.Combine (dylibPath, "SimpleClassDylib.dylib")); + string itemGroup = " FalseDynamic "; + string projectPath = TI.GenerateEXEProject (new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedExample.csproj", ItemGroup = itemGroup }); + string buildResults = TI.BuildProject (projectPath, isUnified : true); + Assert.IsFalse (buildResults.Contains ("MM2006"), "BuildUnifiedProject_WittJustNativeRefNoLinkWith_Builds found 2006 warning: " + buildResults); + Assert.IsTrue (File.Exists (Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MonoBundle/SimpleClassDylib.dylib"))); + + StringBuilder output = new StringBuilder (); + Xamarin.Bundler.Driver.RunCommand ("/usr/bin/otool", "-L " + Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MacOS/UnifiedExample"), null, output); + Assert.IsTrue (output.ToString ().Contains ("SimpleClassDylib.dylib")); + }); + } + + [Test] + public void Build_BindingLibrary_SmokeTest () + { + RunMSBuildTest (tmpDir => { + foreach (string projectName in new []{"XM45Binding.csproj", "MobileBinding.csproj", "BindingProjectWithNoTag.csproj"}) { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { ProjectName = projectName }; + string projectPath = TI.GenerateBindingLibraryProject (test); + TI.BuildProject (projectPath, isUnified : true); + } + }); + } + } +} diff --git a/tests/mtouch/.gitignore b/tests/mtouch/.gitignore new file mode 100644 index 000000000000..d71152c75690 --- /dev/null +++ b/tests/mtouch/.gitignore @@ -0,0 +1,5 @@ +test-results +TestResult.xml +index.html +.failed-stamp +test.config diff --git a/tests/mtouch/MTouch.cs b/tests/mtouch/MTouch.cs new file mode 100644 index 000000000000..a8664c18ea6c --- /dev/null +++ b/tests/mtouch/MTouch.cs @@ -0,0 +1,2447 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; + +using MTouchTests; +using Xamarin.Tests; + +using NUnit.Framework; + +namespace Xamarin.Tests { + static class TestTarget { + public static string ToolPath { + get { + return Path.Combine (Configuration.SdkBinDir, "mtouch"); + } + } + } +} + +namespace MTouchTests +{ + [TestFixture] + public class MTouch + { + [Test] + [TestCase ("single", "-sdkroot {2} -v -v -v -v --dev {0} -sdk {3} --targetver 6.0 {1} -r:{4} --cache={5}/cache")] + [TestCase ("dual", "-sdkroot {2} -v -v -v -v --dev {0} -sdk {3} --targetver 6.0 {1} -r:{4} --cache={5}/cache --abi=armv7,arm64")] + [TestCase ("llvm", "-sdkroot {2} -v -v -v -v --dev {0} -sdk {3} --targetver 6.0 {1} -r:{4} --cache={5}/cache --abi=armv7+llvm")] + [TestCase ("debug", "-sdkroot {2} -v -v -v -v --dev {0} -sdk {3} --targetver 6.0 {1} -r:{4} --cache={5}/cache --debug")] + public void RebuildTest (string name, string format) + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + DateTime dt = DateTime.MinValue; + + Action> checkNotModified = (filename, skip) => { + var failed = new List (); + var files = Directory.EnumerateFiles (app, "*", SearchOption.AllDirectories); + foreach (var file in files) { + if (skip != null && skip.Contains (Path.GetFileName (file))) + continue; + var info = new FileInfo (file); + if (info.LastWriteTime > dt) { + failed.Add (string.Format ("{0} is modified, timestamp: {1}", file, info.LastWriteTime)); + } else { + Console.WriteLine ("{0} not modified", file); + } + } + Assert.IsTrue (failed.Count == 0, filename + "\n" + string.Join ("\n", failed.ToArray ())); + }; + + Directory.CreateDirectory (app); + try { + var exe = CompileUnifiedTestAppExecutable (testDir); + var args = string.Format (format, app, exe, Configuration.xcode_root, Configuration.sdk_version, Configuration.XamarinIOSDll, testDir); + ExecutionHelper.Execute (TestTarget.ToolPath, args); + dt = DateTime.Now; + System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. + ExecutionHelper.Execute (TestTarget.ToolPath, args); + + checkNotModified (name, null); + + // Test that a rebuild (where something changed, in this case the .exe) + // actually work. We compile with custom code to make sure it's different + // from the previous exe we built. + var subDir = Path.Combine (testDir, "other"); + Directory.CreateDirectory (subDir); + var exe2 = CompileUnifiedTestAppExecutable (subDir, + /* the code here only changes the class name (default: 'TestApp' changed to 'TestApp2') to minimize the related + * changes (there should be no changes in Xamarin.iOS.dll nor mscorlib.dll, even after linking) */ + code: "public class TestApp2 { static void Main () { System.Console.WriteLine (typeof (ObjCRuntime.Runtime).ToString ()); } }"); + File.Copy (exe2, exe, true); + ExecutionHelper.Execute (TestTarget.ToolPath, args); + + var skip = new string [] { "testApp", "testApp.exe", "testApp.armv7.aotdata", "testApp.arm64.aotdata" }; + checkNotModified (name + "-rebuilt", skip); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void RebuildTest_Intl () + { + using (var tool = new MTouchTool ()) { + tool.Profile = Profile.Unified; + tool.I18N = I18N.West; + tool.Verbosity = 5; + tool.Cache = Path.Combine (tool.CreateTemporaryDirectory (), "mtouch-test-cache"); + tool.CreateTemporaryApp (); + + Assert.AreEqual (0, tool.Execute (MTouchAction.BuildSim)); + + var pre_files = Directory.EnumerateFiles (tool.AppPath, "*", SearchOption.AllDirectories).ToArray (); + + Directory.Delete (tool.AppPath, true); + Directory.CreateDirectory (tool.AppPath); + + Assert.AreEqual (0, tool.Execute (MTouchAction.BuildSim)); + + var post_files = Directory.EnumerateFiles (tool.AppPath, "*", SearchOption.AllDirectories).ToArray (); + + Assert.That (post_files, Is.EquivalentTo (pre_files), "files"); + } + } + + public enum Target { Sim, Dev } + public enum Config { Debug, Release } + public enum PackageMdb { Default, WithMdb, WoutMdb } + public enum MSym { Default, WithMSym, WoutMSym } + public enum Profile { Classic, Unified, TVOS, WatchOS } + + [Test] + // Simulator + [TestCase (Target.Sim, Config.Release, PackageMdb.Default, MSym.Default, false, false, "")] + [TestCase (Target.Sim, Config.Debug, PackageMdb.Default, MSym.Default, true, false, "")] + [TestCase (Target.Sim, Config.Debug, PackageMdb.WoutMdb, MSym.Default, false, false, "")] + [TestCase (Target.Sim, Config.Release, PackageMdb.WithMdb, MSym.Default, true, false, "")] + [TestCase (Target.Sim, Config.Debug, PackageMdb.WoutMdb, MSym.Default, false, false, "--nofastsim --nolink")] + // Device + [TestCase (Target.Dev, Config.Release, PackageMdb.WithMdb, MSym.Default, true, false, "")] + [TestCase (Target.Dev, Config.Release, PackageMdb.WithMdb, MSym.WoutMSym, true, false, "")] + [TestCase (Target.Dev, Config.Release, PackageMdb.Default, MSym.Default, false, false, "--abi:armv7,arm64")] + [TestCase (Target.Dev, Config.Debug, PackageMdb.WoutMdb, MSym.Default, false, false, "")] + [TestCase (Target.Dev, Config.Debug, PackageMdb.WoutMdb, MSym.WithMSym, false, true, "")] + [TestCase (Target.Dev, Config.Release, PackageMdb.WithMdb, MSym.Default, true, false, "--abi:armv7+llvm")] + public void SymbolicationData (Target target, Config configuration, PackageMdb package_mdb, MSym msym, bool has_mdb, bool has_msym, string extra_mtouch_args) + { + var testDir = GetTempDirectory (); + var appDir = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (appDir); + + try { + var is_sim = target == Target.Sim; + var exe = CompileUnifiedTestAppExecutable (testDir); + var msymDir = appDir + ".msym"; + var args = extra_mtouch_args; + + args += is_sim ? " --sim {0} " : " --dev {0} "; + + if (configuration == Config.Debug) + args += "--debug "; + + if (package_mdb == PackageMdb.WithMdb) + args += "--package-mdb:true "; + else if (package_mdb == PackageMdb.WoutMdb) + args += "--package-mdb:false "; + + if (msym == MSym.WithMSym) + args += "--msym:true "; + else if (msym == MSym.WoutMSym) + args += "--msym:false "; + + args += " --sdkroot {2} -v -v -v -sdk {3} {1} -r:{4}"; + + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format (args, appDir, exe, Configuration.xcode_root, Configuration.sdk_version, Configuration.XamarinIOSDll)); + + if (is_sim) { + Assert.AreEqual (has_mdb, File.Exists (Path.Combine (appDir, "mscorlib.dll.mdb")), "#mdb"); + } else { + Assert.AreEqual (has_mdb, File.Exists (Path.Combine (appDir, ".monotouch-32", "mscorlib.dll.mdb")), "#mdb"); + } + if (is_sim) { + Assert.AreEqual (has_msym, File.Exists (Path.Combine (msymDir, "mscorlib.dll.msym")), "#msym"); + } else { + Assert.AreEqual (has_msym, File.Exists (Path.Combine (msymDir, "32", "mscorlib.dll.msym")), "#msym"); + } + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void ExecutableName () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --executable=CustomExecutable -v -v -v --nosign --nofastsim --nolink --sim {0} -sdk " + Configuration.sdk_version + " {1} -debug --fastdev", app, exe)); + Assert.That (File.Exists (Path.Combine (app, "CustomExecutable")), "1"); + Assert.That (!File.Exists (Path.Combine (app, "testApp")), "2"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0015 () + { + Asserts.Throws (() => + ExecutionHelper.Execute (TestTarget.ToolPath, "--abi invalid-arm"), + "error MT0015: Invalid ABI: invalid-arm. Supported ABIs are: i386, x86_64, armv7, armv7+llvm, armv7+llvm+thumb2, armv7s, armv7s+llvm, armv7s+llvm+thumb2, armv7k, arm64 and arm64+llvm.\n"); + } + + [Test] + public void MT0016 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + var deprecated_list = new string [] { + "-d={0}", "--dir={0}", "--cp", "--crossprefix", "--libdir", "-n", "--keeptemp", + "--main", "--nomanifest", "--mapinject", "--nosign", "--displayname", "--bundleid", + "--mainnib", "--icon", "-c", "--certificate", "--enable-background-fetch", + "--llvm", "--thumb", "--armv7", "--noregistrar", "--unsupported--enable-generics-in-registrar" + }; + + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.Unified); + var args = string.Format (string.Join (" ", deprecated_list), app); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--sdkroot {5} --dev {0} {1} -r:{2} {3} --sdk {4}", app, exe, Configuration.XamarinIOSDll, args, Configuration.sdk_version, Configuration.xcode_root), hide_output: false), + "Xamarin.iOS .* using framework:.*\n" + + "error MT0016: The option '--dir' has been deprecated.\n" + + "error MT0016: The option '--dir' has been deprecated.\n" + + "error MT0016: The option '--crossprefix' has been deprecated.\n" + + "error MT0016: The option '--libdir' has been deprecated.\n" + + "error MT0016: The option '-n' has been deprecated.\n" + + "error MT0016: The option '--keeptemp' has been deprecated.\n" + + "error MT0016: The option '--main' has been deprecated.\n" + + "error MT0016: The option '--mapinject' has been deprecated.\n" + + "error MT0016: The option '--nosign' has been deprecated.\n" + + "error MT0016: The option '--displayname' has been deprecated.\n" + + "error MT0016: The option '--mainnib' has been deprecated.\n" + + "error MT0016: The option '--certificate' has been deprecated.\n" + + "error MT0016: The option '--enable-background-fetch' has been deprecated.\n" + + "error MT0016: The option '--llvm' has been deprecated.\n" + + "error MT0016: The option '--thumb' has been deprecated.\n" + + "error MT0016: The option '--armv7' has been deprecated.\n" + + "error MT0016: The option '--noregistrar' has been deprecated.\n" + + "error MT0016: The option '--unsupported--enable-generics-in-registrar' has been deprecated.\n"); + + + exe = CompileTestAppExecutable (testDir); + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--sdkroot {5} --dev {0} {1} -r:{2} {3} --sdk {4}", app, exe, Configuration.MonoTouchDll, args, Configuration.sdk_version, Configuration.xcode_root), hide_output: false), + "Xamarin.iOS .* using framework:.*\n" + + "warning MT0016: The option '--dir' has been deprecated.\n" + + "warning MT0016: The option '--dir' has been deprecated.\n" + + "warning MT0016: The option '--crossprefix' has been deprecated.\n" + + "warning MT0016: The option '--libdir' has been deprecated.\n" + + "warning MT0016: The option '-n' has been deprecated.\n" + + "warning MT0016: The option '--keeptemp' has been deprecated.\n" + + "warning MT0016: The option '--main' has been deprecated.\n" + + "warning MT0016: The option '--mapinject' has been deprecated.\n" + + "warning MT0016: The option '--displayname' has been deprecated.\n" + + "warning MT0016: The option '--mainnib' has been deprecated.\n" + + "warning MT0016: The option '--certificate' has been deprecated.\n" + + "warning MT0016: The option '--enable-background-fetch' has been deprecated.\n" + + "warning MT0016: The option '--llvm' has been deprecated.\n" + + "warning MT0016: The option '--thumb' has been deprecated.\n" + + "warning MT0016: The option '--armv7' has been deprecated.\n" + + "warning MT0016: The option '--noregistrar' has been deprecated.\n" + + "warning MT0016: The option '--unsupported--enable-generics-in-registrar' has been deprecated.\n" + + "error MT0022: The options '--unsupported--enable-generics-in-registrar' and '--registrar' are not compatible.\n" + ); + + + } finally { + Directory.Delete (testDir, true); + } + + } + + [Test] + [TestCase (Profile.Classic, Profile.Unified)] + [TestCase (Profile.Classic, Profile.TVOS)] + [TestCase (Profile.Classic, Profile.WatchOS)] + [TestCase (Profile.Unified, Profile.Classic)] + [TestCase (Profile.Unified, Profile.TVOS)] + [TestCase (Profile.Unified, Profile.WatchOS)] + [TestCase (Profile.TVOS, Profile.Classic)] + [TestCase (Profile.TVOS, Profile.Unified)] + [TestCase (Profile.TVOS, Profile.WatchOS)] + [TestCase (Profile.WatchOS, Profile.Classic)] + [TestCase (Profile.WatchOS, Profile.Unified)] + [TestCase (Profile.WatchOS, Profile.TVOS)] + public void MT0041 (Profile profile, Profile other) + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = profile; + mtouch.CreateTemporaryApp (); + mtouch.References = new string [] { + GetBaseLibrary (profile), + GetBaseLibrary (other), + }; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError (41, string.Format ("Cannot reference '{0}' in a {1} app.", Path.GetFileName (GetBaseLibrary (other)), GetPlatformName (profile))); + } + } + + [Test] + public void MT0042 () + { + using (var mtouch = new MTouchTool ()) { + mtouch.CreateTemporaryApp (); + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError (42, "No reference to either monotouch.dll or Xamarin.iOS.dll was found. A reference to monotouch.dll will be added."); + } + } + + [Test] + public void MT0073 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.Unified); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --targetver 3.1 --abi=armv7s,arm64 {1} -debug -r:" + Configuration.XamarinIOSDll, app, exe)), + "Xamarin.iOS .* using framework:.*\nerror MT0073: Xamarin.iOS .* does not support a deployment target of 3.1 .the minimum is 5.1.1.. Please select a newer deployment target in your project's Info.plist.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --targetver 3.1 --abi=armv7s {1} -debug -r:" + Configuration.XamarinIOSDll, app, exe)), + "Xamarin.iOS .* using framework:.*\nerror MT0073: Xamarin.iOS .* does not support a deployment target of 3.1 .the minimum is 5.1.1.. Please select a newer deployment target in your project's Info.plist.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --targetver 5.1 --abi=arm64 {1} -debug -r:" + Configuration.XamarinIOSDll, app, exe)), + "Xamarin.iOS .* using framework:.*\nerror MT0073: Xamarin.iOS .* does not support a deployment target of 5.1 .the minimum is 5.1.1.. Please select a newer deployment target in your project's Info.plist.\n"); + + // No exception here. + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --targetver 5.1.1 --abi=arm64 {1} -debug -r:" + Configuration.XamarinIOSDll, app, exe)); + + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0074 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.Unified); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --targetver 400.0.0 --abi=armv7s,arm64 {1} -debug -r:" + Configuration.XamarinIOSDll, app, exe)), + string.Format ("Xamarin.iOS .* using framework:.*\nerror MT0074: Xamarin.iOS .* does not support a deployment target of 400.0.0 .the maximum is " + Configuration.sdk_version + ".. Please select an older deployment target in your project's Info.plist or upgrade to a newer version of Xamarin.iOS.\n", Configuration.sdk_version)); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0048 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.Unified); + + Asserts.ThrowsPattern (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --targetver 5.1.1 --abi=armv7s {1} -debug -r:{2} --crashreporting-api-key APIKEY", app, exe, Configuration.XamarinIOSDll), hide_output: false), + "error MT0016: The option '--crashreporting-api-key' has been deprecated."); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic, Profile.Unified)] + [TestCase (Profile.Classic, Profile.TVOS)] + [TestCase (Profile.Classic, Profile.WatchOS)] + [TestCase (Profile.Unified, Profile.Classic)] + [TestCase (Profile.Unified, Profile.TVOS)] + [TestCase (Profile.Unified, Profile.WatchOS)] + [TestCase (Profile.TVOS, Profile.Classic)] + [TestCase (Profile.TVOS, Profile.Unified)] + [TestCase (Profile.TVOS, Profile.WatchOS)] + [TestCase (Profile.WatchOS, Profile.Classic)] + [TestCase (Profile.WatchOS, Profile.Unified)] + [TestCase (Profile.WatchOS, Profile.TVOS)] + public void MT0034 (Profile exe_profile, Profile dll_profile) + { + using (var mtouch = new MTouchTool ()) { + var app = mtouch.CreateTemporaryAppDirectory (); + var testDir = Path.GetDirectoryName (app); + + string exe = Path.Combine (testDir, "testApp.exe"); + string dll = Path.Combine (testDir, "testLib.dll"); + + var dllCode = @"public class TestLib { + public TestLib () + { + System.Console.WriteLine (typeof (%PROFILE_NAMESPACE%Foundation.NSObject).ToString ()); + } +}"; + + var exeCode = @"public class TestApp { + static void Main () + { + System.Console.WriteLine (typeof (%PROFILE_NAMESPACE%Foundation.NSObject).ToString ()); + System.Console.WriteLine (new TestLib ()); + } +}"; + + CompileCSharpCode (dll_profile, dllCode, dll); + CompileCSharpCode (exe_profile, exeCode, exe, "-r:" + dll); + + mtouch.Profile = exe_profile; + mtouch.Executable = exe; + mtouch.References = new string [] { GetBaseLibrary (exe_profile) }; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildSim), "build"); + var dllBase = Path.GetFileName (GetBaseLibrary (dll_profile)); + mtouch.AssertError (34, string.Format ("Cannot reference '{0}' in a {1} project - it is implicitly referenced by 'testLib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.", dllBase, GetPlatformName (exe_profile))); + } + } + + [Test] + public void MT0037 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --dev {0} -sdk " + Configuration.sdk_version + " --targetver 3.1 --abi=arm64 {1} -debug -r:{2}", app, exe, Configuration.MonoTouchDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0037: monotouch.dll is not 64-bit compatible. Either reference Xamarin.iOS.dll, or do not build for a 64-bit architecture [(]ARM64 or x86_64[)].\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --dev {0} -sdk " + Configuration.sdk_version + " --targetver 3.1 --abi=x86_64 {1} -debug -r:{2}", app, exe, Configuration.MonoTouchDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0037: monotouch.dll is not 64-bit compatible. Either reference Xamarin.iOS.dll, or do not build for a 64-bit architecture [(]ARM64 or x86_64[)].\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0038 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.Unified); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --dev {0} -sdk " + Configuration.sdk_version + " --registrar:oldstatic --targetver 5.1.1 --abi=arm64 {1} -debug -r:{2} ", app, exe, Configuration.XamarinIOSDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0038: The legacy registrars [(]--registrar:legacy|legacystatic|legacydynamic[)] are not supported with the Unified API.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --sim {0} -sdk " + Configuration.sdk_version + " --registrar:olddynamic --targetver 5.1.1 --abi=x86_64 {1} -debug -r:{2}", app, exe, Configuration.XamarinIOSDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0038: The legacy registrars [(]--registrar:legacy|legacystatic|legacydynamic[)] are not supported with the Unified API.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --sim {0} -sdk " + Configuration.sdk_version + " --registrar:legacy --targetver 5.1.1 --abi=x86_64 {1} -debug -r:{2}", app, exe, Configuration.XamarinIOSDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0038: The legacy registrars [(]--registrar:legacy|legacystatic|legacydynamic[)] are not supported with the Unified API.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --sim {0} -sdk " + Configuration.sdk_version + " --registrar:legacystatic --targetver 5.1.1 --abi=x86_64 {1} -debug -r:{2}", app, exe, Configuration.XamarinIOSDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0038: The legacy registrars [(]--registrar:legacy|legacystatic|legacydynamic[)] are not supported with the Unified API.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --sim {0} -sdk " + Configuration.sdk_version + " --registrar:legacydynamic --targetver 5.1.1 --abi=x86_64 {1} -debug -r:{2}", app, exe, Configuration.XamarinIOSDll)), + "Xamarin.iOS .* using framework:.*\nerror MT0038: The legacy registrars [(]--registrar:legacy|legacystatic|legacydynamic[)] are not supported with the Unified API.\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0051 () + { + if (Directory.Exists ("/Applications/Xcode44.app/Contents/Developer")) { + Asserts.ThrowsPattern (() => { + ExecutionHelper.Execute (TestTarget.ToolPath, "-sdkroot /Applications/Xcode44.app/Contents/Developer -sim /tmp/foo"); + }, "error MT0051: Xamarin.iOS .* requires Xcode 6.0 or later. The current Xcode version [(]found in /Applications/Xcode44.app/Contents/Developer[)] is 4.*"); + } + + if (Directory.Exists (Configuration.xcode5_root)) { + Asserts.ThrowsPattern (() => { + ExecutionHelper.Execute (TestTarget.ToolPath, "-sdkroot /Applications/Xcode511.app/Contents/Developer -sim /tmp/foo"); + }, "error MT0051: Xamarin.iOS .* requires Xcode 6.0 or later. The current Xcode version [(]found in " + Configuration.xcode5_root + "[)] is 5.1.1"); + } + } + + [Test] + public void MT0055 () + { + Asserts.ThrowsPattern (() => { + ExecutionHelper.Execute (TestTarget.ToolPath, "--sdkroot /dir/that/does/not/exist"); + }, "error MT0055: The Xcode path '/dir/that/does/not/exist' does not exist."); + } + + [Test] + public void MT0060 () + { + var msg = string.Empty; + if (!Directory.Exists ("/Applications/Xcode.app")) { + msg = "warning MT0060: Could not find the currently selected Xcode on the system. 'xcode-select --print-path' returned '/dir/that/does/not/exist', but that directory does not exist.\n" + + "error MT0056: Cannot find Xcode in the default location ./Applications/Xcode.app.. Please install Xcode, or pass a custom path using --sdkroot .\n"; + } else { + msg = "warning MT0060: Could not find the currently selected Xcode on the system. 'xcode-select --print-path' returned '/dir/that/does/not/exist', but that directory does not exist.\n" + + "warning MT0062: No Xcode.app specified .using --sdkroot or 'xcode-select --print-path'., using the default Xcode instead: /Applications/Xcode.app\n" + + "Xamarin.iOS .* using framework: .*\n" + + "error MT0052: No command specified."; + } + + Asserts.ThrowsPattern (() => { + var envvars = new Dictionary + { + { "DEVELOPER_DIR", "/dir/that/does/not/exist" } + }; + ExecutionHelper.Execute (TestTarget.ToolPath, "", environmentVariables: envvars); + }, msg); + } + + [Test] + public void MT0061 () + { + // The MT0070 warning depends on system configuration, so it's optional in the regexp + Asserts.ThrowsPattern (() => { + ExecutionHelper.Execute (TestTarget.ToolPath, ""); + }, "warning MT0061: No Xcode.app specified .using --sdkroot., using the system Xcode as reported by 'xcode-select --print-path': .*\n" + + "(warning MT0078: The recommended Xcode version for Xamarin.iOS [0-9.]* is Xcode [0-9.]* or later. The current Xcode version .found in .* is .*)?\\s?" + + "Xamarin.iOS .* using framework: .*\n" + + "error MT0052: No command specified."); + } + + public void MT0062 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileUnifiedTestAppExecutable (testDir); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --sim {0} -sdk {4} --targetver 7.1 --framework /foo/bar/zap.framework -r:{2} {1}", app, exe, Configuration.XamarinIOSDll, Configuration.xcode_root, Configuration.sdk_version), hide_output: false), + "Xamarin.iOS .* using framework:.*\nerror MT0062: Xamarin.iOS only supports embedded frameworks when deployment target is at least 8.0 .current deployment target: '7.1'; embedded frameworks: '/foo/bar/zap.framework'.\n"); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --sim {0} -sdk {4} --targetver 7.1 --mono:framework -r:{2} {1}", app, exe, Configuration.XamarinIOSDll, Configuration.xcode_root, Configuration.sdk_version), hide_output: false), + "Xamarin.iOS .* using framework:.*\nerror MT0062: Xamarin.iOS only supports embedded frameworks when deployment target is at least 8.0 .current deployment target: '7.1'; embedded frameworks: '.*/Mono.framework'.\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0064 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --nosign --sim {0} -sdk {4} --targetver {4} --framework /foo/bar/zap.framework -r:{2} {1}", app, exe, Configuration.MonoTouchDll, Configuration.xcode_root, Configuration.sdk_version), hide_output: false), + "Xamarin.iOS .* using framework:.*\nerror MT0064: Xamarin.iOS only supports embedded frameworks with Unified projects.\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0075 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --nosign --dev {0} -sdk {4} -r:{2} {1} --abi armv7k", app, exe, Configuration.MonoTouchDll, Configuration.xcode_root, Configuration.sdk_version), hide_output: false), + "Xamarin.iOS .* using framework:.*\n" + + "error MT0075: Invalid architecture 'ARMv7k' for iOS projects. Valid architectures are: ARMv7, ARMv7.Thumb, ARMv7.LLVM, ARMv7.LLVM.Thumb, ARMv7s, ARMv7s.Thumb, ARMv7s.LLVM, ARMv7s.LLVM.Thumb"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0076 () + { + if (!Configuration.include_watchos || !Configuration.include_tvos) + Assert.Ignore ("This test requires WatchOS and TVOS to be enabled."); + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.WatchOS); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --nosign --dev {0} -sdk {4} -r:{2} {1} --target-framework Xamarin.WatchOS,v1.0", app, exe, Configuration.XamarinWatchOSDll, Configuration.xcode_root, Configuration.watchos_sdk_version), hide_output: false), + "error MT0076: No architecture specified .using the --abi argument.. An architecture is required for Xamarin.WatchOS projects."); + + exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.TVOS); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --nosign --dev {0} -sdk {4} -r:{2} {1} --target-framework Xamarin.TVOS,v1.0", app, exe, Configuration.XamarinTVOSDll, Configuration.xcode_root, Configuration.tvos_sdk_version), hide_output: false), + "error MT0076: No architecture specified .using the --abi argument.. An architecture is required for Xamarin.TVOS projects."); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT0077 () + { + if (!Configuration.include_watchos) + Assert.Ignore ("This test requires WatchOS and TVOS to be enabled."); + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir, profile: MTouch.Profile.WatchOS); + + Asserts.ThrowsPattern (() => + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {3} --nosign --dev {0} -sdk {4} -r:{2} {1} --target-framework Xamarin.WatchOS,v1.0 --abi armv7k", app, exe, Configuration.XamarinWatchOSDll, Configuration.xcode_root, Configuration.watchos_sdk_version), hide_output: false), + "error MT0077: WatchOS projects must be extensions."); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] MT0077 interferring. + [TestCase (Profile.Unified)] + [TestCase (Profile.Classic)] + public void MT0085 (Profile profile) + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = profile; + mtouch.CreateTemporaryApp (); + mtouch.TargetFramework = GetTargetFramework (profile); + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError (85, string.Format ("No reference to '{0}' was found. It will be added automatically.", Path.GetFileName (GetBaseLibrary (profile)))); + } + } + + [Test] + [TestCase (Profile.TVOS)] + [TestCase (Profile.WatchOS)] + public void MT0086 (Profile profile) + { + using (var mtouch = new MTouchTool ()) { + mtouch.CreateTemporaryApp (); + mtouch.References = new string [] { GetBaseLibrary (profile) }; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError (86, "A target framework (--target-framework) must be specified when building for TVOS or WatchOS."); + } + } + + [Test] + [TestCase (Profile.TVOS, "tvOS")] + [TestCase (Profile.Unified, "iOS")] + [TestCase (Profile.Classic, "iOS")] + public void MT0091 (Profile profile, string name) + { + // Any old Xcode would do. + if (!Directory.Exists (Configuration.xcode72_root)) + Assert.Ignore ("This test needs Xcode 7.0"); + + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = profile; + mtouch.CreateTemporaryApp (); + mtouch.SdkRoot = Configuration.xcode72_root; + mtouch.Linker = MTouchLinker.DontLink; + mtouch.Sdk = "9.0"; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError (91, String.Format ("This version of Xamarin.iOS requires the {0} {1} SDK (shipped with Xcode {2}) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker.", name, GetSdkVersion (profile), Configuration.XcodeVersion)); + } + } + + [Test] + public void ExtensionBuild () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + File.WriteAllText (Path.Combine (app, "Info.plist"), @" + + + + CFBundleDisplayName + Extensiontest + CFBundleIdentifier + com.xamarin.extensiontest + MinimumOSVersion + 5.1.1 + UIDeviceFamily + + 1 + 2 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + +"); + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --sim {0} -sdk {3} --targetver {3} --extension -r:{2} {1}", app, exe, Configuration.MonoTouchDll, Configuration.sdk_version), hide_output: false); + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --dev {0} -sdk {3} --targetver {3} --extension -r:{2} {1}", app, exe, Configuration.MonoTouchDll, Configuration.sdk_version), hide_output: false); + } finally { + Directory.Delete (testDir, true); + } + } + + static string BindingsLibrary { + get { + return Path.Combine (Configuration.SourceRoot, "xamarin-macios/tests/bindings-test/bin/Debug/bindings-test.dll"); + } + } + + static string GetBindingsLibrary (Profile profile) + { + string fn; + + if (profile == Profile.Classic) { + fn = Path.Combine (Configuration.SourceRoot, "xamarin-macios", "tests", "bindings-test", "bin", GetConfiguration (profile), "bindings-test.dll"); + } else { + fn = Path.Combine (Configuration.SourceRoot, "xamarin-macios", "tests", "bindings-test", "bin", "Any CPU", GetConfiguration (profile), "bindings-test.dll"); + } + + if (!File.Exists (fn)) { + var csproj = Path.Combine (Configuration.SourceRoot, "xamarin-macios", "tests", "bindings-test", "bindings-test" + GetProjectSuffix (profile) + ".csproj"); + XBuild.Build (csproj, platform: "AnyCPU"); + } + + return fn; + } + + public static string GetBaseLibrary (Profile profile) + { + switch (profile) { + case Profile.Classic: + return Configuration.MonoTouchDll; + case Profile.Unified: + return Configuration.XamarinIOSDll; + case Profile.TVOS: + return Configuration.XamarinTVOSDll; + case Profile.WatchOS: + return Configuration.XamarinWatchOSDll; + default: + throw new NotImplementedException (); + } + } + + public static string GetCompiler (Profile profile, StringBuilder args) + { + args.Append (" -lib:").Append (Path.GetDirectoryName (GetBaseLibrary (profile))).Append (' '); + return "/Library/Frameworks/Mono.framework/Commands/mcs"; + } + + static string GetConfiguration (Profile profile) + { + switch (profile) { + case Profile.Classic: + return "Debug"; + case Profile.Unified: + return "Debug-unified"; + case Profile.TVOS: + return "Debug-tvos"; + case Profile.WatchOS: + return "Debug-watchos"; + default: + throw new NotImplementedException (); + } + } + + public static string GetTargetFramework (Profile profile) + { + switch (profile) { + case Profile.Classic: + return "MonoTouch,v1.0"; + case Profile.Unified: + return "Xamarin.iOS,v1.0"; + case Profile.TVOS: + return "Xamarin.TVOS,v1.0"; + case Profile.WatchOS: + return "Xamarin.WatchOS,v1.0"; + default: + throw new NotImplementedException (); + } + } + + public static string GetDeviceArchitecture (Profile profile) + { + switch (profile) { + case Profile.Classic: + case Profile.Unified: + return "armv7"; + case Profile.TVOS: + return "arm64"; + case Profile.WatchOS: + return "armv7k"; + default: + throw new NotImplementedException (); + } + } + + public static string GetSimulatorArchitecture (Profile profile) + { + switch (profile) { + case Profile.Classic: + case Profile.Unified: + case Profile.WatchOS: + return "i386"; + case Profile.TVOS: + return "x86_64"; + default: + throw new NotImplementedException (); + } + } + + public static string GetArchitecture (Profile profile, Target target) + { + return target == Target.Dev ? GetDeviceArchitecture (profile) : GetSimulatorArchitecture (profile); + } + + static string GetPlatformName (Profile profile) + { + switch (profile) { + case Profile.Classic: + return "MonoTouch"; + case Profile.Unified: + return "Xamarin.iOS"; + case Profile.TVOS: + return "Xamarin.TVOS"; + case Profile.WatchOS: + return "Xamarin.WatchOS"; + default: + throw new NotImplementedException (); + } + } + + static string GetProjectSuffix (Profile profile) + { + switch (profile) { + case Profile.Classic: + return string.Empty; + case Profile.Unified: + return "-unified"; + case Profile.TVOS: + return "-tvos"; + case Profile.WatchOS: + return "-watchos"; + default: + throw new NotImplementedException (); + } + } + + public static string GetSdkVersion (Profile profile) + { + switch (profile) { + case Profile.Classic: + case Profile.Unified: + return Configuration.sdk_version; + case Profile.TVOS: + return Configuration.tvos_sdk_version; + case Profile.WatchOS: + return Configuration.watchos_sdk_version; + default: + throw new NotImplementedException (); + } + } + + [Test] + public void LinkAll_Frameworks () + { + // Make sure that mtouch does not link with unused frameworks. + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + var bin = Path.Combine (app, Path.GetFileNameWithoutExtension (exe)); + + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " -v -v -v --nosign --sim {0} -sdk " + Configuration.sdk_version + " {1} -debug", app, exe)); + + var load_commands = ExecutionHelper.Execute ("otool", "-l \"" + bin + "\""); + Asserts.DoesNotContain ("SafariServices", load_commands, "SafariServices"); + Asserts.DoesNotContain ("GameController", load_commands, "GameController"); + Asserts.DoesNotContain ("QuickLook", load_commands, "QuickLook"); + Asserts.DoesNotContain ("NewsstandKit", load_commands, "NewsstandKit"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_LinkWithTest (Profile profile) + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + // --fastdev with static registrar and linkwith library - this will fail to build if the linkwith dylib isn't linked with the corresponding native library. + var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Executable = CompileTestAppExecutableLinkWith (testDir, profile), + AppPath = app, + NoFastSim = true, + Registrar = MTouchRegistrar.Static, + }; + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev), "build"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_NoFastSim_NoLink (Profile profile) + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + // --sim --nofastsim --nolink --fastdev + var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Executable = CompileTestAppExecutableLinkWith (testDir, profile), + AppPath = app, + NoFastSim = true, + Linker = MTouchLinker.DontLink, + }; + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim), "build"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_NoFastSim_LinkAll (Profile profile) + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + // --sim --nofastsim --fastdev + var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Executable = CompileTestAppExecutableLinkWith (testDir, profile), + AppPath = app, + NoFastSim = true, + }; + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim), "build"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_NoFastSim_LinkSDK (Profile profile) + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + // --sim --nofastsim --linksdkonly --fastdev + var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Linker = MTouchLinker.LinkSdk, + Executable = CompileTestAppExecutableLinkWith (testDir, profile), + AppPath = app, + NoFastSim = true, + }; + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim), "build"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_Sim (Profile profile) + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + // --sim --fastdev + var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Executable = CompileTestAppExecutableLinkWith (testDir, profile), + AppPath = app, + }; + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim), "build"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_LinkAll (Profile profile) + { + using (var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + }) { + mtouch.CreateTemporaryApp_LinkWith (); + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev), "build"); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_NoLink (Profile profile) + { + + // --fastdev w/no link + using (var mtouch = new MTouchTool () + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Linker = MTouchLinker.DontLink, + }) { + mtouch.CreateTemporaryApp_LinkWith (); + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev), "build 1"); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_LinkAll_Then_NoLink (Profile profile) + { + using (var mtouch = new MTouchTool + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + }) { + mtouch.CreateTemporaryApp_LinkWith (); + + // --fastdev w/all link + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev), "build 1"); + + // --fastdev w/no link + mtouch.Linker = MTouchLinker.DontLink; + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev), "build 2"); + } + } + + [Test] + [TestCase (Profile.Classic)] + [TestCase (Profile.Unified)] + [TestCase (Profile.TVOS)] + //[TestCase (Profile.WatchOS)] // needs testing improvement + public void FastDev_LinkSDK (Profile profile) + { + using (var mtouch = new MTouchTool + { + Profile = profile, + Debug = true, + FastDev = true, + References = new string [] { GetBindingsLibrary (profile) }, + Linker = MTouchLinker.LinkSdk, + }) { + mtouch.CreateTemporaryApp_LinkWith (); + + // --fastdev w/sdk link + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev), "build"); + } + } + + [Test] + public void FastDev_Dual () + { + using (var mtouch = new MTouchTool () + { + Profile = Profile.Unified, + FastDev = true, + Abi = "armv7,arm64", + }) { + mtouch.CreateTemporaryApp (); + + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildDev)); + var bin = mtouch.NativeExecutablePath; + VerifyArchitectures (bin, "arm7s/64", "armv7", "arm64"); + foreach (var dylib in Directory.GetFileSystemEntries (mtouch.AppPath, "*.dylib")) { + if (Path.GetFileName (dylib).StartsWith ("libmono")) + continue; + if (Path.GetFileName (dylib).StartsWith ("libxamarin")) + continue; + VerifyArchitectures (dylib, dylib + ": arm7s/64", "armv7", "arm64"); + } + } + } + + [Test] + [TestCase (Target.Dev, "armv7")] + [TestCase (Target.Dev, "armv7s")] + [TestCase (Target.Dev, "armv7,armv7s")] + [TestCase (Target.Sim, "i386")] + public void Architectures_Classic (Target target, string abi) + { + using (var mtouch = new MTouchTool ()) { + mtouch.CreateTemporaryApp (); + + mtouch.Abi = abi; + + var bin = Path.Combine (mtouch.AppPath, Path.GetFileNameWithoutExtension (mtouch.Executable)); + + Assert.AreEqual (0, mtouch.Execute (target == Target.Dev ? MTouchAction.BuildDev : MTouchAction.BuildSim)); + VerifyArchitectures (bin, abi, abi.Split (',')); + } + } + + [Test] + public void Architectures_Classic_Invalid () + { + using (var mtouch = new MTouchTool ()) { + mtouch.CreateTemporaryApp (); + + mtouch.Abi = "armv6"; + Assert.AreEqual (1, mtouch.Execute (MTouchTests.MTouchAction.BuildDev)); + mtouch.AssertError ("MT", 15, "Invalid ABI: armv6. Supported ABIs are: i386, x86_64, armv7, armv7+llvm, armv7+llvm+thumb2, armv7s, armv7s+llvm, armv7s+llvm+thumb2, armv7k, arm64 and arm64+llvm."); + + mtouch.Abi = "armv7"; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError ("MT", 75, "Invalid architecture 'ARMv7' for iOS projects. Valid architectures are: i386"); + } + } + + [Test] + [TestCase (Target.Dev, "armv7")] + [TestCase (Target.Dev, "armv7s")] + [TestCase (Target.Dev, "armv7,armv7s")] + [TestCase (Target.Dev, "arm64")] + [TestCase (Target.Dev, "arm64+llvm")] + [TestCase (Target.Dev, "armv7,arm64")] + [TestCase (Target.Dev, "armv7s,arm64")] + [TestCase (Target.Dev, "armv7,armv7s,arm64")] + [TestCase (Target.Sim, "i386")] + [TestCase (Target.Sim, "x86_64")] + public void Architectures_Unified (Target target, string abi) + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = Profile.Unified; + mtouch.CreateTemporaryApp (); + + mtouch.Abi = abi; + + var bin = Path.Combine (mtouch.AppPath, Path.GetFileNameWithoutExtension (mtouch.Executable)); + + Assert.AreEqual (0, mtouch.Execute (target == Target.Dev ? MTouchAction.BuildDev : MTouchAction.BuildSim)); + + VerifyArchitectures (bin, abi, abi.Replace ("+llvm", string.Empty).Split (',')); + } + } + + [Test] + public void Architectures_Unified_FatSimulator () + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = Profile.Unified; + mtouch.CreateTemporaryApp (); + + mtouch.Abi = "i386,x86_64"; + + var bin = Path.Combine (mtouch.AppPath, Path.GetFileNameWithoutExtension (mtouch.Executable)); + var bin32 = Path.Combine (mtouch.AppPath, ".monotouch-32", Path.GetFileNameWithoutExtension (mtouch.Executable)); + var bin64 = Path.Combine (mtouch.AppPath, ".monotouch-64", Path.GetFileNameWithoutExtension (mtouch.Executable)); + + Assert.AreEqual (0, mtouch.Execute (MTouchAction.BuildSim)); + + Assert.IsFalse (File.Exists (bin), "none"); + VerifyArchitectures (bin64, "64/x86_64", "x86_64"); + VerifyArchitectures (bin32, "32/i386", "i386"); + } + } + + [Test] + public void Architectures_Unified_Invalid () + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = Profile.Unified; + mtouch.CreateTemporaryApp (); + + mtouch.Abi = "armv6"; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildDev)); + mtouch.AssertError ("MT", 15, "Invalid ABI: armv6. Supported ABIs are: i386, x86_64, armv7, armv7+llvm, armv7+llvm+thumb2, armv7s, armv7s+llvm, armv7s+llvm+thumb2, armv7k, arm64 and arm64+llvm."); + + mtouch.Abi = "armv7"; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildSim)); + mtouch.AssertError ("MT", 75, "Invalid architecture 'ARMv7' for iOS projects. Valid architectures are: i386, x86_64"); + } + } + + [Test] + [TestCase (Target.Dev, null)] + [TestCase (Target.Dev, "arm64+llvm")] + [TestCase (Target.Sim, null)] + public void Architectures_TVOS (Target target, string abi) + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = MTouch.Profile.TVOS; + mtouch.Abi = abi; + mtouch.CreateTemporaryApp (); + + var bin = Path.Combine (mtouch.AppPath, Path.GetFileNameWithoutExtension (mtouch.Executable)); + + Assert.AreEqual (0, mtouch.Execute (target == Target.Dev ? MTouchAction.BuildDev : MTouchAction.BuildSim), "build"); + VerifyArchitectures (bin, "arch", target == Target.Dev ? "arm64" : "x86_64"); + } + } + + [Test] + public void Architectures_TVOS_Invalid () + { + using (var mtouch = new MTouchTool ()) { + mtouch.Profile = Profile.TVOS; + mtouch.CreateTemporaryApp (); + + mtouch.Abi = "armv7"; + Assert.AreEqual (1, mtouch.Execute (MTouchAction.BuildDev), "device - armv7"); + mtouch.AssertError ("MT", 75, "Invalid architecture 'ARMv7' for TVOS projects. Valid architectures are: ARM64, ARM64+LLVM"); + } + } + + [Test] + public void GarbageCollectors () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + var bin = Path.Combine (app, Path.GetFileNameWithoutExtension (exe)); + var common_args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --sim {0} -sdk " + Configuration.sdk_version + " --abi=i386 {1} -debug ", app, exe); + var compat_args = common_args + " -r:" + Configuration.MonoTouchDll; + + ExecutionHelper.Execute (TestTarget.ToolPath, compat_args); + VerifyGC (bin, false, "compat/default"); + + ExecutionHelper.Execute (TestTarget.ToolPath, compat_args + " --sgen"); + VerifyGC (bin, false, "compat/sgen"); + + ExecutionHelper.Execute (TestTarget.ToolPath, compat_args + " --boehm"); + VerifyGC (bin, false, "compat/boehm"); + } finally { + Directory.Delete (testDir, true); + } + + Directory.CreateDirectory (app); + try { + var code = "public class TestApp { static void Main () { System.Console.WriteLine (typeof (UIKit.UIWindow).ToString ()); } }"; + var exe = CompileTestAppExecutable (testDir, code: code, profile: MTouch.Profile.Unified); + var bin = Path.Combine (app, Path.GetFileNameWithoutExtension (exe)); + var common_args = string.Format ("-sdkroot " + Configuration.xcode_root + " --sim {0} -sdk " + Configuration.sdk_version + " --targetver 5.1.1 --abi=i386 {1} -debug -gcc_flags -Wl,-w ", app, exe); + var newstyle_args = common_args + "-r:" + Configuration.XamarinIOSDll; + ExecutionHelper.Execute (TestTarget.ToolPath, newstyle_args); + VerifyGC (bin, false, "dual/default"); + + ExecutionHelper.Execute (TestTarget.ToolPath, newstyle_args + " --sgen"); + VerifyGC (bin, false, "dual/sgen"); + + var output = ExecutionHelper.Execute (TestTarget.ToolPath, newstyle_args + " --boehm"); + VerifyGC (bin, false, "dual/boehm"); + VerifyOutput ("Test", output, + "Xamarin.iOS .* using framework:.*", + "warning MT0043: The Boehm garbage collector is not supported. The SGen garbage collector has been selected instead.", + ".*testApp.app built successfully."); + } finally { + Directory.Delete (testDir, true); + } + } + + void ExecuteWithStats (string binary, string arguments) + { + ExecutionHelper.Execute (TestTarget.ToolPath, arguments); + var fi = new FileInfo (binary); + Console.WriteLine ("Binary Size: {0} bytes = {1} kb", fi.Length, fi.Length / 1024); + } + + string ReplaceExtraArgs (string contents, string replace) + { + return ReplaceCsprojData (contents, "MtouchExtraArgs", replace); + } + + string ReplaceCompilerDefines (string contents, string replace) + { + return ReplaceCsprojData (contents, "DefineConstants", replace); + } + + string ReplaceCsprojData (string contents, string key, string replace) + { + int idx = 0; + while (true) { + var start = contents.IndexOf ("<" + key + ">", idx); + if (start == -1) + return contents; + var end = contents.IndexOf("", start); + if (end == -1) + return contents; + contents = contents.Substring (0, start + ("<" + key + ">").Length) + replace + contents.Substring (end); + idx = end; + } + } + + static string MDToolPath { + get { + return "/Applications/Xamarin Studio.app/Contents/MacOS/mdtool"; + } + } + + void BuildMonotouchTests (string registrar, string defines) + { + string dir = Environment.CurrentDirectory; + while (dir != null && !Directory.Exists (Path.Combine (dir, "monotouch-test"))) { + dir = Path.GetDirectoryName (dir); + } + if (dir == null) + Assert.Ignore ("Could not find the monotouch-test directory."); + + var proj = Path.Combine (Path.Combine (dir, "monotouch-test"), "monotouch-test.csproj"); + var tmpproj = Path.Combine (Path.Combine (dir, "monotouch-test"), ".tmp-monotouch-test.csproj"); + var contents = File.ReadAllText (proj); + var sln = Path.Combine (dir, "tests.sln"); + var tmpsln = Path.Combine (dir, ".tmp-tests.sln"); + var slncontents = File.ReadAllText (sln); + + try { + var tmpcontents = ReplaceExtraArgs (contents, "-v -v -v --registrar:" + registrar); + tmpcontents = ReplaceCompilerDefines (contents, defines); + File.WriteAllText (tmpproj, tmpcontents); + var tmpslncontents = slncontents.Replace ("\\monotouch-test.csproj", "\\.tmp-monotouch-test.csproj"); + File.WriteAllText (tmpsln, tmpslncontents); + using (var p = new Process ()) { + p.StartInfo.FileName = MDToolPath; + p.StartInfo.Arguments = "-v build -t:Build \"-c:Debug|iPhoneSimulator\" -p:.tmp-monotouch-test ../.tmp-tests.sln"; + p.StartInfo.WorkingDirectory = Path.GetDirectoryName (tmpproj); + p.StartInfo.UseShellExecute = false; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; + p.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => { Console.Error.WriteLine (e.Data); }; + p.OutputDataReceived += (object sender, DataReceivedEventArgs e) => { Console.WriteLine (e.Data); }; + Console.WriteLine ("{0} {1}", p.StartInfo.FileName, p.StartInfo.Arguments); + p.Start (); + p.BeginErrorReadLine (); + p.BeginOutputReadLine (); + p.WaitForExit (); + if (p.ExitCode != 0) + Assert.Fail ("Failed to compile monotouch-test with --registrar:{0} for Debug|iPhoneSimulator", registrar); + } + } finally { + // delete temporary project file + try { + File.Delete (tmpproj); + } catch { + } + try { + File.Delete (tmpsln); + } catch { + } + } + } + + [Test] + public void BuildMonoTouchTests_StaticRegistrar () + { + BuildMonotouchTests ("static --compiler:clang", "DEBUG;STATICREGISTRAR"); + } + + [Test] + public void BuildMonoTouchTests_OldStaticRegistrar () + { + BuildMonotouchTests ("oldstatic", "DEBUG;OLDSTATICREGISTRAR"); + } + + [Test] + public void Registrar () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + var bin = Path.Combine (app, Path.GetFileNameWithoutExtension (exe)); + var common_args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --dev {0} -sdk {2} {1} -debug", app, exe, Configuration.sdk_version); + + // fully linked + llvm (+thumb) + default registrar (currently llvm fails to build with clang, so we should transparently switch to gcc in this case) + ExecuteWithStats (bin, common_args + " --registrar:static --abi:armv7+llvm"); + ExecuteWithStats (bin, common_args + " --registrar:static --abi:armv7+llvm+thumb2"); + + // non-linked device build + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:static"); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:oldstatic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:dynamic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:olddynamic"); + + // sdk device build + ExecuteWithStats (bin, common_args + " --compiler:clang --linksdkonly --registrar:static"); + ExecuteWithStats (bin, common_args + " --compiler:clang --linksdkonly --registrar:oldstatic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --linksdkonly --registrar:dynamic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --linksdkonly --registrar:olddynamic"); + + // fully linked device build + ExecuteWithStats (bin, common_args + " --compiler:clang --registrar:static"); + ExecuteWithStats (bin, common_args + " --compiler:clang --registrar:oldstatic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --registrar:dynamic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --registrar:olddynamic"); + + // non-linked device build + common_args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --sim {0} -sdk {2} {1} -debug", app, exe, Configuration.sdk_version); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:static"); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:oldstatic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:dynamic"); + ExecuteWithStats (bin, common_args + " --compiler:clang --nolink --registrar:olddynamic"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + [TestCase ("")] + [TestCase ("-nolink")] + [TestCase ("-linksdkonly")] + public void ExportedSymbols (string linker_flag) + { + // + // Here we test that symbols P/Invokes and [Field] attributes references are not + // stripped by the native linker. mtouch has to pass '-u _SYMBOL' to the native linker + // for this to work. + // + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + var cache = Path.Combine (testDir, "cache"); + Directory.CreateDirectory (app); + + try { + var nativeCode = @" +void DummyMethod () {} +int dummy_field = 0; +"; + // var nativeLib = CompileNativeLibrary (testDir, nativeCode); + var extraCode = @" +public class BindingApp { + [MonoTouch.Foundation.Field (""dummy_field"", ""__Internal"")] + public static string DummyField { get { return null; } } + + [System.Runtime.InteropServices.DllImport (""__Internal"")] + public static extern void DummyMethod (); +} +"; + var bindingLib = CreateBindingLibrary (testDir, nativeCode, null, null, extraCode); + var exe = CompileTestAppExecutable (testDir, @" +public class TestApp { + static void Main () { + System.Console.WriteLine (typeof (MonoTouch.UIKit.UIWindow).ToString ()); + System.Console.WriteLine (BindingApp.DummyField); + BindingApp.DummyMethod (); + } +} +", + "-r:" + bindingLib); + var bin = Path.Combine (app, Path.GetFileNameWithoutExtension (exe)); + var args = string.Format ("-sdkroot {4} --nosign -sdk {2} {1} -debug --cache {0} -v -v -v -v -r:{3} -dev {5} " + linker_flag, + cache, exe, Configuration.sdk_version, bindingLib, Configuration.xcode_root, app); + + // each variation is tested twice so that we don't break when everything is found in the cache the second time around. + + ExecutionHelper.Execute (TestTarget.ToolPath, args); + var symbols = ExecutionHelper.Execute ("nm", bin, hide_output: true).Split ('\n'); + Assert.That (symbols, Has.Some.EndsWith (" S _dummy_field"), "Field not found in initial build"); + Assert.That (symbols, Has.Some.EndsWith (" T _DummyMethod"), "P/invoke not found in initial build"); + + ExecutionHelper.Execute ("touch", bindingLib); // This will make it so that the second identical variation won't skip the final link step. + ExecutionHelper.Execute (TestTarget.ToolPath, args); + symbols = ExecutionHelper.Execute ("nm", bin, hide_output: true).Split ('\n'); + Assert.That (symbols, Has.Some.EndsWith (" S _dummy_field"), "Field not found in second build"); + Assert.That (symbols, Has.Some.EndsWith (" T _DummyMethod"), "P/invoke not found in second build"); + } finally { + Directory.Delete (testDir, true); + } + } + + + [Test] + public void ExportedSymbols_VerifyLinkedAwayField () + { + // + // Here we test that unused P/Invokes and [Field] members are properly linked away + // (and we do not request the native linker to preserve those symbols). + // + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + var cache = Path.Combine (testDir, "cache"); + + Directory.CreateDirectory (app); + + try { + var nativeCode = @" +void DummyMethod () {} +int dummy_field = 0; +"; + // var nativeLib = CompileNativeLibrary (testDir, nativeCode); + var extraCode = @" +public class BindingApp { + [MonoTouch.Foundation.Field (""dummy_field"", ""__Internal"")] + public static string DummyField { get { return null; } } + + [System.Runtime.InteropServices.DllImport (""__Internal"")] + public static extern void DummyMethod (); +} +"; + var bindingLib = CreateBindingLibrary (testDir, nativeCode, null, null, extraCode); + var exe = CompileTestAppExecutable (testDir, @" +public class TestApp { + static void Main () { + System.Console.WriteLine (typeof (MonoTouch.UIKit.UIWindow).ToString ()); + } +} +", + "-r:" + bindingLib); + var bin = Path.Combine (app, Path.GetFileNameWithoutExtension (exe)); + var common_args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign -sdk {2} {1} -debug --cache {0} -v -v -v -v --registrar:static -r:{3}", + cache, exe, Configuration.sdk_version, bindingLib); + + var variations = new string [] { + // each variation is tested twice so that we don't break when everything is found in the cache the second time around. + " -dev {0}", + " -dev {0}", + }; + + for (int v = 0; v < variations.Length; v++) { + var variation = variations [v]; + + ExecutionHelper.Execute ("touch", bindingLib); // This will make it so that the second identical variation won't skip the final link step. + + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format (common_args + variation, app)); + var lines = ExecutionHelper.Execute ("nm", bin, hide_output: true).Split ('\n'); + var found_field = false; + var found_pinvoke = false; + foreach (var line in lines) { + found_field |= line.EndsWith (" S _dummy_field"); + found_pinvoke |= line.EndsWith (" T _DummyMethod"); + if (found_field && found_pinvoke) + break; + } + + Assert.IsFalse (found_field, string.Format ("Field found for variation #{0}: {1}", v, variation)); + Assert.IsFalse (found_field, string.Format ("P/Invoke found for variation #{0}: {1}", v, variation)); + } + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void LinkerWarnings () + { + string output; + var testDir = GetTempDirectory (); + + try { + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + var exe = CompileTestAppExecutable (testDir); + + output = ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {2} --nosign --dev {0} -sdk {3} --force --abi=armv7,armv7s {1} -debug", app, exe, Configuration.xcode_root, Configuration.sdk_version)); + Asserts.DoesNotContain ("ld: warning:", output, "#a"); + + output = ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot {2} --nosign --dev {0} -sdk {3} --force --abi=armv7 {1} -debug --gcc_flags={4}", app, exe, Configuration.xcode_root, Configuration.sdk_version, Quote (Path.Combine (Configuration.SourceRoot, "xamarin-maciostools/tests/test-libraries/.libs/ios/libtest.armv7s.a")))); + Asserts.Contains ("libtest.armv7s.a, file was built for archive which is not the architecture being linked (armv7)", output, "#b"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void NativeLinker_AllLoad () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=17199 + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileTestAppExecutable (testDir); + + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --dev {0} -sdk " + Configuration.sdk_version + " --targetver 7.0 --abi=armv7s {1} -debug --gcc_flags -all_load", app, exe)); + + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void CachedManagedLinker () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=17506 + + var testDir = GetTempDirectory (); + + foreach (var linker in new string [] { "", "--linksdkonly", "--nolink" }) { + try { + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + var exe = CompileTestAppExecutable (testDir); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("{3} -sdkroot " + Configuration.xcode_root + " --nosign --dev {0} -sdk " + Configuration.sdk_version + " --targetver 7.0 --abi=armv7 {1} --cache={2}", app, exe, cache, linker); + ExecutionHelper.Execute (TestTarget.ToolPath, args); + File.Delete (Path.Combine (app, "testApp")); // This will force the final native link to succeed, while everything before has been cached. + ExecutionHelper.Execute (TestTarget.ToolPath, args); + } finally { + Directory.Delete (testDir, true); + } + } + } + + [Test] + public void MT1015 () + { + // BXC 18659 + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + + try { + Directory.CreateDirectory (Path.Combine (app, "testApp")); + + var exe = CompileTestAppExecutable (testDir); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --nolink --sim {0} -sdk " + Configuration.sdk_version + " --abi=i386 {1} --cache={2} --r:{3}", app, exe, cache, Configuration.MonoTouchDll); + Asserts.ThrowsPattern (() => ExecutionHelper.Execute (TestTarget.ToolPath, args, hide_output: false), + "Xamarin.iOS .* using framework:.*\nerror MT1015: Failed to create the executable '.*/testApp.app/testApp': .*/testApp.app/testApp is a directory\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT1016 () + { + // #20607 + + var testDir = GetTempDirectory (); + + try { + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (Path.Combine (app, "NOTICE")); + + var exe = CompileTestAppExecutable (testDir); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --nolink --dev {0} -sdk {4} -targetver {4} --abi=armv7 {1} --cache={2} --r:{3} ", app, exe, cache, Configuration.MonoTouchDll, Configuration.sdk_version); + Asserts.ThrowsPattern (() => ExecutionHelper.Execute (TestTarget.ToolPath, args, hide_output: false), + "Xamarin.iOS .* using framework:.*\nerror MT1016: Failed to create the NOTICE file because a directory already exists with the same name.\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT1017 () + { + // #20607 + + var testDir = GetTempDirectory (); + + try { + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + File.WriteAllText (Path.Combine (app, "NOTICE"), "contents"); + var fi = new FileInfo (Path.Combine (app, "NOTICE")); + fi.IsReadOnly = true; + + var exe = CompileTestAppExecutable (testDir); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --nolink --dev {0} -sdk {4} -targetver {4} --abi=armv7 {1} --cache={2} --r:{3}", app, exe, cache, Configuration.MonoTouchDll, Configuration.sdk_version); + Asserts.ThrowsPattern (() => ExecutionHelper.Execute (TestTarget.ToolPath, args, hide_output: false), + "Xamarin.iOS .* using framework:.*\nerror MT1017: Failed to create the NOTICE file: Access to the path \".*/testApp.app/NOTICE\" is denied.\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT1202 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:vX; -sdkroot {0}", Configuration.xcode_root)), "error MT1202: Invalid simulator configuration: :vX;\n"); + } + + [Test] + public void MT1203 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2;a -sdkroot {0}", Configuration.xcode_root)), "error MT1203: Invalid simulator specification: a\n"); + } + + [Test] + public void MT1204 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2; -sdkroot {0}", Configuration.xcode_root)), "error MT1204: Invalid simulator specification '': runtime not specified.\n"); + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2;devicetype=1 -sdkroot {0}", Configuration.xcode_root)), "error MT1204: Invalid simulator specification 'devicetype=1': runtime not specified.\n"); + } + + [Test] + public void MT1205 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2;runtime=1 -sdkroot {0}", Configuration.xcode_root)), "error MT1205: Invalid simulator specification 'runtime=1': device type not specified.\n"); + } + + [Test] + public void MT1206 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2;runtime=1,devicetype=2 -sdkroot {0}", Configuration.xcode_root)), "error MT1206: Could not find the simulator runtime '1'.\n"); + } + + [Test] + public void MT1207 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2;runtime=com.apple.CoreSimulator.SimRuntime.iOS-" + Configuration.sdk_version.Replace ('.', '-') + ",devicetype=2 -sdkroot {0}", Configuration.xcode_root)), "error MT1207: Could not find the simulator device type '2'.\n"); + } + + // I don't know which --runtime values would cause MT1208, I always end up with MT1215 instead + + // I don't know which --device values would cause MT1209 + + [Test] + public void MT1210 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--launchsim /tmp --device=:v2;a=1 -sdkroot {0}", Configuration.xcode_root)), "error MT1210: Invalid simulator specification: 'a=1', unknown key 'a'\n"); + } + + [Test] + public void MT1211 () + { + Assert.Ignore ("There are no device types in the iOS 9 simulator that the 8.1 simulator (earliest simulator Xcode 7 can run) doesn't support, so there's no way to produce the MT1211 error"); + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath,"--sdkroot " + Configuration.xcode_root + " --launchsim /path/to/somewhere --device=:v2;runtime=com.apple.CoreSimulator.SimRuntime.iOS-7-1,devicetype=com.apple.CoreSimulator.SimDeviceType.Apple-Watch-38mm"), + "error MT1211: The simulator version '7.1' does not support the simulator type 'Resizable iPhone'\n"); + } + + // MT1213: unused + // MT1214: unused + // MT1215: unused + + [Test] + public void MT1216 () + { + Asserts.Throws (() => ExecutionHelper.Execute (TestTarget.ToolPath, "--sdkroot " + Configuration.xcode_root + " --launchsim /tmp --device=:v2;udid=unknown"), "error MT1216: Could not find the simulator UDID 'unknown'.\n"); + } + + [Test] + public void MT5211_UnifiedApp () + { + var testDir = GetTempDirectory (); + + try { + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + var code = @" +using System; +using System.Runtime.InteropServices; +using UIKit; +using Foundation; + +class Test { + [Register (""Inexistent"", true)] + public class Inexistent : NSObject {} + + public class Subexistent : Inexistent { } + + static void Main () + { + Console.WriteLine (typeof (Subexistent)); + } +} +"; + var exe = CompileTestAppExecutable (testDir, code, profile: MTouch.Profile.Unified); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var mtouch = new MTouchTool (); + + Assert.AreEqual (1, mtouch.Execute ("-sdkroot {5} --dev {0} -sdk {4} -targetver {4} --abi=armv7,arm64 {1} --cache={2} --r:{3}", app, exe, cache, Configuration.XamarinIOSDll, Configuration.sdk_version, Configuration.xcode_root), "build failure expected"); + + mtouch.AssertOutputPattern ("Undefined symbols for architecture arm64:"); + mtouch.AssertOutputPattern (".*_OBJC_METACLASS_._Inexistent., referenced from:.*"); + mtouch.AssertOutputPattern (".*_OBJC_METACLASS_._Test_Subexistent in registrar.arm64.o.*"); + mtouch.AssertOutputPattern (".*_OBJC_CLASS_._Inexistent., referenced from:.*"); + mtouch.AssertOutputPattern (".*_OBJC_CLASS_._Test_Subexistent in registrar.arm64.o.*"); + mtouch.AssertOutputPattern (".*objc-class-ref in registrar.arm64.o.*"); + mtouch.AssertOutputPattern (".*ld: symbol.s. not found for architecture arm64.*"); + mtouch.AssertOutputPattern (".*clang: error: linker command failed with exit code 1 .use -v to see invocation.*"); + + mtouch.AssertErrorPattern ("MT", 5210, "Native linking failed, undefined symbol: _OBJC_METACLASS_._Inexistent. Please verify that all the necessary frameworks have been referenced and native libraries are properly linked in."); + mtouch.AssertErrorPattern ("MT", 5211, "Native linking failed, undefined Objective-C class: Inexistent. The symbol ._OBJC_CLASS_._Inexistent. could not be found in any of the libraries or frameworks linked with your application."); + mtouch.AssertErrorPattern ("MT", 5202, "Native linking failed. Please review the build log."); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void MT5214 () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var code = @" +using System; +using System.Runtime.InteropServices; + +namespace UIKit { +} + +namespace MonoTouch.UIKit { +class Test { + [DllImport (""__Internal"")] + public static extern void InexistentFunc (); + + static void Main () + { + Console.WriteLine (typeof (UIWindow)); + } + +} +} +"; + var exe = CompileTestAppExecutable (testDir, code); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("-sdkroot " + Configuration.xcode_root + " --nosign --nolink --sim {0} -sdk {4} -targetver {4} --abi=i386 {1} --cache={2} --r:{3} -nofastsim", app, exe, cache, Configuration.MonoTouchDll, Configuration.sdk_version); + Asserts.ThrowsPattern (() => ExecutionHelper.Execute (TestTarget.ToolPath, args, hide_output: false), + "Xamarin.iOS .* using framework:.*\n" + + "Process exited with code 1.*\n" + + "/Applications/.*clang.*\n" + + "Undefined symbols.*\n" + + ".*_InexistentFunc.*\n" + + ".*command line option.*\n" + + ".*ld: symbol.*not found.*\n" + + ".*clang: error.*\n" + + "\n" + + "error MT5214: Native linking failed, undefined symbol: _InexistentFunc. This symbol was referenced by the managed member MonoTouch.UIKit.Test.InexistentFunc. Please verify that all the necessary frameworks have been referenced and native libraries linked.\n" + + "error MT5202: Native linking failed. Please review the build log.\n"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void TestCaseMismatchedAssemblyName () + { + // desk #90367 (and others in the past as well) + + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (testDir); + + try { + string dllcs = Path.Combine (testDir, "testLibrary.cs"); + string exe = Path.Combine (testDir, "testApp.exe"); + string dll = Path.Combine (testDir, "testLibrary.dll"); + string DLL = Path.Combine (testDir, "TESTLIBRARY.dll"); + string args; + string output; + + File.WriteAllText (dllcs, "public class TestLib { public TestLib () { System.Console.WriteLine (typeof (UIKit.UIWindow).ToString ()); } }"); + + args = string.Format ("\"{0}\" /debug:full /noconfig /t:library /nologo /out:\"{1}\" /r:" + Configuration.XamarinIOSDll, dllcs, dll); + File.WriteAllText (DLL + ".config", ""); + if (ExecutionHelper.Execute (Configuration.SmcsPath, args, out output) != 0) + throw new Exception (output); + + var execs = @"public class TestApp { + static void Main () + { + System.Console.WriteLine (typeof (UIKit.UIWindow).ToString ()); + System.Console.WriteLine (new TestLib ()); + } +}"; + + var exeF = Path.Combine (testDir, "testExe.cs"); + + File.WriteAllText (exeF, execs); + + var cmds = string.Format ("\"{0}\" /noconfig /t:exe /nologo /out:\"{1}\" \"/r:{2}\" -r:{3}", exeF, exe, dll, Configuration.XamarinIOSDll); + if (ExecutionHelper.Execute (Configuration.SmcsPath, cmds, out output) != 0) + throw new Exception (output); + + File.Move (dll, DLL); + + Action check = (v) => + { + var msg = new StringBuilder (); + int counter = 0; + foreach (var file in Directory.EnumerateFiles (app, "*", SearchOption.AllDirectories)) { + if (file.Contains ("TESTLIBRARY")) { + msg.AppendFormat ("File {0} has incorrect case.\n", file); + } + counter++; + } + Console.WriteLine ("Checked {0} files", counter); + if (msg.Length > 0) + Assert.Fail (v + "\n" + msg.ToString ()); + }; + + string [][] tests = new string[][] { + new string [] { "linkall", "-sdkroot {0} --dev {1} -sdk {2} --targetver {2} --abi=armv7s {3} -debug -r:{4} -r:{5}" }, + new string [] { "dontlink", "-sdkroot {0} --dev {1} -sdk {2} --targetver {2} --abi=armv7s {3} -debug -r:{4} -r:{5} --nolink" }, + new string [] { "dual", "-sdkroot {0} --dev {1} -sdk {2} --targetver {2} --abi=armv7,arm64 {3} -debug -r:{4} -r:{5}" } + }; + + foreach (var kvp in tests) { + var name = kvp [0]; + var format = kvp [1]; + var mtouch_fmt = string.Format (format, Configuration.xcode_root, app, Configuration.sdk_version, exe, Configuration.XamarinIOSDll, DLL); + Directory.CreateDirectory (app); + ExecutionHelper.Execute (TestTarget.ToolPath, mtouch_fmt, hide_output: false); + check (name); + Directory.Delete (app, true); + } + + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void TestDuplicatedFatApp () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileUnifiedTestAppExecutable (testDir); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("-sdkroot {5} --dev {0} -sdk {4} -targetver {4} --abi=armv7,arm64 {1} --cache={2} --r:{3} ", app, exe, cache, Configuration.XamarinIOSDll, Configuration.sdk_version, Configuration.xcode_root); + ExecutionHelper.Execute (TestTarget.ToolPath, args, hide_output: false); + var ufe = Mono.Unix.UnixFileInfo.GetFileSystemEntry (Path.Combine (app, ".monotouch-32", "testApp.exe")); + Assert.IsTrue (ufe.IsSymbolicLink, "testApp.exe IsSymbolicLink"); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void TestAllLoad () + { + var testDir = GetTempDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + try { + var exe = CompileUnifiedTestAppExecutable (testDir); + var cache = Path.Combine (testDir, "mtouch-cache"); + + var args = string.Format ("-sdkroot {5} --dev {0} -sdk {4} -targetver {4} --abi=armv7,arm64 {1} --cache={2} --r:{3} -gcc_flags -all_load", app, exe, cache, Configuration.XamarinIOSDll, Configuration.sdk_version, Configuration.xcode_root); + ExecutionHelper.Execute (TestTarget.ToolPath, args, hide_output: false); + } finally { + Directory.Delete (testDir, true); + } + } + + [Test] + public void ListDev () + { + ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("--listdev --sdkroot {0}", Configuration.xcode_root)); + } + + [Test] + public void LaunchOnDevice () + { + var mtouch = new MTouchTool (); + var devices = mtouch.FindAvailableDevices (new string [] { "iPad", "iPhone" }).ToArray (); + if (devices.Length == 0) + Assert.Ignore ("Could not find any connected devices."); + + var projectDir = Path.Combine (Configuration.SourceRoot, "xamarin-macios", "tests", "link all"); + var project = Path.Combine (projectDir, "link all.csproj"); + XBuild.Build (project, platform: "iPhone"); + var appPath = Path.Combine (projectDir, "bin", "iPhone", "Debug", "link all.app"); + foreach (var device in devices) { + if (mtouch.InstallOnDevice (device, appPath) != 0) { + Console.WriteLine ("Could not install on the device '{0}'.", device); + continue; + } + if (mtouch.LaunchOnDevice (device, appPath, false, false) != 0) { + if (mtouch.HasErrorPattern ("MT", 1031, "Could not launch the app '.*' on the device '.*' because the device is locked. Please unlock the device and try again.")) + continue; + Assert.Fail ("Failed to launch on device."); + } else { + return; + } + } + + Assert.Ignore ("Could not find any non-locked devices."); + } + + [Test] + public void LaunchOnWatchDevice () + { + var mtouch = new MTouchTool (); + mtouch.Verbosity = 2; + var devices = mtouch.FindAvailableDevices (new string [] { "Watch" }).ToArray (); + if (devices.Length == 0) + Assert.Ignore ("Could not find any connected watches."); + + var projectDir = Path.Combine (Configuration.SourceRoot, "xamarin-macios", "msbuild", "tests", "MyWatch2Container"); + var project = Path.Combine (projectDir, "MyWatch2Container.csproj"); + var containerPath = Path.Combine (projectDir, "bin", "iPhone", "Debug", "MyWatch2Container.app"); + var appPath = Path.Combine (containerPath, "Watch", "MyWatchApp2.app"); + + XBuild.Build (project, platform: "iPhone"); + if (!Directory.Exists (appPath)) + Assert.Fail ("Failed to build the watchOS app."); + + foreach (var device in devices) { + if (device.Companion == null) + continue; + + if (mtouch.InstallOnDevice (device.Companion, containerPath, "ios,watch") != 0) { + Console.WriteLine ("Could not install on the phone '{0}'. Trying another one.", device.Name); + continue; + } + + if (mtouch.LaunchOnDevice (device, appPath, false, false) != 0) { + if (mtouch.HasErrorPattern ("MT", 1031, "Could not launch the app '.*' on the device '.*' because the device is locked. Please unlock the device and try again.")) + continue; + Assert.Fail ("Failed to launch on device."); + } else { + return; + } + } + + Assert.Ignore ("Could not find any suitable devices."); + } + + [Test] + [TestCase (Profile.Unified)] + public void DlsymDisabled (Profile profile) + { + using (var tool = new MTouchTool ()) { + tool.Profile = profile; + tool.Verbosity = 5; + tool.Cache = Path.Combine (tool.CreateTemporaryDirectory (), "mtouch-test-cache"); + tool.CreateTemporaryApp ("using UIKit; class C { static void Main (string[] args) { UIApplication.Main (args); } }"); + tool.FastDev = true; + tool.Dlsym = false; + + Assert.AreEqual (0, tool.Execute (MTouchAction.BuildDev)); + } + } + +#region Helper functions + static string CompileUnifiedTestAppExecutable (string targetDirectory, string code = null, string extraArg = "") + { + return CompileTestAppExecutable (targetDirectory, code, extraArg, profile: MTouch.Profile.Unified); + } + + public static string CompileTestAppExecutable (string targetDirectory, string code = null, string extraArg = "", Profile profile = Profile.Classic) + { + string cs = Path.Combine (targetDirectory, "testApp.cs"); + string exe = Path.Combine (targetDirectory, "testApp.exe"); + var root_library = GetBaseLibrary (profile); + + if (code == null) { + if (profile != Profile.Classic) { + code = "public class TestApp { static void Main () { System.Console.WriteLine (typeof (ObjCRuntime.Runtime).ToString ()); } }"; + } else { + code = "public class TestApp { static void Main () { System.Console.WriteLine (typeof (MonoTouch.ObjCRuntime.Runtime).ToString ()); } }"; + } + } + + File.WriteAllText (cs, code); + + string output; + StringBuilder args = new StringBuilder (); + string fileName = GetCompiler (profile, args); + args.AppendFormat (" /noconfig /t:exe /nologo /out:{1} /r:{0} {2} {3}", Quote (root_library), Quote (exe), cs, extraArg); + if (ExecutionHelper.Execute (fileName, args.ToString (), out output) != 0) { + Console.WriteLine ("{0} {1}", fileName, args); + Console.WriteLine (output); + throw new Exception (output); + } + + return exe; + } + + static string CreateBindingLibrary (string targetDirectory, string nativeCode, string bindingCode, string linkWith = null, string extraCode = "") + { + var o = CompileNativeLibrary (targetDirectory, nativeCode); + var cs = Path.Combine (targetDirectory, "bindingCode.cs"); + var dll = Path.Combine (targetDirectory, "bindingLibrary.dll"); + + if (linkWith == null) { + linkWith = @" +using System; +using MonoTouch.ObjCRuntime; + +[assembly: LinkWith (""{0}"", LinkTarget.ArmV7, ForceLoad = true, SmartLink = true)] +"; + linkWith = string.Format (linkWith, Path.GetFileName (o)); + } + + File.WriteAllText (cs, bindingCode); + + extraCode = linkWith + "\n" + extraCode; + + var x = Path.Combine (targetDirectory, "extraBindingCode.cs"); + File.WriteAllText (x, extraCode); + + ExecutionHelper.Execute (Configuration.BtouchPath, + string.Format ("{0} --out:{1} --link-with={2},{3} -x:{4}", cs, dll, o, Path.GetFileName (o), x)); + + return dll; + } + + static string CompileNativeLibrary (string targetDirectory, string code) + { + var m = Path.Combine (targetDirectory, "testCode.m"); + + File.WriteAllText (m, code); + + string output; + string fileName = Path.Combine (Configuration.xcode_root, "Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"); + string args = string.Format ("-gdwarf-2 -arch armv7 -std=c99 -isysroot {0}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS{2}.sdk -miphoneos-version-min=3.1 " + + "-c -DDEBUG -o {1}/testCode.o -x objective-c {1}/testCode.m", + Configuration.xcode_root, targetDirectory, Configuration.sdk_version); + + if (ExecutionHelper.Execute (fileName, args, out output) != 0) { + Console.WriteLine ("{0} {1}", fileName, args); + Console.WriteLine (output); + throw new Exception (output); + } + + return Path.Combine (targetDirectory, "testCode.o"); + } + + void CompileCSharpCode (Profile profile, string code, string outputPath, params string[] additional_arguments) + { + code = code.Replace ("%PROFILE_NAMESPACE%", profile == Profile.Classic ? "MonoTouch." : string.Empty); + var tmpFile = Path.GetTempFileName (); + try { + File.WriteAllText (tmpFile, code); + + string output; + var args = new StringBuilder (); + var compiler = GetCompiler (profile, args); + + args.Append (" -target:").Append (outputPath.EndsWith (".dll") ? "library" : "exe"); + args.Append (" -r:").Append (Quote (GetBaseLibrary (profile))); + args.Append (" -out:").Append (Quote (outputPath)); + args.Append (" ").Append (Quote (tmpFile)); + foreach (var aa in additional_arguments) + args.Append (" ").Append (aa); + + if (ExecutionHelper.Execute (compiler, args.ToString (), out output) != 0) + throw new Exception (output); + } finally { + File.Delete (tmpFile); + } + } + + static Dictionary compiled_linkwith_apps = new Dictionary (); + public static string CompileTestAppExecutableLinkWith (string targetDirectory, Profile profile = Profile.Classic) + { + string compiled_linkwith_app; + if (compiled_linkwith_apps.TryGetValue (profile, out compiled_linkwith_app) && File.Exists (compiled_linkwith_app)) + return compiled_linkwith_app; + + string cs = Path.Combine (targetDirectory, "testApp.cs"); + string exe = Path.Combine (targetDirectory, "testApp" + GetProjectSuffix (profile) + ".exe"); + string ns_prefix = profile == Profile.Classic ? "MonoTouch." : string.Empty; + File.WriteAllText (cs, string.Format (@" +using System; +public class TestApp {{ + static void Main () + {{ + Console.WriteLine (typeof ({0}UIKit.UIWindow).ToString ()); + Console.WriteLine (Bindings.Test.CFunctions.theUltimateAnswer ()); + Console.WriteLine (typeof (Bindings.Test.UltimateMachine).ToString ()); + }} + }}", ns_prefix)); + + string output; + var args = new StringBuilder (); + args.AppendFormat ("\"{0}\" /noconfig /t:exe /nologo /out:\"{1}\" \"/r:{2}\" /r:\"{3}\"", cs, exe, GetBaseLibrary (profile), GetBindingsLibrary (profile)); + var compiler = GetCompiler (profile, args); + if (ExecutionHelper.Execute (compiler, args.ToString (), out output) != 0) + throw new Exception (output); + + compiled_linkwith_apps [profile] = exe; + return exe; + } + + static void VerifyGC (string file, bool isBoehm, string message) + { + var symbols = ExecutionHelper.Execute ("nm", file, hide_output: true); + var _sgen_gc_lock = symbols.Contains ("_sgen_gc_lock"); + if (isBoehm && _sgen_gc_lock) { + Assert.Fail ("Expected '{0}' to use Boehm: {1}", file, message); + } else if (!isBoehm && !_sgen_gc_lock) { + Assert.Fail ("Expected '{0}' to use SGen: {1}", file, message); + } + } + + static void VerifyArchitectures (string file, string message, params string[] expected) + { + var actual = GetArchitectures (file).ToArray (); + + Array.Sort (expected); + Array.Sort (actual); + + var e = string.Join (", ", expected); + var a = string.Join (", ", actual); + + Assert.AreEqual (e, a, message); + } + + static void VerifyOutput (string msg, string actual, params string[] expected) + { + var split = actual.Split (new char[] {'\n', '\r'}, StringSplitOptions.RemoveEmptyEntries); + var actual_messages = new HashSet (split, new Registrar.PatternEquality ()); + var exp_messages = new HashSet (expected, new Registrar.PatternEquality ()); + + actual_messages.ExceptWith (exp_messages); + exp_messages.ExceptWith (split); + + var text = new StringBuilder (); + foreach (var a in actual_messages) + text.AppendFormat ("Unexpected error/warning ({0}):\n\t{1}\n", msg, a); + foreach (var a in exp_messages) + text.AppendFormat ("Expected error/warning not shown ({0}):\n\t{1}\n", msg, a); + if (text.Length != 0) + Assert.Fail (text.ToString ()); + } + + static List GetArchitectures (string file) + { + var result = new List (); + + using (var fs = File.OpenRead (file)) { + using (var reader = new BinaryReader (fs)) { + int magic = reader.ReadInt32 (); + switch ((uint) magic) { + case 0xCAFEBABE: // little-endian fat binary + throw new NotImplementedException ("little endian fat binary"); + case 0xBEBAFECA: + int architectures = System.Net.IPAddress.NetworkToHostOrder (reader.ReadInt32 ()); + for (int i = 0; i < architectures; i++) { + result.Add (GetArch (System.Net.IPAddress.NetworkToHostOrder (reader.ReadInt32 ()), System.Net.IPAddress.NetworkToHostOrder (reader.ReadInt32 ()))); + // skip to next entry + reader.ReadInt32 (); // offset + reader.ReadInt32 (); // size + reader.ReadInt32 (); // align + } + break; + case 0xFEEDFACE: // little-endian mach-o header + case 0xFEEDFACF: // little-endian 64-big mach-o header + result.Add (GetArch (reader.ReadInt32 (), reader.ReadInt32 ())); + break; + case 0xCFFAEDFE: + case 0xCEFAEDFE: + result.Add (GetArch (System.Net.IPAddress.NetworkToHostOrder (reader.ReadInt32 ()), System.Net.IPAddress.NetworkToHostOrder (reader.ReadInt32 ()))); + break; + default: + throw new Exception (string.Format ("File '{0}' is neither a Universal binary nor a Mach-O binary (magic: 0x{1})", file, magic.ToString ("x"))); + } + } + } + + return result; + } + + static string GetArch (int cputype, int cpusubtype) + { + const int ABI64 = 0x01000000; + const int X86 = 7; + const int ARM = 12; + + switch (cputype) { + case ARM : // arm + switch (cpusubtype) { + case 6: return "armv6"; + case 9: return "armv7"; + case 11: return "armv7s"; + default: + return "unknown arm variation: " + cpusubtype.ToString (); + } + case ARM | ABI64: + switch (cpusubtype) { + case 0: + return "arm64"; + default: + return "unknown arm/64 variation: " + cpusubtype.ToString (); + } + case X86: // x86 + return "i386"; + case X86 | ABI64: // x64 + return "x86_64"; + } + + return string.Format ("unknown: {0}/{1}", cputype, cpusubtype); + } + + public static string Quote (string f) + { + if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1) + return f; + + var s = new StringBuilder (); + + s.Append ('"'); + foreach (var c in f){ + if (c == '"' || c == '\\') + s.Append ('\\'); + + s.Append (c); + } + s.Append ('"'); + + return s.ToString (); + } + + public static string GetTempDirectory () + { + var tmp = Path.GetTempFileName (); + File.Delete (tmp); + Directory.CreateDirectory (tmp); + return tmp; + } +#endregion + } + + class McsException : Exception { + public McsException (string output) + : base (output) + { + } + } + + class ActivationException : Exception { + public ActivationException (string output) + : base (output) + { + } + } +} diff --git a/tests/mtouch/MTouchTool.cs b/tests/mtouch/MTouchTool.cs new file mode 100644 index 000000000000..6d670f1ebfc8 --- /dev/null +++ b/tests/mtouch/MTouchTool.cs @@ -0,0 +1,366 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Text; +using System.Xml; + +using Xamarin.Tests; + +namespace MTouchTests +{ + public enum MTouchAction + { + None, + BuildDev, + BuildSim, + } + + enum MTouchLinker + { + Unspecified, + LinkAll, + LinkSdk, + DontLink, + } + + enum MTouchRegistrar + { + Unspecified, + Dynamic, + Static, + } + + [Flags] + enum I18N + { + None = 0, + + CJK = 1, + MidEast = 2, + Other = 4, + Rare = 8, + West = 16, + + All = CJK | MidEast | Other | Rare | West, + Base + } + + class MTouchTool : Tool, IDisposable + { + public const string None = "None"; + +#pragma warning disable 649 + // These map directly to mtouch options + public int Verbosity; + public string SdkRoot; + public bool? NoSign; + public bool? Debug; + public bool? FastDev; + public bool? Dlsym; + public string Sdk; + public string [] References; + public string Executable; + public string TargetFramework; + public string Abi; + public string AppPath; + public string Cache; + public MTouchLinker Linker; + public bool? NoFastSim; + public MTouchRegistrar Registrar; + public I18N I18N; +#pragma warning restore 649 + + // These are a bit smarter + public MTouch.Profile Profile = MTouch.Profile.Classic; + + static XmlDocument device_list_cache; + + List directories_to_delete; + + public class DeviceInfo + { + public string UDID; + public string Name; + public string CompanionIdentifier; + public string DeviceClass; + + public DeviceInfo Companion; + } + + string GetVerbosity () + { + if (Verbosity == 0) { + return string.Empty; + } else if (Verbosity > 0) { + return new string ('-', Verbosity).Replace ("-", "-v "); + } else { + return new string ('-', -Verbosity).Replace ("-", "-q "); + } + } + + public int LaunchOnDevice (DeviceInfo device, string appPath, bool waitForUnlock, bool waitForExit) + { + return Execute ("--devname \"{0}\" --launchdev \"{1}\" --sdkroot \"{2}\" --wait-for-unlock:{3} --wait-for-exit:{4} {5}", device.Name, appPath, Configuration.xcode_root, waitForUnlock ? "yes" : "no", waitForExit ? "yes" : "no", GetVerbosity ()); + } + + public int InstallOnDevice (DeviceInfo device, string appPath, string devicetype = null) + { + return Execute ("--devname \"{0}\" --installdev \"{1}\" --sdkroot \"{2}\" {3} {4}", device.Name, appPath, Configuration.xcode_root, GetVerbosity (), devicetype == null ? string.Empty : "--device " + devicetype); + } + + public int Execute (MTouchAction action) + { + return Execute (BuildArguments (action)); + } + + string BuildArguments (MTouchAction action) + { + var sb = new StringBuilder (); + var isDevice = false; + + switch (action) { + case MTouchAction.None: + break; + case MTouchAction.BuildDev: + if (AppPath == null) + throw new Exception ("No AppPath specified."); + isDevice = true; + sb.Append (" --dev ").Append (MTouch.Quote (AppPath)); + break; + case MTouchAction.BuildSim: + isDevice = false; + if (AppPath == null) + throw new Exception ("No AppPath specified."); + sb.Append (" --sim ").Append (MTouch.Quote (AppPath)); + break; + default: + throw new NotImplementedException (); + } + + if (SdkRoot == None) { + // do nothing + } else if (!string.IsNullOrEmpty (SdkRoot)) { + sb.Append (" --sdkroot ").Append (MTouch.Quote (SdkRoot)); + } else { + sb.Append (" --sdkroot ").Append (MTouch.Quote (Configuration.xcode_root)); + } + + sb.Append (" ").Append (GetVerbosity ()); + + if (!NoSign.HasValue && Profile == MTouch.Profile.Classic) { + sb.Append (" --nosign"); + } else if (NoSign.HasValue && NoSign.Value && Profile == MTouch.Profile.Classic) + sb.Append (" --nosign"); + + if (Sdk == None) { + // do nothing + } else if (!string.IsNullOrEmpty (Sdk)) { + sb.Append (" --sdk ").Append (Sdk); + } else { + sb.Append (" --sdk ").Append (MTouch.GetSdkVersion (Profile)); + } + + if (Debug.HasValue && Debug.Value) + sb.Append (" --debug"); + + if (FastDev.HasValue && FastDev.Value) + sb.Append (" --fastdev"); + + if (Dlsym.HasValue) + sb.Append (" --dlsym:").Append (Dlsym.Value ? "true" : "false"); + + if (References != null) { + foreach (var r in References) + sb.Append (" -r:").Append (MTouch.Quote (r)); + } + + if (!string.IsNullOrEmpty (Executable)) + sb.Append (" ").Append (MTouch.Quote (Executable)); + + if (TargetFramework == None) { + // do nothing + } else if (!string.IsNullOrEmpty (TargetFramework)) { + sb.Append (" --target-framework ").Append (TargetFramework); + } else { + // make the implicit default the way tests have been running until now, and at the same time the very minimum to make apps build. + switch (Profile) { + case MTouch.Profile.Classic: + break; + case MTouch.Profile.Unified: + sb.Append (" -r:").Append (MTouch.Quote (Configuration.XamarinIOSDll)); + break; + case MTouch.Profile.TVOS: + case MTouch.Profile.WatchOS: + sb.Append (" --target-framework ").Append (MTouch.GetTargetFramework (Profile)); + sb.Append (" -r:").Append (MTouch.Quote (MTouch.GetBaseLibrary (Profile))); + break; + default: + throw new NotImplementedException (); + } + } + + if (!string.IsNullOrEmpty (Abi)) { + sb.Append (" --abi ").Append (Abi); + } else { + switch (Profile) { + case MTouch.Profile.Classic: + case MTouch.Profile.Unified: + break; // not required + case MTouch.Profile.TVOS: + sb.Append (isDevice ? " --abi arm64" : " --abi x86_64"); + break; + case MTouch.Profile.WatchOS: + sb.Append (isDevice ? " --abi armv7k" : " --abi i386"); + break; + default: + throw new NotImplementedException (); + } + } + + switch (Linker) { + case MTouchLinker.LinkAll: + case MTouchLinker.Unspecified: + break; + case MTouchLinker.DontLink: + sb.Append (" --nolink"); + break; + case MTouchLinker.LinkSdk: + sb.Append (" --linksdkonly"); + break; + default: + throw new NotImplementedException (); + } + + if (NoFastSim.HasValue && NoFastSim.Value) + sb.Append (" --nofastsim"); + + switch (Registrar) { + case MTouchRegistrar.Unspecified: + break; + case MTouchRegistrar.Dynamic: + sb.Append (" --registrar:static"); + break; + case MTouchRegistrar.Static: + sb.Append (" --registrar:static"); + break; + default: + throw new NotImplementedException (); + } + + if (I18N != I18N.None) { + sb.Append (" --i18n "); + int count = 0; + if ((I18N & I18N.CJK) == I18N.CJK) + sb.Append (count++ == 0 ? string.Empty : ",").Append ("cjk"); + if ((I18N & I18N.MidEast) == I18N.MidEast) + sb.Append (count++ == 0 ? string.Empty : ",").Append ("mideast"); + if ((I18N & I18N.Other) == I18N.Other) + sb.Append (count++ == 0 ? string.Empty : ",").Append ("other"); + if ((I18N & I18N.Rare) == I18N.Rare) + sb.Append (count++ == 0 ? string.Empty : ",").Append ("rare"); + if ((I18N & I18N.West) == I18N.West) + sb.Append (count++ == 0 ? string.Empty : ",").Append ("west"); + } + + if (!string.IsNullOrEmpty (Cache)) + sb.Append (" --cache ").Append (MTouch.Quote (Cache)); + + return sb.ToString (); + } + + XmlDocument FetchDeviceList (bool allowCache = true) + { + if (device_list_cache == null || !allowCache) { + var output_file = Path.GetTempFileName (); + try { + if (Execute ("--listdev:{1} --sdkroot {0} --output-format xml", Configuration.xcode_root, output_file) != 0) + throw new Exception ("Failed to list devices."); + device_list_cache = new XmlDocument (); + device_list_cache.Load (output_file); + } finally { + File.Delete (output_file); + } + } + return device_list_cache; + } + + public List ListDevices () + { + var rv = new List (); + + foreach (XmlNode node in FetchDeviceList ().SelectNodes ("//MTouch/Device")) { + rv.Add (new DeviceInfo () { + UDID = node.SelectSingleNode ("UDID")?.InnerText, + Name = node.SelectSingleNode ("Name")?.InnerText, + CompanionIdentifier = node.SelectSingleNode ("CompanionIdentifier")?.InnerText, + DeviceClass = node.SelectSingleNode ("DeviceClass")?.InnerText, + }); + } + + foreach (var device in rv) { + if (string.IsNullOrEmpty (device.CompanionIdentifier)) + continue; + + device.Companion = rv.FirstOrDefault ((d) => d.UDID == device.CompanionIdentifier); + } + + return rv; + } + + public IEnumerable FindAvailableDevices (string [] deviceClasses) + { + return ListDevices ().Where ((info) => deviceClasses.Contains (info.DeviceClass)); + } + + public string NativeExecutablePath { + get { + return Path.Combine (AppPath, Path.GetFileNameWithoutExtension (Executable)); + } + } + + public void CreateTemporaryApp (string code = null) + { + var testDir = CreateTemporaryDirectory (); + var app = Path.Combine (testDir, "testApp.app"); + Directory.CreateDirectory (app); + + AppPath = app; + Executable = MTouch.CompileTestAppExecutable (testDir, code: code, profile: Profile); + } + + public string CreateTemporaryDirectory () + { + var tmpDir = MTouch.GetTempDirectory (); + if (directories_to_delete == null) + directories_to_delete = new List (); + directories_to_delete.Add (tmpDir); + return tmpDir; + } + + public void CreateTemporaryApp_LinkWith () + { + AppPath = CreateTemporaryAppDirectory (); + Executable = MTouch.CompileTestAppExecutableLinkWith (Path.GetDirectoryName (AppPath), profile: Profile); + } + + public string CreateTemporaryAppDirectory () + { + if (AppPath != null) + throw new Exception ("There already is an App directory"); + + AppPath = Path.Combine (CreateTemporaryDirectory (), "testApp.app"); + Directory.CreateDirectory (AppPath); + + return AppPath; + } + + void IDisposable.Dispose () + { + if (directories_to_delete != null) { + foreach (var dir in directories_to_delete) + Directory.Delete (dir, true); + } + } + } +} diff --git a/tests/mtouch/Makefile b/tests/mtouch/Makefile new file mode 100644 index 000000000000..83b6fb7a9ab1 --- /dev/null +++ b/tests/mtouch/Makefile @@ -0,0 +1,45 @@ +TOP=../../../xamarin-macios + +include $(TOP)/Make.config + +export MD_MTOUCH_SDK_ROOT=$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX) +export XBUILD_FRAMEWORK_FOLDERS_PATH=$(IOS_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks +export MSBuildExtensionsPath=$(IOS_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild + +check: run-tests + +NUNIT_MSBUILD_DIR=$(TOP)/tests/packages/NUnit.Runners.2.6.4/tools/lib + +all-local:: + $(MAKE) dependencies + $(MAKE) run-tests + +run-tests: test.config + rm -f .failed-stamp + cd $(NUNIT_MSBUILD_DIR) && $(SYSTEM_MONO) ../nunit-console.exe $(abspath $(TOP)/tests/mtouch/bin/Debug/mtouch.dll) -xml=$(abspath $(CURDIR)/TestResult.xml) -noshadow $(TEST_FIXTURE) -labels -nodots || touch .failed-stamp + @# Create an html file and tell MonkeyWrench to upload it (if we're running there) + @[[ -z "$$BUILD_REPOSITORY" ]] || \ + ( xsltproc $(TOP)/tests/HtmlTransform.xslt TestResult.xml > index.html && \ + echo "@MonkeyWrench: AddFile: $$PWD/index.html") + @[[ ! -e .failed-stamp ]] + +build: + $(Q) $(SYSTEM_MONO) /Library/Frameworks//Mono.framework/Versions/Current/lib/mono/nuget/NuGet.exe restore $(TOP)/tests/tests.sln + $(SYSTEM_XBUILD) mtouch.csproj $(XBUILD_VERBOSITY) + $(Q) rm -f .failed-stamp + +mt9000: build + /Library/Frameworks/Mono.framework/Commands/nunit-console4 -labels bin/Debug/*.dll -noshadow -fixture=MTouchTests.MTouch -run MTouchTests.MTouch.MT9008 || touch .failed-stamp + +test.config: $(TOP)/Make.config Makefile + @rm -f $@ + @echo "MONOTOUCH_PREFIX=$(MONOTOUCH_PREFIX)" >> $@ + @echo "SDK_VERSION=$(IOS_SDK_VERSION)" >> $@ + @echo "XCODE_DEVELOPER_ROOT=$(XCODE_DEVELOPER_ROOT)" >> $@ + @echo "DESTDIR=$(IOS_DESTDIR)" >> $@ + @echo "IOS_DESTDIR=$(IOS_DESTDIR)" >> $@ + +dependencies: + cd .. && $(MAKE) + $(MAKE) -C $(TOP)/tests/test-libraries + $(MAKE) build diff --git a/tests/mtouch/MiscTests.cs b/tests/mtouch/MiscTests.cs new file mode 100644 index 000000000000..78054aeda12c --- /dev/null +++ b/tests/mtouch/MiscTests.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; +using Xamarin.Tests; + +using NUnit.Framework; + +namespace Xamarin.Tests +{ + [TestFixture] + public class Misc + { + [Test] + public void InvalidStructOffset () + { + var str = "invalid struct offset"; + var contents = ASCIIEncoding.ASCII.GetBytes (str); + + foreach (var sdk in new string [] { "iphoneos", "iphonesimulator"}) { + foreach (var ext in new string [] { "dylib", "a" }) { + var fn = Path.Combine (Configuration.MonoTouchRootDirectory, "SDKs", "MonoTouch." + sdk + ".sdk", "usr", "lib", "libmonosgen-2.0." + ext); + Assert.IsFalse (Contains (fn, contents), "Found \"{0}\" in {1}", str, fn); + } + } + } + + bool Contains (string file, byte[] contents) + { + var pagesize = 4096; + var buffer = new byte [pagesize * 1024]; + int read; + + using (var fs = new FileStream (file, FileMode.Open, FileAccess.Read)) { + while ((read = fs.Read (buffer, 0, buffer.Length)) > 0) { + for (int i = 0; i < read - contents.Length; i++) { + if (buffer [i] == contents [0]) { + var found = true; + for (int c = 1; c < contents.Length; c++) { + if (buffer [i + c] != contents [c]) { + found = false; + break; + } + } + if (found) + return true; + } + } + if (fs.Position == fs.Length) + break; + fs.Position -= pagesize; // return a bit so that we don't miss contents spanning multiple reads. + } + } + + return false; + } + + [Test] + public void VerifySymbols () + { + var prohibited_symbols = new string [] { "_NSGetEnviron", "PKService", "SPPluginDelegate" }; + + foreach (var symbol in prohibited_symbols) { + var contents = ASCIIEncoding.ASCII.GetBytes (symbol); + var sdk = "iphoneos"; // we don't care about private symbols for simulator builds + foreach (var static_lib in Directory.EnumerateFiles (Path.Combine (Configuration.MonoTouchRootDirectory, "SDKs", "MonoTouch." + sdk + ".sdk", "usr", "lib"), "*.a")) { + Assert.IsFalse (Contains (static_lib, contents), "Found \"{0}\" in {1}", symbol, static_lib); + } + } + } + } +} + diff --git a/tests/mtouch/RegistrarTest.cs b/tests/mtouch/RegistrarTest.cs new file mode 100644 index 000000000000..02a2d8aea768 --- /dev/null +++ b/tests/mtouch/RegistrarTest.cs @@ -0,0 +1,1388 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; +using Xamarin.Tests; + +using NUnit.Framework; + +namespace MTouchTests +{ + [TestFixture] + public class Registrar + { + enum R { + OldStatic = 1, + OldDynamic = 2, + Static = 4, + Dynamic = 8, + AllOld = OldStatic | OldDynamic, + AllNew = Static | Dynamic, + All = AllOld | AllNew, + AllStatic = OldStatic | Static, + AllDynamic = OldDynamic | Dynamic, + } + + [Test] + public void InvalidParameterTypes () + { + var code = @" +class Foo : NSObject { + [Export (""bar1:"")] + public void Bar1 (object[] arg) + { + } + + [Export (""bar2:"")] + public void Bar2 (ref object arg) + { + } + + [Export (""bar3:"")] + public void Bar3 (out object arg) + { + arg = null; + } + + [Export (""bar4:"")] + public void Bar4 (object arg) + { + } + + [Export (""bar5"")] + public object Bar5 () + { + return null; + } + + [Export (""bar6:"")] + public void Bar6 (int? arg) + { + } + + [Export (""bar7"")] + public int? Bar7 () + { + return null; + } + + [Export (""bar8:"")] + public void Bar8 (ref int?[] arg) + { + } + + [Export (""bar9:"")] + public static void Bar9 (Attribute attribute) + { + } + + [Export (""bar10"")] + public object Bar10 { get; set; } + + public object[] Bar11 { + [Export (""bar11Getter"")] + get { return null; } + [Export (""bar11Setter:"")] + set {} + } +} +"; + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4138: The registrar cannot marshal the property type 'System.Object' of the property 'Foo.Bar10'.", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Object[]' of the parameter 'arg' in the method 'Foo.Bar1(System.Object[])'", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Object&' of the parameter 'arg' in the method 'Foo.Bar2(System.Object&)'", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Object&' of the parameter 'arg' in the method 'Foo.Bar3(System.Object&)'", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Object' of the parameter 'arg' in the method 'Foo.Bar4(System.Object)'", + ".*/Test.cs(.*): error MT4104: The registrar cannot marshal the return value of type `System.Object` in the method `Foo.Bar5()`.", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Nullable`1' of the parameter 'arg' in the method 'Foo.Bar6(System.Nullable`1)'", + ".*/Test.cs(.*): error MT4104: The registrar cannot marshal the return value of type `System.Nullable`1` in the method `Foo.Bar7()`.", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Nullable`1[]&' of the parameter 'arg' in the method 'Foo.Bar8(System.Nullable`1[]&)'", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Attribute' of the parameter 'attribute' in the method 'Foo.Bar9(System.Attribute)'", + ".*/Test.cs(.*): error MT4104: The registrar cannot marshal the return value of type `System.Object[]` in the method `Foo.get_Bar11()`.", + ".*/Test.cs(.*): error MT4136: The registrar cannot marshal the parameter type 'System.Object[]' of the parameter 'value' in the method 'Foo.set_Bar11(System.Object[])'"); + + Verify (R.OldStatic, code, false, "error MT4111: The registrar cannot build a signature for type `System.Object' in method `Foo.get_Bar10`."); + } + + [Test] + public void MT4102 () + { + var code = @" +class DateMembers : NSObject { + [Export (""F1:"")] + void F1 (DateTime a) {} + + [Export (""F2"")] + DateTime F2 () { throw new Exception (); } + + [Export (""F3:"")] + void F3 (ref DateTime d) {} + + [Export (""F4"")] + DateTime F4 { get; set; } +} +"; + + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4138: The registrar cannot marshal the property type 'System.DateTime' of the property 'DateMembers.F4'.", + ".*/Test.cs(.*): error MT4102: The registrar found an invalid type `System.DateTime` in signature for method `DateMembers.F1`. Use `MonoTouch.Foundation.NSDate` instead.", + ".*/Test.cs(.*): error MT4102: The registrar found an invalid type `System.DateTime` in signature for method `DateMembers.F2`. Use `MonoTouch.Foundation.NSDate` instead.", + ".*/Test.cs(.*): error MT4102: The registrar found an invalid type `System.DateTime` in signature for method `DateMembers.F3`. Use `MonoTouch.Foundation.NSDate` instead."); + Verify (R.OldStatic, code, false, + "error MT4102: The registrar found an invalid type `System.DateTime` in signature for method `DateMembers.set_F4`. Use `MonoTouch.Foundation.NSDate` instead.", + "error MT4102: The registrar found an invalid type `System.DateTime` in signature for method `DateMembers.F1`. Use `MonoTouch.Foundation.NSDate` instead.", + "error MT4102: The registrar found an invalid type `System.DateTime` in signature for method `DateMembers.F3`. Use `MonoTouch.Foundation.NSDate` instead."); + } + + [Test] + public void MT4117 () + { + var code = @" +class ArgCount : NSObject { + [Export (""F1"")] + void F1 (int a) {} + + [Export (""F2:"")] + void F2 () {} + + [Export (""F3"", IsVariadic = true)] + void F3 () {} +} +"; + + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4117: The registrar found a signature mismatch in the method 'ArgCount.F1' - the selector 'F1' indicates the method takes 0 parameters, while the managed method has 1 parameters.", + ".*/Test.cs(.*): error MT4117: The registrar found a signature mismatch in the method 'ArgCount.F2' - the selector 'F2:' indicates the method takes 1 parameters, while the managed method has 0 parameters.", + ".*/Test.cs(.*): error MT4140: The registrar found a signature mismatch in the method 'ArgCount.F3' - the selector 'F3' indicates the variadic method takes 1 parameters, while the managed method has 0 parameters."); + Verify (R.OldStatic, code, true); + } + + [Test] + public void MT4123 () + { + var code = @" +class ArgCount : NSObject { + [Export (""F2"", IsVariadic = true)] + void F2 (System.IntPtr foo) {} + + [Export (""F3"", IsVariadic = true)] + void F3 (int foo) {} + + [Export (""F4:"", IsVariadic = true)] + void F4 (int foo, IntPtr bar) {} +} +"; + + Verify (R.Static, code, false, ".*/Test.cs(.*): error MT4123: The type of the variadic parameter in the variadic function 'F3(System.Int32)' must be System.IntPtr."); + Verify (R.OldStatic, code, true); + } + + [Test] + public void MT4127 () + { + var str1 = @" +[Protocol] +interface IFoo1 { + [Preserve (Conditional = true)] + [Export (""foo"")] + void GetFoo (); +} + +[Protocol] +interface IFoo2 { + [Preserve (Conditional = true)] + [Export (""foo"")] + void GetFoo (); +} + +[Preserve ()] +class MyObjectErr : NSObject, IFoo1, IFoo2 +{ + public void GetFoo () + { + throw new NotImplementedException (); + } +} +"; + + Verify (R.Static, str1, false, + "error MT4127: Cannot register more than one interface method for the method 'MyObjectErr.GetFoo' (which is implementing 'IFoo1.GetFoo' and 'IFoo2.GetFoo')."); + + } + + [Test] + public void MT4134 () + { + if (!Directory.Exists (Configuration.xcode6_root)) + Assert.Ignore ("Xcode 6 ({0}) is required for this test.", Configuration.xcode6_root); + + // This test will have to be updated when new frameworks are introduced. + VerifyWithXcode (R.Static, MTouch.Profile.Unified, string.Empty, false, Configuration.xcode6_root, "8.0", + "warning MT0079: The recommended Xcode version for Xamarin.iOS .* is Xcode .* or later. The current Xcode version .found in " + Configuration.xcode6_root + ". is 6.*.", + "error MT4134: Your application is using the 'Contacts' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'CoreSpotlight' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'GameplayKit' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'MetalKit' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'ModelIO' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'MetalPerformanceShaders' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'WatchKit' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 8.2, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'ContactsUI' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'ReplayKit' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options.", + "error MT4134: Your application is using the 'WatchConnectivity' framework, which isn't included in the iOS SDK you're using to build your app (this framework was introduced in iOS 9.0, while you're building with the iOS 8.0 SDK.) This configuration is only supported with the legacy registrar (pass --registrar:legacy as an additional mtouch argument in your project's iOS Build option to select). Alternatively select a newer SDK in your app's iOS Build options."); + VerifyWithXcode (R.OldStatic, string.Empty, true, Configuration.xcode6_root, "8.0", + "warning MT0079: The recommended Xcode version for Xamarin.iOS .* is Xcode .* or later. The current Xcode version .found in " + Configuration.xcode6_root + ". is 6.*."); + } + + [Test] + public void MT4135 () + { + var code = @" +class C : NSObject { + [Export ()] + public void Foo () {} + + [Export (null)] + public void Bar () {} + + [Export ("""")] + public void Zap () {} +}"; + Verify (R.Static, code, false, + ".*Test.cs(.*): error MT4135: The member 'C.Foo' has an Export attribute without a selector. A selector is required.", + ".*Test.cs(.*): error MT4135: The member 'C.Bar' has an Export attribute without a selector. A selector is required.", + ".*Test.cs(.*): error MT4135: The member 'C.Zap' has an Export attribute without a selector. A selector is required."); + } + + [Test] + public void MT4138 () + { + var code = @" +class C : NSObject { + [Export (""foo"")] + object Foo { get { return null; } } +} +"; + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4138: The registrar cannot marshal the property type 'System.Object' of the property 'C.Foo'."); + Verify (R.OldStatic, code, false, "error MT4111: The registrar cannot build a signature for type `System.Object' in method `C.get_Foo`."); + } + + [Test] + public void MT4139 () + { + var code = @" +class C : NSObject { + [Connect] + object P1 { get { return null; } } + + [Connect] + int P2 { get { return 0; } } +} +"; + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4139: The registrar cannot marshal the property type 'System.Object' of the property 'C.P1'. Properties with the .Connect. attribute must have a property type of NSObject (or a subclass of NSObject).", + ".*/Test.cs(.*): error MT4139: The registrar cannot marshal the property type 'System.Int32' of the property 'C.P2'. Properties with the .Connect. attribute must have a property type of NSObject (or a subclass of NSObject)."); + Verify (R.OldStatic, code, true); + } + + [Test] + public void MT4141 () + { + var code = @" +class C : NSObject { + [Export (""retain"")] + new void Retain () {} + + [Export (""release"")] + new void Release () {} + + [Export (""dealloc"")] + new void Dealloc () {} +} +"; + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4141: Cannot register the selector 'retain' on the member 'C.Retain' because Xamarin.iOS implicitly registers this selector.", + ".*/Test.cs(.*): error MT4141: Cannot register the selector 'release' on the member 'C.Release' because Xamarin.iOS implicitly registers this selector."); + Verify (R.OldStatic, code, true); + } + + [Test] + public void MT4145 () + { + var code = @" +[Native] +public enum Foo : int +{ +} +class C : NSObject { + [Export (""nativeEnum1:"")] + void NativeEnum1 (Foo foo) {} +} +"; + VerifyDual (R.Static, code, false, "error MT4145: Invalid enum 'Foo': enums with the [Native] attribute must have a underlying enum type of either 'long' or 'ulong'."); + + Verify (R.Static, code, true); + } + + [Test] + public void MT4146 () + { + var code = @" +[Register ("" C"")] +class C : NSObject { +} +"; + VerifyDual (R.Static, code, true, "warning MT4146: The Name parameter of the Registrar attribute on the class 'C' contains an invalid character: ' ' (0x20)"); + Verify (R.Static, code, true, "warning MT4146: The Name parameter of the Registrar attribute on the class 'C' contains an invalid character: ' ' (0x20)"); + } + + [Test] + public void MT4148 () + { + var code = @" +[Protocol] +interface IProtocol { +} +[Protocol] +interface IProtocol2 { + [Export (""M"")] + void M (); +} +"; + VerifyDual (R.Static, code, false, + "error MT4148: The registrar found a generic protocol: 'IProtocol`1'. Exporting generic protocols is not supported.", + "error MT4113: The registrar found a generic method: 'IProtocol2.M()'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes"); + Verify (R.Static, code, false, + "error MT4148: The registrar found a generic protocol: 'IProtocol`1'. Exporting generic protocols is not supported.", + "error MT4113: The registrar found a generic method: 'IProtocol2.M()'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes"); + } + + [Test] + public void MT4149 () + { + var code = @" +[Category (typeof (NSString))] +public static class Category +{ + [Export (""foo"")] + public static void Foo (this int bar) {} +} +"; + VerifyDual (R.Static, code, false, + ".*/Test.cs(.*): error MT4149: Cannot register the extension method 'Category.Foo' because the type of the first parameter ('System.Int32') does not match the category type ('Foundation.NSString')."); + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4149: Cannot register the extension method 'Category.Foo' because the type of the first parameter ('System.Int32') does not match the category type ('MonoTouch.Foundation.NSString')."); + } + + [Test] + public void MT4150 () + { + var code = @" +[Category (typeof (string))] +public static class Category +{ +} +"; + VerifyDual (R.Static, code, false, + "error MT4150: Cannot register the type 'Category' because the category type 'System.String' in its Category attribute does not inherit from NSObject."); + Verify (R.Static, code, false, + "error MT4150: Cannot register the type 'Category' because the category type 'System.String' in its Category attribute does not inherit from NSObject."); + } + + [Test] + public void MT4151 () + { + var code = @" +[Category (null)] +public static class Category +{ +} +"; + VerifyDual (R.Static, code, false, + "error MT4151: Cannot register the type 'Category' because the Type property in its Category attribute isn't set."); + Verify (R.Static, code, false, + "error MT4151: Cannot register the type 'Category' because the Type property in its Category attribute isn't set."); + } + + [Test] + public void MT4152 () + { + var code = @" +[Category (typeof (NSString))] +public class Category1 : NSObject +{ +} +[Category (typeof (NSString))] +public class Category2 : INativeObject +{ + public IntPtr Handle { get { return IntPtr.Zero; } } +} +"; + VerifyDual (R.Static, code, false, + "error MT4152: Cannot register the type 'Category1' as a category because it implements INativeObject or subclasses NSObject.", + "error MT4152: Cannot register the type 'Category2' as a category because it implements INativeObject or subclasses NSObject."); + Verify (R.Static, code, false, + "error MT4152: Cannot register the type 'Category1' as a category because it implements INativeObject or subclasses NSObject.", + "error MT4152: Cannot register the type 'Category2' as a category because it implements INativeObject or subclasses NSObject."); + } + + [Test] + public void MT4153 () + { + var code = @" +[Category (typeof (NSString))] +public class Category +{ +} +"; + VerifyDual (R.Static, code, false, + "error MT4153: Cannot register the type 'Category`1' as a category because it's generic."); + Verify (R.Static, code, false, + "error MT4153: Cannot register the type 'Category`1' as a category because it's generic."); + } + + [Test] + public void MT4154 () + { + var code = @" +[Category (typeof (NSString))] +public class Category +{ + [Export (""foo"")] + public static void Foo () {} +} +"; + VerifyDual (R.Static, code, false, + ".*/Test.cs(.*): error MT4154: Cannot register the method 'Category.Foo' as a category method because it's generic."); + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4154: Cannot register the method 'Category.Foo' as a category method because it's generic."); + } + + // MT4155 only happens with the dynamic registrar + + [Test] + public void MT4156 () + { + var code = @" +[Category (typeof (NSString), Name = ""C"")] +public class Category1 +{ +} +[Category (typeof (NSString), Name = ""C"")] +public class Category2 +{ +} +"; + VerifyDual (R.Static, code, false, + "error MT4156: Cannot register two categories ('Category2, Test' and 'Category1, Test') with the same native name ('C')"); + Verify (R.Static, code, false, + "error MT4156: Cannot register two categories ('Category2, Test' and 'Category1, Test') with the same native name ('C')"); + } + + // MT4157 Can't be produced using C#, since it requires using [Extension] manually: + // Test.cs(14,35): error CS1112: Do not use `System.Runtime.CompilerServices.ExtensionAttribute' directly. Use parameter modifier `this' instead + + [Test] + public void MT4158 () + { + var code = @" +[Category (typeof (NSString))] +public class Category +{ + [Export (""init"")] + public Category () {} +} +"; + VerifyDual (R.Static, code, false, + ".*/Test.cs(.*): error MT4158: Cannot register the constructor Category..ctor() in the category Category because constructors in categories are not supported."); + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4158: Cannot register the constructor Category..ctor() in the category Category because constructors in categories are not supported."); + } + + [Test] + public void MT4159 () + { + var code = @" +[Category (typeof (NSString))] +public class Category +{ + [Export (""foo"")] + public void Foo () {} +} +"; + VerifyDual (R.Static, code, false, + ".*/Test.cs(.*): error MT4159: Cannot register the method 'Category.Foo' as a category method because category methods must be static."); + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4159: Cannot register the method 'Category.Foo' as a category method because category methods must be static."); + } + + [Test] + public void MT4160 () + { + var code = @" +public class TestInvalidChar : NSObject +{ + [Export (""xy z"")] + public void XyZ () {} + [Export (""ab\tc"")] + public void AbC () {} +} +"; + VerifyDual (R.Static, code, false, + ".*/Test.cs(.*): error MT4160: Invalid character ' ' (0x20) found in selector 'xy z' for 'TestInvalidChar.XyZ()'", + ".*/Test.cs(.*): error MT4160: Invalid character '\t' (0x9) found in selector 'ab\tc' for 'TestInvalidChar.AbC()'" + ); + Verify (R.Static, code, false, + ".*/Test.cs(.*): error MT4160: Invalid character ' ' (0x20) found in selector 'xy z' for 'TestInvalidChar.Xyz()'", + ".*/Test.cs(.*): error MT4160: Invalid character '\t' (0x9) found in selector 'ab\tc' for 'TestInvalidChar.AbC()'"); + } + + [Test] + public void MT4161 () + { + var code = @" +public class TestInvalidChar : NSObject +{ + [Export (""foo1"")] + public FooA Foo1 () { return new FooA (); } + + [Export (""foo2:"")] + public void Foo2 (FooB foo) { } + + [Export (""foo3:"")] + public void Foo3 (ref FooC foo) { } + + [Export (""foo4:"")] + public void Foo4 (out FooD foo) { foo = new FooD (); } + + [Export (""foo5:"")] + public void Foo5 (FooE[] foo) { } + + [Export (""foo6"")] + public FooF[] Foo6 () { return null; } +} +public struct FooA { public NSObject Obj; } +public struct FooB { public NSObject Obj; } +public struct FooC { public NSObject Obj; } +public struct FooD { public NSObject Obj; } +public struct FooE { public NSObject Obj; } +public struct FooF { public NSObject Obj; } +"; + VerifyDual (R.Static, code, false, + ".*/Test.cs(.*): error MT4161: The registrar found an unsupported structure 'FooA': All fields in a structure must also be structures (field 'Obj' with type 'Foundation.NSObject' is not a structure).", + ".*/Test.cs(.*): error MT4161: The registrar found an unsupported structure 'FooB': All fields in a structure must also be structures (field 'Obj' with type 'Foundation.NSObject' is not a structure).", + ".*/Test.cs(.*): error MT4161: The registrar found an unsupported structure 'FooC': All fields in a structure must also be structures (field 'Obj' with type 'Foundation.NSObject' is not a structure).", + ".*/Test.cs(.*): error MT4161: The registrar found an unsupported structure 'FooD': All fields in a structure must also be structures (field 'Obj' with type 'Foundation.NSObject' is not a structure).", + ".*/Test.cs(.*): error MT4111: The registrar cannot build a signature for type `FooE[]' in method `TestInvalidChar.Foo5`.", + ".*/Test.cs(.*): error MT4111: The registrar cannot build a signature for type `FooF[]' in method `TestInvalidChar.Foo6`." + + ); + } + + + [Test] + [TestCase (MTouch.Profile.Unified, "iOS")] + [TestCase (MTouch.Profile.TVOS, "tvOS")] + //[TestCase (MTouch.Profile.WatchOS, "watchOS")] // MT0077 interferes + public void MT4162 (MTouch.Profile profile, string name) + { + var code = @" + [Introduced (PlatformName.iOS, 99, 0, 0, PlatformArchitecture.All, ""use Z instead"")] + [Introduced (PlatformName.TvOS, 99, 0, 0, PlatformArchitecture.All, ""use Z instead"")] + [Introduced (PlatformName.WatchOS, 99, 0, 0, PlatformArchitecture.All, ""use Z instead"")] + [Introduced (PlatformName.iOS, 89, 0, 0, PlatformArchitecture.All)] + [Introduced (PlatformName.TvOS, 89, 0, 0, PlatformArchitecture.All)] + [Introduced (PlatformName.WatchOS, 89, 0, 0, PlatformArchitecture.All)] + [Register (IsWrapper = true)] + class FutureType : NSObject + { + public FutureType () {} + } + + class CurrentType : FutureType + { + [Export (""foo:"")] + public void Foo (FutureType ft) + { + } + + [Export (""bar"")] + public FutureType Bar () + { + throw new NotImplementedException (); + } + + [Export (""zap"")] + public FutureType Zap { get; set; } + + // This is actually working now, but only because we erase the generic argument when converting to ObjC. + [Export (""zaps"")] + public NSSet Zaps { get; set; } + } + + [Protocol (Name = ""FutureProtocol"")] + [ProtocolMember (IsRequired = false, IsProperty = true, IsStatic = false, Name = ""FutureProperty"", Selector = ""futureProperty"", PropertyType = typeof (FutureEnum), GetterSelector = ""futureProperty"", SetterSelector = ""setFutureProperty:"", ArgumentSemantic = ArgumentSemantic.UnsafeUnretained)] + [ProtocolMember (IsRequired = true, IsProperty = false, IsStatic = false, Name = ""FutureMethod"", Selector = ""futureMethod"", ReturnType = typeof (FutureEnum), ParameterType = new Type [] { typeof (FutureEnum) }, ParameterByRef = new bool [] { false })] + public interface IFutureProtocol : INativeObject, IDisposable + { + } + + [Introduced (PlatformName.iOS, 99, 0, 0, PlatformArchitecture.All)] + [Introduced (PlatformName.TvOS, 99, 0, 0, PlatformArchitecture.All)] + [Introduced (PlatformName.WatchOS, 99, 0, 0, PlatformArchitecture.All)] + public enum FutureEnum { + } +"; + + Verify (R.Static, profile, code, false, + $"error MT4162: The type 'FutureType' (used as a base type of CurrentType) is not available in {name} .* (it was introduced in {name} 99.0.0): 'use Z instead'. Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $"error MT4162: The type 'FutureType' (used as a base type of CurrentType) is not available in {name} .* (it was introduced in {name} 89.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $".*/Test.cs(.*): error MT4162: The type 'FutureType' (used as the property type of CurrentType.Zap) is not available in {name} .* (it was introduced in {name} 99.0.0): 'use Z instead'. Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $".*/Test.cs(.*): error MT4162: The type 'FutureType' (used as the property type of CurrentType.Zap) is not available in {name} .* (it was introduced in {name} 89.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $".*/Test.cs(.*): error MT4162: The type 'FutureType' (used as a parameter in CurrentType.Foo) is not available in {name} .* (it was introduced in {name} 99.0.0): 'use Z instead'. Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $".*/Test.cs(.*): error MT4162: The type 'FutureType' (used as a parameter in CurrentType.Foo) is not available in {name} .* (it was introduced in {name} 89.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $".*/Test.cs(.*): error MT4162: The type 'FutureType' (used as a return type in CurrentType.Bar) is not available in {name} .* (it was introduced in {name} 99.0.0): 'use Z instead'. Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $".*/Test.cs(.*): error MT4162: The type 'FutureType' (used as a return type in CurrentType.Bar) is not available in {name} .* (it was introduced in {name} 89.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $"error MT4162: The type 'FutureEnum' (used as the property type of IFutureProtocol.FutureProperty) is not available in {name} .* (it was introduced in {name} 99.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $"error MT4162: The type 'FutureEnum' (used as a return type in IFutureProtocol.FutureMethod) is not available in {name} .* (it was introduced in {name} 99.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode).", + $"error MT4162: The type 'FutureEnum' (used as a parameter in IFutureProtocol.FutureMethod) is not available in {name} .* (it was introduced in {name} 99.0.0). Please build with a newer {name} SDK (usually done by using the most recent version of Xcode)." + + ); + } + + [Test] + public void MT4164 () + { + var code = @" + class FutureType : NSObject + { + [Export (""auto"")] string Auto { get; set; } + [Export (""break"")] string Break { get; set; } + [Export (""case"")] string Case { get; set; } + [Export (""char"")] string Char { get; set; } + [Export (""const"")] string Const { get; set; } + [Export (""continue"")] string Continue { get; set; } + [Export (""default"")] string Default { get; set; } + [Export (""do"")] string Do { get; set; } + [Export (""double"")] string Double { get; set; } + [Export (""else"")] string Else { get; set; } + [Export (""enum"")] string Enum { get; set; } + [Export (""export"")] string Export { get; set; } + [Export (""extern"")] string Extern { get; set; } + [Export (""float"")] string Float { get; set; } + [Export (""for"")] string For { get; set; } + [Export (""goto"")] string Goto { get; set; } + [Export (""if"")] string If { get; set; } + [Export (""inline"")] string Inline { get; set; } + [Export (""int"")] string Int { get; set; } + [Export (""long"")] string Long { get; set; } + [Export (""register"")] string Register { get; set; } + [Export (""return"")] string Return { get; set; } + [Export (""short"")] string Short { get; set; } + [Export (""signed"")] string Signed { get; set; } + [Export (""sizeof"")] string Sizeof { get; set; } + [Export (""static"")] string Static { get; set; } + [Export (""struct"")] string Struct { get; set; } + [Export (""switch"")] string Switch { get; set; } + [Export (""template"")] string Template { get; set; } + [Export (""typedef"")] string Typedef { get; set; } + [Export (""union"")] string Union { get; set; } + [Export (""unsigned"")] string Unsigned { get; set; } + [Export (""void"")] string Void { get; set; } + [Export (""volatile"")] string Volatile { get; set; } + [Export (""while"")] string While { get; set; } + [Export (""_Bool"")] string Bool { get; set; } + [Export (""_Complex"")] string Complex { get; set; } + } +"; + + Verify (R.Static, MTouch.Profile.Unified, code, false, MTouch.Target.Sim, + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Auto' because its selector 'auto' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Break' because its selector 'break' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Case' because its selector 'case' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Char' because its selector 'char' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Const' because its selector 'const' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Continue' because its selector 'continue' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Default' because its selector 'default' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Do' because its selector 'do' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Double' because its selector 'double' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Else' because its selector 'else' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Enum' because its selector 'enum' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Export' because its selector 'export' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Extern' because its selector 'extern' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Float' because its selector 'float' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'For' because its selector 'for' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Goto' because its selector 'goto' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'If' because its selector 'if' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Inline' because its selector 'inline' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Int' because its selector 'int' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Long' because its selector 'long' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Register' because its selector 'register' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Return' because its selector 'return' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Short' because its selector 'short' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Signed' because its selector 'signed' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Sizeof' because its selector 'sizeof' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Static' because its selector 'static' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Struct' because its selector 'struct' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Switch' because its selector 'switch' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Template' because its selector 'template' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Typedef' because its selector 'typedef' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Union' because its selector 'union' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Unsigned' because its selector 'unsigned' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Void' because its selector 'void' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Volatile' because its selector 'volatile' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'While' because its selector 'while' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Bool' because its selector '_Bool' is an Objective-C keyword. Please use a different name.", + ".*/Test.cs(.*): error MT4164: Cannot export the property 'Complex' because its selector '_Complex' is an Objective-C keyword. Please use a different name."); + } + + [Test] + public void MultiplePropertiesInHierarchy () + { + // https://bugzilla.xamarin.com/show_bug.cgi?id=18337 + + var code = @" +class C : NSObject { + [Outlet] + string Foo { get; set; } +} +class D : C { + [Outlet] + string Foo { get; set; } +} + +class E : NSObject { + [Export ()] + string Foo { get; set; } +} + +class F : E { + [Export ()] + string Foo { get; set; } +} + +class G : NSObject { + [Connect ()] + NSString Foo { get; set; } +} + +class H : G { + [Connect ()] + NSString Foo { get; set; } +} +"; + + Verify (R.AllStatic, code, true); + } + + void Verify (R registrars, string code, bool success, params string [] expected_messages) + { + VerifyWithXcode (registrars, MTouch.Profile.Classic, code, success, Configuration.xcode_root, Configuration.sdk_version, expected_messages); + } + + void Verify (R registrars, MTouch.Profile profile, string code, bool success, params string [] expected_messages) + { + Verify (registrars, profile, code, success, MTouch.Target.Dev, expected_messages); + } + + void Verify (R registrars, MTouch.Profile profile, string code, bool success, MTouch.Target target, params string [] expected_messages) + { + VerifyWithXcode (registrars, profile, code, success, Configuration.xcode_root, MTouch.GetSdkVersion (profile), target, expected_messages); + } + + void VerifyDual (R registrars, string code, bool success, params string [] expected_messages) + { + VerifyWithXcode (registrars, MTouch.Profile.Unified, code, success, Configuration.xcode_root, Configuration.sdk_version, expected_messages); + } + + void VerifyWithXcode (R registrars, string code, bool success, string xcode, string sdk_version, params string [] expected_messages) + { + VerifyWithXcode (registrars, MTouch.Profile.Classic, code, success, xcode, sdk_version, expected_messages); + } + + void VerifyWithXcode (R registrars, MTouch.Profile profile, string code, bool success, string xcode, string sdk_version, params string [] expected_messages) + { + VerifyWithXcode (registrars, profile, code, success, xcode, sdk_version, MTouch.Target.Dev, expected_messages); + } + + void VerifyWithXcode (R registrars, MTouch.Profile profile, string code, bool success, string xcode, string sdk_version, MTouch.Target target, params string [] expected_messages) + { + foreach (R value in Enum.GetValues (typeof (R))) { + if ((registrars & value) == 0) + continue; + + if (value != R.Dynamic && value != R.Static && value != R.OldDynamic && value != R.OldStatic) + continue; + + string result = string.Empty; + + try { + var header = @" +using System; +using System.Collections.Generic;"; + + if (profile != MTouch.Profile.Classic) { + header += @" +using Foundation; +using UIKit; +using ObjCRuntime;"; + } else { + header += @" +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime;"; + } + + header += @" +class Test { + static void Main () { Console.WriteLine (typeof (NSObject)); } +}"; + + + result = CreateTestApp (profile, header + code, "--registrar:" + value.ToString ().ToLower (), xcode, sdk_version, target); + Assert.IsTrue (success, string.Format ("Expected '{0}' to show the error(s) '{1}' with --registrar:\n\t{2}", code, string.Join ("\n\t", expected_messages), value.ToString ().ToLower ())); + } catch (TestExecutionException mee) { + Assert.IsFalse (success, string.Format ("Expected '{0}' to compile with --registrar:{1}", code, value.ToString ().ToLower ())); + result = mee.Message; + } + + var split = result.Split (new char[] {'\n', '\r'}, StringSplitOptions.RemoveEmptyEntries); + var actual_messages = new HashSet (split, new PatternEquality ()); + var exp_messages = new HashSet (expected_messages, new PatternEquality ()); + + actual_messages.Remove (".*Test.app built successfully."); + actual_messages.Remove ("Xamarin.iOS .* using.*"); + actual_messages.Remove ("warning MT5303: Native linking warning: warning: relocatable dylibs (e.g. embedded frameworks) are only supported on iOS 8.0 and later .*"); + actual_messages.Remove ("warning MT5303: Native linking warning: warning: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@rpath/PushKit.framework/PushKit)"); + + actual_messages.ExceptWith (exp_messages); + exp_messages.ExceptWith (split); + + var text = new StringBuilder (); + foreach (var a in actual_messages) + text.AppendFormat ("Unexpected error/warning with --registrar:{0}:\n\t{1}\n", value.ToString ().ToLower (), a); + foreach (var a in exp_messages) + text.AppendFormat ("Expected with --registrar:{0} to show:\n\t{1}\n", value.ToString ().ToLower (), a); + if (text.Length != 0) + Assert.Fail (text.ToString ()); + } + } + + + internal class PatternEquality : IEqualityComparer + { + public bool Equals (string x, string y) + { + if (x == y) + return true; + try { + if (Regex.IsMatch (x, "^" + y.Replace ("(", "[(]").Replace (")", "[)]").Replace ("[]", "[[][]]") + "$")) { + return true; + } + } catch { + // do nothing + } + + try { + if (Regex.IsMatch (y, "^" + x.Replace ("(", "[(]").Replace (")", "[)]").Replace ("[]", "[[][]]") + "$")) { + return true; + } + } catch { + // do nothing + } + + return false; + } + public int GetHashCode (string obj) + { + return 0; + } + } + + [Test] + public void GenericType_Warnings () + { + var code = @" +class Open : NSObject {} +class Closed : Open {} +class Generic2 : NSObject where T: struct {} +class Generic3 : NSObject where T: System.IConvertible {} +"; + // here we're testing the warnings for the old static registrar. + Verify (R.OldStatic, code, true, + "warning MT4112: The registrar found a generic type: Open`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4112: The registrar found a generic type: Generic2`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4112: The registrar found a generic type: Generic3`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information." + ); + + // and the lack of warnings/errors in the new static registrar. + Verify (R.Static, code, true); + } + + [Test] + public void GenericType_NonConstrainedTypeArguments () + { + var code = @" + class Open : NSObject where U: NSObject + { + [Export (""foo:"")] + public void Foo (V arg) {} // Not OK + + [Export (""foozap"")] + public V FooZap { get { return default (V); } } // Not OK + + [Export (""bar"")] + public V Bar { get; set; } + }"; + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4132: The registrar found an invalid generic return type 'V' in the property 'Open`2.FooZap'. The return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4132: The registrar found an invalid generic return type 'V' in the property 'Open`2.Bar'. The return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'V' in the parameter arg of the method 'Open`2.Foo(V)'. The generic parameter must have an 'NSObject' constraint."); + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: Open`2. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`2.get_FooZap'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`2.get_Bar'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`2.set_Bar'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`2.Foo'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4104: The registrar cannot marshal the return value for type `V` in signature for method `Open`2.get_FooZap`.", + "error MT4104: The registrar cannot marshal the return value for type `V` in signature for method `Open`2.get_Bar`.", + "error MT4105: The registrar cannot marshal the parameter of type `V` in signature for method `Open`2.set_Bar`.", + "error MT4105: The registrar cannot marshal the parameter of type `V` in signature for method `Open`2.Foo`."); + } + + [Test] + public void GenericType_StaticMembersOnOpenGenericType () + { + var code = @" +class Open : NSObject +{ + [Export (""foo"")] + public static void Foo () {} // Not OK + + [Export (""foo:"")] + public static void Foo (U arg) {} // Not OK + + [Export (""zap"")] + public static string Zap { get; set; } // Not OK +} + +"; + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4131: The registrar cannot export static properties in generic classes ('Open`1.Zap').", + ".*Test.cs.*: error MT4130: The registrar cannot export static methods in generic classes ('Open`1.Foo()').", + ".*Test.cs.*: error MT4130: The registrar cannot export static methods in generic classes ('Open`1.Foo(U)')."); + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: Open`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.Foo'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4105: The registrar cannot marshal the parameter of type `U` in signature for method `Open`1.Foo`."); + } + + [Test] + public void NestedGenericType () + { + var code = @" + + class Parent { + public class Nested : NSObject { + [Export (""foo:"")] + public void Foo (T foo) { + } + } + } +"; + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'T' in the parameter foo of the method 'Parent`1/Nested.Foo(T)'. The generic parameter must have an 'NSObject' constraint."); + + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: Parent`1/Nested. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Parent`1/Nested.Foo'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4105: The registrar cannot marshal the parameter of type `T` in signature for method `Parent`1/Nested.Foo`."); + } + + [Test] + public void GenericType_WithDerivedClosedOverride () + { + var code = @" + class GenericTestClass : NSObject + { + [Export (""arg1:"")] + public virtual void Arg1 (T t) {} + } + + class DerivedClosed : GenericTestClass + { + public override void Arg1 (UIView t) {} + } +"; + + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'T' in the parameter t of the method 'GenericTestClass`1.Arg1(T)'. The generic parameter must have an 'NSObject' constraint."); + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: GenericTestClass`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'GenericTestClass`1.Arg1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'GenericTestClass`1.Arg1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4105: The registrar cannot marshal the parameter of type `T` in signature for method `GenericTestClass`1.Arg1`.", + "error MT4105: The registrar cannot marshal the parameter of type `T` in signature for method `DerivedClosed.Arg1`."); + } + + [Test] + public void GenericType_WithInvalidParameterTypes () + { + var code = @" + class Open : NSObject where U: NSObject + { + [Export (""bar:"")] + public void Bar (List arg) {} // Not OK, can't marshal lists. + } +"; + + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4136: The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1)'"); + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: Open`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.Bar'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4108: The registrar cannot get the ObjectiveC type for managed type `System.Collections.Generic.List`1`."); + } + + [Test] + public void GenericType_WithINativeObjectConstraint () + { + var code = @" + class Open : NSObject where U: INativeObject + { + [Export (""bar:"")] + public void Bar (U arg) {} // Not OK + + [Export (""zap:"")] + public void Zap (U[] arg) {} // Not OK + + [Export (""xyz"")] + public U XyZ () { return default (U); } // Not OK + + [Export (""barzap"")] + public U BarZap { get { return default (U); } } // Not OK + + [Export (""zapbar"")] + public Action ZapBar () { return null; } // Not OK + + [Export (""xyz"")] + public void XyZ (Action f) {} + + [Export (""foozap"")] + public void FooZap (List>>> f) {} + + [Export (""zapfoo"")] + public List> ZapBoo () { return null; } + + [Export (""f1"")] + public U F1 { get; set; } + + [Export (""f2"")] + public List> F2 { get { return null; } } + + [Export (""f3"")] + public Action F3 { set { } } + } +"; + + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4132: The registrar found an invalid generic return type 'U' in the property 'Open`1.BarZap'. The return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4132: The registrar found an invalid generic return type 'U' in the property 'Open`1.F1'. The return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4132: The registrar found an invalid generic return type 'System.Collections.Generic.List`1>' in the property 'Open`1.F2'. The return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4132: The registrar found an invalid generic return type 'System.Action`1' in the property 'Open`1.F3'. The return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'U' in the parameter arg of the method 'Open`1.Bar(U)'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'U[]' in the parameter arg of the method 'Open`1.Zap(U[])'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4129: The registrar found an invalid generic return type 'U' in the method 'Open`1.XyZ()'. The generic return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4129: The registrar found an invalid generic return type 'System.Action`1' in the method 'Open`1.ZapBar()'. The generic return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'System.Action`1' in the parameter f of the method 'Open`1.XyZ(System.Action`1)'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'System.Collections.Generic.List`1>>>' in the parameter f of the method 'Open`1.FooZap(System.Collections.Generic.List`1>>>)'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4129: The registrar found an invalid generic return type 'System.Collections.Generic.List`1>' in the method 'Open`1.ZapBoo()'. The generic return type must have an 'NSObject' constraint." + ); + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: Open`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.get_BarZap'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.get_F1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.set_F1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.get_F2'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.Bar'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.XyZ'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.ZapBar'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.FooZap'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'Open`1.ZapBoo'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4104: The registrar cannot marshal the return value for type `U` in signature for method `Open`1.get_BarZap`.", + "error MT4104: The registrar cannot marshal the return value for type `U` in signature for method `Open`1.get_F1`.", + "error MT4105: The registrar cannot marshal the parameter of type `U` in signature for method `Open`1.set_F1`.", + "error MT4104: The registrar cannot marshal the return value for type `System.Collections.Generic.List`1>` in signature for method `Open`1.get_F2`.", + "error MT4105: The registrar cannot marshal the parameter of type `U` in signature for method `Open`1.Bar`.", + "error MT4105: The registrar cannot marshal the parameter of type `U[]` in signature for method `Open`1.Zap`.", + "error MT4104: The registrar cannot marshal the return value for type `U` in signature for method `Open`1.XyZ`.", + "error MT4104: The registrar cannot marshal the return value for type `System.Action`1` in signature for method `Open`1.ZapBar`.", + "error MT4108: The registrar cannot get the ObjectiveC type for managed type `System.Collections.Generic.List`1`.", + "error MT4104: The registrar cannot marshal the return value for type `System.Collections.Generic.List`1>` in signature for method `Open`1.ZapBoo`."); + } + + [Test] + public void GenericType_WithINativeObjectConstraint2 () + { + var code = @" + unsafe class Open : NSObject where U: INativeObject + { + [Export (""bar:"")] + public void Bar (ref U arg) {} // Not OK + + [Export (""zap:"")] + public void Zap (out U[] arg) { arg = null; } // Not OK + } +"; + + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'U&' in the parameter arg of the method 'Open`1.Bar(U&)'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'U[]&' in the parameter arg of the method 'Open`1.Zap(U[]&)'. The generic parameter must have an 'NSObject' constraint."); + Verify (R.OldStatic, code, false, + "warning MT4112: The registrar found a generic type: Open`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4105: The registrar cannot marshal the parameter of type `U&` in signature for method `Open`1.Bar`.", + "error MT4105: The registrar cannot marshal the parameter of type `U[]&` in signature for method `Open`1.Zap`."); + } + + [Test] + public void GenericMethods () + { + var str1 = @" +[Register (""GenericMethodClass"")] +class GenericMethodClass : NSObject { + [Export (""foo:"")] + public static void Foo (T foo) {} + [Export (""GenericMethod"")] + public virtual void GenericMethod (T foo) { } + +} +"; + Verify (R.OldStatic, str1, false, + "warning MT4113: The registrar found a generic method: 'GenericMethodClass.Foo'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'GenericMethodClass.GenericMethod'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4105: The registrar cannot marshal the parameter of type `T` in signature for method `GenericMethodClass.GenericMethod`.", + "error MT4105: The registrar cannot marshal the parameter of type `T` in signature for method `GenericMethodClass.Foo`."); + Verify (R.Static, str1, false, + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'GenericMethodClass.GenericMethod(T)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes", + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'GenericMethodClass.Foo(T)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes" + ); + } + + [Test] + public void GenericMethods1 () + { + var code = @" +class GenericMethodClass : NSObject { + [Export (""Foo:"")] + public virtual void Foo (System.Action func) {} +} +"; + Verify (R.AllStatic, code, true); + } + + [Test] + public void GenericMethods2 () + { + var str1 = @" +class NullableGenericTestClass : NSObject where T: struct +{ + [Export (""init:"")] + public NullableGenericTestClass (T? foo) + { + } + + [Export (""Z1:"")] + public void Z1 (Z? foo) where Z: struct + { + } + + [Export (""Z2"")] + public Z Z2 () where Z: struct + { + throw new System.NotImplementedException (); + } + + [Export (""Z3"")] + public void Z3 (Z foo) + { + } + + [Export (""T1"")] + public void T1 (T foo) + { + } + + [Export (""T2:"")] + public void T2 (T? foo) + { + } + + [Export (""T3"")] + public T T3 () + { + throw new System.NotImplementedException (); + } +} +"; + Verify (R.Static, str1, false, + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.Z1(System.Nullable`1)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes", + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.Z2()'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes", + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.Z3(Z)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'T' in the parameter foo of the method 'NullableGenericTestClass`1.T1(T)'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4128: The registrar found an invalid generic parameter type 'System.Nullable`1' in the parameter foo of the method 'NullableGenericTestClass`1.T2(System.Nullable`1)'. The generic parameter must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4129: The registrar found an invalid generic return type 'T' in the method 'NullableGenericTestClass`1.T3()'. The generic return type must have an 'NSObject' constraint.", + ".*Test.cs.*: error MT4136: The registrar cannot marshal the parameter type 'System.Nullable`1' of the parameter 'foo' in the method 'NullableGenericTestClass`1..ctor(System.Nullable`1)'"); + + Verify (R.OldStatic, str1, false, + "warning MT4112: The registrar found a generic type: NullableGenericTestClass`1. Registering generic types with ObjectiveC is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1..ctor'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.Z1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.Z2'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.Z3'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.T1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.T2'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'NullableGenericTestClass`1.T3'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4105: The registrar cannot marshal the parameter of type `System.Nullable`1` in signature for method `NullableGenericTestClass`1..ctor`.", + "error MT4105: The registrar cannot marshal the parameter of type `System.Nullable`1` in signature for method `NullableGenericTestClass`1.Z1`.", + "error MT4104: The registrar cannot marshal the return value for type `Z` in signature for method `NullableGenericTestClass`1.Z2`.", + "error MT4105: The registrar cannot marshal the parameter of type `Z` in signature for method `NullableGenericTestClass`1.Z3`.", + "error MT4105: The registrar cannot marshal the parameter of type `T` in signature for method `NullableGenericTestClass`1.T1`.", + "error MT4105: The registrar cannot marshal the parameter of type `System.Nullable`1` in signature for method `NullableGenericTestClass`1.T2`.", + "error MT4104: The registrar cannot marshal the return value for type `T` in signature for method `NullableGenericTestClass`1.T3`."); + } + + [Test] + public void GenericMethods3 () + { + var code = @" + +class G : NSObject { + [Export (""fooX1:"")] + public virtual X Foo1 (int x) where X : NSObject { return default(X); }// Not OK + + [Export (""fooX2:"")] + public virtual X Foo2 (int x) { return default(X); } // Not OK + + [Export (""fooX3:"")] + public void Foo3 (X x) { } // Not OK +} +"; + + Verify (R.Static, code, false, + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'G.Foo1(System.Int32)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes", + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'G.Foo2(System.Int32)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes", + ".*Test.cs.*: error MT4113: The registrar found a generic method: 'G.Foo3(X)'. Exporting generic methods is not supported, and will lead to random behavior and/or crashes"); + Verify (R.OldStatic, code, false, + "warning MT4113: The registrar found a generic method: 'G.Foo1'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'G.Foo2'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "warning MT4113: The registrar found a generic method: 'G.Foo3'. Exporting generic methods is not supported with the legacy registrar, and will lead to random behavior and/or crashes. Please remove any --registrar arguments passed as additional mtouch arguments in your project's iOS Build options. See http://docs.xamarin.com/guides/ios/advanced_topics/registrar for more information.", + "error MT4104: The registrar cannot marshal the return value for type `X` in signature for method `G.Foo1`.", + "error MT4104: The registrar cannot marshal the return value for type `X` in signature for method `G.Foo2`.", + "error MT4105: The registrar cannot marshal the parameter of type `X` in signature for method `G.Foo3`." + ); + } + + [Test] + public void ConformsToProtocolTest () + { + var code = @" +class CTP : NSObject { + public override bool ConformsToProtocol (IntPtr protocol) { return base.ConformsToProtocol (protocol); } +} + +class CTP1 : NSObject { + public override bool ConformsToProtocol (IntPtr protocol) { return base.ConformsToProtocol (protocol); } +} +class CTP2 : CTP1 { + public override bool ConformsToProtocol (IntPtr protocol) { return base.ConformsToProtocol (protocol); } +} + + +class CTP3 : NSObject { } +class CTP4 : CTP3 { + public override bool ConformsToProtocol (IntPtr protocol) { return base.ConformsToProtocol (protocol); } +} +"; + Verify (R.Static, code, true); + Verify (R.OldStatic, code, true); + } + +#region Helper functions + // Creates an app with the specified source as the executable. + // Compiles it using smcs, will throw a McsException if it fails. + // Then runs mtouch to try to create an app (for device), will throw MTouchException if it fails. + // This method should not leave anything behind on disk. + static string CreateTestApp (MTouch.Profile profile, string source, string extra_args = "", string xcode = null, string sdk_version = null, MTouch.Target target = MTouch.Target.Dev) + { + string path = MTouch.GetTempDirectory (); + try { + string cs = Path.Combine (path, "Test.cs"); + string exe = Path.Combine (path, "Test.exe"); + File.WriteAllText (cs, source); + Compile (cs, profile); + string app = Path.Combine (path, "Test.app"); + string cache = Path.Combine (path, "cache"); + Directory.CreateDirectory (cache); + Directory.CreateDirectory (app); + + if (xcode == null) + xcode = Configuration.xcode_root; + + if (sdk_version == null) + sdk_version = MTouch.GetSdkVersion (profile); + + return ExecutionHelper.Execute (TestTarget.ToolPath, string.Format ("{0} {10} {1} --sdk {2} -targetver {2} --abi={9} {3} --sdkroot {4} --cache {5} --nolink {7} --debug -r:{6} --target-framework:{8}", exe, app, sdk_version, extra_args, xcode, cache, MTouch.GetBaseLibrary (profile), profile != MTouch.Profile.Classic ? string.Empty : "--nosign", MTouch.GetTargetFramework (profile), MTouch.GetArchitecture (profile, target), target == MTouch.Target.Sim ? "-sim" : "-dev"), hide_output: false); + } finally { + Directory.Delete (path, true); + } + } + + // Compile the filename with mcs + // Does not clean up anything. + static void Compile (string filename, MTouch.Profile profile = MTouch.Profile.Classic) + { + StringBuilder output = new StringBuilder (); + using (var p = new Process ()) { + var args = new StringBuilder (); + args.Append (" /unsafe /debug:full /nologo "); + args.Append (MTouch.Quote (filename)); + args.Append (" -r:").Append (MTouch.Quote (MTouch.GetBaseLibrary (profile))); + p.StartInfo.FileName = MTouch.GetCompiler (profile, args); + p.StartInfo.Arguments = args.ToString (); + p.StartInfo.UseShellExecute = false; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; + Console.WriteLine ("{0} {1}", p.StartInfo.FileName, p.StartInfo.Arguments); + p.Start (); + p.BeginErrorReadLine (); + p.BeginOutputReadLine (); + p.ErrorDataReceived += (sender, e) => + { + if (e.Data != null) { + lock (output) { + output.AppendLine (e.Data); + } + } + }; + p.OutputDataReceived += (sender, e) => + { + if (e.Data != null) { + lock (output) { + output.AppendLine (e.Data); + } + } + }; + p.WaitForExit (); + + Console.WriteLine (output); + + if (p.ExitCode != 0) + throw new McsException (output.ToString ()); + } + } +#endregion + } +} + diff --git a/tests/mtouch/SdkTest.cs b/tests/mtouch/SdkTest.cs new file mode 100644 index 000000000000..a0fd20330d05 --- /dev/null +++ b/tests/mtouch/SdkTest.cs @@ -0,0 +1,137 @@ +// Copyright 2015 Xamarin Inc. All rights reserved. + +using System; +using System.IO; + +using NUnit.Framework; + +using Xamarin.Tests; + +namespace Xamarin.Linker { + + public abstract class BaseProfile { + + protected abstract bool IsSdk (string assemblyName); + } + + public class ProfilePoker : MobileProfile { + + static ProfilePoker p = new ProfilePoker (); + + public static bool IsWellKnownSdk (string assemblyName) + { + return p.IsSdk (assemblyName); + } + } + + [TestFixture] + public partial class SdkTest { + + static string ClassicPath { get { return Path.Combine (Configuration.MonoTouchRootDirectory, "lib/mono/2.1/"); } } + static string UnifiedPath { get { return Path.Combine (Configuration.MonoTouchRootDirectory, "lib/mono/Xamarin.iOS/"); } } + static string tvOSPath { get { return Path.Combine (Configuration.MonoTouchRootDirectory, "lib/mono/Xamarin.TVOS/"); } } + static string watchOSPath { get { return Path.Combine (Configuration.MonoTouchRootDirectory, "lib/mono/Xamarin.WatchOS/"); } } + + void BCL (string path) + { + foreach (var file in Directory.GetFiles (path, "*.dll")) { + var aname = Path.GetFileNameWithoutExtension (file); + switch (aname) { + case "FSharp.Core": + case "I18N": + case "I18N.CJK": + case "I18N.MidEast": + case "I18N.Other": + case "I18N.Rare": + case "I18N.West": + // need to be sure they are link-capable to include them into MobileProfile + break; + case "MonoTouch.Dialog-1": + case "MonoTouch.NUnitLite": + case "monotouch": + case "Xamarin.iOS": + case "Xamarin.TVOS": + case "Xamarin.WatchOS": + // product assembly (use a different check than SDK/BCL) + break; + case "Newtonsoft.Json": + case "Xamarin.iOS.Tasks": + case "Xamarin.iOS.Tasks.Core": + case "Xamarin.ObjcBinding.Tasks": + case "Xamarin.MacDev": + case "Xamarin.MacDev.Tasks": + case "Xamarin.MacDev.Tasks.Core": + // other stuff that is not part of the SDK but shipped in the same 2.1 directory + if (path != ClassicPath) + Assert.Fail (aname); + break; + default: + Assert.IsTrue (ProfilePoker.IsWellKnownSdk (aname), aname); + break; + } + } + } + + void REPL (string path) + { + var repl = Path.Combine (path, "repl"); + foreach (var file in Directory.GetFiles (repl, "*.dll")) { + var aname = Path.GetFileNameWithoutExtension (file); + switch (aname) { + // sub-list that are SDK assemblies + case "mscorlib": + case "System": + case "System.Core": + case "System.Xml": + case "Mono.CSharp": + Assert.IsTrue (ProfilePoker.IsWellKnownSdk (aname), aname); + break; + default: + Assert.Fail (aname); + break; + } + } + } + + void Facades (string path) + { + var facades = Path.Combine (path, "Facades"); + foreach (var file in Directory.GetFiles (facades, "*.dll")) { + var aname = Path.GetFileNameWithoutExtension (file); + Assert.IsTrue (ProfilePoker.IsWellKnownSdk (aname), aname); + } + } + + [Test] + public void iOS_Classic () + { + BCL (ClassicPath); + REPL (ClassicPath); + Facades (ClassicPath); + } + + [Test] + public void iOS_Unified () + { + BCL (UnifiedPath); + REPL (UnifiedPath); + Facades (UnifiedPath); + } + + [Test] + public void tvOS () + { + BCL (tvOSPath); + REPL (tvOSPath); + Facades (tvOSPath); + } + + [Test] + public void watchOS () + { + BCL (watchOSPath); + REPL (watchOSPath); + Facades (watchOSPath); + } + } +} \ No newline at end of file diff --git a/tests/mtouch/mtouch.csproj b/tests/mtouch/mtouch.csproj new file mode 100644 index 000000000000..1fe9c9fe084e --- /dev/null +++ b/tests/mtouch/mtouch.csproj @@ -0,0 +1,54 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8} + Library + MTouchTests + mtouch + + + full + False + bin\Debug + 4 + True + MONOTOUCH + + + + + + + + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + + + + + + + AssertHelpers.cs + + + ExecutionHelper.cs + + + Configuration.cs + + + + MobileProfile.cs + + + + + + + + + + diff --git a/tests/mtouch/packages.config b/tests/mtouch/packages.config new file mode 100644 index 000000000000..a7462f842505 --- /dev/null +++ b/tests/mtouch/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tests/mtouch/runSingleTest.sh b/tests/mtouch/runSingleTest.sh new file mode 100755 index 000000000000..daed07c8b70d --- /dev/null +++ b/tests/mtouch/runSingleTest.sh @@ -0,0 +1 @@ +MT_SDK_ROOT=/Developer/MonoTouch SDK_VERSION=7.1 /Library/Frameworks/Mono.framework/Commands/nunit-console4 -labels bin/Debug/*.dll -noshadow -run=Mono.Activation.Tests.Activation.$1 diff --git a/tests/no-mmp/.gitignore b/tests/no-mmp/.gitignore new file mode 100644 index 000000000000..cb89ca4b5dfb --- /dev/null +++ b/tests/no-mmp/.gitignore @@ -0,0 +1,4 @@ +*.exe +*.dylib +*.app +no-mmp diff --git a/tests/no-mmp/Main.cs b/tests/no-mmp/Main.cs new file mode 100644 index 000000000000..fe7578b0fa2a --- /dev/null +++ b/tests/no-mmp/Main.cs @@ -0,0 +1,11 @@ +using System; +using MonoMac.AppKit; + +class NoMMP { + static int Main () + { + NSApplication.Init (); + Console.WriteLine ("Success"); + return 0; + } +} \ No newline at end of file diff --git a/tests/no-mmp/Makefile b/tests/no-mmp/Makefile new file mode 100644 index 000000000000..69c67b04ee3f --- /dev/null +++ b/tests/no-mmp/Makefile @@ -0,0 +1,28 @@ +TOP = ../.. + +include $(TOP)/Make.config +include $(TOP)/mk/rules.mk + +no-mmp: main.m + clang -o$@ main.m -framework AppKit -arch i386 + +no-mmp.exe: Main.cs XamMac.dll libxammac.dylib + $(SYSTEM_MCS) Main.cs -out:$@ -r:XamMac.dll + +XamMac.dll: $(TOP)/src/build/mac/compat/XamMac.dll + cp $^ $@ + +libxammac.dylib: $(TOP)/launcher/.libs/libxammac.dylib + cp $^ $@ + +no-mmp.app: no-mmp.exe no-mmp + rm -Rf no-mmp.app + mkdir -p no-mmp.app/Contents/MacOS + cp no-mmp no-mmp.app/Contents/MacOS + mkdir -p no-mmp.app/Contents/MonoBundle + cp no-mmp.exe* no-mmp.app/Contents/MonoBundle + cp libxammac.dylib no-mmp.app/Contents/MonoBundle + cp XamMac.dll* no-mmp.app/Contents/MonoBundle + +run: no-mmp.app + no-mmp.app/Contents/MacOS/no-mmp diff --git a/tests/no-mmp/main.m b/tests/no-mmp/main.m new file mode 100644 index 000000000000..54003ef83e66 --- /dev/null +++ b/tests/no-mmp/main.m @@ -0,0 +1,47 @@ +//gcc -m32 monostub.m -o monostub -framework AppKit + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#import + +#define MONO_LIB_PATH(lib) "/Library/Frameworks/Mono.framework/Versions/Current/lib/"lib + +typedef int (* mono_main) (int argc, char **argv); + +void *libmono; + +int main (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + libmono = dlopen (MONO_LIB_PATH ("libmono-2.0.dylib"), RTLD_LAZY); + + if (libmono == NULL) { + fprintf (stderr, "Failed to load libmono-2.0.dylib: %s\n", dlerror ()); + abort (); + } + + mono_main _mono_main = (mono_main) dlsym (libmono, "mono_main"); + if (!_mono_main) { + fprintf (stderr, "Could not load mono_main(): %s\n", dlerror ()); + abort (); + } + + [pool drain]; + + NSString *appDir = [[NSBundle mainBundle] bundlePath]; + char *argv2 [2]; + argv2 [0] = argv [0]; + argv2 [1] = [[appDir stringByAppendingPathComponent:@"Contents/MonoBundle/no-mmp.exe"] UTF8String]; + + return _mono_main (2, argv2); +} \ No newline at end of file diff --git a/tests/package-mac-tests.sh b/tests/package-mac-tests.sh new file mode 100755 index 000000000000..79a30404c10d --- /dev/null +++ b/tests/package-mac-tests.sh @@ -0,0 +1,28 @@ +#!/bin/bash -ex + +#git clean -xfdq + +DIR=$(pwd)/mac-test-package/mac-test-package +ZIP=$DIR.zip +rm -Rf $DIR +mkdir -p $DIR + +make build-mac + +for app in */bin/x86/*/*.app; do + mkdir -p $DIR/tests/$app + cp -R $app $DIR/tests/$app/.. +done + +cp -p Makefile-mac.inc $DIR/tests +cp -p common.mk $DIR/tests +cp -p Makefile $DIR/tests +cp -p ../Make.config $DIR +mkdir -p $DIR/../xamarin-macios/mk +cp -p ../../xamarin-macios/Make.config $DIR/../xamarin-macios +cp -p ../../xamarin-macios/mk/subdirs.mk $DIR/../xamarin-macios/mk +cp -p ../../xamarin-macios/mk/rules.mk $DIR/../xamarin-macios/mk +cp -p ../../xamarin-macios/mk/quiet.mk $DIR/../xamarin-macios/mk + +# 7za compresses better, because there are many duplicated files +cd mac-test-package && zip -r ../mac-test-package.zip * diff --git a/tests/qa-regression/EndSheet/AppDelegate.cs b/tests/qa-regression/EndSheet/AppDelegate.cs new file mode 100644 index 000000000000..8ccaf45818e8 --- /dev/null +++ b/tests/qa-regression/EndSheet/AppDelegate.cs @@ -0,0 +1,24 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace EndSheet +{ + public partial class AppDelegate : NSApplicationDelegate + { + MainWindowController mainWindowController; + + public AppDelegate () + { + } + + public override void FinishedLaunching (NSObject notification) + { + mainWindowController = new MainWindowController (); + mainWindowController.Window.MakeKeyAndOrderFront (this); + } + } +} + diff --git a/tests/qa-regression/EndSheet/AppDelegate.designer.cs b/tests/qa-regression/EndSheet/AppDelegate.designer.cs new file mode 100644 index 000000000000..5aa7728c7018 --- /dev/null +++ b/tests/qa-regression/EndSheet/AppDelegate.designer.cs @@ -0,0 +1,10 @@ + +namespace EndSheet +{ + // Should subclass MonoMac.AppKit.NSResponder + [MonoMac.Foundation.Register("AppDelegate")] + public partial class AppDelegate + { + } +} + diff --git a/tests/qa-regression/EndSheet/EndSheet.csproj b/tests/qa-regression/EndSheet/EndSheet.csproj new file mode 100644 index 000000000000..329cec76e065 --- /dev/null +++ b/tests/qa-regression/EndSheet/EndSheet.csproj @@ -0,0 +1,100 @@ + + + + Debug + x86 + 10.0.0 + 2.0 + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + EndSheet + Resources + EndSheet + + + true + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + Mac Developer + false + false + x86 + + + true + bin\Release + prompt + 4 + Full + false + true + false + true + Developer ID Application + true + false + x86 + + + true + bin\x86\AppStore + prompt + 4 + Full + false + true + 3rd Party Mac Developer Installer + false + true + 3rd Party Mac Developer Application + true + true + x86 + + + + + + + + + + + + + + + + + MainWindow.cs + + + + + AppDelegate.cs + + + + + MainSheet.cs + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/qa-regression/EndSheet/EndSheet.sln b/tests/qa-regression/EndSheet/EndSheet.sln new file mode 100644 index 000000000000..fcab1bd408d8 --- /dev/null +++ b/tests/qa-regression/EndSheet/EndSheet.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndSheet", "EndSheet.csproj", "{986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + AppStore|x86 = AppStore|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}.AppStore|x86.ActiveCfg = AppStore|x86 + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}.AppStore|x86.Build.0 = AppStore|x86 + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}.Debug|x86.ActiveCfg = Debug|x86 + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}.Debug|x86.Build.0 = Debug|x86 + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}.Release|x86.ActiveCfg = Release|x86 + {986B23BB-04F7-4950-BEA0-B0AF85D6AFB5}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = EndSheet.csproj + EndGlobalSection +EndGlobal diff --git a/tests/qa-regression/EndSheet/Info.plist b/tests/qa-regression/EndSheet/Info.plist new file mode 100644 index 000000000000..f39a76d7fecf --- /dev/null +++ b/tests/qa-regression/EndSheet/Info.plist @@ -0,0 +1,16 @@ + + + + + CFBundleName + EndSheet + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/qa-regression/EndSheet/Main.cs b/tests/qa-regression/EndSheet/Main.cs new file mode 100644 index 000000000000..d8d4411523c1 --- /dev/null +++ b/tests/qa-regression/EndSheet/Main.cs @@ -0,0 +1,17 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace EndSheet +{ + class MainClass + { + static void Main (string [] args) + { + NSApplication.Init (); + NSApplication.Main (args); + } + } +} \ No newline at end of file diff --git a/tests/qa-regression/EndSheet/MainMenu.xib b/tests/qa-regression/EndSheet/MainMenu.xib new file mode 100644 index 000000000000..e7af6f68792c --- /dev/null +++ b/tests/qa-regression/EndSheet/MainMenu.xib @@ -0,0 +1,4074 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + EndSheet + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + MacCocoaApp + + YES + + + About EndSheet + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide EndSheet + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit EndSheet + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + EndSheet Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + NSFontManager + + + AppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + delegate + + + + 534 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 496 + + + YES + + + + + + 497 + + + YES + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + YES + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + YES + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 533 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBEditorWindowLastContentRect + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 507.IBPluginDependency + 508.IBEditorWindowLastContentRect + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{453, 408}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{613, 618}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{346, 722}, {402, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{563, 648}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{497, 648}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{580, 408}, {175, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{684, 668}, {142, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{674, 260}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{878, 180}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{355, 508}, {183, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{411, 488}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 534 + + + + YES + + AppDelegate + NSResponder + + IBUserSource + + + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../MacCocoaApp.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/tests/qa-regression/EndSheet/MainSheet.cs b/tests/qa-regression/EndSheet/MainSheet.cs new file mode 100644 index 000000000000..acd2d5fe2664 --- /dev/null +++ b/tests/qa-regression/EndSheet/MainSheet.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace EndSheet +{ + public partial class MainSheet : MonoMac.AppKit.NSWindow + { + #region Constructors + + // Called when created from unmanaged code + public MainSheet (IntPtr handle) : base (handle) + { + Initialize (); + } + // Called when created directly from a XIB file + [Export ("initWithCoder:")] + public MainSheet (NSCoder coder) : base (coder) + { + Initialize (); + } + // Shared initialization code + void Initialize () + { + } + #endregion + } +} + diff --git a/tests/qa-regression/EndSheet/MainSheet.designer.cs b/tests/qa-regression/EndSheet/MainSheet.designer.cs new file mode 100644 index 000000000000..092baf0a8d65 --- /dev/null +++ b/tests/qa-regression/EndSheet/MainSheet.designer.cs @@ -0,0 +1,34 @@ +// WARNING +// +// This file has been generated automatically by Xamarin Studio to store outlets and +// actions made in the Xcode designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// +using MonoMac.Foundation; + +namespace EndSheet +{ + [Register ("MainSheetController")] + partial class MainSheetController + { + [Outlet] + MonoMac.AppKit.NSButton dismissSheetButton { get; set; } + + void ReleaseDesignerOutlets () + { + if (dismissSheetButton != null) { + dismissSheetButton.Dispose (); + dismissSheetButton = null; + } + } + } + + [Register ("MainSheet")] + partial class MainSheet + { + + void ReleaseDesignerOutlets () + { + } + } +} diff --git a/tests/qa-regression/EndSheet/MainSheet.xib b/tests/qa-regression/EndSheet/MainSheet.xib new file mode 100644 index 000000000000..7b497553af27 --- /dev/null +++ b/tests/qa-regression/EndSheet/MainSheet.xib @@ -0,0 +1,322 @@ + + + + 1080 + 12E55 + 3084 + 1187.39 + 626.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 3084 + + + YES + NSButton + NSButtonCell + NSCustomObject + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + MainSheetController + + + FirstResponder + + + NSApplication + + + 7 + 2 + {{131, 74}, {272, 141}} + 611844096 + Sheet + MainSheet + + + + + 256 + + YES + + + 268 + {{72, 13}, {128, 32}} + + + _NS:9 + YES + + 67108864 + 134217728 + Dismiss Sheet + + LucidaGrande + 13 + 1044 + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{17, 73}, {238, 48}} + + + + _NS:9 + {250, 750} + YES + + 67108864 + 272629760 + Dismiss the sheet and run it a few more times. + + LucidaGrande + 20 + 16 + + _NS:9 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + NO + YES + + + {272, 141} + + + + + {{0, 0}, {2560, 1418}} + {10000000000000, 10000000000000} + YES + + + + + YES + + + window + + + + 6 + + + + dismissSheetButton + + + + 15 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 2 + + + YES + + + + + + 3 + + + YES + + + + + + + 7 + + + YES + + + + + + 8 + + + + + 11 + + + YES + + + + + + 12 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 11.IBPluginDependency + 12.IBPluginDependency + 2.IBPluginDependency + 2.IBWindowTemplateEditedContentRect + 2.NSWindowTemplate.visibleAtLaunch + 3.IBPluginDependency + 7.IBPluginDependency + 8.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{319, 371}, {606, 354}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + + + + YES + + + + + 15 + + + + YES + + MainSheet + NSWindow + + IBProjectSource + ./Classes/MainSheet.h + + + + MainSheetController + NSWindowController + + dismissSheetButton + NSButton + + + dismissSheetButton + + dismissSheetButton + NSButton + + + + IBProjectSource + ./Classes/MainSheetController.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + diff --git a/tests/qa-regression/EndSheet/MainSheetController.cs b/tests/qa-regression/EndSheet/MainSheetController.cs new file mode 100644 index 000000000000..eb8b9c35cdb0 --- /dev/null +++ b/tests/qa-regression/EndSheet/MainSheetController.cs @@ -0,0 +1,31 @@ +using System; + +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace EndSheet +{ + public partial class MainSheetController : NSWindowController + { + public MainSheetController (IntPtr handle) : base (handle) + { + } + + [Export ("initWithCoder:")] + public MainSheetController (NSCoder coder) : base (coder) + { + } + + public MainSheetController () : base ("MainSheet") + { + } + + public override void AwakeFromNib () + { + dismissSheetButton.Activated += (sender, e) => { + NSApplication.SharedApplication.EndSheet (Window); + Window.OrderOut (this); + }; + } + } +} \ No newline at end of file diff --git a/tests/qa-regression/EndSheet/MainWindow.cs b/tests/qa-regression/EndSheet/MainWindow.cs new file mode 100644 index 000000000000..703691518556 --- /dev/null +++ b/tests/qa-regression/EndSheet/MainWindow.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace EndSheet +{ + public partial class MainWindow : MonoMac.AppKit.NSWindow + { + #region Constructors + + // Called when created from unmanaged code + public MainWindow (IntPtr handle) : base (handle) + { + Initialize (); + } + // Called when created directly from a XIB file + [Export ("initWithCoder:")] + public MainWindow (NSCoder coder) : base (coder) + { + Initialize (); + } + // Shared initialization code + void Initialize () + { + } + #endregion + } +} + diff --git a/tests/qa-regression/EndSheet/MainWindow.designer.cs b/tests/qa-regression/EndSheet/MainWindow.designer.cs new file mode 100644 index 000000000000..b0a57056b41c --- /dev/null +++ b/tests/qa-regression/EndSheet/MainWindow.designer.cs @@ -0,0 +1,42 @@ +// WARNING +// +// This file has been generated automatically by Xamarin Studio to store outlets and +// actions made in the Xcode designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// +using MonoMac.Foundation; + +namespace EndSheet +{ + [Register ("MainWindowController")] + partial class MainWindowController + { + [Outlet] + MonoMac.AppKit.NSButton runSheetButton { get; set; } + + [Outlet] + MonoMac.AppKit.NSTextField dismissCountLabel { get; set; } + + void ReleaseDesignerOutlets () + { + if (runSheetButton != null) { + runSheetButton.Dispose (); + runSheetButton = null; + } + + if (dismissCountLabel != null) { + dismissCountLabel.Dispose (); + dismissCountLabel = null; + } + } + } + + [Register ("MainWindow")] + partial class MainWindow + { + + void ReleaseDesignerOutlets () + { + } + } +} diff --git a/tests/qa-regression/EndSheet/MainWindow.xib b/tests/qa-regression/EndSheet/MainWindow.xib new file mode 100644 index 000000000000..42c7bb92912d --- /dev/null +++ b/tests/qa-regression/EndSheet/MainWindow.xib @@ -0,0 +1,469 @@ + + + + 1080 + 12E55 + 3084 + 1187.39 + 626.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 3084 + + + YES + NSBox + NSButton + NSButtonCell + NSCustomObject + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + MainWindowController + + + FirstResponder + + + NSApplication + + + 7 + 2 + {{131, 74}, {384, 142}} + 611844096 + EndSheet Regression Test + MainWindow + + + + + 256 + + YES + + + 268 + {{17, 74}, {350, 48}} + + + + _NS:9 + {250, 750} + YES + + 67108864 + 272629760 + Run and dismiss the sheet multiple times to ensure no crash happens. + + LucidaGrande + 20 + 16 + + _NS:9 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + NO + YES + + + + 268 + {{141, 13}, {103, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Run Sheet + + LucidaGrande + 13 + 1044 + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 12 + + YES + + + 274 + + YES + + + 268 + {{15, 11}, {69, 17}} + + + + _NS:1535 + YES + + 68157504 + 138413056 + 0 + + _NS:1535 + + + + + NO + + + {{1, 1}, {99, 34}} + + + + _NS:11 + + + {{17, 16}, {101, 50}} + + + + _NS:9 + {0, 0} + + 67108864 + 0 + Dismiss Count + + LucidaGrande + 11 + 3100 + + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + + + {384, 142} + + + + + {{0, 0}, {2560, 1418}} + {10000000000000, 10000000000000} + YES + + + + + YES + + + window + + + + 6 + + + + runSheetButton + + + + 15 + + + + dismissCoutLabel + + + + 21 + + + + dismissCountLabel + + + + 22 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 2 + + + YES + + + + + + 3 + + + YES + + + + + + + + 9 + + + YES + + + + + + 10 + + + + + 13 + + + YES + + + + + + 14 + + + + + 18 + + + YES + + + + + + 19 + + + YES + + + + + + 20 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 10.IBPluginDependency + 13.IBPluginDependency + 14.IBPluginDependency + 18.IBPluginDependency + 19.IBPluginDependency + 2.IBNSWindowAutoPositionCentersHorizontal + 2.IBNSWindowAutoPositionCentersVertical + 2.IBPluginDependency + 2.IBWindowTemplateEditedContentRect + 2.NSWindowTemplate.visibleAtLaunch + 20.IBPluginDependency + 3.IBPluginDependency + 9.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + com.apple.InterfaceBuilder.CocoaPlugin + {{319, 371}, {606, 354}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + + + + YES + + + + + 22 + + + + YES + + MainWindow + NSWindow + + IBProjectSource + ./Classes/MainWindow.h + + + + MainWindowController + NSWindowController + + YES + + YES + dismissCoutLabel + runSheetButton + + + YES + NSTextField + NSButton + + + + YES + + YES + dismissCoutLabel + runSheetButton + + + YES + + dismissCoutLabel + NSTextField + + + runSheetButton + NSButton + + + + + IBProjectSource + ./Classes/MainWindowController.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + diff --git a/tests/qa-regression/EndSheet/MainWindowController.cs b/tests/qa-regression/EndSheet/MainWindowController.cs new file mode 100644 index 000000000000..4e0cc03cd2b8 --- /dev/null +++ b/tests/qa-regression/EndSheet/MainWindowController.cs @@ -0,0 +1,31 @@ +using System; + +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace EndSheet +{ + public partial class MainWindowController : NSWindowController + { + public MainWindowController (IntPtr handle) : base (handle) + { + } + + [Export ("initWithCoder:")] + public MainWindowController (NSCoder coder) : base (coder) + { + } + + public MainWindowController () : base ("MainWindow") + { + } + + public override void AwakeFromNib () + { + runSheetButton.Activated += (sender, e) => + NSApplication.SharedApplication.BeginSheet ( + new MainSheetController ().Window, Window, () => + dismissCountLabel.IntValue++); + } + } +} \ No newline at end of file diff --git a/tests/qa-regression/ObjCBlocks/Info.plist b/tests/qa-regression/ObjCBlocks/Info.plist new file mode 100644 index 000000000000..49411e68918b --- /dev/null +++ b/tests/qa-regression/ObjCBlocks/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + ObjCBlocksTest + CFBundleIdentifier + com.your-company.ObjCBlocksTest + CFBundleName + ObjCBlocksTest + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/qa-regression/ObjCBlocks/Makefile b/tests/qa-regression/ObjCBlocks/Makefile new file mode 100644 index 000000000000..e0a2213f4c5a --- /dev/null +++ b/tests/qa-regression/ObjCBlocks/Makefile @@ -0,0 +1,48 @@ +ifeq ($(IN_TREE),1) +FRAMEWORK = ../../../_mac-build/Library/Frameworks/Xamarin.Mac.framework/Versions/Current +else +FRAMEWORK = /Library/Frameworks/Xamarin.Mac.framework/Versions/Current +endif + +BMAC = $(FRAMEWORK)/bin/bmac +MMP = $(FRAMEWORK)/bin/mmp +XAMMAC = $(FRAMEWORK)/lib/mono/XamMac.dll +SYSTEM_LAUNCHER = $(FRAMEWORK)/lib/mono/XamMacLauncher + +.PHONY: all run clean + +all: run + +block.dylib: block.m + clang -dynamiclib -m32 -o $@ -ObjC -framework Foundation $< + +block.dll: block.dylib block.cs $(BMAC) + $(BMAC) block.cs -out:$@ -outdir:generated -baselib:$(XAMMAC) -r:System.Drawing + +app.exe: block.dll app.cs + mcs -debug app.cs -out:$@ -r:block.dll -r:$(XAMMAC) + cp $(XAMMAC){,.mdb} . + +SystemLauncher.app: app.exe + rm -rf $@ + mkdir -p $@/Contents/MonoBundle + cp XamMac.dll block.dll block.dylib $@/Contents/MonoBundle + cp app.exe $@/Contents/MonoBundle/SystemLauncher.exe + mkdir -p $@/Contents/MacOS + cp $(SYSTEM_LAUNCHER) $@/Contents/MacOS/SystemLauncher + cp Info.plist $@/Contents + chmod +x $@/Contents/MacOS/SystemLauncher + +LinkedLauncher.app: app.exe + rm -rf $@ + $(MMP) --nolink $< -name LinkedLauncher + cp Info.plist $@/Contents + mv $@/Contents/MonoBundle/app.exe $@/Contents/MonoBundle/LinkedLauncher.exe + cp block.dylib $@/Contents/MonoBundle + +run: SystemLauncher.app LinkedLauncher.app + SystemLauncher.app/Contents/MacOS/SystemLauncher + LinkedLauncher.app/Contents/MacOS/LinkedLauncher + +clean: + rm -rf *.exe *.dll *.mdb *.dylib generated *.app diff --git a/tests/qa-regression/ObjCBlocks/app.cs b/tests/qa-regression/ObjCBlocks/app.cs new file mode 100644 index 000000000000..c1963e83dca2 --- /dev/null +++ b/tests/qa-regression/ObjCBlocks/app.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; + +using MonoMac.AppKit; + +using Test; + +static class App +{ + [DllImport ("dl")] + static extern IntPtr dlopen (string path, int mode); + + static void Main () + { + Console.WriteLine ("[managed] enter Main"); + var selfPath = Path.GetDirectoryName (typeof (App).Assembly.Location); + var libHandle = dlopen (Path.Combine (selfPath, "block.dylib"), 2 /* RTLD_NOW */); + Console.WriteLine ("[managed] block.dylib handle: {0}", libHandle); + + Console.WriteLine ("[managed] about to call NSApplication.Init"); + NSApplication.Init (); + Console.WriteLine ("[managed] NSApplication.Init has exited"); + + Console.WriteLine ("[managed] about to instantiate ObjCBlocksTest"); + using (var test = new ObjCBlocksTest ()) { + Console.WriteLine ("[managed] about to call DoInvoke"); + test.DoInvoke (() => Console.WriteLine ("[managed] DoInvoke blockHandler")); + Console.WriteLine ("[managed] DoInvoke has exited"); + } + Console.WriteLine ("[managed] ObjBlocksTest has been disposed"); + Console.WriteLine ("[managed] exit Main (0)"); + } +} diff --git a/tests/qa-regression/ObjCBlocks/block.cs b/tests/qa-regression/ObjCBlocks/block.cs new file mode 100644 index 000000000000..ff2fb523ec5b --- /dev/null +++ b/tests/qa-regression/ObjCBlocks/block.cs @@ -0,0 +1,13 @@ +using System; + +using MonoMac.Foundation; + +namespace Test { + + [BaseType (typeof (NSObject))] + interface ObjCBlocksTest { + + [Export ("doInvoke:")] + void DoInvoke (Action blockHandler); + } +} diff --git a/tests/qa-regression/ObjCBlocks/block.m b/tests/qa-regression/ObjCBlocks/block.m new file mode 100644 index 000000000000..d123a2d97ce7 --- /dev/null +++ b/tests/qa-regression/ObjCBlocks/block.m @@ -0,0 +1,19 @@ +#import + +@interface ObjCBlocksTest : NSObject + +- (void)doInvoke:(void (^)(void))blockHandler; + +@end + +@implementation ObjCBlocksTest : NSObject + +- (void)doInvoke:(void (^)(void))blockHandler +{ + printf ("[native] ENTER ObjCBlocksTest_Invoke (blockHandler = %p)\n", + blockHandler); + blockHandler (); + printf ("[native] LEAVE ObjCBlocksTest_Invoke\n"); +} + +@end diff --git a/tests/qa-regression/WebKitDelegateEvents/AppDelegate.cs b/tests/qa-regression/WebKitDelegateEvents/AppDelegate.cs new file mode 100644 index 000000000000..0f11a90efc36 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/AppDelegate.cs @@ -0,0 +1,24 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace WebKitDelegateEvents +{ + public partial class AppDelegate : NSApplicationDelegate + { + MainWindowController mainWindowController; + + public AppDelegate () + { + } + + public override void FinishedLaunching (NSObject notification) + { + mainWindowController = new MainWindowController (); + mainWindowController.Window.MakeKeyAndOrderFront (this); + } + } +} + diff --git a/tests/qa-regression/WebKitDelegateEvents/AppDelegate.designer.cs b/tests/qa-regression/WebKitDelegateEvents/AppDelegate.designer.cs new file mode 100644 index 000000000000..f9e54e01f8d1 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/AppDelegate.designer.cs @@ -0,0 +1,10 @@ + +namespace WebKitDelegateEvents +{ + // Should subclass MonoMac.AppKit.NSResponder + [MonoMac.Foundation.Register ("AppDelegate")] + public partial class AppDelegate + { + } +} + diff --git a/tests/qa-regression/WebKitDelegateEvents/Info.plist b/tests/qa-regression/WebKitDelegateEvents/Info.plist new file mode 100644 index 000000000000..9adf2ed076d4 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + WebKitDelegateEvents + CFBundleIdentifier + com.your-company.WebKitDelegateEvents + CFBundleName + WebKitDelegateEvents + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/qa-regression/WebKitDelegateEvents/Main.cs b/tests/qa-regression/WebKitDelegateEvents/Main.cs new file mode 100644 index 000000000000..c26869a87831 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/Main.cs @@ -0,0 +1,18 @@ +using System; +using System.Drawing; +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.ObjCRuntime; + +namespace WebKitDelegateEvents +{ + class MainClass + { + static void Main (string[] args) + { + NSApplication.Init (); + NSApplication.Main (args); + } + } +} + diff --git a/tests/qa-regression/WebKitDelegateEvents/MainMenu.xib b/tests/qa-regression/WebKitDelegateEvents/MainMenu.xib new file mode 100644 index 000000000000..fd6e0cef2d25 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/MainMenu.xib @@ -0,0 +1,4074 @@ + + + + 1060 + 10D573 + 762 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 762 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + WebKitDelegateEvents + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + MacCocoaApp + + YES + + + About WebKitDelegateEvents + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide WebKitDelegateEvents + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit WebKitDelegateEvents + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + YES + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + YES + + + Font + + 2147483647 + + + submenuAction: + + Font + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + Ligature + + YES + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + YES + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + YES + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + YES + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + YES + + + WebKitDelegateEvents Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + NSFontManager + + + AppDelegate + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + terminate: + + + + 449 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + delegate + + + + 534 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + + + 80 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + YES + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + 377 + + + YES + + + + + + 388 + + + YES + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + YES + + + + + + 398 + + + YES + + + + + + 399 + + + YES + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + YES + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + YES + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + YES + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + YES + + + + + + 451 + + + YES + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + YES + + + + + + 491 + + + YES + + + + + + 492 + + + + + 496 + + + YES + + + + + + 497 + + + YES + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + YES + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + YES + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 533 + + + + + + + YES + + YES + -3.IBPluginDependency + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 375.IBPluginDependency + 376.IBEditorWindowLastContentRect + 376.IBPluginDependency + 377.IBPluginDependency + 388.IBEditorWindowLastContentRect + 388.IBPluginDependency + 389.IBPluginDependency + 390.IBPluginDependency + 391.IBPluginDependency + 392.IBPluginDependency + 393.IBPluginDependency + 394.IBPluginDependency + 395.IBPluginDependency + 396.IBPluginDependency + 397.IBPluginDependency + 398.IBPluginDependency + 399.IBPluginDependency + 400.IBPluginDependency + 401.IBPluginDependency + 402.IBPluginDependency + 403.IBPluginDependency + 404.IBPluginDependency + 405.IBPluginDependency + 406.IBPluginDependency + 407.IBPluginDependency + 408.IBPluginDependency + 409.IBPluginDependency + 410.IBPluginDependency + 411.IBPluginDependency + 412.IBPluginDependency + 413.IBPluginDependency + 414.IBPluginDependency + 415.IBPluginDependency + 416.IBPluginDependency + 417.IBPluginDependency + 418.IBPluginDependency + 419.IBPluginDependency + 450.IBPluginDependency + 451.IBEditorWindowLastContentRect + 451.IBPluginDependency + 452.IBPluginDependency + 453.IBPluginDependency + 454.IBPluginDependency + 457.IBPluginDependency + 459.IBPluginDependency + 460.IBPluginDependency + 462.IBPluginDependency + 465.IBPluginDependency + 466.IBPluginDependency + 485.IBPluginDependency + 490.IBPluginDependency + 491.IBEditorWindowLastContentRect + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBEditorWindowLastContentRect + 497.IBPluginDependency + 498.IBPluginDependency + 499.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 500.IBPluginDependency + 501.IBPluginDependency + 502.IBPluginDependency + 503.IBPluginDependency + 504.IBPluginDependency + 505.IBPluginDependency + 506.IBPluginDependency + 507.IBPluginDependency + 508.IBEditorWindowLastContentRect + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 187}, {275, 113}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{453, 408}, {254, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{187, 434}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{753, 217}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{613, 618}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{346, 722}, {402, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{563, 648}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{746, 287}, {220, 133}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{497, 648}, {83, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{580, 408}, {175, 283}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{753, 197}, {170, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{684, 668}, {142, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{674, 260}, {204, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{878, 180}, {164, 173}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{355, 508}, {183, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{411, 488}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{145, 474}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 534 + + + + YES + + AppDelegate + NSResponder + + IBUserSource + + + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFontManager + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../MacCocoaApp.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/tests/qa-regression/WebKitDelegateEvents/MainWindow.cs b/tests/qa-regression/WebKitDelegateEvents/MainWindow.cs new file mode 100644 index 000000000000..2b9e5ca8ec45 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/MainWindow.cs @@ -0,0 +1,19 @@ +using System; + +using MonoMac.Foundation; +using MonoMac.AppKit; + +namespace WebKitDelegateEvents +{ + public partial class MainWindow : NSWindow + { + public MainWindow (IntPtr handle) : base (handle) + { + } + + [Export ("initWithCoder:")] + public MainWindow (NSCoder coder) : base (coder) + { + } + } +} \ No newline at end of file diff --git a/tests/qa-regression/WebKitDelegateEvents/MainWindow.designer.cs b/tests/qa-regression/WebKitDelegateEvents/MainWindow.designer.cs new file mode 100644 index 000000000000..6d1df8511f28 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/MainWindow.designer.cs @@ -0,0 +1,67 @@ +// WARNING +// +// This file has been generated automatically by Xamarin Studio to store outlets and +// actions made in the UI designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// +using MonoMac.Foundation; +using System.CodeDom.Compiler; + +namespace WebKitDelegateEvents +{ + [Register ("MainWindowController")] + partial class MainWindowController + { + [Outlet] + MonoMac.AppKit.NSTextField locationTextField { get; set; } + + [Outlet] + MonoMac.AppKit.NSSegmentedControl navigationButtons { get; set; } + + [Outlet] + MonoMac.AppKit.NSOutlineView outlineView { get; set; } + + [Outlet] + MonoMac.AppKit.NSButton populateOutlineViewButton { get; set; } + + [Outlet] + MonoMac.WebKit.WebView webView { get; set; } + + void ReleaseDesignerOutlets () + { + if (locationTextField != null) { + locationTextField.Dispose (); + locationTextField = null; + } + + if (navigationButtons != null) { + navigationButtons.Dispose (); + navigationButtons = null; + } + + if (webView != null) { + webView.Dispose (); + webView = null; + } + + if (outlineView != null) { + outlineView.Dispose (); + outlineView = null; + } + + if (populateOutlineViewButton != null) { + populateOutlineViewButton.Dispose (); + populateOutlineViewButton = null; + } + } + } + + [Register ("MainWindow")] + partial class MainWindow + { + + void ReleaseDesignerOutlets () + { + } + } +} diff --git a/tests/qa-regression/WebKitDelegateEvents/MainWindow.xib b/tests/qa-regression/WebKitDelegateEvents/MainWindow.xib new file mode 100644 index 000000000000..6b93e6e16061 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/MainWindow.xib @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/qa-regression/WebKitDelegateEvents/MainWindowController.cs b/tests/qa-regression/WebKitDelegateEvents/MainWindowController.cs new file mode 100644 index 000000000000..7f69411fd586 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/MainWindowController.cs @@ -0,0 +1,145 @@ +using System; + +using MonoMac.Foundation; +using MonoMac.AppKit; +using MonoMac.WebKit; + +namespace WebKitDelegateEvents +{ + public partial class MainWindowController : NSWindowController + { + string currentLocation; + + public MainWindowController (IntPtr handle) : base (handle) + { + } + + [Export ("initWithCoder:")] + public MainWindowController (NSCoder coder) : base (coder) + { + } + + public MainWindowController () : base ("MainWindow") + { + } + + void Navigate () + { + var location = locationTextField.StringValue; + if (currentLocation != location) { + currentLocation = location; + webView.MainFrame.LoadRequest (new NSUrlRequest (new NSUrl (location))); + Window.MakeFirstResponder (webView); + } + } + + class DomOutlineViewDelegate : NSOutlineViewDelegate + { + public override void SelectionDidChange (NSNotification notification) + { + Console.WriteLine ("SELECTION CHANGE VIA DELEGATE"); + } + } + + class DomOutlineViewDataSource : NSOutlineViewDataSource + { + WebView webView; + + DomNodeList GetChildren (NSObject item) + { + var node = item as DomNode; + if (node != null && node.HasChildNodes ()) + return node.ChildNodes; + + return null; + } + + public DomOutlineViewDataSource (WebView webView) + { + this.webView = webView; + } + + public override int GetChildrenCount (NSOutlineView outlineView, NSObject item) + { + if (item == null) + return 1; + + var children = GetChildren (item); + if (children != null) + return children.Count; + + return 0; + } + + public override NSObject GetChild (NSOutlineView outlineView, int childIndex, NSObject item) + { + if (item == null) + return webView.MainFrameDocument; + + var children = GetChildren (item); + if (children != null) + return children.GetItem (childIndex); + + return null; + } + + public override NSObject GetObjectValue (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) + { + return item; + } + + public override bool ItemExpandable (NSOutlineView outlineView, NSObject item) + { + return GetChildren (item) != null; + } + } + + void PopulateOutlineView () + { + outlineView.DataSource = new DomOutlineViewDataSource (webView); + outlineView.ReloadData (); + outlineView.ExpandItem (null, true); + } + + public override void AwakeFromNib () + { + navigationButtons.SetEnabled (false, 0); + navigationButtons.SetEnabled (false, 1); + navigationButtons.Activated += (sender, e) => { + switch (navigationButtons.SelectedSegment) { + case 0: + if (webView.CanGoBack ()) + webView.GoBack (); + break; + case 1: + if (webView.CanGoForward ()) + webView.GoForward (); + break; + } + }; + + populateOutlineViewButton.Activated += (sender, e) => PopulateOutlineView (); + + locationTextField.Activated += (sender, e) => Navigate (); + + webView.ReceivedTitle += (sender, e) => { + Console.WriteLine ("TITLE RECEIVED: {0}", e.Title); + if (e.ForFrame == webView.MainFrame) + Window.Title = e.Title; + }; + + webView.FinishedLoad += (sender, e) => { + Console.WriteLine ("FINISHED LOAD"); + navigationButtons.SetEnabled (webView.CanGoBack (), 0); + navigationButtons.SetEnabled (webView.CanGoForward (), 1); + PopulateOutlineView (); + }; + + //outlineView.Delegate = new DomOutlineViewDelegate (); + outlineView.SelectionDidChange += (sender, e) => { Console.WriteLine ("SELECTION CHANGE VIA EVENT"); }; + + locationTextField.StringValue = "http://catoverflow.com"; + Navigate (); + } + } +} \ No newline at end of file diff --git a/tests/qa-regression/WebKitDelegateEvents/WebKitDelegateEvents.csproj b/tests/qa-regression/WebKitDelegateEvents/WebKitDelegateEvents.csproj new file mode 100644 index 000000000000..ff4d7d99564e --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/WebKitDelegateEvents.csproj @@ -0,0 +1,93 @@ + + + + Debug + AnyCPU + 12.0.0 + 2.0 + {A361515F-4931-46EB-805D-404A7E096A15} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + WebKitDelegateEvents + Resources + WebKitDelegateEvents + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + false + false + Mac Developer + false + false + + + full + true + bin\Release + prompt + 4 + false + Full + false + true + false + Developer ID Application + true + true + + + full + true + bin\AppStore + prompt + 4 + false + Full + false + true + 3rd Party Mac Developer Installer + true + 3rd Party Mac Developer Application + true + true + + + + + + + + + + + + + + + + + MainWindow.cs + + + + + AppDelegate.cs + + + + + + + + + + + \ No newline at end of file diff --git a/tests/qa-regression/WebKitDelegateEvents/WebKitDelegateEvents.sln b/tests/qa-regression/WebKitDelegateEvents/WebKitDelegateEvents.sln new file mode 100644 index 000000000000..1248c4453533 --- /dev/null +++ b/tests/qa-regression/WebKitDelegateEvents/WebKitDelegateEvents.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebKitDelegateEvents", "WebKitDelegateEvents.csproj", "{A361515F-4931-46EB-805D-404A7E096A15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + AppStore|Any CPU = AppStore|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A361515F-4931-46EB-805D-404A7E096A15}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU + {A361515F-4931-46EB-805D-404A7E096A15}.AppStore|Any CPU.Build.0 = AppStore|Any CPU + {A361515F-4931-46EB-805D-404A7E096A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A361515F-4931-46EB-805D-404A7E096A15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A361515F-4931-46EB-805D-404A7E096A15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A361515F-4931-46EB-805D-404A7E096A15}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = WebKitDelegateEvents\WebKitDelegateEvents.csproj + EndGlobalSection +EndGlobal diff --git a/tests/scripted/Makefile b/tests/scripted/Makefile new file mode 100644 index 000000000000..52641689cf58 --- /dev/null +++ b/tests/scripted/Makefile @@ -0,0 +1,20 @@ +TOP=../../../xamarin-macios +include $(TOP)/Make.config + +ALL_TESTS=select-native-compiler bug-13945 bug-35786 + +all-local tests run-tests:: $(ALL_TESTS) + +select-native-compiler: + $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch armv7 -mno-thumb -miphoneos-version-min=$(IOS_SDK_VERSION) -isysroot $(XCODE_DEVELOPER_ROOT)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk -Wall -g -c select-native-compiler/native.cpp -o select-native-compiler/libNative.a + mkdir -p select-native-compiler/SelectNativeCompiler.app + $(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/btouch select-native-compiler/binding.cs --link-with=select-native-compiler/libNative.a,Native -s:select-native-compiler/managed.cs -o:select-native-compiler/binding.dll + $(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/smcs select-native-compiler/app.cs -r:$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/lib/mono/2.1/monotouch.dll -r:select-native-compiler/binding.dll -out:select-native-compiler/app.exe + $(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/mtouch -r:select-native-compiler/binding.dll select-native-compiler/app.exe -nosign --abi=armv7 -sdk "$(IOS_SDK_VERSION)" -dev:select-native-compiler/SelectNativeCompiler.app -sdkroot $(XCODE_DEVELOPER_ROOT) + +bug-13945 bug-35786: + $(MAKE) -C $@ + +.PHONY: $(ALL_TESTS) + +include $(TOP)/mk/rules.mk diff --git a/tests/scripted/bug-13945/.gitignore b/tests/scripted/bug-13945/.gitignore new file mode 100644 index 000000000000..198f6ccbfad3 --- /dev/null +++ b/tests/scripted/bug-13945/.gitignore @@ -0,0 +1,7 @@ +.libs +*.exe +*.dll +*.a +*.m +TheApp.app* +cache* diff --git a/tests/scripted/bug-13945/Makefile b/tests/scripted/bug-13945/Makefile new file mode 100644 index 000000000000..8ccc779e91a7 --- /dev/null +++ b/tests/scripted/bug-13945/Makefile @@ -0,0 +1,33 @@ +TOP=../../../../xamarin-macios +include $(TOP)/Make.config + +all-local:: bug-13945 + +bug-13945: + @git clean -xfdq + @echo "void foo () {}" > nativeA.m + @echo "void bar () {}" > nativeB.m + @mkdir -p .libs + @$(MAKE) .libs/ios/nativeA.armv7.o + @$(MAKE) .libs/ios/nativeB.armv7.o + @rm -Rf TheApp.app cache cache-first + @mkdir -p TheApp.app + @mkdir -p cache + + @cp .libs/ios/nativeA.armv7.o libNative.a + @$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/btouch binding.cs --link-with=libNative.a,Native -s:managed.cs -o:binding.dll + @$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/smcs app.cs -r:$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/lib/mono/2.1/monotouch.dll -r:binding.dll -out:app.exe + @$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/mtouch -r:binding.dll app.exe -nosign --abi=armv7 -sdk "$(IOS_SDK_VERSION)" -dev:TheApp.app -sdkroot $(XCODE_DEVELOPER_ROOT) --cache=$(shell pwd)/cache + + @cp -Rp cache cache-first + + @cp .libs/ios/nativeB.armv7.o libNative.a + @$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/btouch binding.cs --link-with=libNative.a,Native -s:managed.cs -o:binding.dll + # do not rebuild the .exe + @$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/mtouch -r:binding.dll app.exe -nosign --abi=armv7 -sdk "$(IOS_SDK_VERSION)" -dev:TheApp.app -sdkroot $(XCODE_DEVELOPER_ROOT) --cache=$(shell pwd)/cache + + # this will verify that binding.dll wasn't AOT'ed again - if binding.dll.armv7.s differ then the AOT compiler executed. + @diff -u cache-first/binding.dll.armv7.s cache/binding.dll.armv7.s + @echo "$@: Success" + +include $(TOP)/mk/rules.mk diff --git a/tests/scripted/bug-13945/app.cs b/tests/scripted/bug-13945/app.cs new file mode 100644 index 000000000000..80fc987852c5 --- /dev/null +++ b/tests/scripted/bug-13945/app.cs @@ -0,0 +1,7 @@ +class Test { + static void Main () + { + System.Console.WriteLine (typeof (MonoTouch.UIKit.UIButton)); + System.Console.WriteLine (typeof (Native)); + } +} \ No newline at end of file diff --git a/tests/scripted/bug-13945/binding.cs b/tests/scripted/bug-13945/binding.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/scripted/bug-13945/managed.cs b/tests/scripted/bug-13945/managed.cs new file mode 100644 index 000000000000..4e6c882c93b9 --- /dev/null +++ b/tests/scripted/bug-13945/managed.cs @@ -0,0 +1,7 @@ +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; + +[assembly: LinkWith ("Native", ForceLoad = true, LinkTarget = LinkTarget.ArmV7)] + +public class Native { +} \ No newline at end of file diff --git a/tests/scripted/bug-35786/.gitignore b/tests/scripted/bug-35786/.gitignore new file mode 100644 index 000000000000..22a3df7ac78b --- /dev/null +++ b/tests/scripted/bug-35786/.gitignore @@ -0,0 +1,2 @@ +libs + diff --git a/tests/scripted/bug-35786/Main.cs b/tests/scripted/bug-35786/Main.cs new file mode 100644 index 000000000000..80b75b865372 --- /dev/null +++ b/tests/scripted/bug-35786/Main.cs @@ -0,0 +1,8 @@ +class M +{ + static void Main () + { + System.Console.WriteLine (typeof (UIKit.UIWindow)); + All.UseMe (); + } +} \ No newline at end of file diff --git a/tests/scripted/bug-35786/Makefile b/tests/scripted/bug-35786/Makefile new file mode 100644 index 000000000000..0b9b33cfa0ed --- /dev/null +++ b/tests/scripted/bug-35786/Makefile @@ -0,0 +1,44 @@ +TOP=../../../../xamarin-macios +include $(TOP)/Make.config + +all-local:: bug-35786 + +ITERATIONS=100 +ALL_DLLS:=$(shell printf "libs/C%i.dll " {1..$(ITERATIONS)}) + +libs/C%.cs: Makefile + @echo "public class C$* {}" >> $@ + +libs/C%.dll: libs/C%.cs Makefile + $(SYSTEM_MCS) -target:library $< -out:$@ + +libs/All.cs: Makefile + @echo "public class All {" > $@ + @echo " public static void UseMe ()" >> $@ + @echo " {" >> $@ + @printf " System.Console.WriteLine (typeof (C%i));\n" {1..$(ITERATIONS)} >> $@ + @echo " }" >> $@ + @echo "}" >> $@ + +libs/All.dll.rsp: Makefile + @printf -- "-r:libs/C%i.dll\n" {1..$(ITERATIONS)} > $@ + +libs/All.dll: libs/All.cs libs/All.dll.rsp $(ALL_DLLS) + $(SYSTEM_MCS) -target:library @$@.rsp $< -out:$@ + +libs/bug-35786.exe: Main.cs libs/All.dll + $(SYSTEM_MCS) -target:exe $< -out:$@ -r:libs/All.dll -r:$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.iOS/Xamarin.iOS.dll -lib:$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.iOS + +bug-35786: + @git clean -xfdq + @mkdir -p libs + @$(MAKE) -j20 libs/bug-35786.exe + @mkdir -p libs/bug-35786.app + @# ulimit -n=64 works while testing (with the fix for this bug), so use 96 to have some buffer. + @# we lower the ulimit here so that we don't have to create that many assemblies to test with + @# the ulimit default on Yosemite is ulimit=256, which requires 300 assemblies to break the stripper, and 400 assemblies to break the AOT compiler. + @# with 96 here, we only need 20 assemblies to break the stripper, and 35 to break the AOT compiler, so running the test with 100 assemblies should be more than enough. + ulimit -n 96 && $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/bin/mtouch --dev libs/bug-35786.app --abi armv7,arm64 libs/bug-35786.exe --sdkroot $(XCODE_DEVELOPER_ROOT) --sdk $(IOS_SDK_VERSION) -r:$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.iOS/Xamarin.iOS.dll + + +include $(TOP)/mk/rules.mk diff --git a/tests/scripted/select-native-compiler/.gitignore b/tests/scripted/select-native-compiler/.gitignore new file mode 100644 index 000000000000..0bc2cb306dad --- /dev/null +++ b/tests/scripted/select-native-compiler/.gitignore @@ -0,0 +1,5 @@ +*.app +*.dSYM +*.a +*.exe +*.dll diff --git a/tests/scripted/select-native-compiler/app.cs b/tests/scripted/select-native-compiler/app.cs new file mode 100644 index 000000000000..80fc987852c5 --- /dev/null +++ b/tests/scripted/select-native-compiler/app.cs @@ -0,0 +1,7 @@ +class Test { + static void Main () + { + System.Console.WriteLine (typeof (MonoTouch.UIKit.UIButton)); + System.Console.WriteLine (typeof (Native)); + } +} \ No newline at end of file diff --git a/tests/scripted/select-native-compiler/binding.cs b/tests/scripted/select-native-compiler/binding.cs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/scripted/select-native-compiler/managed.cs b/tests/scripted/select-native-compiler/managed.cs new file mode 100644 index 000000000000..e8a2db9b9ae5 --- /dev/null +++ b/tests/scripted/select-native-compiler/managed.cs @@ -0,0 +1,7 @@ +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; + +[assembly: LinkWith ("Native", ForceLoad = true, LinkTarget = LinkTarget.ArmV7, IsCxx = true)] + +public class Native { +} \ No newline at end of file diff --git a/tests/scripted/select-native-compiler/native.cpp b/tests/scripted/select-native-compiler/native.cpp new file mode 100644 index 000000000000..983732173a25 --- /dev/null +++ b/tests/scripted/select-native-compiler/native.cpp @@ -0,0 +1,4 @@ +void do_cpp_stuff () +{ + throw "exception"; +} \ No newline at end of file diff --git a/tests/scriptingbridge/Makefile b/tests/scriptingbridge/Makefile new file mode 100644 index 000000000000..adf27f25e1b0 --- /dev/null +++ b/tests/scriptingbridge/Makefile @@ -0,0 +1,41 @@ +TOP = ../.. + +include $(TOP)/Make.config +include $(TOP)/mk/rules.mk + +MMP=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/bin/mmp +BMAC=$(MAC_DESTDIR)/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/bin/bmac + +all-local:: build/compat/test.app build/mobile-32/test.app build/mobile-64/test.app + +exec-compat: build/compat/test.app + ./build/compat/test.app/Contents/MacOS/test | grep Passed + +exec-mobile-%: build/mobile-%/test.app + ./build/mobile-$*/test.app/Contents/MacOS/test | grep Passed + +run run-test run-tests: build/compat/test.app build/mobile-32/test.app build/mobile-64/test.app + @rm -f .$@-failure.stamp + @$(MAKE) exec-compat || echo "run-compat failed" >> .$@-failure.stamp + @$(MAKE) exec-mobile-32 || echo "run-mobile-32 failed" >> .$@-failure.stamp + @$(MAKE) exec-mobile-64 || echo "run-mobile-64 failed" >> .$@-failure.stamp + @if test -e .$@-failure.stamp; then cat .$@-failure.stamp; rm .$@-failure.stamp; exit 1; fi + +build/compat/test.app: build/compat/finder.dll + rm -Rf $@ + $(SYSTEM_MCS) "/out:build/compat/test.exe" "/r:build/compat/finder.dll" /r:$(TOP)/src/build/mac/compat/XamMac.dll /t:exe "test.cs" + $(MMP) -nolink "-minos=10.7" -o "build/compat" -n "test" --profile "4.5" -a $(TOP)/src/build/mac/compat/XamMac.dll -a "build/compat/finder.dll" "build/compat/test.exe" + +build/compat/finder.dll: + $(BMAC) --out=build/compat/finder.dll --outdir=build/compat/ -r:/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/System.Drawing.dll -baselib:$(TOP)/src/build/mac/compat/XamMac.dll finder.cs + +build/mobile-%/test.app: build/mobile-%/finder.dll + rm -Rf $@ + $(SYSTEM_MCS) "/out:build/mobile-$*/test.exe" "/r:build/mobile-$*/finder.dll" /r:$(TOP)/src/build/mac/mobile-$*/Xamarin.Mac.dll /t:exe "test.cs" -define:XAMCORE_2_0 + $(MMP) -nolink "-minos=10.7" -o "build/mobile-$*" -n "test" --profile "4.5" -a $(TOP)/src/build/mac/mobile-$*/Xamarin.Mac.dll -a "build/mobile-$*/finder.dll" "build/mobile-$*/test.exe" --profile mobile --arch $(shell test '$*' == '32' && echo i386 || echo x86_64) + +build/mobile-%/finder.dll: + $(BMAC) --unified-mobile-profile --out=build/mobile-$*/finder.dll --outdir=build/mobile-$*/ -baselib:$(TOP)/src/build/mac/mobile-$*/Xamarin.Mac.dll -d=XAMCORE_2_0 finder.cs + +clean-local:: + @rm -rf build/ diff --git a/tests/scriptingbridge/finder.cs b/tests/scriptingbridge/finder.cs new file mode 100644 index 000000000000..2263922c6e6c --- /dev/null +++ b/tests/scriptingbridge/finder.cs @@ -0,0 +1,38 @@ +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using ScriptingBridge; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +using MonoMac.ScriptingBridge; +#endif + +namespace Finder +{ + [BaseType (typeof(SBObject))] + interface FinderItem + { + [Export ("name")] + string Name { get; } + } + + [BaseType (typeof(FinderItem))] + interface FinderContainer + { + } + + [BaseType (typeof(FinderContainer))] + interface FinderTrashObject + { + [Export ("items")] + SBElementArray Items { get; } + } + + [BaseType (typeof(SBApplication))] + interface FinderApplication + { + [Export ("trash")] + FinderTrashObject Trash { get; } + } +} diff --git a/tests/scriptingbridge/test.cs b/tests/scriptingbridge/test.cs new file mode 100644 index 000000000000..d835a626ea23 --- /dev/null +++ b/tests/scriptingbridge/test.cs @@ -0,0 +1,33 @@ +using System; +using Finder; +#if XAMCORE_2_0 +using AppKit; +using ScriptingBridge; +#else +using nuint = System.Int32; +using MonoMac.AppKit; +using MonoMac.ScriptingBridge; +#endif + +namespace ScriptingBridge.Tests +{ + public static class MainClass + { + static int Main (string[] args) + { + FinderApplication app = SBApplication.FromBundleIdentifier ("com.apple.finder"); + + if ((int)app.Trash.Items.Count > 0) { + for (int i = 0 ; i < (int)app.Trash.Items.Count ; ++i) { + FinderItem item = app.Trash.Items.GetItem ((nuint)i); + if (item.Name == null) + return 0; + } + } + + Console.WriteLine ("Passed"); + + return 0; + } + } +} diff --git a/tests/tests-mac.sln b/tests/tests-mac.sln new file mode 100644 index 000000000000..3c1a1f64b974 --- /dev/null +++ b/tests/tests-mac.sln @@ -0,0 +1,85 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dontlink-mac-unified", "dontlink-mac\dontlink-mac-unified.csproj", "{FD385098-B3FD-4331-92BF-CC1F918E3334}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mmptest", "mmptest\mmptest.csproj", "{6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "msbuild-mac", "msbuild-mac\msbuild-mac.csproj", "{F8500DCE-2119-4DF9-8360-0F46DDB6930C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiUnit_xammac_mobile", "..\..\xamarin-macios\external\guiunit\src\framework\GuiUnit_xammac_mobile.csproj", "{EACFD119-769E-4E6C-89B7-A6CE3757C431}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "apitest-unified", "apitest\apitest-unified.csproj", "{7A0EDA95-30A6-43E1-AD43-368AD95AC48B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Default|Any CPU = Default|Any CPU + AppStore|Any CPU = AppStore|Any CPU + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|Any CPU.ActiveCfg = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|Any CPU.Build.0 = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Default|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Default|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.AppStore|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.AppStore|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|x86.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|x86.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|x86.ActiveCfg = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|x86.Build.0 = Release|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Debug|Any CPU.ActiveCfg = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Debug|Any CPU.Build.0 = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Release|Any CPU.ActiveCfg = Release|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Release|Any CPU.Build.0 = Release|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Default|Any CPU.ActiveCfg = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Default|Any CPU.Build.0 = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.AppStore|Any CPU.ActiveCfg = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.AppStore|Any CPU.Build.0 = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Debug|x86.ActiveCfg = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Debug|x86.Build.0 = Debug|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Release|x86.ActiveCfg = Release|x86 + {6E5405EC-1F68-4CD8-AD4B-E4CCFBE47977}.Release|x86.Build.0 = Release|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|Any CPU.ActiveCfg = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|Any CPU.Build.0 = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|Any CPU.ActiveCfg = Release|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|Any CPU.Build.0 = Release|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Default|Any CPU.ActiveCfg = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Default|Any CPU.Build.0 = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.AppStore|Any CPU.ActiveCfg = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.AppStore|Any CPU.Build.0 = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|x86.ActiveCfg = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Debug|x86.Build.0 = Debug|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|x86.ActiveCfg = Release|x86 + {F8500DCE-2119-4DF9-8360-0F46DDB6930C}.Release|x86.Build.0 = Release|x86 + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Release|Any CPU.Build.0 = Release|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Default|Any CPU.ActiveCfg = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Default|Any CPU.Build.0 = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Debug|x86.ActiveCfg = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Debug|x86.Build.0 = Debug|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Release|x86.ActiveCfg = Release|Any CPU + {EACFD119-769E-4E6C-89B7-A6CE3757C431}.Release|x86.Build.0 = Release|Any CPU + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Debug|Any CPU.ActiveCfg = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Debug|Any CPU.Build.0 = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Release|Any CPU.ActiveCfg = Release|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Release|Any CPU.Build.0 = Release|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Default|Any CPU.ActiveCfg = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Default|Any CPU.Build.0 = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.AppStore|Any CPU.ActiveCfg = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.AppStore|Any CPU.Build.0 = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Debug|x86.ActiveCfg = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Debug|x86.Build.0 = Debug|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Release|x86.ActiveCfg = Release|x86 + {7A0EDA95-30A6-43E1-AD43-368AD95AC48B}.Release|x86.Build.0 = Release|x86 + EndGlobalSection +EndGlobal diff --git a/tests/tests.sln b/tests/tests.sln new file mode 100644 index 000000000000..f7420cb99b47 --- /dev/null +++ b/tests/tests.sln @@ -0,0 +1,386 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "monotouch-test", "monotouch-test\monotouch-test.csproj", "{AC6D070F-2ED4-4701-B701-81915B931D1D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dont link", "dont link\dont link.csproj", "{208744BD-504E-47D7-9A98-1CF02454A6DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link sdk", "link sdk\link sdk.csproj", "{C47F8F72-A7CA-4149-AA7D-BC4814803EF3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "link all", "link all\link all.csproj", "{370CC763-EDC3-41DA-A21A-D4C82CABEFE4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mtouch", "mtouch\mtouch.csproj", "{9A1177F5-16E6-45DE-AA69-DC9924EC39B8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bindings-test", "bindings-test\bindings-test.csproj", "{D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BundledResources", "BundledResources\BundledResources.csproj", "{FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mscorlib", "bcl-test\mscorlib\mscorlib.csproj", "{34CB1751-E445-4E32-BFA7-03E6831C11EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System", "bcl-test\System\System.csproj", "{EEE20F63-4282-450A-8584-93F640929D13}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Core", "bcl-test\System.Core\System.Core.csproj", "{FBC970AA-8234-4905-B559-BD3F32A63C04}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http", "bcl-test\System.Net.Http\System.Net.Http.csproj", "{D7212E3D-CD1B-4E58-A11D-C7B7898168AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Numerics", "bcl-test\System.Numerics\System.Numerics.csproj", "{4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Security", "bcl-test\Mono.Security\Mono.Security.csproj", "{5023D584-1A32-4917-90C5-A641C800230C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Xml", "bcl-test\System.Xml\System.Xml.csproj", "{93268FFB-571C-4402-8899-027A7778D2C0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Xml.Linq", "bcl-test\System.Xml.Linq\System.Xml.Linq.csproj", "{DB354193-B05D-471B-BEB8-F6C74DA4C93A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Serialization", "bcl-test\System.Runtime.Serialization\System.Runtime.Serialization.csproj", "{B86D100D-895B-4510-A5BB-E08F11E82C3C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Transactions", "bcl-test\System.Transactions\System.Transactions.csproj", "{A12ED440-8270-4701-A35D-0C3C9E0AA735}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Data", "bcl-test\System.Data\System.Data.csproj", "{BEF0140A-A6A6-4074-B55F-03856A6B5862}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Web.Services", "bcl-test\System.Web.Services\System.Web.Services.csproj", "{DA061019-04C3-4221-AF04-63F2BFB5DA42}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mini", "mini\mini.csproj", "{5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.ComponentModel.DataAnnotations", "bcl-test\System.ComponentModel.DataAnnotations\System.ComponentModel.DataAnnotations.csproj", "{3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Json", "bcl-test\System.Json\System.Json.csproj", "{5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.ServiceModel.Web", "bcl-test\System.ServiceModel.Web\System.ServiceModel.Web.csproj", "{2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmbeddedResources", "EmbeddedResources\EmbeddedResources.csproj", "{676F527D-3352-42EA-9DE2-181C45003568}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Data.Sqlite", "bcl-test\Mono.Data.Sqlite\Mono.Data.Sqlite.csproj", "{1ADF4F27-7610-4501-A62E-1157273AED7E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "framework-test", "framework-test\framework-test.csproj", "{2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xharness", "xharness\xharness.csproj", "{E1F53F80-8399-499B-8017-C414B9CD263B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoTouch.NUnitLite", "..\..\xamarin-macios\src\MonoTouch.NUnitLite.csproj", "{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bindings-framework-test", "bindings-framework-test\bindings-framework-test.csproj", "{E40B0B77-3467-4891-9117-7AF8F248E306}" +EndProject +Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "fsharplibrary", "fsharplibrary\fsharplibrary.fsproj", "{C7212169-BA46-413B-91CD-A32C52AD5E0D}" +EndProject +Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "fsharp", "fsharp\fsharp.fsproj", "{7862FE5A-530A-4651-825F-C80836B0A3A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|iPhoneSimulator = Release|iPhoneSimulator + Debug|iPhone = Debug|iPhone + Release|iPhone = Release|iPhone + Debug|Any CPU = Debug|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Debug|iPhone.ActiveCfg = Debug|iPhone + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Debug|iPhone.Build.0 = Debug|iPhone + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Release|iPhone.ActiveCfg = Release|iPhone + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Release|iPhone.Build.0 = Release|iPhone + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {1ADF4F27-7610-4501-A62E-1157273AED7E}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhone.ActiveCfg = Debug|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhone.Build.0 = Debug|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhone.ActiveCfg = Release|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhone.Build.0 = Release|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.ActiveCfg = Debug|iPhone + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.Build.0 = Debug|iPhone + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.ActiveCfg = Release|iPhone + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.Build.0 = Release|iPhone + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {2CF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Debug|iPhone.ActiveCfg = Debug|iPhone + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Debug|iPhone.Build.0 = Debug|iPhone + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Release|iPhone.ActiveCfg = Release|iPhone + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Release|iPhone.Build.0 = Release|iPhone + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {2ECCE3D0-AAD1-46B9-B190-B567249DCF9C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Debug|iPhone.ActiveCfg = Debug|iPhone + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Debug|iPhone.Build.0 = Debug|iPhone + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Release|iPhone.ActiveCfg = Release|iPhone + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Release|iPhone.Build.0 = Release|iPhone + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {34CB1751-E445-4E32-BFA7-03E6831C11EE}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Debug|iPhone.ActiveCfg = Debug|iPhone + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Debug|iPhone.Build.0 = Debug|iPhone + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Release|iPhone.ActiveCfg = Release|iPhone + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Release|iPhone.Build.0 = Release|iPhone + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {370CC763-EDC3-41DA-A21A-D4C82CABEFE4}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.ActiveCfg = Debug|iPhone + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.Build.0 = Debug|iPhone + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.ActiveCfg = Release|iPhone + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.Build.0 = Release|iPhone + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {3DF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.ActiveCfg = Debug|iPhone + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.Build.0 = Debug|iPhone + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.ActiveCfg = Release|iPhone + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.Build.0 = Release|iPhone + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {4EF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {5023D584-1A32-4917-90C5-A641C800230C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {5023D584-1A32-4917-90C5-A641C800230C}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {5023D584-1A32-4917-90C5-A641C800230C}.Debug|iPhone.ActiveCfg = Debug|iPhone + {5023D584-1A32-4917-90C5-A641C800230C}.Debug|iPhone.Build.0 = Debug|iPhone + {5023D584-1A32-4917-90C5-A641C800230C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {5023D584-1A32-4917-90C5-A641C800230C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {5023D584-1A32-4917-90C5-A641C800230C}.Release|iPhone.ActiveCfg = Release|iPhone + {5023D584-1A32-4917-90C5-A641C800230C}.Release|iPhone.Build.0 = Release|iPhone + {5023D584-1A32-4917-90C5-A641C800230C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {5023D584-1A32-4917-90C5-A641C800230C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Debug|iPhone.ActiveCfg = Debug|iPhone + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Debug|iPhone.Build.0 = Debug|iPhone + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Release|iPhone.ActiveCfg = Release|iPhone + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Release|iPhone.Build.0 = Release|iPhone + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {5BDBB8B4-5D6B-43E8-9664-C4D5CA3C9B11}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.ActiveCfg = Debug|iPhone + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhone.Build.0 = Debug|iPhone + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.ActiveCfg = Release|iPhone + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhone.Build.0 = Release|iPhone + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {5FF294C6-91F1-407B-8A0C-AFACC7C1BDE8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {676F527D-3352-42EA-9DE2-181C45003568}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Debug|Any CPU.Build.0 = Debug|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Debug|iPhone.Build.0 = Debug|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Release|iPhone.ActiveCfg = Release|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Release|iPhone.Build.0 = Release|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {676F527D-3352-42EA-9DE2-181C45003568}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {93268FFB-571C-4402-8899-027A7778D2C0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {93268FFB-571C-4402-8899-027A7778D2C0}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {93268FFB-571C-4402-8899-027A7778D2C0}.Debug|iPhone.ActiveCfg = Debug|iPhone + {93268FFB-571C-4402-8899-027A7778D2C0}.Debug|iPhone.Build.0 = Debug|iPhone + {93268FFB-571C-4402-8899-027A7778D2C0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {93268FFB-571C-4402-8899-027A7778D2C0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {93268FFB-571C-4402-8899-027A7778D2C0}.Release|iPhone.ActiveCfg = Release|iPhone + {93268FFB-571C-4402-8899-027A7778D2C0}.Release|iPhone.Build.0 = Release|iPhone + {93268FFB-571C-4402-8899-027A7778D2C0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {93268FFB-571C-4402-8899-027A7778D2C0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Release|iPhone.ActiveCfg = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Release|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Release|iPhoneSimulator.Build.0 = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Debug|iPhone.Build.0 = Debug|Any CPU + {9A1177F5-16E6-45DE-AA69-DC9924EC39B8}.Release|iPhone.Build.0 = Debug|Any CPU + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Debug|iPhone.ActiveCfg = Debug|iPhone + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Debug|iPhone.Build.0 = Debug|iPhone + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Release|iPhone.ActiveCfg = Release|iPhone + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Release|iPhone.Build.0 = Release|iPhone + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {A12ED440-8270-4701-A35D-0C3C9E0AA735}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Debug|iPhone.ActiveCfg = Debug|iPhone + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Debug|iPhone.Build.0 = Debug|iPhone + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Release|iPhone.ActiveCfg = Release|iPhone + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Release|iPhone.Build.0 = Release|iPhone + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {AC6D070F-2ED4-4701-B701-81915B931D1D}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Debug|iPhone.ActiveCfg = Debug|iPhone + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Debug|iPhone.Build.0 = Debug|iPhone + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Release|iPhone.ActiveCfg = Release|iPhone + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Release|iPhone.Build.0 = Release|iPhone + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {B86D100D-895B-4510-A5BB-E08F11E82C3C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Debug|iPhone.ActiveCfg = Debug|iPhone + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Debug|iPhone.Build.0 = Debug|iPhone + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Release|iPhone.ActiveCfg = Release|iPhone + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Release|iPhone.Build.0 = Release|iPhone + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {BEF0140A-A6A6-4074-B55F-03856A6B5862}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Debug|iPhone.ActiveCfg = Debug|iPhone + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Debug|iPhone.Build.0 = Debug|iPhone + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Release|iPhone.ActiveCfg = Release|iPhone + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Release|iPhone.Build.0 = Release|iPhone + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {C47F8F72-A7CA-4149-AA7D-BC4814803EF3}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Debug|iPhone.Build.0 = Debug|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Release|iPhone.ActiveCfg = Release|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Release|iPhone.Build.0 = Release|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Debug|iPhone.ActiveCfg = Debug|iPhone + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Debug|iPhone.Build.0 = Debug|iPhone + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Release|iPhone.ActiveCfg = Release|iPhone + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Release|iPhone.Build.0 = Release|iPhone + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {D7212E3D-CD1B-4E58-A11D-C7B7898168AA}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Debug|iPhone.ActiveCfg = Debug|iPhone + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Debug|iPhone.Build.0 = Debug|iPhone + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Release|iPhone.ActiveCfg = Release|iPhone + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Release|iPhone.Build.0 = Release|iPhone + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {DA061019-04C3-4221-AF04-63F2BFB5DA42}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Debug|iPhone.ActiveCfg = Debug|iPhone + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Debug|iPhone.Build.0 = Debug|iPhone + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Release|iPhone.ActiveCfg = Release|iPhone + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Release|iPhone.Build.0 = Release|iPhone + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {DB354193-B05D-471B-BEB8-F6C74DA4C93A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhone.Build.0 = Debug|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhone.ActiveCfg = Release|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhone.Build.0 = Release|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Debug|iPhone.Build.0 = Debug|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Release|iPhone.ActiveCfg = Release|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Release|iPhone.Build.0 = Release|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {E1F53F80-8399-499B-8017-C414B9CD263B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Debug|iPhone.Build.0 = Debug|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Release|iPhone.ActiveCfg = Release|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Release|iPhone.Build.0 = Release|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {E40B0B77-3467-4891-9117-7AF8F248E306}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {EEE20F63-4282-450A-8584-93F640929D13}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {EEE20F63-4282-450A-8584-93F640929D13}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {EEE20F63-4282-450A-8584-93F640929D13}.Debug|iPhone.ActiveCfg = Debug|iPhone + {EEE20F63-4282-450A-8584-93F640929D13}.Debug|iPhone.Build.0 = Debug|iPhone + {EEE20F63-4282-450A-8584-93F640929D13}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {EEE20F63-4282-450A-8584-93F640929D13}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {EEE20F63-4282-450A-8584-93F640929D13}.Release|iPhone.ActiveCfg = Release|iPhone + {EEE20F63-4282-450A-8584-93F640929D13}.Release|iPhone.Build.0 = Release|iPhone + {EEE20F63-4282-450A-8584-93F640929D13}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {EEE20F63-4282-450A-8584-93F640929D13}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Debug|iPhone.ActiveCfg = Debug|iPhone + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Debug|iPhone.Build.0 = Debug|iPhone + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Release|iPhone.ActiveCfg = Release|iPhone + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Release|iPhone.Build.0 = Release|iPhone + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {FBC970AA-8234-4905-B559-BD3F32A63C04}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Debug|iPhone.Build.0 = Debug|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Release|iPhone.ActiveCfg = Release|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Release|iPhone.Build.0 = Release|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {FE6EDEE9-ADF6-4F42-BCF2-B68C0A44EC3D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Debug|iPhone.Build.0 = Debug|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Release|iPhone.ActiveCfg = Release|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Release|iPhone.Build.0 = Release|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7212169-BA46-413B-91CD-A32C52AD5E0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Debug|iPhone.ActiveCfg = Debug|iPhone + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Debug|iPhone.Build.0 = Debug|iPhone + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Release|iPhone.ActiveCfg = Release|iPhone + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Release|iPhone.Build.0 = Release|iPhone + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {7862FE5A-530A-4651-825F-C80836B0A3A1}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + EndGlobalSection +EndGlobal diff --git a/tests/watchos/App/App.csproj b/tests/watchos/App/App.csproj new file mode 100644 index 000000000000..0c6c49beab2a --- /dev/null +++ b/tests/watchos/App/App.csproj @@ -0,0 +1,107 @@ + + + + Debug + iPhoneSimulator + {A9A6EAC2-568B-4F3E-869D-32CBBA122DF2};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 8.0.30703 + 2.0 + {34A6793F-37B2-4A7F-9286-7BDF52F412F3} + Library + App + Resources + App + obj\$(Platform)\$(Configuration)-watchos-app + + + bin\iPhoneSimulator\Debug-watchos-app + true + full + false + DEBUG; + prompt + 4 + false + i386 + None + true + true + true + true + iPhone Developer + true + true + + + bin\iPhone\Release-watchos-app + full + true + prompt + 4 + false + ARMv7k + %WATCHAPP_PATH%Entitlements.plist + true + true + iPhone Developer + true + + + bin\iPhoneSimulator\Release-watchos-app + full + true + prompt + 4 + false + i386 + None + true + iPhone Developer + true + + + bin\iPhone\Debug-watchos-app + true + full + false + DEBUG; + prompt + 4 + false + ARMv7k + %WATCHAPP_PATH%Entitlements.plist + true + iPhone Developer + true + true + true + true + true + + + + + + + + + + + + + Info.plist + + + + + + + + + + %WATCHEXTENSION_GUID% + %WATCHEXTENSION_NAME% + True + + + \ No newline at end of file diff --git a/tests/watchos/App/Entitlements.plist b/tests/watchos/App/Entitlements.plist new file mode 100644 index 000000000000..9ae599370b42 --- /dev/null +++ b/tests/watchos/App/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/watchos/App/Info.plist b/tests/watchos/App/Info.plist new file mode 100644 index 000000000000..6c79287b39b9 --- /dev/null +++ b/tests/watchos/App/Info.plist @@ -0,0 +1,29 @@ + + + + + CFBundleName + Don't Link + CFBundleIdentifier + %APP_CFBUNDLEIDENTIFER% + CFBundleDevelopmentRegion + en + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.33 + MinimumOSVersion + 2.0 + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + WKCompanionAppBundleIdentifier + com.xamarin.dontlink + WKWatchKitApp + + XSAppIconAssets + Resources/Images.xcassets/AppIcons.appiconset + + diff --git a/tests/watchos/App/Interface.storyboard b/tests/watchos/App/Interface.storyboard new file mode 100644 index 000000000000..8be34f1f6535 --- /dev/null +++ b/tests/watchos/App/Interface.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Contents.json b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Contents.json new file mode 100644 index 000000000000..1e37f2647694 --- /dev/null +++ b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Contents.json @@ -0,0 +1,165 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "57x57", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "size" : "57x57", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "size" : "24x24", + "idiom" : "watch", + "scale" : "2x", + "filename" : "Icon-24x24@2x.png", + "role" : "notificationCenter", + "subtype" : "38mm" + }, + { + "size" : "27.5x27.5", + "idiom" : "watch", + "scale" : "2x", + "filename" : "Icon-27.5x27.5@2x.png", + "role" : "notificationCenter", + "subtype" : "42mm" + }, + { + "size" : "29x29", + "idiom" : "watch", + "filename" : "Icon-29x29@2x.png", + "role" : "companionSettings", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "watch", + "filename" : "Icon-29x29@3x.png", + "role" : "companionSettings", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "watch", + "scale" : "2x", + "filename" : "Icon-40x40@2x.png", + "role" : "appLauncher", + "subtype" : "38mm" + }, + { + "size" : "44x44", + "idiom" : "watch", + "scale" : "2x", + "filename" : "Icon-44x44@2x.png", + "role" : "longLook", + "subtype" : "42mm" + }, + { + "size" : "86x86", + "idiom" : "watch", + "scale" : "2x", + "filename" : "Icon-86x86@2x.png", + "role" : "quickLook", + "subtype" : "38mm" + }, + { + "size" : "98x98", + "idiom" : "watch", + "scale" : "2x", + "filename" : "Icon-98x98@2x.png", + "role" : "quickLook", + "subtype" : "42mm" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-24x24@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-24x24@2x.png new file mode 100644 index 000000000000..7d9f6aa9487c Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-24x24@2x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-27.5x27.5@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-27.5x27.5@2x.png new file mode 100644 index 000000000000..1a3ab595d876 Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-27.5x27.5@2x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-29x29@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-29x29@2x.png new file mode 100644 index 000000000000..e84a3424f039 Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-29x29@2x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-29x29@3x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-29x29@3x.png new file mode 100644 index 000000000000..8446ac8c9b92 Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-29x29@3x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-40x40@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-40x40@2x.png new file mode 100644 index 000000000000..bfda50a10d31 Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-40x40@2x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-44x44@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-44x44@2x.png new file mode 100644 index 000000000000..9f8fb94d447f Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-44x44@2x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-86x86@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-86x86@2x.png new file mode 100644 index 000000000000..66122f86b7e5 Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-86x86@2x.png differ diff --git a/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-98x98@2x.png b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-98x98@2x.png new file mode 100644 index 000000000000..7dbce7772adf Binary files /dev/null and b/tests/watchos/App/Resources/Images.xcassets/AppIcons.appiconset/Icon-98x98@2x.png differ diff --git a/tests/watchos/Container/AppDelegate.cs b/tests/watchos/Container/AppDelegate.cs new file mode 100644 index 000000000000..d2650ba61a4e --- /dev/null +++ b/tests/watchos/Container/AppDelegate.cs @@ -0,0 +1,59 @@ +using Foundation; +using UIKit; + +namespace Container +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to application events from iOS. + [Register ("AppDelegate")] + public class AppDelegate : UIApplicationDelegate + { + // class-level declarations + + public override UIWindow Window { + get; + set; + } + + public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions) + { + // Override point for customization after application launch. + // If not required for your application you can safely delete this method + + return true; + } + + public override void OnResignActivation (UIApplication application) + { + // Invoked when the application is about to move from active to inactive state. + // This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) + // or when the user quits the application and it begins the transition to the background state. + // Games should use this method to pause the game. + } + + public override void DidEnterBackground (UIApplication application) + { + // Use this method to release shared resources, save user data, invalidate timers and store the application state. + // If your application supports background exection this method is called instead of WillTerminate when the user quits. + } + + public override void WillEnterForeground (UIApplication application) + { + // Called as part of the transiton from background to active state. + // Here you can undo many of the changes made on entering the background. + } + + public override void OnActivated (UIApplication application) + { + // Restart any tasks that were paused (or not yet started) while the application was inactive. + // If the application was previously in the background, optionally refresh the user interface. + } + + public override void WillTerminate (UIApplication application) + { + // Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground. + } + } +} + + diff --git a/tests/watchos/Container/Container.csproj b/tests/watchos/Container/Container.csproj new file mode 100644 index 000000000000..70f64960bb63 --- /dev/null +++ b/tests/watchos/Container/Container.csproj @@ -0,0 +1,117 @@ + + + + Debug + iPhoneSimulator + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {E5F28C19-AF9E-498C-9362-F2E514DE1487} + Exe + Container + Resources + Container + obj\$(Platform)\$(Configuration)-watchos + XAMCORE_2_0;XAMCORE_3_0; + + + true + full + false + DEBUG;$(DefineConstants) + bin\iPhoneSimulator\Debug-watchos + prompt + 4 + false + i386 + None + true + true + true + true + iPhone Developer + true + + + bin\iPhone\Release-watchos + full + true + prompt + 4 + false + ARMv7 + %CONTAINER_PATH%Entitlements.plist + true + true + iPhone Developer + true + Full + + + bin\iPhoneSimulator\Release-watchos + full + true + prompt + 4 + false + i386 + None + true + iPhone Developer + true + + + bin\iPhone\Debug-watchos + true + full + false + DEBUG;$(DefineConstants) + prompt + 4 + false + ARMv7 + Full + %CONTAINER_PATH%Entitlements.plist + true + iPhone Developer + true + true + true + true + true + true + + + + + + + + + + + + + + + + + Info.plist + + + + + + + + + %CONTAINER_PATH%ViewController.cs + + + + + {34A6793F-37B2-4A7F-9286-7BDF52F412F3} + %WATCHAPP_NAME% + True + + + + \ No newline at end of file diff --git a/tests/watchos/Container/Container.sln b/tests/watchos/Container/Container.sln new file mode 100644 index 000000000000..298632ffba37 --- /dev/null +++ b/tests/watchos/Container/Container.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Container", "Container.csproj", "{E5F28C19-AF9E-498C-9362-F2E514DE1487}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator + Debug|iPhone = Debug|iPhone + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Debug|iPhone.ActiveCfg = Debug|iPhone + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Debug|iPhone.Build.0 = Debug|iPhone + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Release|iPhone.ActiveCfg = Release|iPhone + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Release|iPhone.Build.0 = Release|iPhone + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {E5F28C19-AF9E-498C-9362-F2E514DE1487}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + EndGlobalSection +EndGlobal diff --git a/tests/watchos/Container/Entitlements.plist b/tests/watchos/Container/Entitlements.plist new file mode 100644 index 000000000000..9ae599370b42 --- /dev/null +++ b/tests/watchos/Container/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/watchos/Container/Info.plist b/tests/watchos/Container/Info.plist new file mode 100644 index 000000000000..aecfa9734d12 --- /dev/null +++ b/tests/watchos/Container/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleName + Container + CFBundleIdentifier + %CONTAINER_CFBUNDLEIDENTIFER% + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 9.0 + UIDeviceFamily + + 1 + 2 + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIMainStoryboardFile~ipad + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Resources/Images.xcassets/AppIcons.appiconset + + diff --git a/tests/watchos/Container/Main.cs b/tests/watchos/Container/Main.cs new file mode 100644 index 000000000000..722a192dee65 --- /dev/null +++ b/tests/watchos/Container/Main.cs @@ -0,0 +1,15 @@ +using UIKit; + +namespace Container +{ + public class Application + { + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } + } +} diff --git a/tests/watchos/Container/Main.storyboard b/tests/watchos/Container/Main.storyboard new file mode 100644 index 000000000000..15478fed9bf6 --- /dev/null +++ b/tests/watchos/Container/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/watchos/Container/Resources/Images.xcassets/AppIcons.appiconset/Contents.json b/tests/watchos/Container/Resources/Images.xcassets/AppIcons.appiconset/Contents.json new file mode 100644 index 000000000000..4e646784cbaa --- /dev/null +++ b/tests/watchos/Container/Resources/Images.xcassets/AppIcons.appiconset/Contents.json @@ -0,0 +1,157 @@ +{ + "images": [ + { + "idiom": "iphone", + "size": "29x29", + "scale": "1x" + }, + { + "idiom": "iphone", + "size": "29x29", + "scale": "2x" + }, + { + "idiom": "iphone", + "size": "29x29", + "scale": "3x" + }, + { + "idiom": "iphone", + "size": "40x40", + "scale": "2x" + }, + { + "idiom": "iphone", + "size": "40x40", + "scale": "3x" + }, + { + "idiom": "iphone", + "size": "57x57", + "scale": "1x" + }, + { + "idiom": "iphone", + "size": "57x57", + "scale": "2x" + }, + { + "idiom": "iphone", + "size": "60x60", + "scale": "2x" + }, + { + "idiom": "iphone", + "size": "60x60", + "scale": "3x" + }, + { + "idiom": "ipad", + "size": "29x29", + "scale": "1x" + }, + { + "idiom": "ipad", + "size": "29x29", + "scale": "2x" + }, + { + "idiom": "ipad", + "size": "40x40", + "scale": "1x" + }, + { + "idiom": "ipad", + "size": "40x40", + "scale": "2x" + }, + { + "idiom": "ipad", + "size": "50x50", + "scale": "1x" + }, + { + "idiom": "ipad", + "size": "50x50", + "scale": "2x" + }, + { + "idiom": "ipad", + "size": "72x72", + "scale": "1x" + }, + { + "idiom": "ipad", + "size": "72x72", + "scale": "2x" + }, + { + "idiom": "ipad", + "size": "76x76", + "scale": "1x" + }, + { + "idiom": "ipad", + "size": "76x76", + "scale": "2x" + }, + { + "size": "24x24", + "idiom": "watch", + "scale": "2x", + "role": "notificationCenter", + "subtype": "38mm" + }, + { + "size": "27.5x27.5", + "idiom": "watch", + "scale": "2x", + "role": "notificationCenter", + "subtype": "42mm" + }, + { + "size": "29x29", + "idiom": "watch", + "role": "companionSettings", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "watch", + "role": "companionSettings", + "scale": "3x" + }, + { + "size": "40x40", + "idiom": "watch", + "scale": "2x", + "role": "appLauncher", + "subtype": "38mm" + }, + { + "size": "44x44", + "idiom": "watch", + "scale": "2x", + "role": "longLook", + "subtype": "42mm" + }, + { + "size": "86x86", + "idiom": "watch", + "scale": "2x", + "role": "quickLook", + "subtype": "38mm" + }, + { + "size": "98x98", + "idiom": "watch", + "scale": "2x", + "role": "quickLook", + "subtype": "42mm" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/tests/watchos/Container/Resources/LaunchScreen.xib b/tests/watchos/Container/Resources/LaunchScreen.xib new file mode 100644 index 000000000000..45d35d137256 --- /dev/null +++ b/tests/watchos/Container/Resources/LaunchScreen.xib @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/watchos/Container/ViewController.cs b/tests/watchos/Container/ViewController.cs new file mode 100644 index 000000000000..d5eaae030eff --- /dev/null +++ b/tests/watchos/Container/ViewController.cs @@ -0,0 +1,26 @@ +using System; + +using UIKit; + +namespace Container +{ + public partial class ViewController : UIViewController + { + public ViewController (IntPtr handle) : base (handle) + { + } + + public override void ViewDidLoad () + { + base.ViewDidLoad (); + // Perform any additional setup after loading the view, typically from a nib. + } + + public override void DidReceiveMemoryWarning () + { + base.DidReceiveMemoryWarning (); + // Release any cached data, images, etc that aren't in use. + } + } +} + diff --git a/tests/watchos/Container/ViewController.designer.cs b/tests/watchos/Container/ViewController.designer.cs new file mode 100644 index 000000000000..20ce04fb4886 --- /dev/null +++ b/tests/watchos/Container/ViewController.designer.cs @@ -0,0 +1,17 @@ +// +// This file has been generated automatically by MonoDevelop to store outlets and +// actions made in the Xcode designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// +using Foundation; + +namespace Container +{ + [Register ("ViewController")] + partial class ViewController + { + void ReleaseDesignerOutlets () + { + } + } +} diff --git a/tests/watchos/Extension/InterfaceController.cs b/tests/watchos/Extension/InterfaceController.cs new file mode 100644 index 000000000000..8cf983d251a8 --- /dev/null +++ b/tests/watchos/Extension/InterfaceController.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections; +using System.Linq; +using System.Threading; + +using WatchKit; +using Foundation; + +using NUnit.Framework.Internal.Filters; +using MonoTouch.NUnit.UI; + +namespace monotouchtestWatchKitExtension +{ + [Register ("InterfaceController")] + public partial class InterfaceController : WKInterfaceController + { + WatchOSRunner runner; + + [Action ("runTests:")] + partial void RunTests (NSObject obj); + + [Outlet ("lblStatus")] + WatchKit.WKInterfaceLabel lblStatus { get; set; } + + [Outlet ("lblSuccess")] + WatchKit.WKInterfaceLabel lblSuccess { get; set; } + + [Outlet ("lblFailed")] + WatchKit.WKInterfaceLabel lblFailed { get; set; } + + [Outlet ("lblIgnored")] + WatchKit.WKInterfaceLabel lblIgnored { get; set; } + + [Outlet ("lblInconclusive")] + WatchKit.WKInterfaceLabel lblInconclusive { get; set; } + + [Outlet ("cmdRun")] + WatchKit.WKInterfaceButton cmdRun { get; set; } + + public InterfaceController (IntPtr handle) : base (handle) + { + } + + public override void Awake (NSObject context) + { + base.Awake (context); + + BeginInvokeOnMainThread (LoadTests); + } + + void LoadTests () + { + runner = new WatchOSRunner (); + runner.Filter = new NotFilter (new CategoryExpression ("MobileNotWorking,NotOnMac,NotWorking,ValueAdd,CAS,InetAccess,NotWorkingInterpreter").Filter); + runner.Add (GetType ().Assembly); + ThreadPool.QueueUserWorkItem ((v) => + { + runner.LoadSync (); + BeginInvokeOnMainThread (() => + { + lblStatus.SetText (string.Format ("{0} tests", runner.TestCount)); + RenderResults (); + cmdRun.SetEnabled (true); + cmdRun.SetHidden (false); + + runner.AutoRun (); + }); + }); + } + + void RunTests () + { + cmdRun.SetEnabled (false); + lblStatus.SetText ("Running"); + BeginInvokeOnMainThread (() => { + runner.Run (); + + BeginInvokeOnMainThread (RenderResults); + }); + } + + void RenderResults () + { + lblSuccess.SetText (string.Format ("Passed: {0}/{1} {2}%", runner.PassedCount, runner.TestCount, 100 * runner.PassedCount / runner.TestCount)); + lblFailed.SetText (string.Format ("Failed: {0}/{1} {2}%", runner.FailedCount, runner.TestCount, 100 * runner.FailedCount / runner.TestCount)); + lblIgnored.SetText (string.Format ("Ignored: {0}/{1} {2}%", runner.IgnoredCount, runner.TestCount, 100 * runner.IgnoredCount / runner.TestCount)); + lblInconclusive.SetText (string.Format ("Inconclusive: {0}/{1} {2}%", runner.InconclusiveCount, runner.TestCount, 100 * runner.InconclusiveCount / runner.TestCount)); + } + + partial void RunTests (NSObject obj) + { + RunTests (); + } + } +} + diff --git a/tests/watchos/Extension/InterfaceController.fs b/tests/watchos/Extension/InterfaceController.fs new file mode 100644 index 000000000000..80c16da09030 --- /dev/null +++ b/tests/watchos/Extension/InterfaceController.fs @@ -0,0 +1,80 @@ +namespace monotouchtestWatchKitExtension + +open System +open System.Collections +open System.Linq +open System.Threading + +open WatchKit +open Foundation + +open NUnit.Framework.Internal.Filters +open MonoTouch.NUnit.UI + +[] +type InterfaceController (handle: IntPtr) = + inherit WKInterfaceController (handle) + + let mutable runner = Unchecked.defaultof + + [] + member val lblStatus = Unchecked.defaultof with get, set + + [] + member val lblSuccess = Unchecked.defaultof with get, set + + [] + member val lblFailed = Unchecked.defaultof with get, set + + [] + member val lblIgnored = Unchecked.defaultof with get, set + + [] + member val lblInconclusive = Unchecked.defaultof with get, set + + [] + member val cmdRun = Unchecked.defaultof with get, set + + member this.LoadTests () = + runner <- new WatchOSRunner () + let ce = new CategoryExpression ("MobileNotWorking,NotOnMac,NotWorking,ValueAdd,CAS,InetAccess,NotWorkingInterpreter") + runner.Filter <- new NotFilter (ce.Filter) + let tp = this.GetType () + runner.Add (tp.Assembly) + ThreadPool.QueueUserWorkItem (fun v -> + runner.LoadSync () + this.BeginInvokeOnMainThread (fun x -> + this.lblStatus.SetText (String.Format ("{0} tests", runner.TestCount)) + this.RenderResults () + this.cmdRun.SetEnabled (true) + this.cmdRun.SetHidden (false) + ) + ) + |> ignore + + override this.Awake (context: NSObject) = + base.Awake (context) + this.BeginInvokeOnMainThread (fun x -> + this.LoadTests () + () + ) + + member this.RenderResults () = + this.lblSuccess.SetText (String.Format ("Passed: {0}/{1} {2}%", runner.PassedCount, runner.TestCount, 100 * runner.PassedCount / runner.TestCount)) + this.lblFailed.SetText (String.Format ("Failed: {0}/{1} {2}%", runner.FailedCount, runner.TestCount, 100 * runner.FailedCount / runner.TestCount)) + this.lblIgnored.SetText (String.Format ("Ignored: {0}/{1} {2}%", runner.IgnoredCount, runner.TestCount, 100 * runner.IgnoredCount / runner.TestCount)) + this.lblInconclusive.SetText (String.Format ("Inconclusive: {0}/{1} {2}%", runner.InconclusiveCount, runner.TestCount, 100 * runner.InconclusiveCount / runner.TestCount)) + + member this.RunTests () = + this.cmdRun.SetEnabled (false) + this.lblStatus.SetText ("Running") + this.BeginInvokeOnMainThread (fun v -> + runner.Run () + this.BeginInvokeOnMainThread (fun x -> + this.RenderResults () + ) + ) + + member this.RunTests (obj: NSObject) = + this.RunTests () + diff --git a/tests/xharness/AppRunner.cs b/tests/xharness/AppRunner.cs new file mode 100644 index 000000000000..4fc5c4e63127 --- /dev/null +++ b/tests/xharness/AppRunner.cs @@ -0,0 +1,858 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Xml; + +namespace xharness +{ + public class AppRunner + { + public Harness Harness; + public string ProjectFile; + + XmlDocument simulator_data; + + string appName; + string appPath; + string launchAppPath; + string bundle_identifier; + string platform; + bool isSimulator; + + string device_name; + string companion_device_name; + + class IData { + public XmlNode Node; + + public string udid { get { return Node.Attributes ["UDID"].Value; } } + } + + class SimulatorData : IData { + public string datapath { get { return Node.SelectSingleNode ("DataPath").InnerText; } } + public string logpath { get { return Node.SelectSingleNode ("LogPath").InnerText; } } + public string devicetype { get { return Node.SelectSingleNode ("SimDeviceType").InnerText; } } + public string runtime { get { return Node.SelectSingleNode ("SimRuntime").InnerText; } } + public string system_log { get { return Path.Combine (logpath, "system.log"); } } + public string name { get { return Node.Attributes ["Name"].Value; } } + } + + class DeviceData : IData { + public string DeviceIdentifier { get { return Node.SelectSingleNode ("DeviceIdentifier")?.InnerText; } } + public string DeviceClass { get { return Node.SelectSingleNode ("DeviceClass")?.InnerText; } } + public string CompanionIdentifier { get { return Node.SelectSingleNode ("CompanionIdentifier")?.InnerText; } } + public string Name { get { return Node.SelectSingleNode ("Name")?.InnerText; } } + } + + // For watch apps we end up with 2 simulators, the watch simulator (the main one), and the iphone simulator (the companion one). + SimulatorData[] simulators; + SimulatorData simulator { get { return simulators [0]; } } + SimulatorData companion_simulator { get { return simulators.Length == 2 ? simulators [1] : null; } } + + string mode; + + string SymbolicateCrashReport (string report) + { + var symbolicatecrash = Path.Combine (Harness.XcodeRoot, "Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash"); + if (!File.Exists (symbolicatecrash)) { + Harness.Log ("Can't symbolicate {0} because the symbolicatecrash script {1} does not exist", report, symbolicatecrash); + return report; + } + + var output = new StringBuilder (); + if (ExecuteCommand (symbolicatecrash, "\"" + report + "\"", true, captured_output: output, environment_variables: new Dictionary { { "DEVELOPER_DIR", Path.Combine (Harness.XcodeRoot, "Contents", "Developer") }})) { + File.WriteAllText (report + ".symbolicated", output.ToString ()); + Harness.Log ("Symbolicated {0} successfully.", report); + return report + ".symbolicated"; + } + + Harness.Log ("Failed to symbolicate {0}:\n{1}", report, output.ToString ()); + + return report; + } + + void FindSimulator () + { + string simulator_devicetype; + string simulator_runtime; + + switch (Harness.Target) { + case "ios-simulator-32": + simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.iPhone-5"; + simulator_runtime = "com.apple.CoreSimulator.SimRuntime.iOS-" + Xamarin.SdkVersions.iOS.Replace ('.', '-'); + break; + case "ios-simulator-64": + simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.iPhone-5s"; + simulator_runtime = "com.apple.CoreSimulator.SimRuntime.iOS-" + Xamarin.SdkVersions.iOS.Replace ('.', '-'); + break; + case "ios-simulator": + simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.iPhone-4s"; + simulator_runtime = "com.apple.CoreSimulator.SimRuntime.iOS-" + Xamarin.SdkVersions.iOS.Replace ('.', '-'); + break; + case "tvos-simulator": + simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p"; + simulator_runtime = "com.apple.CoreSimulator.SimRuntime.tvOS-" + Xamarin.SdkVersions.TVOS.Replace ('.', '-'); + break; + case "watchos-simulator": + simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-38mm"; + simulator_runtime = "com.apple.CoreSimulator.SimRuntime.watchOS-" + Xamarin.SdkVersions.WatchOS.Replace ('.', '-'); + break; + default: + throw new Exception (string.Format ("Unknown simulator target: {0}", Harness.Target)); + } + + var tmpfile = Path.GetTempFileName (); + try { + ExecuteCommand (Harness.MlaunchPath, string.Format ("--sdkroot {0} --listsim {1}", Harness.XcodeRoot, tmpfile), output_verbosity_level: 1); + simulator_data = new XmlDocument (); + simulator_data.LoadWithoutNetworkAccess (tmpfile); + SimulatorData candidate = null; + simulators = null; + foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevices/SimDevice")) { + var data = new SimulatorData { Node = sim }; + if (data.runtime == simulator_runtime && data.devicetype == simulator_devicetype) { + var udid = data.udid; + var secondaryData = (SimulatorData) null; + var nodeCompanion = simulator_data.SelectSingleNode ("/MTouch/Simulator/AvailableDevicePairs/SimDevicePair/Companion[text() = '" + udid + "']"); + var nodeGizmo = simulator_data.SelectSingleNode ("/MTouch/Simulator/AvailableDevicePairs/SimDevicePair/Gizmo[text() = '" + udid + "']"); + + if (nodeCompanion != null) { + var gizmo_udid = nodeCompanion.ParentNode.SelectSingleNode ("Gizmo").InnerText; + var node = simulator_data.SelectSingleNode ("/MTouch/Simulator/AvailableDevices/SimDevice[@UDID = '" + gizmo_udid + "']"); + secondaryData = new SimulatorData () { Node = node }; + } else if (nodeGizmo != null) { + var companion_udid = nodeGizmo.ParentNode.SelectSingleNode ("Companion").InnerText; + var node = simulator_data.SelectSingleNode ("/MTouch/Simulator/AvailableDevices/SimDevice[@UDID = '" + companion_udid + "']"); + secondaryData = new SimulatorData () { Node = node }; + } + if (secondaryData != null) { + simulators = new SimulatorData[] { data, secondaryData }; + break; + } else { + candidate = data; + } + } + } + if (simulators == null) + simulators = new SimulatorData[] { candidate }; + } finally { + File.Delete (tmpfile); + } + + if (simulators == null) + throw new Exception ("Could not find simulator"); + + Harness.Log (1, "Found simulator: {0} {1}", simulators [0].name, simulators [0].udid); + if (simulators.Length > 1) + Harness.Log (1, "Found companion simulator: {0} {1}", simulators [1].name, simulators [1].udid); + } + + void FindDevice () + { + if (device_name != null) + return; + + device_name = Environment.GetEnvironmentVariable ("DEVICE_NAME"); + if (!string.IsNullOrEmpty (device_name)) + return; + + var tmpfile = Path.GetTempFileName (); + try { + ExecuteCommand (Harness.MlaunchPath, string.Format ("--sdkroot {0} --listdev={1} --output-format=xml", Harness.XcodeRoot, tmpfile), output_verbosity_level: 1); + var doc = new XmlDocument (); + doc.LoadWithoutNetworkAccess (tmpfile); + var nodes = new List (); + foreach (XmlNode dev in doc.SelectNodes ("/MTouch/Device")) { + nodes.Add (new DeviceData { Node = dev }); + } + + if (nodes.Count == 0) + throw new Exception ("No devices connected"); + + string [] deviceClasses; + switch (mode) { + case "ios": + deviceClasses = new string [] { "iPhone", "iPad" }; + break; + case "watchos": + deviceClasses = new string [] { "Watch" }; + break; + case "tvos": + deviceClasses = new string [] { "AppleTV" }; // Untested + break; + default: + throw new Exception ($"unknown mode: {mode}"); + } + + var selected = nodes.Where ((v) => deviceClasses.Contains (v.DeviceClass)); + DeviceData selected_data; + if (selected.Count () == 0) { + throw new Exception ($"Could not find any applicable devices with device class(es): {string.Join (", ", deviceClasses)}"); + } else if (selected.Count () > 1) { + selected_data = selected.First (); + Harness.Log ("Found {0} devices for device class(es) {1}: {2}. Selected: '{3}'", selected.Count (), string.Join (", ", deviceClasses), string.Join (", ", selected.Select ((v) => v.Name).ToArray ()), selected_data.Name); + } else { + selected_data = selected.First (); + } + device_name = selected_data.Name; + + if (mode == "watchos") { + var companion = nodes.Where ((v) => v.DeviceIdentifier == selected_data.CompanionIdentifier); + if (companion.Count () == 0) + throw new Exception ($"Could not find the companion device for '{selected_data.Name}'"); + else if (companion.Count () > 1) + Harness.Log ("Found {0} companion devices for {1}?!?", companion.Count (), selected_data.Name); + companion_device_name = companion.First ().Name; + } + } finally { + File.Delete (tmpfile); + } + } + + void PrepareSimulator () + { + if (SkipSimulatorSetup) { + Harness.Log (0, "Simulator setup skipped."); + return; + } + + KillEverything (); + ShowSimulatorList (); + + // We shutdown and erase all simulators. + // We only fixup TCC.db on the main simulator. + + foreach (var sim in simulators) { + var udid = sim.udid; + // erase the simulator (make sure the device isn't running first) + ExecuteXcodeCommand ("simctl", "shutdown " + udid, true, output_verbosity_level: 1, timeout: TimeSpan.FromMinutes (1)); + ExecuteXcodeCommand ("simctl", "erase " + udid, true, output_verbosity_level: 1, timeout: TimeSpan.FromMinutes (1)); + + // boot & shutdown to make sure it actually works + ExecuteXcodeCommand ("simctl", "boot " + udid, true, output_verbosity_level: 1, timeout: TimeSpan.FromMinutes (1)); + ExecuteXcodeCommand ("simctl", "shutdown " + udid, true, output_verbosity_level: 1, timeout: TimeSpan.FromMinutes (1)); + } + + // Edit the permissions to prevent dialog boxes in the test app + var TCC_db = Path.Combine (simulator.datapath, "data", "Library", "TCC", "TCC.db"); + if (!File.Exists (TCC_db)) { + Harness.Log ("Opening simulator to create TCC.db"); + var simulator_app = Path.Combine (Harness.XcodeRoot, "Contents", "Developer", "Applications", "Simulator.app"); + if (!Directory.Exists (simulator_app)) + simulator_app = Path.Combine (Harness.XcodeRoot, "Contents", "Developer", "Applications", "iOS Simulator.app"); + + ExecuteCommand ("open", "-a \"" + simulator_app + "\" --args -CurrentDeviceUDID " + simulator.udid, output_verbosity_level: 1); + + var tcc_creation_timeout = 60; + var watch = new Stopwatch (); + watch.Start (); + while (!File.Exists (TCC_db) && watch.Elapsed.TotalSeconds < tcc_creation_timeout) { + Harness.Log ("Waiting for simulator to create TCC.db... {0}", (int) (tcc_creation_timeout - watch.Elapsed.TotalSeconds)); + Thread.Sleep (TimeSpan.FromSeconds (1)); + } + } + + if (File.Exists (TCC_db)) { + var sim_services = new string [] { + "kTCCServiceAddressBook", + "kTCCServicePhotos", + "kTCCServiceUbiquity", + "kTCCServiceWillow" + }; + + var failure = false; + var tcc_edit_timeout = 5; + var watch = new Stopwatch (); + watch.Start (); + do { + failure = false; + foreach (var service in sim_services) { + if (!ExecuteCommand ("sqlite3", string.Format ("{0} \"DELETE FROM access WHERE service = '{1}' and client ='{2}';\"", TCC_db, service, bundle_identifier), true, output_verbosity_level: 1)) { + failure = true; + } else { + if (!ExecuteCommand ("sqlite3", string.Format ("{0} \"INSERT INTO access VALUES('{1}','{2}',0,1,0,NULL,NULL);\"", TCC_db, service, bundle_identifier), true, output_verbosity_level: 1)) { + failure = true; + } + } + } + if (failure) { + if (watch.Elapsed.TotalSeconds > tcc_edit_timeout) + break; + Harness.Log ("Failed to edit TCC.db, trying again in 1 second... ", (int) (tcc_edit_timeout - watch.Elapsed.TotalSeconds)); + Thread.Sleep (TimeSpan.FromSeconds (1)); + } + } while (failure); + + if (failure) { + Harness.Log ("Failed to edit TCC.db, the test run might hang due to permission request dialogs"); + } else { + Harness.Log ("Successfully edited TCC.db"); + } + } else { + Harness.Log ("No TCC.db found for the simulator {0} (SimRuntime={1} and SimDeviceType={1})", simulator.udid, simulator.runtime, simulator.devicetype); + } + + foreach (var sim in simulators) { + if (!File.Exists (sim.system_log)) { + Harness.Log ("No system log found for SimRuntime={0} and SimDeviceType={1}", sim.runtime, sim.devicetype); + } else { + File.WriteAllText (sim.system_log, string.Format (" *** This log file was cleared out by Xamarin.iOS's test run at {0} **** \n", DateTime.Now.ToString ())); + } + } + + KillEverything (); + + ExecuteXcodeCommand ("simctl", "shutdown " + simulator.udid, true, output_verbosity_level: 1, timeout: TimeSpan.FromMinutes (1)); + } + + void Initialize () + { + var csproj = new XmlDocument (); + csproj.LoadWithoutNetworkAccess (ProjectFile); + appName = csproj.GetAssemblyName (); + var info_plist_path = csproj.GetInfoPListInclude (); + var info_plist = new XmlDocument (); + info_plist.LoadWithoutNetworkAccess (Path.Combine (Path.GetDirectoryName (ProjectFile), info_plist_path)); + bundle_identifier = info_plist.GetCFBundleIdentifier (); + + switch (Harness.Target) { + case "ios-simulator-32": + mode = "sim32"; + platform = "iPhoneSimulator"; + isSimulator = true; + break; + case "ios-simulator-64": + mode = "sim64"; + platform = "iPhoneSimulator"; + isSimulator = true; + break; + case "ios-simulator": + mode = "classic"; + platform = "iPhoneSimulator"; + isSimulator = true; + break; + case "ios-device": + mode = "ios"; + platform = "iPhone"; + isSimulator = false; + break; + case "tvos-simulator": + mode = "tvos"; + platform = "iPhoneSimulator"; + isSimulator = true; + break; + case "tvos-device": + mode = "tvos"; + platform = "iPhone"; + isSimulator = false; + break; + case "watchos-simulator": + mode = "watchos"; + platform = "iPhoneSimulator"; + isSimulator = true; + break; + case "watchos-device": + mode = "watchos"; + platform = "iPhone"; + isSimulator = false; + break; + default: + throw new Exception (string.Format ("Unknown target: {0}", Harness.Target)); + } + + appPath = Path.Combine (Path.GetDirectoryName (ProjectFile), csproj.GetOutputPath (platform, Harness.Configuration).Replace ('\\', '/'), appName + ".app"); + if (!Directory.Exists (appPath)) + throw new Exception (string.Format ("The app directory {0} does not exist. This is probably a bug in the test harness.", appPath)); + + if (mode == "watchos") { + launchAppPath = Directory.GetDirectories (Path.Combine (appPath, "Watch"), "*.app") [0]; + } else { + launchAppPath = appPath; + } + } + + public int Install () + { + Initialize (); + + if (isSimulator) { + // We reset the simulator when running, so a separate install step does not make much sense. + throw new Exception ("Installing to a simulator is not supported."); + } + + FindDevice (); + + var args = new StringBuilder (); + if (!string.IsNullOrEmpty (Harness.XcodeRoot)) + args.Append (" --sdkroot ").Append (Harness.XcodeRoot); + for (int i = -1; i < Harness.Verbosity; i++) + args.Append (" -v "); + + args.Append (" --installdev"); + args.AppendFormat (" \"{0}\" ", appPath); + AddDeviceName (args, companion_device_name ?? device_name); + + if (mode == "watchos") + args.Append (" --device ios,watchos"); + + var success = ExecuteCommand (Harness.MlaunchPath, args.ToString ()); + return success ? 0 : 1; + } + + bool SkipSimulatorSetup { + get { + return !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("SKIP_SIMULATOR_SETUP")); + } + } + + public int Run () + { + HashSet start_crashes = null; + string device_system_log = null; + + Initialize (); + + var args = new StringBuilder (); + if (!string.IsNullOrEmpty (Harness.XcodeRoot)) + args.Append (" --sdkroot ").Append (Harness.XcodeRoot); + for (int i = -1; i < Harness.Verbosity; i++) + args.Append (" -v "); + args.Append (" -argument=-connection-mode -argument=none"); // This will prevent the app from trying to connect to any IDEs + args.Append (" -argument=-app-arg:-autostart"); + args.Append (" -setenv=NUNIT_AUTOSTART=true"); + args.Append (" -argument=-app-arg:-autoexit"); + args.Append (" -setenv=NUNIT_AUTOEXIT=true"); + args.Append (" -argument=-app-arg:-enablenetwork"); + args.Append (" -setenv=NUNIT_ENABLE_NETWORK=true"); + if (isSimulator) { + args.Append (" -argument=-app-arg:-hostname:127.0.0.1"); + args.Append (" -setenv=NUNIT_HOSTNAME=127.0.0.1"); + } else { + var ips = new StringBuilder (); + var ipAddresses = System.Net.Dns.GetHostEntry (System.Net.Dns.GetHostName ()).AddressList; + for (int i = 0; i < ipAddresses.Length; i++) { + if (i > 0) + ips.Append (','); + ips.Append (ipAddresses [i].ToString ()); + } + + args.AppendFormat (" -argument=-app-arg:-hostname:{0}", ips.ToString ()); + args.AppendFormat (" -setenv=NUNIT_HOSTNAME={0}", ips.ToString ()); + } + var transport = mode == "watchos" ? "HTTP" : "TCP"; + args.AppendFormat (" -argument=-app-arg:-transport:{0}", transport); + args.AppendFormat (" -setenv=NUNIT_TRANSPORT={0}", transport); + + SimpleListener listener; + switch (transport) { + case "HTTP": + listener = new SimpleHttpListener (); + break; + case "TCP": + listener = new SimpleTcpListener (); + break; + default: + throw new NotImplementedException (); + } + listener.LogPath = Path.GetDirectoryName (Harness.LogFile); + listener.LogFile = Path.GetFileName (Harness.LogFile); + listener.AutoExit = true; + listener.Address = System.Net.IPAddress.Any; + listener.Initialize (); + + args.AppendFormat (" -argument=-app-arg:-hostport:{0}", listener.Port); + args.AppendFormat (" -setenv=NUNIT_HOSTPORT={0}", listener.Port); + + if (File.Exists (Harness.LogFile)) + File.Delete (Harness.LogFile); + + bool? success = null; + bool timed_out = false; + + if (isSimulator) { + FindSimulator (); + + Harness.Log ("*** Executing {0}/{1} in the simulator ***", appName, mode); + + PrepareSimulator (); + + args.Append (" --launchsim"); + args.AppendFormat (" \"{0}\" ", launchAppPath); + args.Append (" --device=:v2:udid=").Append (simulator.udid).Append (" "); + + start_crashes = CreateCrashReportsSnapshot (true); + + listener.StartAsync (); + Harness.Log ("Starting test run"); + var proc = new XProcess () { + Harness = Harness, + FileName = Harness.MlaunchPath, + Arguments = args.ToString (), + VerbosityLevel = 0, + }; + proc.Start (); + + var launchState = 0; // 0: launching, 1: launch timed out, 2: run timed out, 3: completed + var launchMutex = new Mutex (); + var runCompleted = new ManualResetEvent (false); + ThreadPool.QueueUserWorkItem ((v) => { + if (!listener.WaitForConnection (TimeSpan.FromMinutes (Harness.LaunchTimeout))) { + lock (launchMutex) { + if (launchState == 0) { + launchState = 1; + runCompleted.Set (); + } + } + Harness.Log ("Test launch timed out after {0} minute(s).", Harness.LaunchTimeout); + } else { + Harness.Log ("Test run started"); + } + }); + ThreadPool.QueueUserWorkItem ((v) => { + var rv = proc.WaitForExit (TimeSpan.FromMinutes (Harness.Timeout)); + + lock (launchMutex) { + if (launchState == 0) + launchState = rv ? 3 : 2; + runCompleted.Set (); + } + + if (rv) { + Harness.Log ("Test run completed"); + } else { + Harness.Log ("Test run timed out after {0} minute(s).", Harness.Timeout); + } + }); + + runCompleted.WaitOne (); + + switch (launchState) { + case 1: + case 2: + success = false; + timed_out = true; + + // find pid + var pid = -1; + var output = proc.ReadCurrentOutput (); + foreach (var line in output.ToString ().Split ('\n')) { + if (line.StartsWith ("Application launched. PID = ", StringComparison.Ordinal)) { + var pidstr = line.Substring ("Application launched. PID = ".Length); + if (!int.TryParse (pidstr, out pid)) + Harness.Log ("Could not parse pid: {0}", pidstr); + } else if (line.Contains ("Xamarin.Hosting: Launched ") && line.Contains (" with pid ")) { + var pidstr = line.Substring (line.LastIndexOf (' ')); + if (!int.TryParse (pidstr, out pid)) + Harness.Log ("Could not parse pid: {0}", pidstr); + } + } + if (pid > 0) { + KillPid (proc, pid, TimeSpan.FromSeconds (5), TimeSpan.FromMinutes (launchState == 1 ? Harness.LaunchTimeout : Harness.Timeout), launchState == 1 ? "Launch" : "Completion"); + } else { + Harness.Log ("Could not find pid in mtouch output."); + } + // kill mtouch too + kill (proc.Id, 9); + break; + case 3: + // Success! + break; + case 0: // shouldn't happen ever + default: + throw new Exception ($"Invalid launch state: {launchState}"); + } + + listener.Cancel (); + + // cleanup after us + KillEverything (); + } else { + FindDevice (); + + Harness.Log ("*** Executing {0}/{1} on device ***", appName, mode); + + args.Append (" --launchdev"); + args.AppendFormat (" \"{0}\" ", launchAppPath); + + AddDeviceName (args); + + device_system_log = Harness.LogFile + ".device.log"; + var logdev = new DeviceLogCapturer () { + Harness = Harness, + LogPath = device_system_log, + DeviceName = device_name, + }; + logdev.StartCapture (); + + start_crashes = CreateCrashReportsSnapshot (false); + + listener.StartAsync (); + Harness.Log ("Starting test run"); + ExecuteCommand (Harness.MlaunchPath, args.ToString ()); + if (listener.WaitForCompletion (TimeSpan.FromMinutes (Harness.Timeout))) { + Harness.Log ("Test run completed"); + } else { + Harness.Log ("Test run did not complete in {0} minutes.", Harness.Timeout); + listener.Cancel (); + success = false; + timed_out = true; + } + + logdev.StopCapture (); + + // Upload the system log + if (File.Exists (device_system_log)) { + Harness.Log (1, "A capture of the device log is: {0}", device_system_log); + if (Harness.InWrench) + Harness.LogWrench ("@MonkeyWrench: AddFile: {0}", Path.GetFullPath (device_system_log)); + } + } + + listener.Dispose (); + + // check the final status + var crashed = false; + if (File.Exists (Harness.LogFile)) { + Harness.LogWrench ("@MonkeyWrench: AddFile: {0}", Path.GetFullPath (Harness.LogFile)); + var log = File.ReadAllText (Harness.LogFile); + if (log.Contains ("Tests run")) { + var tests_run = string.Empty; + var log_lines = File.ReadAllLines (Harness.LogFile); + var failed = false; + foreach (var line in log_lines) { + if (line.Contains ("Tests run:")) { + Console.WriteLine (line); + tests_run = line.Replace ("Tests run: ", ""); + break; + } else if (line.Contains ("FAIL")) { + Console.WriteLine (line); + failed = true; + } + } + + if (failed) { + Harness.LogWrench ("@MonkeyWrench: AddSummary: {0} failed: {1}
", mode, tests_run); + Harness.Log ("Test run failed"); + } else { + Harness.LogWrench ("@MonkeyWrench: AddSummary: {0} succeeded: {1}
", mode, tests_run); + Harness.Log ("Test run succeeded"); + success = true; + } + } else if (timed_out) { + Harness.LogWrench ("@MonkeyWrench: AddSummary: {0} timed out
", mode); + } else { + Harness.LogWrench ("@MonkeyWrench: AddSummary: {0} crashed
", mode); + Harness.Log ("Test run crashed"); + crashed = true; + } + } else if (timed_out) { + Harness.LogWrench ("@MonkeyWrench: AddSummary: {0} never launched
", mode); + Harness.Log ("Test run never launched"); + } else { + Harness.LogWrench ("@MonkeyWrench: AddSummary: {0} crashed at startup (no log)
", mode); + Harness.Log ("Test run crashed before it started (no log file produced)"); + crashed = true; + } + + // Check for crash reports + var crash_report_search_done = false; + var crash_report_search_timeout = 5; + var watch = new Stopwatch (); + watch.Start (); + do { + var end_crashes = CreateCrashReportsSnapshot (isSimulator); + end_crashes.ExceptWith (start_crashes); + if (end_crashes.Count > 0) { + Harness.Log ("Found {0} new crash report(s)", end_crashes.Count); + if (!isSimulator) { + // Download crash reports from the device. We put them in the project directory so that they're automatically deleted on wrench + // (if we put them in /tmp, they'd never be deleted). + var downloaded_crash_reports = new HashSet (); + foreach (var file in end_crashes) { + var crash_report_target = Path.Combine (Path.GetDirectoryName (ProjectFile), Path.GetFileName (file)); + if (ExecuteCommand (Harness.MlaunchPath, "--download-crash-report=" + file + " --download-crash-report-to=" + crash_report_target + " --sdkroot " + Harness.XcodeRoot)) { + Harness.Log ("Downloaded crash report {0} to {1}", file, crash_report_target); + crash_report_target = SymbolicateCrashReport (crash_report_target); + downloaded_crash_reports.Add (crash_report_target); + } else { + Harness.Log ("Could not download crash report {0}", file); + } + } + end_crashes = downloaded_crash_reports; + } + foreach (var cp in end_crashes) { + Harness.LogWrench ("@MonkeyWrench: AddFile: {0}", Path.GetFullPath (cp)); + Harness.Log (" {0}", cp); + } + crash_report_search_done = true; + } else if (!crashed && !timed_out) { + crash_report_search_done = true; + } else { + if (watch.Elapsed.TotalSeconds > crash_report_search_timeout) { + crash_report_search_done = true; + } else { + Harness.Log ("No crash reports, waiting a second to see if the crash report service just didn't complete in time ({0})", (int) (crash_report_search_timeout - watch.Elapsed.TotalSeconds)); + Thread.Sleep (TimeSpan.FromSeconds (1)); + } + } + } while (!crash_report_search_done); + + if (!success.HasValue) + success = false; + + if (isSimulator) { + foreach (var sim in simulators) { + // Upload the system log + if (File.Exists (sim.system_log)) { + Harness.Log (success.Value ? 1 : 0, "System log for the '{1}' simulator is: {0}", sim.system_log, sim.name); + if (Harness.InWrench) { + var syslog = Harness.LogFile + (sim == simulator ? ".system.log" : ".companion.system.log"); + File.Copy (sim.system_log, syslog, true); + Harness.LogWrench ("@MonkeyWrench: AddFile: {0}", Path.GetFullPath (syslog)); + } + } + } + } + + return success.Value ? 0 : 1; + } + + public void AddDeviceName (StringBuilder args) + { + AddDeviceName (args, device_name); + } + + public static void AddDeviceName (StringBuilder args, string device_name) + { + if (!string.IsNullOrEmpty (device_name)) { + args.Append (" --devname "); + args.Append (Harness.Quote (device_name)); + } + } + + [DllImport ("/usr/lib/libc.dylib")] + static extern void kill (int pid, int sig); + + void KillPid (XProcess proc, int pid, TimeSpan kill_separation, TimeSpan timeout, string type) + { + Harness.Log ("{2} timeout ({1} s) reached, will now send SIGQUIT to the app (PID: {0})", pid, timeout.TotalSeconds, type); + kill (pid, 3 /* SIGQUIT */); // print managed stack traces. + if (!proc.WaitForExit (kill_separation /* wait for at most 5 seconds to see if something happens */)) { + Harness.Log ("{2} timeout ({1} s) reached, will now send SIGABRT to the app (PID: {0})", pid, timeout.TotalSeconds, type); + kill (pid, 6 /* SIGABRT */); // print native stack traces. + if (!proc.WaitForExit (kill_separation /* wait another 5 seconds */)) { + Harness.Log ("{2} timeout ({1} s) reached, will now send SIGKILL to the app (PID: {0})", pid, timeout.TotalSeconds, type); + kill (pid, 9 /* SIGKILL */); // terminate unconditionally. + } + } + } + + HashSet CreateCrashReportsSnapshot (bool simulator) + { + HashSet rv; + + if (simulator) { + rv = new HashSet (Directory.EnumerateFiles (Path.Combine (Environment.GetEnvironmentVariable ("HOME"), "Library", "Logs", "DiagnosticReports"))); + } else { + var tmp = Path.GetTempFileName (); + if (ExecuteCommand (Harness.MlaunchPath, "--list-crash-reports=" + tmp + " --sdkroot " + Harness.XcodeRoot, true)) { + rv = new HashSet (File.ReadAllLines (tmp)); + } else { + rv = new HashSet (); + } + File.Delete (tmp); + } + + return rv; + } + + void KillEverything () + { + var to_kill = new string [] { "iPhone Simulator", "iOS Simulator", "Simulator", "Simulator (Watch)", "com.apple.CoreSimulator.CoreSimulatorService" }; + foreach (var k in to_kill) + ExecuteCommand ("killall", "-9 \"" + k + "\"", true, output_verbosity_level: 1); + } + + void ShowSimulatorList () + { + if (Harness.Verbosity > 0) + ExecuteXcodeCommand ("simctl", "list", ignore_errors: true, timeout: TimeSpan.FromSeconds (10)); + } + + bool ExecuteXcodeCommand (string executable, string args, bool ignore_errors = false, int output_verbosity_level = 1, TimeSpan? timeout = null) + { + return ExecuteCommand (Path.Combine (Harness.XcodeRoot, "Contents", "Developer", "usr", "bin", executable), args, ignore_errors, output_verbosity_level, timeout: timeout); + } + + bool ExecuteCommand (string filename, string args, bool ignore_errors = false, int output_verbosity_level = 1, StringBuilder captured_output = null, TimeSpan? timeout = null, Dictionary environment_variables = null) + { + int exitcode; + return ExecuteCommand (filename, args, out exitcode, ignore_errors, output_verbosity_level, captured_output, timeout, environment_variables); + } + + bool ExecuteCommand (string filename, string args, out int exitcode, bool ignore_errors = false, int output_verbosity_level = 1, StringBuilder captured_output = null, TimeSpan? timeout = null, Dictionary environment_variables = null) + { + if (captured_output == null) + captured_output = new StringBuilder (); + var streamEnds = new CountdownEvent (2); + using (var p = new Process ()) { + p.StartInfo.FileName = filename; + p.StartInfo.Arguments = args; + p.StartInfo.UseShellExecute = false; + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.RedirectStandardError = true; + if (environment_variables != null) { + foreach (var kvp in environment_variables) + p.StartInfo.EnvironmentVariables.Add (kvp.Key, kvp.Value); + } + p.OutputDataReceived += (object sender, DataReceivedEventArgs e) => + { + if (e.Data == null) { + streamEnds.Signal (); + } else { + lock (captured_output) { + captured_output.AppendLine (e.Data); + Harness.Log (output_verbosity_level, e.Data); + } + } + }; + p.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => + { + if (e.Data == null) { + streamEnds.Signal (); + } else { + lock (captured_output) { + captured_output.AppendLine (e.Data); + Harness.Log (output_verbosity_level, e.Data); + } + } + }; + Harness.Log (output_verbosity_level, "{0} {1}", p.StartInfo.FileName, p.StartInfo.Arguments); + p.Start (); + p.BeginOutputReadLine (); + p.BeginErrorReadLine (); + if (p.WaitForExit (!timeout.HasValue ? int.MaxValue : (int) timeout.Value.TotalMilliseconds )) { + streamEnds.Wait (); + exitcode = p.ExitCode; + if (p.ExitCode != 0 && !ignore_errors) + throw new Exception (string.Format ("Failed to execute {0}:\n{1}", filename, captured_output.ToString ())); + return p.ExitCode == 0; + } else { + if (!ignore_errors) + throw new Exception (string.Format ("Execution of {0} timed out after {2} minutes:\n{1}", filename, captured_output.ToString (), timeout.Value.TotalMinutes)); + else + Harness.Log ("Execution of {0} timed out after {2} minutes:\n{1}", filename, captured_output.ToString (), timeout.Value.TotalMinutes); + exitcode = 0; + kill (p.Id, 9); + return false; + } + } + } + } +} + diff --git a/tests/xharness/BCLTarget.cs b/tests/xharness/BCLTarget.cs new file mode 100644 index 000000000000..0f46148dac70 --- /dev/null +++ b/tests/xharness/BCLTarget.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace xharness +{ + public class BCLTarget + { + public Harness Harness; + public string MonoPath; // MONO_PATH + public string WatchMonoPath; // WATCH_MONO_PATH + public string TVOSMonoPath; // TVOS_MONO_PATH + public string TestName; + + static readonly Dictionary ignored_tests = new Dictionary { + { "Microsoft.Win32", null }, + { "System.Diagnostics.Contracts", null }, + { "System.Runtime.Remoting", null }, + { "System.Security.AccessControl", null }, + { "System.Security.Permissions", null }, + { "System.Security.Policy", null }, + { "System.Reflection.Emit", null }, + // System + { "System.CodeDom", null }, + { "System.Configuration", null }, + { "System.IO.Ports", null }, + { "System.Web", new [] { "System_test.dll.sources" } }, + { "Microsoft.CSharp", null }, + { "Microsoft.VisualBasic", null }, + // System.Core + { "System.IO.Pipes", null }, + // System.Data + { "System.Data.Odbc", null }, + { "System.Data.OleDb", null }, + // System.Web.Services + { "System.Web.Services.Configuration", null } + }; + + public BCLTarget () + { + } + + public void Convert () + { + var testName = TestName == "mscorlib" ? "corlib" : TestName; + var main_test_sources = Path.Combine (MonoPath, "mcs", "class", testName, testName + "_test.dll.sources"); + var main_test_files = File.ReadAllLines (main_test_sources); + var watch_test_sources = Path.Combine (WatchMonoPath, "mcs", "class", testName, testName + "_test.dll.sources"); + var watch_test_files = File.ReadAllLines (watch_test_sources); + var tvos_test_sources = Path.Combine (TVOSMonoPath, "mcs", "class", testName, testName + "_test.dll.sources"); + var tvos_test_files = File.ReadAllLines (tvos_test_sources); + var template_path = Path.Combine (Harness.RootDirectory, "bcl-test", TestName, TestName + ".csproj.template"); + var csproj_input = File.ReadAllText (template_path); + var project_path = Path.Combine (Harness.RootDirectory, "bcl-test", TestName, TestName + ".csproj"); + var csproj_output = project_path; + + var sb = new StringBuilder (); + + var files_path = Path.GetDirectoryName (main_test_sources).Replace ("/", "\\"); + foreach (var s in main_test_files) { + if (string.IsNullOrEmpty (s)) + continue; + + if (IsNotSupported (main_test_sources, s)) + continue; + + sb.AppendFormat (" \r\n", files_path, s.Replace ("/", "\\").Trim ()); + + var link_path = Path.GetDirectoryName (s); + if (string.IsNullOrEmpty (link_path) || link_path [0] == '.') + sb.AppendFormat (" {0}\r\n", Path.GetFileName (s)); + else + sb.AppendFormat (" {0}\\{1}\r\n", link_path, Path.GetFileName (s)); + + sb.AppendFormat (" \r\n"); + } + + var watch_files_path = Path.GetDirectoryName (watch_test_sources).Replace ("/", "\\"); + foreach (var s in watch_test_files) { + if (string.IsNullOrEmpty (s)) + continue; + + if (IsNotSupported (watch_test_sources, s)) + continue; + + sb.AppendFormat (" \r\n", watch_files_path, s.Replace ("/", "\\").Trim ()); + + var link_path = Path.GetDirectoryName (s); + if (string.IsNullOrEmpty (link_path) || link_path [0] == '.') + sb.AppendFormat (" {0}\r\n", Path.GetFileName (s)); + else + sb.AppendFormat (" {0}\\{1}\r\n", link_path, Path.GetFileName (s)); + + sb.AppendFormat (" \r\n"); + } + + var tvos_files_path = Path.GetDirectoryName (tvos_test_sources).Replace ("/", "\\"); + foreach (var s in tvos_test_files) { + if (string.IsNullOrEmpty (s)) + continue; + + if (IsNotSupported (tvos_test_sources, s)) + continue; + + sb.AppendFormat (" \r\n", tvos_files_path, s.Replace ("/", "\\").Trim ()); + + var link_path = Path.GetDirectoryName (s); + if (string.IsNullOrEmpty (link_path) || link_path [0] == '.') + sb.AppendFormat (" {0}\r\n", Path.GetFileName (s)); + else + sb.AppendFormat (" {0}\\{1}\r\n", link_path, Path.GetFileName (s)); + + sb.AppendFormat (" \r\n"); + } + + Harness.Save (csproj_input.Replace ("#FILES#", sb.ToString ()), csproj_output); + } + + bool IsNotSupported (string sourcesFile, string path) + { + foreach (var p in ignored_tests) { + if (path.Contains (p.Key)) { + if (p.Value == null) + return true; + + foreach (var assembly in p.Value) { + if (sourcesFile.Contains (Path.DirectorySeparatorChar + assembly)) + return true; + } + } + } + + return false; + } + } +} + diff --git a/tests/xharness/ClassicTarget.cs b/tests/xharness/ClassicTarget.cs new file mode 100644 index 000000000000..f0d5233143af --- /dev/null +++ b/tests/xharness/ClassicTarget.cs @@ -0,0 +1,37 @@ +using System; + +namespace xharness +{ + public class ClassicTarget : Target + { + protected override void ExecuteInternal () + { + // nothing to do here + } + + public override string Suffix { + get { + return "-classic"; + } + } + + public override string Platform { + get { + return "ios"; + } + } + + public override string MakefileWhereSuffix { + get { + return "classic"; + } + } + + public override string ProjectFileSuffix { + get { + return string.Empty; + } + } + } +} + diff --git a/tests/xharness/DeviceLogCapturer.cs b/tests/xharness/DeviceLogCapturer.cs new file mode 100644 index 000000000000..fa5bb09e02df --- /dev/null +++ b/tests/xharness/DeviceLogCapturer.cs @@ -0,0 +1,70 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading; + +namespace xharness +{ + public class DeviceLogCapturer + { + public Harness Harness; + public string LogPath; + public string DeviceName; + + StreamWriter writer; + Process process; + CountdownEvent streamEnds; + + public void StartCapture () + { + writer = new StreamWriter (new FileStream (LogPath, FileMode.Create)); + streamEnds = new CountdownEvent (2); + + process = new Process (); + process.StartInfo.FileName = Harness.MlaunchPath; + var sb = new StringBuilder (); + sb.Append ("--logdev "); + sb.Append ("--sdkroot ").Append (Harness.Quote (Harness.XcodeRoot)).Append (' '); + AppRunner.AddDeviceName (sb, DeviceName); + process.StartInfo.Arguments = sb.ToString (); + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => { + if (e.Data == null) { + streamEnds.Signal (); + } else { + lock (writer) { + writer.WriteLine (e.Data); + } + } + }; + process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => { + if (e.Data == null) { + streamEnds.Signal (); + } else { + lock (writer) { + writer.WriteLine (e.Data); + } + } + }; + Harness.Log (1, "{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + process.Start (); + process.BeginOutputReadLine (); + process.BeginErrorReadLine (); + } + + public void StopCapture () + { + process.Kill (); + if (!streamEnds.Wait (TimeSpan.FromSeconds (5))) { + Harness.Log ("Could not kill 'mtouch --logdev' process in 5 seconds."); + } + process.Dispose (); + writer.Flush (); + writer.Dispose (); + } + } +} + diff --git a/tests/xharness/Harness.cs b/tests/xharness/Harness.cs new file mode 100644 index 000000000000..a89ba6205052 --- /dev/null +++ b/tests/xharness/Harness.cs @@ -0,0 +1,510 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; + +namespace xharness +{ + public enum HarnessAction + { + None, + Configure, + Run, + Install, + } + + public class Harness + { + public HarnessAction Action { get; set; } + public int Verbosity { get; set; } + + // This is the maccore/tests directory. + string root_directory; + public string RootDirectory { + get { + if (root_directory == null) + root_directory = Environment.CurrentDirectory; + return root_directory; + } + set { + root_directory = value; + } + } + + public List TestProjects { get; set; } = new List (); + public List HardCodedTestProjects { get; set; } = new List (); + public List BclTests { get; set; } = new List (); + + // Configure + public bool AutoConf { get; set; } + public bool Mac { get; set; } + public string WatchOSContainerTemplate { get; set; } + public string WatchOSAppTemplate { get; set; } + public string WatchOSExtensionTemplate { get; set; } + public string MONO_PATH { get; set; } // Use same name as in Makefiles, so that a grep finds it. + public string WATCH_MONO_PATH { get; set; } // Use same name as in Makefiles, so that a grep finds it. + public string TVOS_MONO_PATH { get; set; } // Use same name as in Makefiles, so that a grep finds it. + public bool INCLUDE_WATCH { get; set; } + + // Run + public string Target { get; set; } + public string SdkRoot { get; set; } = "/Applications/Xcode.app"; + public string Configuration { get; set; } = "Debug"; + public string LogFile { get; set; } + public double Timeout { get; set; } = 10; // in minutes + public double LaunchTimeout { get; set; } // in minutes + + public Harness () + { + LaunchTimeout = InWrench ? 1 : 120; + } + + public string XcodeRoot { + get { + var p = SdkRoot; + do { + if (p == "/") { + throw new Exception (string.Format ("Could not find Xcode.app in {0}", SdkRoot)); + } else if (File.Exists (Path.Combine (p, "Contents", "MacOS", "Xcode"))) { + return p; + } + p = Path.GetDirectoryName (p); + } while (true); + } + } + + public string MlaunchPath { + get { + var path = Path.GetFullPath (Path.Combine (Path.GetDirectoryName (Path.GetDirectoryName (RootDirectory)), "maccore", "tools", "mlaunch", "mlaunch")); + if (!File.Exists (path)) { + Log ("Could not find mlaunch locally ({0}), will try in Xamarin Studio.app.", path); + path = "/Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/MonoDevelop.IPhone/mlaunch.app/Contents/MacOS/mlaunch"; + } + + if (!File.Exists (path)) + throw new FileNotFoundException (string.Format ("Could not find mlaunch: {0}", path)); + + return path; + } + } + + public static string Quote (string f) + { + if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1) + return f; + + var s = new StringBuilder (); + + s.Append ('"'); + foreach (var c in f) { + if (c == '"' || c == '\\') + s.Append ('\\'); + + s.Append (c); + } + s.Append ('"'); + + return s.ToString (); + } + + void CreateBCLProjects () + { + foreach (var bclTest in BclTests) { + var target = new BCLTarget () { + Harness = this, + MonoPath = MONO_PATH, + WatchMonoPath = WATCH_MONO_PATH, + TVOSMonoPath = TVOS_MONO_PATH, + TestName = bclTest, + }; + target.Convert (); + } + } + + + void AutoConfigureMac () + { + var test_suites = new string[] { "apitest", "dontlink-mac" }; + var hard_coded_test_suites = new string[] { "mmptest", "msbuild-mac" }; + //var library_projects = new string[] { "BundledResources", "EmbeddedResources", "bindings-test", "bindings-framework-test" }; + //var fsharp_test_suites = new string[] { "fsharp" }; + //var fsharp_library_projects = new string[] { "fsharplibrary" }; + //var bcl_suites = new string[] { "mscorlib", "System", "System.Core", "System.Data", "System.Net.Http", "System.Numerics", "System.Runtime.Serialization", "System.Transactions", "System.Web.Services", "System.Xml", "System.Xml.Linq", "Mono.Security", "System.ComponentModel.DataAnnotations", "System.Json", "System.ServiceModel.Web", "Mono.Data.Sqlite" }; + foreach (var p in test_suites) + TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj"))); + foreach (var p in hard_coded_test_suites) + HardCodedTestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj"))); + //foreach (var p in fsharp_test_suites) + // TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".fsproj"))); + //foreach (var p in library_projects) + //TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj"))); + //foreach (var p in fsharp_library_projects) + //TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".fsproj"))); + //foreach (var p in bcl_suites) + //TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test/" + p + "/" + p + ".csproj"))); + + // BclTests.AddRange (bcl_suites); + + ParseConfigFiles (); + var src_root = Path.Combine (Path.GetDirectoryName (Path.GetDirectoryName (Path.GetDirectoryName (RootDirectory))), "xamarin-macios"); + MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "mono")); + } + + void AutoConfigure () + { + var test_suites = new string [] { "monotouch-test", "dont link", "link sdk", "link all", "framework-test", "mini" }; + var library_projects = new string [] { "BundledResources", "EmbeddedResources", "bindings-test", "bindings-framework-test" }; + var fsharp_test_suites = new string [] { "fsharp" }; + var fsharp_library_projects = new string [] { "fsharplibrary" }; + var bcl_suites = new string [] { "mscorlib", "System", "System.Core", "System.Data", "System.Net.Http", "System.Numerics", "System.Runtime.Serialization", "System.Transactions", "System.Web.Services", "System.Xml", "System.Xml.Linq", "Mono.Security", "System.ComponentModel.DataAnnotations", "System.Json", "System.ServiceModel.Web", "Mono.Data.Sqlite" }; + foreach (var p in test_suites) + TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj"))); + foreach (var p in fsharp_test_suites) + TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".fsproj"))); + foreach (var p in library_projects) + TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj"))); + foreach (var p in fsharp_library_projects) + TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".fsproj"))); + foreach (var p in bcl_suites) + TestProjects.Add (Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test/" + p + "/" + p + ".csproj"))); + + BclTests.AddRange (bcl_suites); + + WatchOSContainerTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "watchos/Container")); + WatchOSAppTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "watchos/App")); + WatchOSExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "watchos/Extension")); + + ParseConfigFiles (); + var src_root = Path.GetDirectoryName (Path.GetDirectoryName (RootDirectory)); + MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "xamarin-macios", "external", "mono")); + WATCH_MONO_PATH = make_config ["WATCH_MONO_PATH"]; + TVOS_MONO_PATH = MONO_PATH; + INCLUDE_WATCH = make_config.ContainsKey ("INCLUDE_WATCH") && !string.IsNullOrEmpty (make_config ["INCLUDE_WATCH"]); + } + + static Dictionary make_config = new Dictionary (); + static IEnumerable FindConfigFiles (string name) + { + var dir = Environment.CurrentDirectory; + while (dir != "/") { + var file = Path.Combine (dir, name); + if (File.Exists (file)) + yield return file; + file = Path.Combine (dir, "xamarin-macios", name); + if (File.Exists (file)) + yield return file; + dir = Path.GetDirectoryName (dir); + } + } + + static void ParseConfigFiles () + { + ParseConfigFiles (FindConfigFiles ("test.config")); + ParseConfigFiles (FindConfigFiles ("Make.config.local")); + ParseConfigFiles (FindConfigFiles ("Make.config")); + } + + static void ParseConfigFiles (IEnumerable files) + { + foreach (var file in files) + ParseConfigFile (file); + } + + static void ParseConfigFile (string file) + { + if (string.IsNullOrEmpty (file)) + return; + + foreach (var line in File.ReadAllLines (file)) { + var eq = line.IndexOf ('='); + if (eq == -1) + continue; + var key = line.Substring (0, eq); + if (!make_config.ContainsKey (key)) + make_config [key] = line.Substring (eq + 1); + } + } + + public int Configure () + { + if (Mac) + ConfigureMac (); + else + ConfigureIOS (); + return 0; + } + + void ConfigureMac () + { + var classic_targets = new List (); + var unified_targets = new List (); + var hardcoded_unified_targets = new List (); + + RootDirectory = Path.GetFullPath (RootDirectory).TrimEnd ('/'); + + if (AutoConf) + AutoConfigureMac (); + + CreateBCLProjects (); + + foreach (var file in TestProjects) { + if (!File.Exists (file)) + throw new FileNotFoundException (file); + + var unifiedMobile = new MacUnifiedTarget (true) { + TemplateProjectPath = file, + Harness = this, + }; + unifiedMobile.Execute (); + unified_targets.Add (unifiedMobile); + + var unifiedXM45 = new MacUnifiedTarget (false) { + TemplateProjectPath = file, + Harness = this, + }; + unifiedXM45.Execute (); + unified_targets.Add (unifiedXM45); + + var classic = new MacClassicTarget () { + TemplateProjectPath = file, + Harness = this, + }; + classic.Execute (); + classic_targets.Add (classic); + } + + foreach (var file in HardCodedTestProjects) { + var unifiedMobile = new MacUnifiedTarget (true, true) + { + TemplateProjectPath = file, + Harness = this, + }; + unifiedMobile.Execute (); + hardcoded_unified_targets.Add (unifiedMobile); + } + + MakefileGenerator.CreateMacMakefile (this, classic_targets.Union (unified_targets).Union (hardcoded_unified_targets) ); + } + + void ConfigureIOS () + { + var classic_targets = new List (); + var unified_targets = new List (); + var tvos_targets = new List (); + var watchos_targets = new List (); + + RootDirectory = Path.GetFullPath (RootDirectory).TrimEnd ('/'); + + if (AutoConf) + AutoConfigure (); + + CreateBCLProjects (); + + foreach (var file in TestProjects) { + if (!File.Exists (file)) + throw new FileNotFoundException (file); + + var watchos = new WatchOSTarget () { + TemplateProjectPath = file, + Harness = this, + }; + watchos.Execute (); + watchos_targets.Add (watchos); + + var tvos = new TVOSTarget () { + TemplateProjectPath = file, + Harness = this, + }; + tvos.Execute (); + tvos_targets.Add (tvos); + + var unified = new UnifiedTarget () { + TemplateProjectPath = file, + Harness = this, + }; + unified.Execute (); + unified_targets.Add (unified); + + var classic = new ClassicTarget () { + TemplateProjectPath = file, + Harness = this, + }; + classic.Execute (); + classic_targets.Add (classic); + } + + SolutionGenerator.CreateSolution (this, watchos_targets, "watchos"); + SolutionGenerator.CreateSolution (this, tvos_targets, "tvos"); + SolutionGenerator.CreateSolution (this, unified_targets, "unified"); + MakefileGenerator.CreateMakefile (this, classic_targets, unified_targets, tvos_targets, watchos_targets); + } + + public int Install () + { + foreach (var project in TestProjects) { + var runner = new AppRunner () { + Harness = this, + ProjectFile = project, + }; + var rv = runner.Install (); + if (rv != 0) + return rv; + } + return 0; + } + + public int Run () + { + foreach (var project in TestProjects) { + var runner = new AppRunner () { + Harness = this, + ProjectFile = project, + }; + var rv = runner.Run (); + if (rv != 0) + return rv; + } + return 0; + } + + public void Log (int min_level, string message) + { + if (Verbosity < min_level) + return; + Console.WriteLine (message); + } + + public void Log (int min_level, string message, params object[] args) + { + if (Verbosity < min_level) + return; + Console.WriteLine (message, args); + } + + public void Log (string message) + { + Log (0, message); + } + + public void Log (string message, params object[] args) + { + Log (0, message, args); + } + + public void LogWrench (string message, params object[] args) + { + if (!InWrench) + return; + + Console.WriteLine (message, args); + } + + public void LogWrench (string message) + { + if (!InWrench) + return; + + Console.WriteLine (message); + } + + public bool InWrench { + get { + return !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("BUILD_REVISION")); + } + } + + public int Execute () + { + switch (Action) { + case HarnessAction.Configure: + return Configure (); + case HarnessAction.Run: + return Run (); + case HarnessAction.Install: + return Install (); + default: + throw new NotImplementedException (Action.ToString ()); + } + } + + public void Save (XmlDocument doc, string path) + { + if (!File.Exists (path)) { + doc.Save (path); + Log (1, "Created {0}", path); + } else { + var tmpPath = path + ".tmp"; + doc.Save (tmpPath); + var existing = File.ReadAllText (path); + var updated = File.ReadAllText (tmpPath); + + if (existing == updated) { + File.Delete (tmpPath); + Log (1, "Not saved {0}, no change", path); + } else { + File.Delete (path); + File.Move (tmpPath, path); + Log (1, "Updated {0}", path); + } + } + } + + public void Save (StringWriter doc, string path) + { + if (!File.Exists (path)) { + File.WriteAllText (path, doc.ToString ()); + Log (1, "Created {0}", path); + } else { + var existing = File.ReadAllText (path); + var updated = doc.ToString (); + + if (existing == updated) { + Log (1, "Not saved {0}, no change", path); + } else { + File.WriteAllText (path, updated); + Log (1, "Updated {0}", path); + } + } + } + + public void Save (string doc, string path) + { + if (!File.Exists (path)) { + File.WriteAllText (path, doc); + Log (1, "Created {0}", path); + } else { + var existing = File.ReadAllText (path); + if (existing == doc) { + Log (1, "Not saved {0}, no change", path); + } else { + File.WriteAllText (path, doc); + Log (1, "Updated {0}", path); + } + } + } + + // We want guids that nobody else has, but we also want to generate the same guid + // on subsequent invocations (so that csprojs don't change unnecessarily, which is + // annoying when XS reloads the projects, and also causes unnecessary rebuilds). + // Nothing really breaks when the sequence isn't identical from run to run, so + // this is just a best minimal effort. + static Random guid_generator = new Random (unchecked ((int) 0xdeadf00d)); + public Guid NewStableGuid () + { + var bytes = new byte [16]; + guid_generator.NextBytes (bytes); + return new Guid (bytes); + } + + bool? disable_watchos_on_wrench; + public bool DisableWatchOSOnWrench { + get { + if (!disable_watchos_on_wrench.HasValue) + disable_watchos_on_wrench = !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("DISABLE_WATCH_ON_WRENCH")); + return disable_watchos_on_wrench.Value; + } + } + } +} diff --git a/tests/xharness/MacClassicTarget.cs b/tests/xharness/MacClassicTarget.cs new file mode 100644 index 000000000000..797998dcce8b --- /dev/null +++ b/tests/xharness/MacClassicTarget.cs @@ -0,0 +1,36 @@ +using System; + +namespace xharness +{ + public class MacClassicTarget : MacTarget + { + protected override void ExecuteInternal () + { + // nothing to do here + } + + public override string Suffix { + get { + return "-classic"; + } + } + + public override string Platform { + get { + return "mac"; + } + } + + public override string MakefileWhereSuffix { + get { + return "mac-classic"; + } + } + + public override string ProjectFileSuffix { + get { + return string.Empty; + } + } + } +} diff --git a/tests/xharness/MacTarget.cs b/tests/xharness/MacTarget.cs new file mode 100644 index 000000000000..9b01f4cb4e10 --- /dev/null +++ b/tests/xharness/MacTarget.cs @@ -0,0 +1,14 @@ +using System; + +namespace xharness +{ + public class MacTarget : Target + { + public string SimplifiedName { + get { + return Name.EndsWith ("-mac", StringComparison.Ordinal) ? Name.Substring (0, Name.Length - 4) : Name; + } + } + } +} + diff --git a/tests/xharness/MacUnifiedTarget.cs b/tests/xharness/MacUnifiedTarget.cs new file mode 100644 index 000000000000..a9854ef98cad --- /dev/null +++ b/tests/xharness/MacUnifiedTarget.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; + +namespace xharness +{ + public class MacUnifiedTarget : MacTarget + { + public bool Mobile { get; private set; } + + bool SkipProjectGeneration; + + public MacUnifiedTarget (bool mobile, bool shouldSkipProjectGeneration = false) : base () + { + Mobile = mobile; + SkipProjectGeneration = shouldSkipProjectGeneration; + } + + public override bool ShouldSkipProjectGeneration + { + get + { + return SkipProjectGeneration; + } + } + + public override string Suffix { + get { + if (SkipProjectGeneration) + return ""; + return "-unified" + (Mobile ? "" : "XM45"); + } + } + + protected override string ProjectTypeGuids { + get { + return "{A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};" + LanguageGuid; + } + } + + protected override string BindingsProjectTypeGuids { + get { + return "{810C163F-4746-4721-8B8E-88A3673A62EA}"; + } + } + + protected override string TargetFrameworkIdentifier { + get { + return "Xamarin.Mac"; + } + } + + protected override string Imports { + get { + return IsFSharp ? "Mac\\Xamarin.Mac.FSharp.targets" : "Mac\\Xamarin.Mac.CSharp.targets"; + } + } + + protected override string BindingsImports { + get { + return "Mac\\Xamarin.Mac.ObjcBinding.CSharp"; + } + } + + protected override string AdditionalDefines { + get { + return "XAMCORE_2_0"; + } + } + + public override bool IsMultiArchitecture { + get { + return true; + } + } + + public override string Platform { + get { + return "mac"; + } + } + + public override string MakefileWhereSuffix { + get { + return "unified" + (Mobile ? "" : "XM45"); + } + } + + public override string DefaultAssemblyReference { get { return "XamMac"; } } + + public override IEnumerable ReferenceToRemove { get { yield return "System.Drawing"; } } + + public override bool ShouldSetTargetFrameworkIdentifier { get { return Mobile; } } + + public override Dictionary NewPropertiesToAdd + { + get + { + if (Mobile) + return new Dictionary () { { "TargetFrameworkVersion", "v2.0" } }; + else + return new Dictionary () { { "TargetFrameworkVersion", "v4.5" }, { "UseXamMacFullFramework", "true" } }; + } + } + } +} diff --git a/tests/xharness/MakefileGenerator.cs b/tests/xharness/MakefileGenerator.cs new file mode 100644 index 000000000000..adda1a22562a --- /dev/null +++ b/tests/xharness/MakefileGenerator.cs @@ -0,0 +1,646 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace xharness +{ + public static class MakefileGenerator + { + static void WriteTarget (this StreamWriter writer, string target, string dependencies, params string [] arguments) + { + var t = string.Format (target, arguments); + if (t.Contains ("\\ ")) { + writer.Write (t.Replace ("\\ ", ""), arguments); + writer.Write (" "); + } + writer.Write (t); + if (!string.IsNullOrEmpty (dependencies)) { + writer.Write (": "); + writer.WriteLine (dependencies, arguments); + } else { + writer.WriteLine (":"); + } + } + + enum MacTargetNameType { Build, Clean, Exec, Run } + + static string MakeMacTargetName (MacTarget target, MacTargetNameType type) + { + if (target is MacClassicTarget) + return MakeMacClassicTargetName (target, type); + else if (target is MacUnifiedTarget) + return MakeMacUnifiedTargetName (target, type); + else + throw new NotImplementedException (); + } + + static string MakeMacClassicTargetName (MacTarget target, MacTargetNameType type) + { + var make_escaped_suffix = "-" + target.Platform.Replace (" ", "\\ "); + var make_escaped_name = target.SimplifiedName.Replace (" ", "\\ "); + + switch (type) + { + case MacTargetNameType.Build: + return string.Format ("build{0}-classic-{1}", make_escaped_suffix, make_escaped_name); + case MacTargetNameType.Clean: + return string.Format ("clean{0}-classic-{1}", make_escaped_suffix, make_escaped_name); + case MacTargetNameType.Exec: + return string.Format ("exec{0}-classic-{1}", make_escaped_suffix, make_escaped_name); + case MacTargetNameType.Run: + return string.Format ("run{0}-classic-{1}", make_escaped_suffix, make_escaped_name); + default: + throw new NotImplementedException (); + } + } + + static string MakeMacUnifiedTargetName (MacTarget target, MacTargetNameType type) + { + var make_escaped_suffix = "-" + target.Platform.Replace (" ", "\\ "); + var make_escaped_name = target.SimplifiedName.Replace (" ", "\\ "); + + switch (type) + { + case MacTargetNameType.Build: + return string.Format ("build{0}-{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + case MacTargetNameType.Clean: + return string.Format ("clean{0}-{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + case MacTargetNameType.Exec: + return string.Format ("exec{0}-{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + case MacTargetNameType.Run: + return string.Format ("run{0}-{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + default: + throw new NotImplementedException (); + } + } + + public static void CreateMacMakefile (Harness harness, IEnumerable targets) + { + var makefile = Path.Combine (harness.RootDirectory, "Makefile-mac.inc"); + using (var writer = new StreamWriter (makefile, false, new UTF8Encoding (false))) { + writer.WriteLine (".stamp-configure-projects-mac: Makefile xharness/xharness.exe"); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --configure --autoconf --rootdir $(CURDIR)"); + writer.WriteLine ("\t$(Q) touch $@"); + writer.WriteLine (); + + var allTargets = new List (); + allTargets.AddRange (targets); + + List allTargetNames = new List (allTargets.Count); + List allTargetCleanNames = new List (allTargets.Count); + + // build/[install/]run targets for specific test projects. + foreach (var target in allTargets) { + var make_escaped_simplified_name = target.SimplifiedName.Replace (" ", "\\ "); + var make_escaped_name = target.Name.Replace (" ", "\\ "); + + writer.WriteLine (); + if (target.ProjectPath != target.TemplateProjectPath) { + writer.WriteLine ("# {0} for {1}", make_escaped_simplified_name, target.Suffix.Replace ("-", "")); + writer.WriteLine (".stamp-configure-projects-mac: {0}", target.TemplateProjectPath.Replace (" ", "\\ ")); + writer.WriteLine ("{0}: .stamp-configure-projects-mac", target.ProjectPath.Replace (" ", "\\ ")); + writer.WriteLine (); + } + + // build project target + if (target.IsBCLProject) { + throw new NotImplementedException (); + } + else if (target is MacClassicTarget) { + allTargetNames.Add (MakeMacClassicTargetName (target, MacTargetNameType.Build)); + allTargetCleanNames.Add (MakeMacClassicTargetName (target, MacTargetNameType.Clean)); + + writer.WriteTarget (MakeMacClassicTargetName (target, MacTargetNameType.Build), "$(GUI_UNIT_PATH)/bin/net_4_5/GuiUnit.exe"); + writer.WriteLine ("\t$(Q) $(MDTOOL) build {0}", target.ProjectPath); + writer.WriteLine (); + + writer.WriteTarget (MakeMacClassicTargetName (target, MacTargetNameType.Clean), ""); + writer.WriteLine ("\t$(Q) $(MDTOOL) build -t:clean {0}", target.ProjectPath); + writer.WriteLine (); + + writer.WriteTarget (MakeMacClassicTargetName (target, MacTargetNameType.Exec), ""); + writer.WriteLine ("\t$(Q) ./{0}/bin/x86/Debug/{0}.app/Contents/MacOS/{0}", make_escaped_name); + writer.WriteLine (); + + writer.WriteTarget (MakeMacClassicTargetName (target, MacTargetNameType.Run), ""); + writer.WriteLine ("\t$(Q) $(MAKE) {0}", MakeMacClassicTargetName (target, MacTargetNameType.Build)); + writer.WriteLine ("\t$(Q) $(MAKE) {0}", MakeMacClassicTargetName (target, MacTargetNameType.Exec)); + writer.WriteLine (); + } + else { + allTargetNames.Add (MakeMacUnifiedTargetName (target, MacTargetNameType.Build)); + allTargetCleanNames.Add (MakeMacUnifiedTargetName (target, MacTargetNameType.Clean)); + + string guiUnitDependency = ((MacUnifiedTarget)target).Mobile ? "$(GUI_UNIT_PATH)/bin/xammac_mobile/GuiUnit.exe" : "$(GUI_UNIT_PATH)/bin/net_4_5/GuiUnit.exe"; + + writer.WriteTarget (MakeMacUnifiedTargetName (target, MacTargetNameType.Build), "{0}", target.ProjectPath.Replace (" ", "\\ ") + " " + guiUnitDependency); + writer.WriteLine ("\t$(Q_XBUILD) $(SYSTEM_XBUILD) \"/property:Configuration=$(CONFIG)\" /t:Build $(XBUILD_VERBOSITY) \"{0}\"", target.ProjectPath); + writer.WriteLine (); + + writer.WriteTarget (MakeMacUnifiedTargetName (target, MacTargetNameType.Clean), ""); + writer.WriteLine ("\t$(Q_XBUILD) $(SYSTEM_XBUILD) \"/property:Configuration=$(CONFIG)\" /t:Clean $(XBUILD_VERBOSITY) \"{0}\"", target.ProjectPath); + writer.WriteLine (); + + writer.WriteTarget (MakeMacUnifiedTargetName (target, MacTargetNameType.Exec), ""); + writer.WriteLine ("\t$(Q) ./{0}/bin/x86/Debug{1}/{0}.app/Contents/MacOS/{0}", make_escaped_name, target.Suffix); + writer.WriteLine (); + + writer.WriteTarget (MakeMacUnifiedTargetName (target, MacTargetNameType.Run), ""); + writer.WriteLine ("\t$(Q) $(MAKE) {0}", MakeMacUnifiedTargetName (target, MacTargetNameType.Build)); + writer.WriteLine ("\t$(Q) $(MAKE) {0}", MakeMacUnifiedTargetName (target, MacTargetNameType.Exec)); + writer.WriteLine (); + } + + writer.WriteLine (); + } + writer.WriteLine ("# Env Variables to use local not system XM"); + writer.WriteLine (); + + var enviromentalVariables = new Dictionary () { { "XBUILD_FRAMEWORK_FOLDERS_PATH", "$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild-frameworks"}, + { "MSBuildExtensionsPath", "$(MAC_DESTDIR)/Library/Frameworks/Mono.framework/External/xbuild"}, + { "MD_APPLE_SDK_ROOT", "$(shell dirname `dirname $(XCODE_DEVELOPER_ROOT)`)"} + }; + + foreach (var key in enviromentalVariables) { + writer.WriteLine ("{0}: export {1}:={2}", string.Join (" ", allTargetNames.ToArray ()), key.Key, key.Value); + writer.WriteLine ("{0}: export {1}:={2}", string.Join (" ", allTargetCleanNames.ToArray ()), key.Key, key.Value); + } + + writer.WriteLine ("# Container targets that run multiple test projects"); + writer.WriteLine (); + + var grouped = allTargets.GroupBy ((target) => target.SimplifiedName); + foreach (MacTargetNameType action in Enum.GetValues (typeof (MacTargetNameType))) { + var actionName = action.ToString ().ToLowerInvariant (); + foreach (var group in grouped) { + var targetName = group.Key; + writer.WriteLine ("{0}-mac-{1}:", actionName, targetName); + writer.WriteLine ("\t$(Q) rm -f \".$@-failure.stamp\""); + foreach (var entry in group) + writer.WriteLine ("\t$(Q) $(MAKE) {0} || echo \"{0} failed\" >> \".$@-failure.stamp\"", MakeMacTargetName (entry, action)); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + } + } + + writer.WriteLine ("mac-run run-mac:"); + writer.WriteLine ("\t$(Q) rm -rf \".$@-failure.stamp\""); + foreach (var target in allTargets) { + if (target is MacClassicTarget) + writer.WriteLine ("\t$(Q) $(MAKE) \"{0}\" || echo \"{0} failed\" >> \".$@-failure.stamp\"", MakeMacClassicTargetName (target, MacTargetNameType.Run)); + else if (target is MacUnifiedTarget) + writer.WriteLine ("\t$(Q) $(MAKE) \"{0}\" || echo \"{0} failed\" >> \".$@-failure.stamp\"", MakeMacUnifiedTargetName (target, MacTargetNameType.Run)); + else + throw new NotImplementedException (); + } + + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + writer.WriteLine ("mac-build mac-build-all build-mac:"); // build everything + writer.WriteLine ("\t$(Q) rm -rf \".$@-failure.stamp\""); + foreach (var target in allTargets) { + if (target is MacClassicTarget) + writer.WriteLine ("\t$(Q) $(MAKE) \"{0}\" || echo \"{0} failed\" >> \".$@-failure.stamp\"", MakeMacClassicTargetName (target, MacTargetNameType.Build)); + else if (target is MacUnifiedTarget) + writer.WriteLine ("\t$(Q) $(MAKE) \"{0}\" || echo \"{0} failed\" >> \".$@-failure.stamp\"", MakeMacUnifiedTargetName (target, MacTargetNameType.Build)); + else + throw new NotImplementedException (); + + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + } + } + + static void WriteCollectionTarget (StreamWriter writer, string target, IEnumerable targets, string mode) + { + writer.WriteLine (); + writer.Write (target); + writer.WriteLine (":"); + foreach (var t in targets.Where ((v) => v.IsExe)) { + if (t is ClassicTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-{2}compat-{1}\" || echo \"run{0}-{2}compat-{1} failed\" >> \".$@-failure.stamp\"", "-ios", t.Name, mode); + } else if (t is UnifiedTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-{2}unified-{1}\" || echo \"run{0}-{2}unified-{1} failed\" >> \".$@-failure.stamp\"", "-ios", t.Name, mode); + } else { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-{2}-{1}\" || echo \"run{0}-{2}-{1} failed\" >> \".$@-failure.stamp\"", t.Suffix, t.Name, mode); + } + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + } + + public static void CreateMakefile (Harness harness, IEnumerable classic_targets, IEnumerable unified_targets, IEnumerable tvos_targets, IEnumerable watchos_targets) + { + var makefile = Path.Combine (harness.RootDirectory, "Makefile.inc"); + using (var writer = new StreamWriter (makefile, false, new UTF8Encoding (false))) { + writer.WriteLine (".stamp-configure-projects: Makefile xharness/xharness.exe"); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --configure --autoconf --rootdir $(CURDIR)"); + writer.WriteLine ("\t$(Q) touch $@"); + writer.WriteLine (); + + var allTargets = new List (); + allTargets.AddRange (classic_targets); + allTargets.AddRange (unified_targets); + allTargets.AddRange (tvos_targets); + allTargets.AddRange (watchos_targets); + + // build/[install/]run targets for specific test projects. + foreach (var target in allTargets) { + var make_escaped_suffix = "-" + target.Platform.Replace (" ", "\\ "); + var make_escaped_name = target.Name.Replace (" ", "\\ "); + + writer.WriteLine (); + if (target.ProjectPath != target.TemplateProjectPath) { + writer.WriteLine ("# {0} for {1}", target.Name, target.Suffix.Replace ("-", "")); + writer.WriteLine (".stamp-configure-projects: {0}", target.TemplateProjectPath.Replace (" ", "\\ ")); + writer.WriteLine ("{0}: .stamp-configure-projects", target.ProjectPath.Replace (" ", "\\ "), target.TemplateProjectPath.Replace (" ", "\\ ")); + writer.WriteLine (); + } + + // build sim project target + if (target.IsBCLProject) { + writer.WriteTarget ("build{0}-bcl-sim{2}-{1}", "build{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Build succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + } + writer.WriteTarget ("build{0}-sim{3}-{1}", "{2}", make_escaped_suffix, make_escaped_name, target.ProjectPath.Replace (" ", "\\ "), target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q_XBUILD) $(SYSTEM_XBUILD) \"/property:Configuration=$(CONFIG)\" \"/property:Platform=iPhoneSimulator\" /t:Build $(XBUILD_VERBOSITY) \"{0}\"", target.ProjectPath); + writer.WriteLine (); + + if (target is ClassicTarget) { + // target that builds both Classic+Unified + writer.WriteTarget ("build{0}-sim-{1}", "build{0}-simclassic-{1} build{0}-simunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Build succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + } + + // clean sim project target + if (target.IsBCLProject) { + writer.WriteTarget ("clean{0}-bcl-sim{2}-{1}", "clean{0}-sim-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Clean succeeded"); // This is important, otherwise we'll end up executing the catch-all clean-% target + writer.WriteLine (); + } + writer.WriteTarget ("clean{0}-sim{2}-{1}", string.Empty, make_escaped_suffix, make_escaped_name, target.ProjectPath.Replace (" ", "\\ "), target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q_XBUILD) $(SYSTEM_XBUILD) \"/property:Configuration=$(CONFIG)\" \"/property:Platform=iPhoneSimulator\" /t:Clean $(XBUILD_VERBOSITY) \"{0}\"", target.ProjectPath); + writer.WriteLine (); + + if (target.IsExe) { + // run sim project target + if (target.IsMultiArchitecture) { + writer.WriteTarget ("run{0}-sim{2}-{1}", string.Empty, make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) rm -f \".$@-failure.stamp\""); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim32-{1} || echo \"exec{0}-sim32-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim64-{1} || echo \"exec{0}-sim64-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + writer.WriteTarget ("run{0}-sim32-{1}", string.Empty, make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim32-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine (); + + writer.WriteTarget ("run{0}-sim64-{1}", string.Empty, make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim64-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine (); + } else { + writer.WriteTarget ("run{0}-sim{2}-{1}", string.Empty, make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine (); + } + + if (target.IsBCLProject) { + writer.WriteTarget ("run{0}-bcl-sim{2}-{1}", "run{0}-sim{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + + if (target.IsMultiArchitecture) { + writer.WriteTarget ("run{0}-bcl-sim32-{1}", "run{0}-sim32-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + + writer.WriteTarget ("run{0}-bcl-sim64-{1}", "run{0}-sim64-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + } + } + + if (target is ClassicTarget) { + // target that runs both Classic+Unified + writer.WriteTarget ("run{0}-sim-{1}", string.Empty, make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) rm -f \".$@-failure.stamp\""); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-simclassic-{1} build{0}-simunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-simclassic-{1} || echo \"exec{0}-simclassic-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim32-{1} || echo \"exec{0}-sim32-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-sim64-{1} || echo \"exec{0}-sim64-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + // compat targets for finger memory + writer.WriteTarget ("run-simcompat-{1}", "run-ios-simclassic-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + + writer.WriteTarget ("run-simdual-{1}", "run-ios-simunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + } + + // exec sim project target + if (target.IsMultiArchitecture) { + writer.WriteTarget ("exec{0}-sim64-{1}", "$(UNIT_SERVER)", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --run \"{0}\" --target {1}-simulator-64 --sdkroot $(XCODE_DEVELOPER_ROOT) --logfile \"$@.log\" --configuration $(CONFIG)", target.ProjectPath, target.Platform); + writer.WriteLine (); + + writer.WriteTarget ("exec{0}-sim32-{1}", "$(UNIT_SERVER)", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --run \"{0}\" --target {1}-simulator-32 --sdkroot $(XCODE_DEVELOPER_ROOT) --logfile \"$@.log\" --configuration $(CONFIG)", target.ProjectPath, target.Platform); + writer.WriteLine (); + } else { + writer.WriteTarget ("exec{0}-sim{2}-{1}", "$(UNIT_SERVER)", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --run \"{0}\" --target {1}-simulator --sdkroot $(XCODE_DEVELOPER_ROOT) --logfile \"$@.log\" --configuration $(CONFIG)", target.ProjectPath, target.Platform); + writer.WriteLine (); + } + + if (target.IsBCLProject) { + writer.WriteTarget ("exec{0}-bcl-sim{2}-{1}", "exec{0}-sim-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Exec succeeded"); // This is important, otherwise we'll end up executing the catch-all exec-% target + writer.WriteLine (); + + if (target.IsMultiArchitecture) { + writer.WriteTarget ("exec{0}-bcl-sim32-{1}", "exec{0}-sim32-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Exec succeeded"); // This is important, otherwise we'll end up executing the catch-all exec-% target + writer.WriteLine (); + + writer.WriteTarget ("exec{0}-bcl-sim64-{1}", "exec{0}-sim64-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Exec succeeded"); // This is important, otherwise we'll end up executing the catch-all exec-% target + writer.WriteLine (); + } + } + } + + // build dev project target + if (target.IsBCLProject) { + writer.WriteTarget ("build{0}-bcl-dev{2}-{1}", "build{0}-dev-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Build succeeded"); // This is important, otherwise we'll end up executing the catch-all clean-% target + writer.WriteLine (); + } + writer.WriteTarget ("build{0}-dev{3}-{1}", "{2} xharness/xharness.exe", make_escaped_suffix, make_escaped_name, target.ProjectPath.Replace (" ", "\\ "), target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q_XBUILD) $(SYSTEM_XBUILD) \"/property:Configuration=$(CONFIG)\" \"/property:Platform=iPhone\" /t:Build $(XBUILD_VERBOSITY) \"{0}\"", target.ProjectPath); + writer.WriteLine (); + + if (target is ClassicTarget) { + // target that builds both Classic+Unified + writer.WriteTarget ("build{0}-dev-{1}", "build{0}-devclassic-{1} build{0}-devunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Build succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + } + + // clean dev project target + if (target.IsBCLProject) { + writer.WriteTarget ("clean{0}-bcl-dev{2}-{1}", "clean{0}-dev-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Clean succeeded"); // This is important, otherwise we'll end up executing the catch-all clean-% target + writer.WriteLine (); + } + writer.WriteTarget ("clean{0}-dev{2}-{1}", string.Empty, make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q_XBUILD) $(SYSTEM_XBUILD) \"/property:Configuration=$(CONFIG)\" \"/property:Platform=iPhone\" /t:Clean $(XBUILD_VERBOSITY) \"{0}\"", target.ProjectPath); + writer.WriteLine (); + + if (target.IsExe) { + // install dev project target + if (target.IsBCLProject) { + writer.WriteTarget ("install{0}-bcl-dev{2}-{1}", "install{0}-dev-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Install succeeded"); // This is important, otherwise we'll end up executing the catch-all install-% target + writer.WriteLine (); + } + writer.WriteTarget ("install{0}-dev{2}-{1}", "xharness/xharness.exe", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --install \"{0}\" --target {1}-device --sdkroot $(XCODE_DEVELOPER_ROOT) --configuration $(CONFIG)", target.ProjectPath, target.Platform); + writer.WriteLine (); + + // run dev project target + if (target.IsBCLProject) { + writer.WriteTarget ("run{0}-bcl-dev{2}-{1}", "run{0}-dev-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + } + writer.WriteTarget ("run{0}-dev{2}-{1}", "xharness/xharness.exe", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-dev{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) install{0}-dev{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-dev{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine (); + + // exec dev project target + if (target.IsBCLProject) { + writer.WriteTarget ("exec{0}-bcl-dev{2}-{1}", "exec{0}-dev{2}-{1}", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) echo Exec succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + } + writer.WriteTarget ("exec{0}-dev{2}-{1}", "xharness/xharness.exe", make_escaped_suffix, make_escaped_name, target.MakefileWhereSuffix); + writer.WriteLine ("\t$(Q) rm -f \"$@.log\""); + writer.WriteLine ("\t$(Q) $(SYSTEM_MONO) --debug xharness/xharness.exe $(XHARNESS_VERBOSITY) --run \"{0}\" --target {1}-device --sdkroot $(XCODE_DEVELOPER_ROOT) --logfile \"$@.log\" --configuration $(CONFIG)", target.ProjectPath, target.Platform); + writer.WriteLine (); + + if (target is ClassicTarget) { + // target that runs both Classic+Unified + writer.WriteTarget ("run{0}-dev-{1}", string.Empty, make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) rm -f \".$@-failure.stamp\""); + writer.WriteLine ("\t$(Q) $(MAKE) build{0}-devclassic-{1} build{0}-devunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) install{0}-devclassic-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-devclassic-{1} || echo \"exec{0}-devclassic-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) install{0}-devunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) exec{0}-devunified-{1} || echo \"exec{0}-devunified-{1} failed\" >> \".$@-failure.stamp\"", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + // compat targets for finger memory + writer.WriteTarget ("run-devcompat-{1}", "run-ios-devclassic-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + + writer.WriteTarget ("run-devdual-{1}", "run-ios-devunified-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + } + } + + // targets that does both sim and device + if (target.IsExe && !(target is UnifiedTarget) /* exclude Unified so that we don't end up duplicating these targets */) { + // build target + writer.WriteTarget ("build{0}-{1}", "build{0}-dev-{1} build{0}-sim-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Build succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + // run target + writer.WriteTarget ("run{0}-{1}", "run{0}-dev-{1} run{0}-sim-{1}", make_escaped_suffix, make_escaped_name); + writer.WriteLine ("\t$(Q) echo Run succeeded"); // This is important, otherwise we'll end up executing the catch-all run-% target + writer.WriteLine (); + } + } + + writer.WriteLine ("# Container targets that run multiple test projects"); + writer.WriteLine (); + writer.WriteLine ("run-local:"); // run every single test we have everywhere + writer.WriteLine ("\t$(Q) rm -rf \".$@-failure.stamp\""); + foreach (var target in allTargets) { + if (!target.IsExe) + continue; + + if (target is ClassicTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-simclassic-{1}\" || echo \"run{0}-simclassic-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-devclassic-{1}\" || echo \"run{0}-devclassic-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + } else if (target is UnifiedTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-simunified-{1}\" || echo \"run{0}-simunified-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-devunified-{1}\" || echo \"run{0}-devunified-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + } else { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-sim-{1}\" || echo \"run{0}-sim-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-dev-{1}\" || echo \"run{0}-dev-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name); + } + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + + writer.WriteLine (); + writer.WriteLine ("run-sim run-all-sim:"); // run every single test we have in the simulator + writer.WriteLine ("\t$(Q) rm -rf \".$@-failure.stamp\""); + foreach (var target in allTargets) { + if (!target.IsExe) + continue; + + if (target is ClassicTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-simcompat-{1}\" || echo \"run{0}-simcompat-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + } else if (target is UnifiedTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-simunified-{1}\" || echo \"run{0}-simunified-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + } else { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-sim-{1}\" || echo \"run{0}-sim-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name); + } + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + + writer.WriteLine (); + writer.WriteLine ("run-dev run-all-dev:"); // run every single test we have on device + writer.WriteLine ("\t$(Q) rm -rf \".$@-failure.stamp\""); + foreach (var target in allTargets) { + if (!target.IsExe) + continue; + + if (target is ClassicTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-devcompat-{1}\" || echo \"run{0}-devcompat-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + } else if (target is UnifiedTarget) { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-devunified-{1}\" || echo \"run{0}-devunified-{1} failed\" >> \".$@-failure.stamp\"", "-ios", target.Name); + } else { + writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-dev-{1}\" || echo \"run{0}-dev-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name); + } + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + + foreach (var mode in new string [] { "sim", "dev" }) { + WriteCollectionTarget (writer, "run-ios-" + mode, allTargets.Where ((v) => v.IsExe && (v is ClassicTarget || v is UnifiedTarget)), mode); + WriteCollectionTarget (writer, "run-tvos-" + mode, tvos_targets.Where ((v) => v.IsExe), mode); + WriteCollectionTarget (writer, "run-watchos-" + mode, watchos_targets.Where ((v) => v.IsExe), mode); + } + + writer.WriteLine (); + writer.WriteLine ("build build-all:"); // build everything + writer.WriteLine ("\t$(Q) rm -rf \".$@-failure.stamp\""); + foreach (var target in classic_targets) { + if (!target.IsExe) + continue; + + writer.WriteLine ("\t$(Q) $(MAKE) \"build-sim-{0}\" \"build-dev-{0}\" || echo \"build-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + + // targets that run all platforms + writer.WriteLine (); + foreach (var target in classic_targets) { + var make_escaped_name = target.Name.Replace (" ", "\\ "); + + writer.WriteTarget ("build-sim-{0}", "build-ios-simclassic-{0} build-ios-simunified-{0} build-tvos-sim-{0} build-watchos-sim-{0}", make_escaped_name); + writer.WriteLine ("\t$(Q) echo Simulator builds succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + + writer.WriteTarget ("build-dev-{0}", "build-ios-devclassic-{0} build-ios-devunified-{0} build-tvos-dev-{0} build-watchos-dev-{0}", make_escaped_name); + writer.WriteLine ("\t$(Q) echo Device builds succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + + writer.WriteTarget ("build-{0}", "build-sim-{0} build-dev-{0}", make_escaped_name); + writer.WriteLine ("\t$(Q) echo Build succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target + writer.WriteLine (); + + writer.WriteTarget ("run-sim-{0}", "build-sim-{0}", make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-simclassic-{0}\" || echo \"exec-sim-iosclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + writer.WriteTarget ("run-dev-{0}", "build-dev-{0}", make_escaped_name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-devclassic-{0}\" || echo \"install-ios-devclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-devclassic-{0}\" || echo \"exec-ios-devclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-devunified-{0}\" || echo \"install-ios-devunified-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-devunified-{0}\" || echo \"exec-ios-devunified-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-tvos-dev-{0}\" || echo \"install-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-dev-{0}\" || echo \"exec-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-watchos-dev-{0}\" || echo \"install-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-dev-{0}\" || echo \"exec-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + writer.WriteTarget ("run-{0}", "build-{0}", make_escaped_name); + // sim + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-simclassic-{0}\" || echo \"exec-sim-iosclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + // dev + writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-devclassic-{0}\" || echo \"install-ios-devclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-devclassic-{0}\" || echo \"exec-ios-devclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-devunified-{0}\" || echo \"install-ios-devunified-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-devunified-{0}\" || echo \"exec-ios-devunified-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-tvos-dev-{0}\" || echo \"install-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-dev-{0}\" || echo \"exec-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"install-watchos-dev-{0}\" || echo \"install-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-dev-{0}\" || echo \"exec-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + // Wrench needs a slightly different approach, because we want to run some tests, even if other tests failed to build + // (the default is to build all, then run all if everything built). The problem is that there's no way (that I've found) + // to make the build parallelizable and support the wrench mode at the same time. + + writer.WriteLine ("wrenchhelper-{0}:", make_escaped_name); + writer.WriteLine ("\t$(Q) rm -f \".$@-failure.stamp\" \".$@-ios-simclassic-build-failure.stamp\" \".$@-ios-simunified-build-failure.stamp\" \".$@-tvos-sim-build-failure.stamp\" \".$@-watchos-sim-build-failure.stamp\""); + writer.WriteLine ("\t$(Q) echo \"@MonkeyWrench: SetSummary:\""); + // first build (serialized) + writer.WriteLine ("\t$(Q) $(MAKE) \"build-ios-simclassic-{0}\" || echo \"@MonkeyWrench: AddSummary: classic failed to build
\" >> \".$@-ios-simclassic-build-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"build-ios-simunified-{0}\" || echo \"@MonkeyWrench: AddSummary: unified failed to build
\" >> \".$@-ios-simunified-build-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) $(MAKE) \"build-tvos-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: tvos failed to build
\" >> \".$@-tvos-sim-build-failure.stamp\"", target.Name); + if (harness.INCLUDE_WATCH) + writer.WriteLine ("\t$(Q) $(MAKE) \"build-watchos-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: watchos failed to build
\" >> \".$@-watchos-sim-build-failure.stamp\"", target.Name); + // then run + writer.WriteLine ("\t$(Q) (test -e \".$@-ios-simclassic-build-failure.stamp\" && cat \".$@-ios-simclassic-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-ios-simclassic-{0}\" || echo \"exec-sim-iosclassic-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) (test -e \".$@-ios-simunified-build-failure.stamp\" && cat \".$@-ios-simunified-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) test -e \".$@-ios-simunified-build-failure.stamp\" || $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + writer.WriteLine ("\t$(Q) (test -e \".$@-tvos-sim-build-failure.stamp\" && cat \".$@-tvos-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + if (harness.INCLUDE_WATCH) { + if (harness.DisableWatchOSOnWrench) { + writer.WriteLine ("\t$(Q) (test -e \".$@-watchos-sim-build-failure.stamp\" && cat \".$@-watchos-sim-build-failure.stamp\" ) || $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" ", target.Name); + } else { + writer.WriteLine ("\t$(Q) (test -e \".$@-watchos-sim-build-failure.stamp\" && cat \".$@-watchos-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name); + } + } + writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi"); + writer.WriteLine (); + + } + + writer.WriteLine (); + } + } + } +} + diff --git a/tests/xharness/PListExtensions.cs b/tests/xharness/PListExtensions.cs new file mode 100644 index 000000000000..49233de2c11f --- /dev/null +++ b/tests/xharness/PListExtensions.cs @@ -0,0 +1,110 @@ +using System; +using System.IO; +using System.Xml; + +namespace xharness +{ + static class PListExtensions + { + public static void LoadWithoutNetworkAccess (this XmlDocument doc, string filename) + { + using (var fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) { + var settings = new XmlReaderSettings () + { + XmlResolver = null, + DtdProcessing = DtdProcessing.Parse, + }; + using (var reader = XmlReader.Create (fs, settings)) { + doc.Load (reader); + } + } + } + + public static void SetMinimumOSVersion (this XmlDocument plist, string value) + { + SetPListStringValue (plist, "MinimumOSVersion", value); + } + + public static string GetMinimumOSVersion (this XmlDocument plist) + { + return GetPListStringValue (plist, "MinimumOSVersion"); + } + + public static void SetCFBundleIdentifier (this XmlDocument plist, string value) + { + SetPListStringValue (plist, "CFBundleIdentifier", value); + } + + public static void SetCFBundleName (this XmlDocument plist, string value) + { + SetPListStringValue (plist, "CFBundleName", value); + } + + public static void SetUIDeviceFamily (this XmlDocument plist, params int[] families) + { + SetPListArrayOfIntegerValues (plist, "UIDeviceFamily", families); + } + + public static string GetCFBundleIdentifier (this XmlDocument plist) + { + return GetPListStringValue (plist, "CFBundleIdentifier"); + } + + public static string GetPListStringValue (this XmlDocument plist, string node) + { + return plist.SelectSingleNode ("//dict/key[text()='" + node + "']").NextSibling.InnerText; + } + + public static void SetPListStringValue (this XmlDocument plist, string node, string value) + { + plist.SelectSingleNode ("//dict/key[text()='" + node + "']").NextSibling.InnerText = value; + } + + public static void AddPListStringValue (this XmlDocument plist, string node, string value) + { + var keyElement = plist.CreateElement ("key"); + keyElement.InnerText = node; + var valueElement = plist.CreateElement ("string"); + valueElement.InnerText = value; + var root = plist.SelectSingleNode ("//dict"); + root.AppendChild (keyElement); + root.AppendChild (valueElement); + } + + public static void AddPListKeyValuePair (this XmlDocument plist, string node, string valueType, string value) + { + var keyElement = plist.CreateElement ("key"); + keyElement.InnerText = node; + var valueElement = plist.CreateElement (valueType); + valueElement.InnerXml = value; + var root = plist.SelectSingleNode ("//dict"); + root.AppendChild (keyElement); + root.AppendChild (valueElement); + } + + public static void SetPListArrayOfIntegerValues (this XmlDocument plist, string node, params int[] values) + { + var key = plist.SelectSingleNode ("//dict/key[text()='" + node + "']"); + key.ParentNode.RemoveChild (key.NextSibling); + var array = plist.CreateElement ("array"); + foreach (var value in values) { + var element = plist.CreateElement ("integer"); + element.InnerText = value.ToString (); + array.AppendChild (element); + } + key.ParentNode.InsertAfter (array, key); + } + + public static void RemoveUIRequiredDeviceCapabilities (this XmlDocument plist) + { + var key = plist.SelectSingleNode ("//dict/key[text()='UIRequiredDeviceCapabilities']"); + key.ParentNode.RemoveChild (key.NextSibling); + key.ParentNode.RemoveChild (key); + } + + public static bool ContainsKey (this XmlDocument plist, string key) + { + return plist.SelectSingleNode ("//dict/key[text()='" + key + "']") != null; + } + } +} diff --git a/tests/xharness/Program.cs b/tests/xharness/Program.cs new file mode 100644 index 000000000000..121e1339fe82 --- /dev/null +++ b/tests/xharness/Program.cs @@ -0,0 +1,58 @@ +using System; + +using Mono.Options; + +namespace xharness +{ + class MainClass + { + public static int Main (string[] args) + { + var harness = new Harness (); + + Action showHelp = null; + var os = new OptionSet () { + { "h|?|help", "Displays the help", (v) => showHelp () }, + { "v|verbose", "Show verbose output", (v) => harness.Verbosity++ }, + // Configure + { "mac", "Configure for Xamarin.Mac instead of iOS.", (v) => harness.Mac = true }, + { "configure", "Creates project files and makefiles.", (v) => harness.Action = HarnessAction.Configure }, + { "autoconf", "Automatically decide what to configure.", (v) => harness.AutoConf = true }, + { "rootdir=", "The root directory for the tests.", (v) => harness.RootDirectory = v }, + { "project=", "Add a project file to process. This can be specified multiple times.", (v) => harness.TestProjects.Add (v) }, + { "watchos-container-template=", "The directory to use as a template for a watchos container app.", (v) => harness.WatchOSContainerTemplate = v }, + { "watchos-app-template=", "The directory to use as a template for a watchos app.", (v) => harness.WatchOSAppTemplate = v }, + // Run + { "run=", "Executes a project.", (v) => + { + harness.Action = HarnessAction.Run; + harness.TestProjects.Add (v); + } + }, + { "install=", "Installs a project.", (v) => + { + harness.Action = HarnessAction.Install; + harness.TestProjects.Add (v); + } + }, + { "sdkroot=", "Where Xcode is", (v) => harness.SdkRoot = v }, + { "target=", "Where to run the project ([ios|watchos|tvos]-[device|simulator|simulator-32|simulator-64]).", (v) => harness.Target = v }, + { "configuration=", "Which configuration to run (defaults to Debug).", (v) => harness.Configuration = v }, + { "logfile=", "Where to store the log.", (v) => harness.LogFile = v }, + { "timeout=", "Timeout for a test run (in minutes). Default is 10 minutes.", (v) => harness.Timeout = double.Parse (v) }, + }; + + showHelp = () => { + os.WriteOptionDescriptions (Console.Out); + System.Environment.Exit (0); + }; + + var input = os.Parse (args); + if (input.Count > 0) + throw new Exception (string.Format ("Unknown arguments: {0}", string.Join (", ", input.ToArray ()))); + if (harness.Action == HarnessAction.None) + showHelp (); + return harness.Execute (); + } + } +} diff --git a/tests/xharness/ProjectFileExtensions.cs b/tests/xharness/ProjectFileExtensions.cs new file mode 100644 index 000000000000..e33aac86aaba --- /dev/null +++ b/tests/xharness/ProjectFileExtensions.cs @@ -0,0 +1,514 @@ +using System; +using System.Xml; + +namespace xharness +{ + static class ProjectFileExtensions { + const string MSBuild_Namespace = "http://schemas.microsoft.com/developer/msbuild/2003"; + + public static void SetProjectTypeGuids (this XmlDocument csproj, string value) + { + SetNode (csproj, "ProjectTypeGuids", value); + } + + public static string GetProjectGuid (this XmlDocument csproj) + { + return csproj.SelectSingleNode ("/*/*/*[local-name() = 'ProjectGuid']").InnerText; + } + + public static void SetProjectGuid (this XmlDocument csproj, string value) + { + csproj.SelectSingleNode ("/*/*/*[local-name() = 'ProjectGuid']").InnerText = value; + } + + public static string GetOutputType (this XmlDocument csproj) + { + return csproj.SelectSingleNode ("/*/*/*[local-name() = 'OutputType']").InnerText; + } + + public static void SetOutputType (this XmlDocument csproj, string value) + { + csproj.SelectSingleNode ("/*/*/*[local-name() = 'OutputType']").InnerText = value; + } + + static string[] eqsplitter = new string[] { "==" }; + static char[] pipesplitter = new char[] { '|' }; + static char[] trimchars = new char[] { '\'', ' ' }; + + static void ParseConditions (this XmlNode node, out string platform, out string configuration) + { + // This parses the platform/configuration out of conditions like this: + // + // Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' " + // + platform = "Any CPU"; + configuration = "Debug"; + while (node != null) { + if (node.Attributes != null) { + var conditionAttribute = node.Attributes ["Condition"]; + if (conditionAttribute != null) { + var condition = conditionAttribute.Value; + var eqsplit = condition.Split (eqsplitter, StringSplitOptions.None); + if (eqsplit.Length == 2) { + var left = eqsplit [0].Trim (trimchars).Split (pipesplitter); + var right = eqsplit [1].Trim (trimchars).Split (pipesplitter); + if (left.Length == right.Length) { + for (int i = 0; i < left.Length; i++) { + switch (left [i]) { + case "$(Configuration)": + configuration = right [i]; + break; + case "$(Platform)": + platform = right [i]; + break; + default: + throw new Exception (string.Format ("Unknown condition logic: {0}", left [i])); + } + } + } + } + + if (string.IsNullOrEmpty (platform) || string.IsNullOrEmpty (configuration)) + throw new Exception (string.Format ("Could not parse the condition: {0}", conditionAttribute.Value)); + } + } + node = node.ParentNode; + } + + if (string.IsNullOrEmpty (platform) || string.IsNullOrEmpty (configuration)) + throw new Exception ("Could not find a condition attribute."); + } + + public static void SetOutputPath (this XmlDocument csproj, string value) + { + var nodes = csproj.SelectNodes ("/*/*/*[local-name() = 'OutputPath']"); + if (nodes.Count == 0) + throw new Exception ("Could not find node OutputPath"); + foreach (XmlNode n in nodes) { + // OutputPath needs to be expanded, otherwise Xamarin Studio isn't able to launch the project. + string platform, configuration; + ParseConditions (n, out platform, out configuration); + n.InnerText = value.Replace ("$(Platform)", platform).Replace ("$(Configuration)", configuration); + } + } + + static bool IsNodeApplicable (XmlNode node, string platform, string configuration) + { + while (node != null) { + if (!EvaluateCondition (node, platform, configuration)) + return false; + node = node.ParentNode; + } + return true; + } + + static bool EvaluateCondition (XmlNode node, string platform, string configuration) + { + if (node.Attributes == null) + return true; + + var condition = node.Attributes ["Condition"]; + if (condition == null) + return true; + + var conditionValue = condition.Value; + conditionValue = conditionValue.Replace ("$(Configuration)", configuration).Replace ("$(Platform)", platform); + + var eqsplit = conditionValue.Split (eqsplitter, StringSplitOptions.None); + if (eqsplit.Length != 2) { + Console.WriteLine ("Could not parse condition; {0}", conditionValue); + return false; + } + + var left = eqsplit [0].Trim (trimchars); + var right = eqsplit [1].Trim (trimchars); + return left == right; + } + + public static string GetOutputPath (this XmlDocument csproj, string platform, string configuration) + { + var nodes = csproj.SelectNodes ("/*/*/*[local-name() = 'OutputPath']"); + if (nodes.Count == 0) + throw new Exception ("Could not find node OutputPath"); + + foreach (XmlNode n in nodes) { + if (IsNodeApplicable (n, platform, configuration)) + return n.InnerText; + } + throw new Exception ("Could not find OutputPath"); + } + + public static void SetIntermediateOutputPath (this XmlDocument csproj, string value) + { + var project = csproj.ChildNodes [1]; + var property_group = project.ChildNodes [0]; + + var intermediateOutputPath = csproj.CreateElement ("IntermediateOutputPath", MSBuild_Namespace); + intermediateOutputPath.InnerText = value; + property_group.AppendChild (intermediateOutputPath); + } + + public static void SetTargetFrameworkIdentifier (this XmlDocument csproj, string value) + { + SetTopLevelPropertyGroupValue (csproj, "TargetFrameworkIdentifier", value); + } + + public static void SetTopLevelPropertyGroupValue (this XmlDocument csproj, string key, string value) + { + var firstPropertyGroups = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup']")[0]; + var targetFrameworkIdentifierNode = firstPropertyGroups.SelectSingleNode (string.Format ("//*[local-name() = '{0}']", key)); + if (targetFrameworkIdentifierNode != null) + { + SetNode (csproj, key, value); + } + else + { + var mea = csproj.CreateElement (key, MSBuild_Namespace); + mea.InnerText = value; + firstPropertyGroups.AppendChild (mea); + } + } + + public static void RemoveTargetFrameworkIdentifier (this XmlDocument csproj) + { + RemoveNode (csproj, "TargetFrameworkIdentifier"); + } + + public static void SetAssemblyName (this XmlDocument csproj, string value) + { + SetNode (csproj, "AssemblyName", value); + } + + public static string GetAssemblyName (this XmlDocument csproj) + { + return csproj.SelectSingleNode ("/*/*/*[local-name() = 'AssemblyName']").InnerText; + } + + public static void SetPlatformAssembly (this XmlDocument csproj, string value) + { + SetAssemblyReference (csproj, "monotouch", value); + } + + public static void SetAssemblyReference (this XmlDocument csproj, string current, string value) + { + var project = csproj.ChildNodes [1]; + var reference = csproj.SelectSingleNode ("/*/*/*[local-name() = 'Reference' and @Include = '" + current + "']"); + if (reference != null) + reference.Attributes ["Include"].Value = value; + } + + public static void RemoveReferences (this XmlDocument csproj, string projectName) + { + var reference = csproj.SelectSingleNode ("/*/*/*[local-name() = 'Reference' and @Include = '" + projectName + "']"); + if (reference != null) + reference.ParentNode.RemoveChild (reference); + } + + public static void SetHintPath (this XmlDocument csproj, string current, string value) + { + var project = csproj.ChildNodes [1]; + var reference = csproj.SelectSingleNode ("/*/*/*[local-name() = 'Reference' and @Include = '" + current + "']"); + if (reference != null) { + var hintPath = csproj.CreateElement ("HintPath", MSBuild_Namespace); + hintPath.InnerText = value; + reference.AppendChild (hintPath); + } + } + + public static void AddCompileInclude (this XmlDocument csproj, string link, string include) + { + var compile_node = csproj.SelectSingleNode ("//*[local-name() = 'Compile']"); + var item_group = compile_node.ParentNode; + + var node = csproj.CreateElement ("Compile", MSBuild_Namespace); + var include_attribute = csproj.CreateAttribute ("Include"); + include_attribute.Value = include; + node.Attributes.Append (include_attribute); + var linkElement = csproj.CreateElement ("Link", MSBuild_Namespace); + linkElement.InnerText = link; + node.AppendChild (linkElement); + item_group.AppendChild (node); + } + + public static void SetImport (this XmlDocument csproj, string value) + { + var imports = csproj.SelectNodes ("/*/*[local-name() = 'Import']"); + if (imports.Count != 1) + throw new Exception ("More than one import"); + imports [0].Attributes ["Project"].Value = value; + } + + public static void SetExtraLinkerDefs (this XmlDocument csproj, string value) + { + var mtouchExtraArgs = csproj.SelectNodes ("//*[local-name() = 'MtouchExtraArgs']"); + foreach (XmlNode mea in mtouchExtraArgs) + mea.InnerText = mea.InnerText.Replace ("extra-linker-defs.xml", value); + var nones = csproj.SelectNodes ("//*[local-name() = 'None' and @Include = 'extra-linker-defs.xml']"); + foreach (XmlNode none in nones) + none.Attributes ["Include"].Value = value; + } + + public static void AddExtraMtouchArgs (this XmlDocument csproj, string value, string platform, string configuration) + { + var mtouchExtraArgs = csproj.SelectNodes ("//*[local-name() = 'MtouchExtraArgs']"); + var found = false; + foreach (XmlNode mea in mtouchExtraArgs) { + if (!IsNodeApplicable (mea, platform, configuration)) + continue; + + mea.InnerText += " " + value; + found = true; + } + + if (found) + return; + + // Not all projects have a MtouchExtraArgs node, so create one of none was found. + var propertyGroups = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup' and @Condition]"); + foreach (XmlNode pg in propertyGroups) { + if (!EvaluateCondition (pg, platform, configuration)) + continue; + + var mea = csproj.CreateElement ("MtouchExtraArgs", MSBuild_Namespace); + mea.InnerText = value; + pg.AppendChild (mea); + } + } + + public static void SetMtouchUseLlvm (this XmlDocument csproj, bool value, string platform, string configuration) + { + SetNode (csproj, "MtouchUseLlvm", true ? "true" : "false", platform, configuration); + } + + public static void SetMtouchUseBitcode (this XmlDocument csproj, bool value, string platform, string configuration) + { + SetNode (csproj, "MtouchEnableBitcode", true ? "true" : "false", platform, configuration); + } + + public static void SetNode (this XmlDocument csproj, string node, string value, string platform, string configuration) + { + var projnode = csproj.SelectNodes ("//*[local-name() = '" + node + "']"); + var found = false; + foreach (XmlNode xmlnode in projnode) { + if (!IsNodeApplicable (xmlnode, platform, configuration)) + continue; + + xmlnode.InnerText = value; + found = true; + } + + if (found) + return; + + // Not all projects have a MtouchExtraArgs node, so create one of none was found. + var propertyGroups = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup' and @Condition]"); + foreach (XmlNode pg in propertyGroups) { + if (!EvaluateCondition (pg, platform, configuration)) + continue; + + var mea = csproj.CreateElement (node, MSBuild_Namespace); + mea.InnerText = value; + pg.AppendChild (mea); + } + } + + + public static string GetImport (this XmlDocument csproj) + { + var imports = csproj.SelectNodes ("/*/*[local-name() = 'Import']"); + if (imports.Count != 1) + throw new Exception ("More than one import"); + return imports [0].Attributes ["Project"].Value; + } + + public static void FixProjectReferences (this XmlDocument csproj, string suffix) + { + var nodes = csproj.SelectNodes ("/*/*/*[local-name() = 'ProjectReference']"); + if (nodes.Count == 0) + return; + foreach (XmlNode n in nodes) { + var include = n.Attributes ["Include"]; + include.Value = include.Value.Replace (".csproj", suffix + ".csproj"); + include.Value = include.Value.Replace (".fsproj", suffix + ".fsproj"); + } + } + + public static void FixTestLibrariesReferences (this XmlDocument csproj, string platform) + { + var nodes = csproj.SelectNodes ("//*[local-name() = 'ObjcBindingNativeLibrary']"); + foreach (XmlNode node in nodes) { + var includeAttribute = node.Attributes ["Include"]; + if (includeAttribute != null) + includeAttribute.Value = includeAttribute.Value.Replace ("test-libraries\\.libs\\ios\\libtest.a", "test-libraries\\.libs\\" + platform + "\\libtest.a"); + } + nodes = csproj.SelectNodes ("//*[local-name() = 'Target' and @Name = 'BeforeBuild']"); + foreach (XmlNode node in nodes) { + var outputsAttribute = node.Attributes ["Outputs"]; + if (outputsAttribute != null) + outputsAttribute.Value = outputsAttribute.Value.Replace ("test-libraries\\.libs\\ios\\libtest.a", "test-libraries\\.libs\\" + platform + "\\libtest.a"); + } + } + + public static void FixArchitectures (this XmlDocument csproj, string simulator_arch, string device_arch) + { + var nodes = csproj.SelectNodes ("/*/*/*[local-name() = 'MtouchArch']"); + if (nodes.Count == 0) + throw new Exception (string.Format ("Could not find MtouchArch at all")); + foreach (XmlNode n in nodes) { + switch (n.InnerText.ToLower ()) { + case "i386": + case "x86_64": + n.InnerText = simulator_arch; + break; + case "armv7": + case "armv7s": + case "arm64": + n.InnerText = device_arch; + break; + default: + throw new NotImplementedException (string.Format ("Unhandled architecture: {0}", n.Value)); + + } + } + } + + public static void FindAndReplace (this XmlDocument csproj, string find, string replace) + { + FindAndReplace (csproj.ChildNodes, find, replace); + } + + static void FindAndReplace (XmlNode node, string find, string replace) + { + if (node.HasChildNodes) { + FindAndReplace (node.ChildNodes, find, replace); + } else { + if (node.NodeType == XmlNodeType.Text) + node.InnerText = node.InnerText.Replace (find, replace); + } + if (node.Attributes != null) { + foreach (XmlAttribute attrib in node.Attributes) + attrib.Value = attrib.Value.Replace (find, replace); + } + } + + static void FindAndReplace (XmlNodeList nodes, string find, string replace) + { + foreach (XmlNode node in nodes) + FindAndReplace (node, find, replace); + } + + public static void FixInfoPListInclude (this XmlDocument csproj, string suffix) + { + var import = csproj.SelectSingleNode ("/*/*/*[local-name() = 'None' and @Include = 'Info.plist']"); + import.Attributes ["Include"].Value = "Info" + suffix + ".plist"; + var logicalName = csproj.CreateElement ("LogicalName", MSBuild_Namespace); + logicalName.InnerText = "Info.plist"; + import.AppendChild (logicalName); + } + + public static string GetInfoPListInclude (this XmlDocument csproj) + { + var logicalNames = csproj.SelectNodes ("//*[local-name() = 'LogicalName']"); + foreach (XmlNode ln in logicalNames) { + if (ln.InnerText != "Info.plist") + continue; + return ln.ParentNode.Attributes ["Include"].Value; + } + var nones = csproj.SelectNodes ("//*[local-name() = 'None' and @Include = 'Info.plist']"); + if (nones.Count > 0) + return "Info.plist"; + throw new Exception ("Could not find Info.plist include"); + } + + public static void SetProjectReferenceValue (this XmlDocument csproj, string projectInclude, string node, string value) + { + var nameNode = csproj.SelectSingleNode ("//*[local-name() = 'ProjectReference' and @Include = '" + projectInclude + "']/*[local-name() = '" + node + "']"); + nameNode.InnerText = value; + } + + public static void CreateProjectReferenceValue (this XmlDocument csproj, string existingInclude, string path, string guid, string name) + { + var referenceNode = csproj.SelectSingleNode ("//*[local-name() = 'Reference' and @Include = '" + existingInclude + "']"); + var projectReferenceNode = csproj.CreateElement ("ProjectReference", MSBuild_Namespace); + var includeAttribute = csproj.CreateAttribute ("Include"); + includeAttribute.Value = path.Replace ('/', '\\'); + projectReferenceNode.Attributes.Append (includeAttribute); + var projectNode = csproj.CreateElement ("Project", MSBuild_Namespace); + projectNode.InnerText = guid; + projectReferenceNode.AppendChild (projectNode); + var nameNode = csproj.CreateElement ("Name", MSBuild_Namespace); + nameNode.InnerText = name; + projectReferenceNode.AppendChild (nameNode); + + XmlNode itemGroup; + if (referenceNode != null) { + itemGroup = referenceNode.ParentNode; + referenceNode.ParentNode.RemoveChild (referenceNode); + } else { + itemGroup = csproj.CreateElement ("ItemGroup", MSBuild_Namespace); + csproj.SelectSingleNode ("//*[local-name() = 'Project']").AppendChild (itemGroup); + } + itemGroup.AppendChild (projectReferenceNode); + } + + public static void AddAdditionalDefines (this XmlDocument csproj, string value) + { + var mainPropertyGroup = csproj.SelectSingleNode ("//*[local-name() = 'PropertyGroup' and not(@Condition)]"); + var mainDefine = mainPropertyGroup.SelectSingleNode ("/*[local-name() = 'DefineConstants']"); + if (mainDefine == null) { + mainDefine = csproj.CreateElement ("DefineConstants", MSBuild_Namespace); + mainDefine.InnerText = value; + mainPropertyGroup.AppendChild (mainDefine); + } else { + mainDefine.InnerText = mainDefine.InnerText + ";" + value; + } + + // make sure all other DefineConstants include the main one + var otherDefines = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup' and @Condition]/*[local-name() = 'DefineConstants']"); + foreach (XmlNode def in otherDefines) { + if (!def.InnerText.Contains ("$(DefineConstants")) + def.InnerText = def.InnerText + ";$(DefineConstants)"; + } + } + + public static void SetNode (this XmlDocument csproj, string node, string value) + { + var nodes = csproj.SelectNodes ("/*/*/*[local-name() = '" + node + "']"); + if (nodes.Count == 0) + throw new Exception (string.Format ("Could not find node {0}", node)); + foreach (XmlNode n in nodes) { + n.InnerText = value; + } + } + + public static void RemoveNode (this XmlDocument csproj, string node) + { + var nodes = csproj.SelectNodes ("/*/*/*[local-name() = '" + node + "']"); + if (nodes.Count == 0) + throw new Exception (string.Format ("Could not find node {0}", node)); + foreach (XmlNode n in nodes) { + n.ParentNode.RemoveChild (n); + } + } + + public static void CloneConfiguration (this XmlDocument csproj, string platform, string configuration, string new_configuration) + { + var projnode = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup']"); + foreach (XmlNode xmlnode in projnode) { + if (xmlnode.Attributes ["Condition"] == null) + continue; + if (!IsNodeApplicable (xmlnode, platform, configuration)) + continue; + + var clone = xmlnode.Clone (); + var condition = clone.Attributes ["Condition"]; + condition.InnerText = condition.InnerText.Replace (configuration, new_configuration); + xmlnode.ParentNode.InsertAfter (clone, xmlnode); + return; + } + + throw new Exception ("Configuration not found."); + } + } +} + diff --git a/tests/xharness/Properties/AssemblyInfo.cs b/tests/xharness/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..53959019bf9b --- /dev/null +++ b/tests/xharness/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("xharness")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("Xamarin")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("(C) Rolf Bjarne Kvinge")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/tests/xharness/SimpleHttpListener.cs b/tests/xharness/SimpleHttpListener.cs new file mode 100644 index 000000000000..7ec53ba996dd --- /dev/null +++ b/tests/xharness/SimpleHttpListener.cs @@ -0,0 +1,105 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace xharness +{ + public class SimpleHttpListener : SimpleListener + { + HttpListener server; + + public override void Initialize () + { + server = new HttpListener (); + + if (Port != 0) + throw new NotImplementedException (); + + // Try and find an unused port + int attemptsLeft = 50; + Random r = new Random ((int) DateTime.Now.Ticks); + while (attemptsLeft-- > 0) { + var newPort = r.Next (49152, 65535); // The suggested range for dynamic ports is 49152-65535 (IANA) + server.Prefixes.Clear (); + server.Prefixes.Add ("http://*:" + newPort + "/"); + try { + server.Start (); + Port = newPort; + break; + } catch (Exception ex) { + Console.WriteLine ("Failed to listen on port {0}: {1}", newPort, ex.Message); + } + } + } + + protected override void Stop () + { + server.Stop (); + } + + protected override void Start () + { + bool processed; + + try { + Console.WriteLine ("Test log server listening on: {0}:{1}", Address, Port); + do { + var context = server.GetContext (); + processed = Processing (context); + } while (!AutoExit || !processed); + } catch (Exception e) { + var se = e as SocketException; + if (se == null || se.SocketErrorCode != SocketError.Interrupted) + Console.WriteLine ("[{0}] : {1}", DateTime.Now, e); + } finally { + try { + server.Stop (); + } finally { + stopped.Set (); + } + } + } + + bool Processing (HttpListenerContext context) + { + var finished = false; + + var request = context.Request; + var response = "OK"; + + var stream = request.InputStream; + var data = string.Empty; + using (var reader = new StreamReader (stream)) + data = reader.ReadToEnd (); + stream.Close (); + + switch (request.RawUrl) { + case "/Start": + Connected (request.RemoteEndPoint.ToString ()); + break; + case "/Finish": + using (var writer = new StreamWriter (OutputStream)) { + writer.Write (data); + writer.Flush (); + } + finished = true; + break; + default: + Console.WriteLine ("Unknown upload url: {0}", request.RawUrl); + response = $"Unknown upload url: {request.RawUrl}"; + break; + } + + var buf = System.Text.Encoding.UTF8.GetBytes (response); + context.Response.ContentLength64 = buf.Length; + context.Response.OutputStream.Write (buf, 0, buf.Length); + context.Response.OutputStream.Close (); + context.Response.Close (); + + return finished; + } + } +} + diff --git a/tests/xharness/SimpleListener.cs b/tests/xharness/SimpleListener.cs new file mode 100644 index 000000000000..91ba0a465b1f --- /dev/null +++ b/tests/xharness/SimpleListener.cs @@ -0,0 +1,104 @@ +using System; +using System.Net; +using System.IO; +using System.Text; +using System.Threading; + +namespace xharness +{ + public abstract class SimpleListener : IDisposable + { + FileStream output_stream; + + protected ManualResetEvent stopped = new ManualResetEvent (false); + protected ManualResetEvent connected = new ManualResetEvent (false); + + public IPAddress Address { get; set; } + public int Port { get; set; } + public string LogPath { get; set; } + public string LogFile { get; set; } = DateTime.UtcNow.Ticks.ToString () + ".log"; + public bool AutoExit { get; set; } + + public abstract void Initialize (); + protected abstract void Start (); + protected abstract void Stop (); + + public string LogFilePath { + get { + return Path.Combine (LogPath, LogFile); + } + } + + public FileStream OutputStream { + get { + return output_stream; + } + } + + protected void Connected (string remote) + { + Console.WriteLine ("Connection from {0} saving logs to {1}", remote, LogFilePath); + connected.Set (); + + if (output_stream != null) { + output_stream.Flush (); + output_stream.Dispose (); + } + + var fs = new FileStream (LogFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); + // a few extra bits of data only available from this side + string header = String.Format ("[Local Date/Time:\t{1}]{0}[Remote Address:\t{2}]{0}", + Environment.NewLine, DateTime.Now, remote); + byte [] array = Encoding.UTF8.GetBytes (header); + fs.Write (array, 0, array.Length); + fs.Flush (); + output_stream = fs; + } + + + public void StartAsync () + { + var t = new Thread (Start) + { + IsBackground = true, + }; + t.Start (); + } + + public bool WaitForConnection (TimeSpan ts) + { + return connected.WaitOne (ts); + } + + public bool WaitForCompletion (TimeSpan ts) + { + return stopped.WaitOne (ts); + } + + public void Cancel () + { + try { + // wait a second just in case more data arrives. + if (!stopped.WaitOne (TimeSpan.FromSeconds (1))) + Stop (); + } catch { + // We might have stopped already, so just ignore any exceptions. + } + } + +#region IDisposable Support + protected virtual void Dispose (bool disposing) + { + if (output_stream != null) + output_stream.Dispose (); + } + + public void Dispose () + { + Dispose (true); + } +#endregion + + } +} + diff --git a/tests/xharness/SimpleTcpListener.cs b/tests/xharness/SimpleTcpListener.cs new file mode 100644 index 000000000000..50f05a1c0a57 --- /dev/null +++ b/tests/xharness/SimpleTcpListener.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace xharness +{ + public class SimpleTcpListener : SimpleListener + { + byte[] buffer = new byte [16 * 1024]; + TcpListener server; + + protected override void Stop () + { + server.Stop (); + } + + public override void Initialize () + { + server = new TcpListener (Address, Port); + server.Start (); + + if (Port == 0) + Port = ((IPEndPoint) server.LocalEndpoint).Port; + } + + protected override void Start () + { + bool processed; + + try { + do { + Console.WriteLine ("Test log server listening on: {0}:{1}", Address, Port); + using (TcpClient client = server.AcceptTcpClient ()) { + processed = Processing (client); + } + } while (!AutoExit || !processed); + }catch (Exception e) { + var se = e as SocketException; + if (se == null || se.SocketErrorCode != SocketError.Interrupted) + Console.WriteLine ("[{0}] : {1}", DateTime.Now, e); + } finally { + try { + server.Stop (); + } finally { + stopped.Set (); + } + } + } + + bool Processing (TcpClient client) + { + Connected (client.Client.RemoteEndPoint.ToString ()); + FileStream fs = OutputStream; + // now simply copy what we receive + int i; + int total = 0; + NetworkStream stream = client.GetStream (); + while ((i = stream.Read (buffer, 0, buffer.Length)) != 0) { + fs.Write (buffer, 0, i); + fs.Flush (); + total += i; + } + + if (total < 16) { + // This wasn't a test run, but a connection from the app (on device) to find + // the ip address we're reachable on. + return false; + } + fs.Flush (); + return true; + } + } +} + diff --git a/tests/xharness/SolutionGenerator.cs b/tests/xharness/SolutionGenerator.cs new file mode 100644 index 000000000000..4bf97a46f8fa --- /dev/null +++ b/tests/xharness/SolutionGenerator.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using System.Text; + +namespace xharness +{ + public static class SolutionGenerator + { + static void AddProjectToSolution (Harness harness, string sln_path, TextWriter solution, string project_path, out string configurations) + { + var project = new XmlDocument (); + project.LoadWithoutNetworkAccess (project_path); + var guid = project.GetProjectGuid (); + solution.WriteLine ("Project(\"{3}\") = \"{0}\", \"{1}\", \"{2}\"", Path.GetFileNameWithoutExtension (project_path), FixProjectPath (sln_path, project_path), guid, project_path.EndsWith (".csproj") ? Target.CSharpGuid : Target.FSharpGuid); + solution.WriteLine ("EndProject"); + + configurations = string.Format ( + "\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n" + + "\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU\n" + + "\t\t{0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU\n" + + "\t\t{0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU\n" + + "\t\t{0}.Debug|iPhone.ActiveCfg = Debug|Any CPU\n" + + "\t\t{0}.Debug|iPhone.Build.0 = Debug|Any CPU\n" + + "\t\t{0}.Release-bitcode|Any CPU.ActiveCfg = Release-bitcode|Any CPU\n" + + "\t\t{0}.Release-bitcode|Any CPU.Build.0 = Release-bitcode|Any CPU\n" + + "\t\t{0}.Release-bitcode|iPhoneSimulator.ActiveCfg = Release-bitcode|Any CPU\n" + + "\t\t{0}.Release-bitcode|iPhoneSimulator.Build.0 = Release-bitcode|Any CPU\n" + + "\t\t{0}.Release-bitcode|iPhone.ActiveCfg = Release-bitcode|Any CPU\n" + + "\t\t{0}.Release-bitcode|iPhone.Build.0 = Release-bitcode|Any CPU\n" + + "\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU\n" + + "\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU\n" + + "\t\t{0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU\n" + + "\t\t{0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU\n" + + "\t\t{0}.Release|iPhone.ActiveCfg = Release|Any CPU\n" + + "\t\t{0}.Release|iPhone.Build.0 = Release|Any CPU\n", guid); + } + + static string FixProjectPath (string sln_path, string project_path) + { + var sln_dir = Path.GetDirectoryName (sln_path); + if (project_path.StartsWith (sln_dir, StringComparison.OrdinalIgnoreCase)) + project_path = project_path.Substring (sln_dir.Length + 1); + project_path = project_path.Replace ('/', '\\'); + return project_path; + } + + public static void CreateSolution (Harness harness, IEnumerable targets, string infix) + { + CreateSolution (harness, targets, null, infix); + } + + public static void CreateSolution (Harness harness, IEnumerable targets, Target exeTarget, string infix) + { + var folders = new StringBuilder (); + + var srcDirectory = Path.Combine (harness.RootDirectory, "..", "..", "xamarin-macios", "src"); + var sln_path = exeTarget == null ? Path.Combine (harness.RootDirectory, "tests-" + infix + ".sln") : Path.Combine (Path.GetDirectoryName (exeTarget.ProjectPath), Path.GetFileNameWithoutExtension (exeTarget.ProjectPath) + ".sln"); + + using (var writer = new StringWriter ()) { + writer.WriteLine (); + writer.WriteLine ("Microsoft Visual Studio Solution File, Format Version 11.00"); + writer.WriteLine ("# Visual Studio 2010"); + foreach (var target in targets) { + var w = target as WatchOSTarget; + var folderGuid = string.Empty; + var useFolders = w != null && w.IsExe && exeTarget == null; + + if (w != null && w.IsExe) { + if (exeTarget == null) { + CreateSolution (harness, targets, target, infix); // create a solution for just this test project as well + } else if (exeTarget != target) { + continue; + } + } + + if (useFolders) { + folderGuid = Guid.NewGuid ().ToString ().ToUpperInvariant (); + writer.WriteLine ("Project(\"{{2150E333-8FDC-42A3-9474-1A3956D46DE8}}\") = \"{0}\", \"{0}\", \"{{{1}}}\"", target.Name, folderGuid); + writer.WriteLine ("EndProject"); + } + + writer.WriteLine ("Project(\"{3}\") = \"{0}\", \"{1}\", \"{2}\"", Path.GetFileNameWithoutExtension (target.ProjectPath), FixProjectPath (sln_path, Path.GetFullPath (target.ProjectPath)), target.ProjectGuid, target.LanguageGuid); + writer.WriteLine ("EndProject"); + + if (w != null && w.IsExe) { + writer.WriteLine ("Project(\"{3}\") = \"{0}\", \"{1}\", \"{2}\"", Path.GetFileNameWithoutExtension (w.WatchOSExtensionProjectPath), FixProjectPath (sln_path, Path.GetFullPath (w.WatchOSExtensionProjectPath)), w.WatchOSExtensionGuid, w.LanguageGuid); + writer.WriteLine ("EndProject"); + writer.WriteLine ("Project(\"{3}\") = \"{0}\", \"{1}\", \"{2}\"", Path.GetFileNameWithoutExtension (w.WatchOSAppProjectPath), FixProjectPath (sln_path, Path.GetFullPath (w.WatchOSAppProjectPath)), w.WatchOSAppGuid, w.LanguageGuid); + writer.WriteLine ("EndProject"); + } + + if (useFolders) { + folders.AppendFormat ("\t\t{0} = {{{1}}}\n", target.ProjectGuid, folderGuid); + folders.AppendFormat ("\t\t{0} = {{{1}}}\n", w.WatchOSExtensionGuid, folderGuid); + folders.AppendFormat ("\t\t{0} = {{{1}}}\n", w.WatchOSAppGuid, folderGuid); + } + } + + // Add reference to MonoTouch.NUnitLite project + string configuration; + AddProjectToSolution (harness, sln_path, writer, Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.NUnitLite." + infix + ".csproj")), out configuration); + string configuration2 = string.Empty; + if (infix != "watchos") + AddProjectToSolution (harness, sln_path, writer, Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.Dialog-1." + infix + ".csproj")), out configuration2); + + writer.WriteLine ("Global"); + + writer.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); + writer.WriteLine ("\t\tDebug|iPhoneSimulator = Debug|iPhoneSimulator"); + writer.WriteLine ("\t\tRelease|iPhoneSimulator = Release|iPhoneSimulator"); + writer.WriteLine ("\t\tDebug|iPhone = Debug|iPhone"); + writer.WriteLine ("\t\tRelease|iPhone = Release|iPhone"); + writer.WriteLine ("\t\tRelease-bitcode|iPhone = Release-bitcode|iPhone"); + writer.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU"); + writer.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU"); + writer.WriteLine ("\tEndGlobalSection"); + + writer.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); + var exePlatforms = new string[] { "iPhone", "iPhoneSimulator" }; + var configurations = new string[] { "Debug", "Release", "Release-bitcode" }; + foreach (var target in targets) { + if (target.IsExe && exeTarget != null && target != exeTarget) + continue; + + foreach (var conf in configurations) { + if (target.IsExe) { + foreach (var platform in exePlatforms) { + writer.WriteLine ("\t\t{0}.{1}|{2}.ActiveCfg = {1}|{2}", target.ProjectGuid, conf, platform); + writer.WriteLine ("\t\t{0}.{1}|{2}.Build.0 = {1}|{2}", target.ProjectGuid, conf, platform); + + } + } else { + foreach (var platform in new string[] { "Any CPU", "iPhone", "iPhoneSimulator" }) { + writer.WriteLine ("\t\t{0}.{1}|{2}.ActiveCfg = {1}|Any CPU", target.ProjectGuid, conf, platform); + writer.WriteLine ("\t\t{0}.{1}|{2}.Build.0 = {1}|Any CPU", target.ProjectGuid, conf, platform); + } + } + } + + if (target.IsExe) { + var w = target as WatchOSTarget; + if (w != null) { + foreach (var conf in configurations) { + foreach (var platform in exePlatforms) { + writer.WriteLine ("\t\t{0}.{1}|{2}.ActiveCfg = {1}|{2}", w.WatchOSExtensionGuid, conf, platform); + writer.WriteLine ("\t\t{0}.{1}|{2}.Build.0 = {1}|{2}", w.WatchOSExtensionGuid, conf, platform); + } + } + foreach (var conf in configurations) { + foreach (var platform in exePlatforms) { + writer.WriteLine ("\t\t{0}.{1}|{2}.ActiveCfg = {1}|{2}", w.WatchOSAppGuid, conf, platform); + writer.WriteLine ("\t\t{0}.{1}|{2}.Build.0 = {1}|{2}", w.WatchOSAppGuid, conf, platform); + } + } + } + } + + } + writer.Write (configuration); + writer.Write (configuration2); + writer.WriteLine ("\tEndGlobalSection"); + + if (folders.Length > 0) { + writer.WriteLine ("\tGlobalSection(NestedProjects) = preSolution"); + writer.Write (folders.ToString ()); + writer.WriteLine ("\tEndGlobalSection"); + } + + writer.WriteLine ("EndGlobal"); + + harness.Save (writer, sln_path); + } + } + } +} + diff --git a/tests/xharness/TVOSTarget.cs b/tests/xharness/TVOSTarget.cs new file mode 100644 index 000000000000..be2b835618c0 --- /dev/null +++ b/tests/xharness/TVOSTarget.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +namespace xharness +{ + public class TVOSTarget : Target + { + public override string Suffix { + get { + return "-tvos"; + } + } + + protected override string BindingsProjectTypeGuids { + get { + return "{4A1ED743-3331-459B-915A-4B17C7B6DBB6}"; + } + } + + protected override string ProjectTypeGuids { + get { + return "{06FA79CB-D6CD-4721-BB4B-1BD202089C55}"; + } + } + + protected override string TargetFrameworkIdentifier { + get { + return "Xamarin.TVOS"; + } + } + + protected override string Imports { + get { + return IsFSharp ? "TVOS\\Xamarin.TVOS.FSharp.targets" : "TVOS\\Xamarin.TVOS.CSharp.targets"; + } + } + + protected override string BindingsImports { + get { + return IsFSharp ? "TVOS\\Xamarin.TVOS.ObjCBinding.FSharp.targets" : "TVOS\\Xamarin.TVOS.ObjCBinding.CSharp.targets"; + } + } + + public override string SimulatorArchitectures { + get { + return "x86_64"; + } + } + + public override string DeviceArchitectures { + get { + return "ARM64"; + } + } + + protected override string GetMinimumOSVersion(string templateMinimumOSVersion) + { + return "9.0"; + } + + protected override int[] UIDeviceFamily { + get { + return new int [] { 3 }; + } + } + + protected override string AdditionalDefines { + get { + return "XAMCORE_2_0;XAMCORE_3_0;"; + } + } + + public override string Platform { + get { + return "tvos"; + } + } + + protected override bool SupportsBitcode { + get { + return true; + } + } + + static Dictionary project_guids = new Dictionary (); + + protected override void ProcessProject () + { + base.ProcessProject (); + + var srcDirectory = Path.Combine (Harness.RootDirectory, "..", "..", "xamarin-macios", "src"); + + var mt_dialog_project_path = Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.Dialog-1.tvos.csproj")); + string project_guid; + if (!project_guids.TryGetValue (mt_dialog_project_path, out project_guid)) { + XmlDocument mt_dialog_project = new XmlDocument (); + mt_dialog_project.LoadWithoutNetworkAccess (mt_dialog_project_path); + project_guid = mt_dialog_project.GetProjectGuid (); + project_guids [mt_dialog_project_path] = project_guid; + } + inputProject.CreateProjectReferenceValue ("MonoTouch.Dialog-1", mt_dialog_project_path, project_guid, "MonoTouch.Dialog-1"); + + var mt_nunitlite_project_path = Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.NUnitLite.tvos.csproj")); + if (!project_guids.TryGetValue (mt_nunitlite_project_path, out project_guid)) { + XmlDocument mt_nunitlite_project = new XmlDocument (); + mt_nunitlite_project.LoadWithoutNetworkAccess (mt_nunitlite_project_path); + project_guid = mt_nunitlite_project.GetProjectGuid (); + project_guids [mt_nunitlite_project_path] = project_guid; + } + inputProject.CreateProjectReferenceValue ("MonoTouch.NUnitLite", mt_nunitlite_project_path, project_guid, "MonoTouch.NUnitLite"); + + inputProject.AddExtraMtouchArgs ("--bitcode:asmonly", "iPhone", "Release"); + inputProject.SetMtouchUseLlvm (true, "iPhone", "Release"); + } + } +} + diff --git a/tests/xharness/Target.cs b/tests/xharness/Target.cs new file mode 100644 index 000000000000..6d3e68b08972 --- /dev/null +++ b/tests/xharness/Target.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; + +namespace xharness +{ + public abstract class Target + { + public Harness Harness; + + protected XmlDocument inputProject; + string outputType; + string bundleIdentifier; + string targetDirectory; + + public string Name { get; protected set; } + public string ProjectGuid { get; protected set; } + public string ProjectPath { get; protected set; } + + public string ProjectFileExtension { get { return IsFSharp ? "fsproj" : "csproj"; } } + public bool IsFSharp { get { return (ProjectPath ?? TemplateProjectPath).EndsWith (".fsproj"); } } + + public string TemplateProjectPath { get; set; } + + public string OutputType { get { return outputType; } } + public string TargetDirectory { get { return targetDirectory; } } + public bool IsLibrary { get { return outputType == "Library"; } } + public bool IsExe { get { return outputType == "Exe"; } } + public bool IsBindingProject { get; private set; } + public bool IsBCLProject { get { return ProjectPath.Contains ("bcl-test"); } } + + public string BundleIdentifier { get { return bundleIdentifier; } protected set { bundleIdentifier = value; } } + + public virtual string Suffix { get { throw new NotImplementedException (); } } + public virtual string MakefileWhereSuffix { get { return string.Empty; } } + public virtual string ProjectFileSuffix { get { return Suffix; } } + protected virtual string ProjectTypeGuids { get { throw new NotImplementedException (); } } + protected virtual string BindingsProjectTypeGuids { get { throw new NotImplementedException (); } } + protected virtual string TargetFrameworkIdentifier { get { throw new NotImplementedException (); } } + protected virtual string Imports { get { throw new NotImplementedException (); } } + protected virtual string BindingsImports { get { throw new NotImplementedException (); } } + protected virtual bool SupportsBitcode { get { return false; } } + public virtual bool IsMultiArchitecture { get { return false; } } + public virtual string SimulatorArchitectures { get { throw new NotImplementedException (); } } + public virtual string DeviceArchitectures { get { throw new NotImplementedException (); } } + protected virtual string GetMinimumOSVersion (string templateMinimumOSVersion) { throw new NotImplementedException (); } + protected virtual int[] UIDeviceFamily { get { throw new NotImplementedException (); } } + protected virtual string AdditionalDefines { get { return string.Empty; } } + public virtual string Platform { get { throw new NotImplementedException (); } } + + public virtual bool ShouldSkipProjectGeneration { get { return false; } } // Only generate makefile to invoke hard coded csproj + public virtual bool ShouldSetTargetFrameworkIdentifier { get { return true; } } + public virtual string DefaultAssemblyReference { get { return "monotouch"; } } + public virtual IEnumerable ReferenceToRemove { get { return Enumerable.Empty (); } } + public virtual Dictionary NewPropertiesToAdd { get { return new Dictionary (); } } + + public const string FSharpGuid = "{F2A71F9B-5D33-465A-A702-920D77279786}"; + public const string CSharpGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; + + public string LanguageGuid { get { return IsFSharp ? FSharpGuid : CSharpGuid; } } + + protected virtual void ProcessProject () + { + if (SupportsBitcode) { + inputProject.CloneConfiguration ("iPhone", "Release", "Release-bitcode"); + inputProject.AddExtraMtouchArgs ("--bitcode:full", "iPhone", "Release-bitcode"); + inputProject.SetMtouchUseLlvm (true, "iPhone", "Release-bitcode"); + } + + inputProject.SetOutputPath ("bin\\$(Platform)\\$(Configuration)" + Suffix); + inputProject.SetIntermediateOutputPath ("obj\\$(Platform)\\$(Configuration)" + Suffix); + + if (ShouldSetTargetFrameworkIdentifier) + inputProject.SetTargetFrameworkIdentifier (TargetFrameworkIdentifier); + + inputProject.SetAssemblyReference (DefaultAssemblyReference, TargetFrameworkIdentifier); + + foreach (var r in ReferenceToRemove) + inputProject.RemoveReferences (r); + + var newProperties = NewPropertiesToAdd; + foreach (var k in newProperties.Keys) + inputProject.SetTopLevelPropertyGroupValue (k, newProperties[k]); + + inputProject.FixProjectReferences (Suffix); + inputProject.SetAssemblyReference ("OpenTK", "OpenTK-1.0"); + inputProject.SetProjectTypeGuids (IsBindingProject ? BindingsProjectTypeGuids : ProjectTypeGuids); + inputProject.SetImport ("$(MSBuildExtensionsPath)\\Xamarin\\" + (IsBindingProject ? BindingsImports : Imports)); + inputProject.FixTestLibrariesReferences (Platform); + if (!string.IsNullOrEmpty (AdditionalDefines)) + inputProject.AddAdditionalDefines (AdditionalDefines); + } + + protected void CreateExecutableProject () + { + ProcessProject (); + if (!Harness.Mac) { + inputProject.FixArchitectures (SimulatorArchitectures, DeviceArchitectures); + inputProject.FixInfoPListInclude (Suffix); + inputProject.SetExtraLinkerDefs ("extra-linker-defs" + Suffix + ".xml"); + } + Harness.Save (inputProject, ProjectPath); + + if (!Harness.Mac) { + ProjectGuid = inputProject.GetProjectGuid (); + + XmlDocument info_plist = new XmlDocument (); + var target_info_plist = Path.Combine (TargetDirectory, "Info" + Suffix + ".plist"); + info_plist.LoadWithoutNetworkAccess (Path.Combine (TargetDirectory, "Info.plist")); + BundleIdentifier = info_plist.GetCFBundleIdentifier (); + info_plist.SetMinimumOSVersion (GetMinimumOSVersion (info_plist.GetMinimumOSVersion ())); + info_plist.SetUIDeviceFamily (UIDeviceFamily); + Harness.Save (info_plist, target_info_plist); + } + } + + protected void CreateLibraryProject () + { + ProcessProject (); + Harness.Save (inputProject, ProjectPath); + + ProjectGuid = inputProject.GetProjectGuid (); + } + + protected virtual void ExecuteInternal () + { + switch (OutputType) { + case "Exe": + CreateExecutableProject (); + break; + case "Library": + CreateLibraryProject (); + break; + default: + throw new Exception (string.Format ("Unknown OutputType: {0}", OutputType)); + } + } + + public void Execute () + { + targetDirectory = Path.GetDirectoryName (TemplateProjectPath); + Name = Path.GetFileName (targetDirectory); + + ProjectPath = Path.Combine (targetDirectory, Path.GetFileNameWithoutExtension (TemplateProjectPath) + ProjectFileSuffix + "." + ProjectFileExtension); + + if (!ShouldSkipProjectGeneration) + { + inputProject = new XmlDocument (); + inputProject.LoadWithoutNetworkAccess (TemplateProjectPath); + + outputType = inputProject.GetOutputType (); + + switch (inputProject.GetImport ()) { + case "$(MSBuildExtensionsPath)\\Xamarin\\iOS\\Xamarin.MonoTouch.CSharp.targets": + case "$(MSBuildExtensionsPath)\\Xamarin\\iOS\\Xamarin.MonoTouch.FSharp.targets": + case "$(MSBuildExtensionsPath)\\Xamarin\\Mac\\Xamarin.Mac.CSharp.targets": + case "$(MSBuildExtensionsPath": + case "$(MSBuildBinPath)\\Microsoft.CSharp.targets": + IsBindingProject = false; + break; + case "$(MSBuildExtensionsPath)\\Xamarin\\Xamarin.ObjcBinding.CSharp.targets": + case "$(MSBuildExtensionsPath)\\Xamarin\\Xamarin.ObjcBinding.FSharp.targets": + case "$(MSBuildExtensionsPath)\\Xamarin\\Mac\\Xamarin.Mac.ObjcBinding.CSharp": + IsBindingProject = true; + break; + default: + throw new Exception (string.Format ("Unknown Imports: {0} in {1}", inputProject.GetImport (), TemplateProjectPath)); + } + + ExecuteInternal (); + } + } + } +} + diff --git a/tests/xharness/UnifiedTarget.cs b/tests/xharness/UnifiedTarget.cs new file mode 100644 index 000000000000..337fe7757987 --- /dev/null +++ b/tests/xharness/UnifiedTarget.cs @@ -0,0 +1,97 @@ +using System; + +namespace xharness +{ + public class UnifiedTarget : Target + { + public override string Suffix { + get { + return "-unified"; + } + } + + protected override string ProjectTypeGuids { + get { + return "{FEACFBD2-3405-455C-9665-78FE426C6842};" + LanguageGuid; + } + } + + protected override string BindingsProjectTypeGuids { + get { + return "{8FFB629D-F513-41CE-95D2-7ECE97B6EEEC}"; + } + } + + protected override string TargetFrameworkIdentifier { + get { + return "Xamarin.iOS"; + } + } + + protected override string Imports { + get { + return IsFSharp ? "iOS\\Xamarin.iOS.FSharp.targets" : "iOS\\Xamarin.iOS.CSharp.targets"; + } + } + + protected override string BindingsImports { + get { + return IsFSharp ? "iOS\\Xamarin.iOS.ObjCBinding.FSharp.targets" : "iOS\\Xamarin.iOS.ObjCBinding.CSharp.targets"; + } + } + + public override string SimulatorArchitectures { + get { + return "i386, x86_64"; + } + } + + public override string DeviceArchitectures { + get { + return "ARMv7, ARM64"; + } + } + + protected override string GetMinimumOSVersion(string templateMinimumOSVersion) + { + return templateMinimumOSVersion; + } + + protected override int[] UIDeviceFamily { + get { + return new int [] { 1, 2 }; + } + } + + protected override string AdditionalDefines { + get { + return "XAMCORE_2_0"; + } + } + + public override bool IsMultiArchitecture { + get { + return true; + } + } + + public override string Platform { + get { + return "ios"; + } + } + + public override string MakefileWhereSuffix { + get { + return "unified"; + } + } + + protected override bool SupportsBitcode { + get { + return true; + } + } + } +} + diff --git a/tests/xharness/WatchOSTarget.cs b/tests/xharness/WatchOSTarget.cs new file mode 100644 index 000000000000..d4e02c235587 --- /dev/null +++ b/tests/xharness/WatchOSTarget.cs @@ -0,0 +1,185 @@ +using System; +using System.IO; +using System.Xml; + +namespace xharness +{ + public class WatchOSTarget : Target + { + public string AppName { get; private set; } + public string ExtensionName { get; private set; } + + public string WatchOSAppGuid { get; private set; } + public string WatchOSExtensionGuid { get; private set; } + public string WatchOSGuid { get { return ProjectGuid; } private set { ProjectGuid = value; } } + + public string WatchOSAppProjectPath { get; private set; } + public string WatchOSExtensionProjectPath { get; private set; } + public string WatchOSProjectPath { get { return ProjectPath; } private set { ProjectPath = value; } } + + void CreateWatchOSAppProject () + { + var csproj = new XmlDocument (); + csproj.LoadWithoutNetworkAccess (Path.Combine (Harness.WatchOSAppTemplate, "App.csproj")); + csproj.FindAndReplace ("%WATCHAPP_PATH%", Path.GetFullPath (Harness.WatchOSAppTemplate).Replace ('/', '\\') + "\\"); + csproj.FindAndReplace ("%WATCHEXTENSION_CSPROJ%", Path.GetFileName (WatchOSExtensionProjectPath)); + csproj.SetProjectReferenceValue (Path.GetFileName (WatchOSExtensionProjectPath), "Project", WatchOSExtensionGuid); + csproj.SetProjectReferenceValue (Path.GetFileName (WatchOSExtensionProjectPath), "Name", Name + "-watchos-extension"); + WatchOSAppGuid = "{" + Harness.NewStableGuid ().ToString ().ToUpper () + "}"; + csproj.SetProjectGuid (WatchOSAppGuid); + Harness.Save (csproj, WatchOSAppProjectPath); + + XmlDocument info_plist = new XmlDocument (); + var target_info_plist = Path.Combine (TargetDirectory, "Info-watchos-app.plist"); + info_plist.LoadWithoutNetworkAccess (Path.Combine (Harness.WatchOSAppTemplate, "Info.plist")); + info_plist.SetCFBundleIdentifier (BundleIdentifier + ".watchkitapp"); + info_plist.SetPListStringValue ("WKCompanionAppBundleIdentifier", BundleIdentifier); + info_plist.SetPListStringValue ("CFBundleName", Name); + Harness.Save (info_plist, target_info_plist); + } + + void CreateWatchOSContainerProject () + { + var csproj = new XmlDocument (); + csproj.LoadWithoutNetworkAccess (Path.Combine (Harness.WatchOSContainerTemplate, "Container.csproj")); + + csproj.FindAndReplace ("%CONTAINER_PATH%", Path.GetFullPath (Harness.WatchOSContainerTemplate).Replace ('/', '\\') + "\\"); + csproj.FindAndReplace ("%WATCHAPP_CSPROJ%", Path.GetFileName (WatchOSAppProjectPath)); + csproj.SetProjectReferenceValue (Path.GetFileName (WatchOSAppProjectPath), "Name", Name + "-watchos-app"); + WatchOSGuid = "{" + Harness.NewStableGuid ().ToString ().ToUpper () + "}"; + csproj.SetProjectGuid (WatchOSGuid); + Harness.Save (csproj, WatchOSProjectPath); + + XmlDocument info_plist = new XmlDocument (); + var target_info_plist = Path.Combine (TargetDirectory, "Info-watchos.plist"); + info_plist.LoadWithoutNetworkAccess (Path.Combine (Harness.WatchOSContainerTemplate, "Info.plist")); + info_plist.SetCFBundleIdentifier (BundleIdentifier); + info_plist.SetCFBundleName (Name); + Harness.Save (info_plist, target_info_plist); + } + + void CreateWatchOSExtensionProject () + { + var csproj = inputProject; + var suffix = "-watchos-extension"; + csproj.SetProjectTypeGuids ("{1E2E965C-F6D2-49ED-B86E-418A60C69EEF};" + LanguageGuid); + csproj.SetOutputPath ("bin\\$(Platform)\\$(Configuration)" + suffix); + csproj.SetIntermediateOutputPath ("obj\\$(Platform)\\$(Configuration)" + suffix); + csproj.RemoveTargetFrameworkIdentifier (); + csproj.SetPlatformAssembly ("Xamarin.WatchOS"); + csproj.SetImport (IsFSharp ? "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.AppExtension.FSharp.targets" : "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.AppExtension.CSharp.targets"); + csproj.FixProjectReferences ("-watchos"); + csproj.FixArchitectures ("i386", "ARMv7k"); + csproj.FixInfoPListInclude (suffix); + csproj.SetOutputType ("Library"); + csproj.AddAdditionalDefines ("XAMCORE_2_0;XAMCORE_3_0"); + csproj.RemoveReferences ("OpenTK"); + var ext = IsFSharp ? "fs" : "cs"; + csproj.AddCompileInclude ("InterfaceController." + ext, Path.Combine (Harness.WatchOSExtensionTemplate, "InterfaceController." + ext)); + csproj.SetExtraLinkerDefs ("extra-linker-defs" + Suffix + ".xml"); + csproj.SetMtouchUseBitcode (true, "iPhone", "Release"); + csproj.SetMtouchUseLlvm (true, "iPhone", "Release"); + + Harness.Save (csproj, WatchOSExtensionProjectPath); + + WatchOSExtensionGuid = csproj.GetProjectGuid (); + + XmlDocument info_plist = new XmlDocument (); + var target_info_plist = Path.Combine (TargetDirectory, "Info-watchos-extension.plist"); + info_plist.LoadWithoutNetworkAccess (Path.Combine (TargetDirectory, "Info.plist")); + BundleIdentifier = info_plist.GetCFBundleIdentifier (); + info_plist.SetCFBundleIdentifier (BundleIdentifier + ".watchkitapp.watchkitextension"); + info_plist.SetMinimumOSVersion ("2.0"); + info_plist.SetUIDeviceFamily (4); + info_plist.AddPListStringValue ("RemoteInterfacePrincipleClass", "InterfaceController"); + info_plist.AddPListKeyValuePair ("NSExtension", "dict", string.Format ( +@" + NSExtensionAttributes + + WKAppBundleIdentifier + {0}.watchkitapp + + NSExtensionPointIdentifier + com.apple.watchkit +", BundleIdentifier)); + if (!info_plist.ContainsKey ("NSAppTransportSecurity")) { + info_plist.AddPListKeyValuePair ("NSAppTransportSecurity", "dict", + @" + NSAllowsArbitraryLoads + + "); + } + Harness.Save (info_plist, target_info_plist); + } + + protected override string Imports { + get { + return IsFSharp ? "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.FSharp.targets" : "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.CSharp.targets"; + } + } + + protected override string BindingsImports { + get { + return IsFSharp ? "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.ObjCBinding.FSharp.targets" : "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.ObjCBinding.CSharp.targets"; + } + } + + void CreateWatchOSLibraryProject () + { + var csproj = inputProject; + csproj.SetProjectTypeGuids ("{FC940695-DFE0-4552-9F25-99AF4A5619A1};" + LanguageGuid); + csproj.SetOutputPath ("bin\\$(Platform)\\$(Configuration)" + Suffix); + csproj.SetIntermediateOutputPath ("obj\\$(Platform)\\$(Configuration)" + Suffix); + csproj.RemoveTargetFrameworkIdentifier (); + csproj.SetPlatformAssembly ("Xamarin.WatchOS"); + csproj.SetImport (IsBindingProject ? BindingsImports : Imports); + csproj.AddAdditionalDefines ("XAMCORE_2_0;XAMCORE_3_0"); + csproj.FixProjectReferences (Suffix); + csproj.SetExtraLinkerDefs ("extra-linker-defs" + Suffix + ".xml"); + csproj.FixTestLibrariesReferences (Platform); + Harness.Save (csproj, WatchOSProjectPath); + + WatchOSGuid = csproj.GetProjectGuid (); + } + + protected override void ExecuteInternal () + { + ExtensionName = Name + " Extension"; + AppName = Name + " App"; + + switch (OutputType) { + case "Exe": + WatchOSExtensionProjectPath = Path.Combine (TargetDirectory, Path.GetFileNameWithoutExtension (TemplateProjectPath) + "-watchos-extension.csproj"); + WatchOSAppProjectPath = Path.Combine (TargetDirectory, Path.GetFileNameWithoutExtension (TemplateProjectPath) + "-watchos-app.csproj"); + CreateWatchOSExtensionProject (); + CreateWatchOSAppProject (); + CreateWatchOSContainerProject (); + break; + case "Library": + CreateWatchOSLibraryProject (); + break; + default: + throw new Exception (string.Format ("Unknown OutputType: {0}", OutputType)); + } + } + + public override string Suffix { + get { + return "-watchos"; + } + } + + public override string Platform { + get { + return "watchos"; + } + } + + protected override bool SupportsBitcode { + get { + return true; + } + } + } +} + diff --git a/tests/xharness/XProcess.cs b/tests/xharness/XProcess.cs new file mode 100644 index 000000000000..852d26499359 --- /dev/null +++ b/tests/xharness/XProcess.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; + +namespace xharness +{ + public class XProcess + { + public Harness Harness; + + public int VerbosityLevel = 1; + Process process = new Process (); + CountdownEvent output_completed = new CountdownEvent (2); + object output_lock = new object (); + StringBuilder output = new StringBuilder (); + + public string FileName { + get { return process.StartInfo.FileName; } + set { process.StartInfo.FileName = value; } + } + + public string Arguments { + get { return process.StartInfo.Arguments; } + set { process.StartInfo.Arguments = value; } + } + + public Dictionary EnvironmentVariables { get; set; } + + public void Start () + { + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.RedirectStandardOutput = true; + + if (EnvironmentVariables != null) { + foreach (var kvp in EnvironmentVariables) + process.StartInfo.EnvironmentVariables.Add (kvp.Key, kvp.Value); + } + + process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => + { + if (e.Data == null) { + output_completed.Signal (); + } else { + lock (output_lock) { + output.AppendLine (e.Data); + Harness.Log (VerbosityLevel, e.Data); + } + } + }; + process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => + { + if (e.Data == null) { + output_completed.Signal (); + } else { + lock (output_lock) { + output.AppendLine (e.Data); + Harness.Log (VerbosityLevel, e.Data); + } + } + }; + + Harness.Log ("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + process.Start (); + process.BeginErrorReadLine (); + process.BeginOutputReadLine (); + } + + public bool WaitForExit (TimeSpan timeout) + { + return process.WaitForExit ((int) timeout.TotalMilliseconds); + } + + public int ExitCode { + get { return process.ExitCode; } + } + + public string ReadCurrentOutput () + { + lock (output_lock) + return output.ToString (); + } + + public int Id { + get { return process.Id; } + } + } +} + diff --git a/tests/xharness/xharness.csproj b/tests/xharness/xharness.csproj new file mode 100644 index 000000000000..820743653018 --- /dev/null +++ b/tests/xharness/xharness.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E1F53F80-8399-499B-8017-C414B9CD263B} + Exe + xharness + xharness + v4.5 + + + true + full + false + . + DEBUG; + prompt + 4 + false + --verbose --configure --autoconf --rootdir ../ + + + full + true + prompt + 4 + true + bin\Release + + + + + + + + + + Options.cs + + + + + + + + + + + + SdkVersions.cs + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/xtro-sharpie/.gitignore b/tests/xtro-sharpie/.gitignore new file mode 100644 index 000000000000..608f8581dc6a --- /dev/null +++ b/tests/xtro-sharpie/.gitignore @@ -0,0 +1,3 @@ +*.results +*.pch* +*.unclassified diff --git a/tests/xtro-sharpie/DesignatedInitializerCheck.cs b/tests/xtro-sharpie/DesignatedInitializerCheck.cs new file mode 100644 index 000000000000..96a2c709bde3 --- /dev/null +++ b/tests/xtro-sharpie/DesignatedInitializerCheck.cs @@ -0,0 +1,82 @@ +// +// The rule reports +// +// !incorrect-designated-initializer! +// when a method, instead of a constructor, is decorated with [DesignatedInitializer] attribute +// +// !missing-designated-initializer! +// when a managed constructor is missing its [DesignatedInitializer] attribute +// +// !extra-designated-initializer! +// when a managed constructor has no business to have an [DesignatedInitializer] attribute +// + +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public class DesignatedInitializerCheck : BaseVisitor { + + static Dictionary types = new Dictionary (); + static Dictionary methods = new Dictionary (); + + static TypeDefinition GetType (ObjCInterfaceDecl decl) + { + TypeDefinition td; + types.TryGetValue (decl.Name, out td); + return td; + } + + static MethodDefinition GetMethod (ObjCMethodDecl decl) + { + MethodDefinition md; + methods.TryGetValue (decl.GetName (), out md); + return md; + } + + + public override void VisitManagedMethod (MethodDefinition method) + { + var key = method.GetName (); + if (key == null) + return; + + // we still have one case to fix with duplicate selectors :| + if (!methods.ContainsKey (key)) + methods.Add (key, method); + } + + public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + + // don't process methods (or types) that are unavailable for the current platform + if (!decl.IsAvailable () || !(decl.DeclContext as Decl).IsAvailable ()) + return; + + var method = GetMethod (decl); + // don't report missing [DesignatedInitializer] for types that are not bound - that's a different problem + if (method == null) + return; + + var designated_initializer = method.IsDesignatedInitializer (); + + if (!method.IsConstructor) { + if (designated_initializer) + Console.WriteLine ("!incorrect-designated-initializer! {0} is not a constructor", method.GetName ()); + } else if (decl.IsDesignatedInitializer) { + if (!designated_initializer) + Console.WriteLine ("!missing-designated-initializer! {0} is missing an [DesignatedInitializer] attribute", method.GetName ()); + } else { + if (designated_initializer) + Console.WriteLine ("!extra-designated-initializer! {0} is incorrectly decorated with an [DesignatedInitializer] attribute", method.GetName ()); + } + } + } +} diff --git a/tests/xtro-sharpie/DllImportCheck.cs b/tests/xtro-sharpie/DllImportCheck.cs new file mode 100644 index 000000000000..625fddc8fc33 --- /dev/null +++ b/tests/xtro-sharpie/DllImportCheck.cs @@ -0,0 +1,110 @@ +// +// The rule reports +// +// !missing-pinvoke! +// if headers defines functions that we have not bound with [DllImport] +// +// !unknown-pinvoke! +// if we have [DllImport] that were not found in headers +// NOTE: introspection tests checks if those exists at runtime, i.e. they might +// just be undocumented (or not in the headers) +// + +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + // track all [DllImport] + class DllImportCheck : BaseVisitor { + + // dupes :| + Dictionary dllimports = new Dictionary (); + + public override void VisitManagedMethod (MethodDefinition method) + { + if (!method.IsPInvokeImpl || !method.HasPInvokeInfo) + return; + + var info = method.PInvokeInfo; + if (info.Module.Name == "__Internal") + return; + + // there are duplicates declarations + // TODO: right now we only check the first one, as the priority is knowing if we have (or not) bindings for them + var name = info.EntryPoint; + if (!dllimports.ContainsKey (name)) + dllimports.Add (name, method); + } + + public override void VisitFunctionDecl (FunctionDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + // skip macros : we generally implement them but their name is lost (so no matching is possible) + if (!decl.IsExternC) + return; + + var name = decl.Name; + // do not consider _* or __* as public API that should be bound + if (name [0] == '_') + return; + + // exclude non-framework code (e.g. all unix headers) + var header_file = decl.PresumedLoc.FileName; + var fxh = header_file.IndexOf (".framework/Headers/", StringComparison.Ordinal); + var framework = String.Empty; + if (fxh > 0) { + var start = header_file.LastIndexOf ('/', fxh) + 1; + framework = header_file.Substring (start, fxh - start); + } else { + // FIXME: we only process the headers in Frameworks, not all the UNIX headers + // that still miss a few things (like objc runtime) but nothing that *requires* binding + return; + } + + // check availability macros to see if the API is available on the OS and not deprecated + if (!decl.IsAvailable ()) + return; + + MethodDefinition md; + if (!dllimports.TryGetValue (name, out md)) { + + // FIXME: we ignore some frameworks we have not bound (too many entries for our data files) + // we do this late because, in some cases like vImage, we do bind a few API + switch (framework) { + // Accelerate and friends + case "vImage": + case "vecLib": + return; + // security + case "GSS": + return; + // exposed in OpenTK-1.dll + case "OpenAL": + case "OpenGLES": + return; + } + + // if we find functions without matching DllImport then we report them + Console.WriteLine ("!missing-pinvoke! {0} is not bound", name); + return; + } + + dllimports.Remove (name); + } + + public override void End () + { + // at this stage anything else we have is not something we could find in Apple's headers + // e.g. a typo in the name + foreach (var extra in dllimports.Keys) { + Console.WriteLine ("!unknown-pinvoke! {0} bound", extra); + } + } + } +} diff --git a/tests/xtro-sharpie/EnumCheck.cs b/tests/xtro-sharpie/EnumCheck.cs new file mode 100644 index 000000000000..f1ecb74c5648 --- /dev/null +++ b/tests/xtro-sharpie/EnumCheck.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + class EnumCheck : BaseVisitor { + + Dictionary enums = new Dictionary (); + + public override void VisitManagedType (TypeDefinition type) + { + // exclude non enum and nested enums, e.g. bunch of Selector enums in CTFont + if (!type.IsEnum || type.IsNested) + return; + + var name = type.Name; + TypeDefinition td; + // e.g. WatchKit.WKErrorCode and WebKit.WKErrorCode :-( + if (!enums.TryGetValue (name, out td)) + enums.Add (name, type); + else { + Console.WriteLine ("!duplicate-type-name! {0} enum exists as both {1} and {2}", name, type.FullName, td.FullName); + } + } + + public override void VisitEnumDecl (EnumDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + if (!decl.IsDefinition) + return; + + string name = decl.Name; + if (name == null) + return; + + // check availability macros to see if the API is available on the OS and not deprecated + if (!decl.IsAvailable ()) + return; + + var mname = Helpers.GetManagedName (name); + TypeDefinition type; + if (!enums.TryGetValue (mname, out type)) { + Console.WriteLine ("!missing-enum! {0} not bound", name); + return; + } else + enums.Remove (mname); + + int native_size = 4; + bool native = false; + // FIXME: this can be simplified + switch (decl.IntegerQualType.ToString ()) { + case "NSInteger": + case "NSUInteger": + case "CFIndex": + case "CFOptionFlags": + native_size = 8; // in managed code it's always the largest size + native = true; + break; + case "unsigned long": + case "unsigned int": + case "int32_t": + case "uint32_t": + case "int": + case "GLint": + case "GLuint": + case "GLenum": + case "SInt32": + case "UInt32": + case "OptionBits": // UInt32 + case "long": + case "FourCharCode": + break; + case "int64_t": + case "uint64_t": + case "unsigned long long": + native_size = 8; + break; + case "UInt16": + case "int16_t": + case "uint16_t": + case "short": + native_size = 2; + break; + case "UInt8": + case "int8_t": + case "uint8_t": + native_size = 1; + break; + default: + throw new NotImplementedException (decl.IntegerQualType.ToString ()); + } + + // check correct [Native] decoration + if (native) { + if (!IsNative (type)) + Console.WriteLine ("!missing-enum-native! {0}", name); + } else { + if (IsNative (type)) + Console.WriteLine ("!extra-enum-native! {0}", name); + } + + int managed_size = 4; + switch (GetEnumUnderlyingType (type).Name) { + case "Byte": + case "SByte": + managed_size = 1; + break; + case "Int16": + case "UInt16": + managed_size = 2; + break; + case "Int32": + case "UInt32": + break; + case "Int64": + case "UInt64": + managed_size = 8; + break; + default: + throw new NotImplementedException (); + } + if (native_size != managed_size) + Console.WriteLine ("!wrong-enum-size! {0} managed {1} vs native {2}", name, managed_size, native_size); + } + + static bool IsNative (TypeDefinition type) + { + if (!type.HasCustomAttributes) + return false; + + foreach (var ca in type.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name == "NativeAttribute") + return true; + } + return false; + } + + public static TypeReference GetEnumUnderlyingType (TypeDefinition self) + { + var fields = self.Fields; + + for (int i = 0; i < fields.Count; i++) { + var field = fields [i]; + if (!field.IsStatic) + return field.FieldType; + } + + throw new ArgumentException (); + } + + public override void End () + { + // report any [Native] decorated enum for which we could not find a match in the header files + // e.g. a typo in the name + foreach (var extra in enums) { + if (IsNative (extra.Value)) + Console.WriteLine ("!unknown-native-enum! {0} bound", extra.Key); + } + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/FieldCheck.cs b/tests/xtro-sharpie/FieldCheck.cs new file mode 100644 index 000000000000..f1848bfef202 --- /dev/null +++ b/tests/xtro-sharpie/FieldCheck.cs @@ -0,0 +1,99 @@ +// +// The rule reports +// +// !duplicate-field-name! +// if we have duplicated [Field] / code to export the same field more than once +// +// !missing-field! +// if headers defines fields that we have not bound as [Field] +// NOTE: we still have amnually bound fields :( +// +// !unknown-field! +// if we have [Field] that were not found in headers +// NOTE: introspection tests checks if those exists at runtime, i.e. they might +// just be undocumented (or not in the headers) +// + +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public class FieldCheck : BaseVisitor { + + Dictionary fields = new Dictionary (); + + public override void VisitManagedType (TypeDefinition type) + { + if (type.HasProperties) { + foreach (var p in type.Properties) { + if (!p.HasCustomAttributes) + continue; + var getter = p.GetMethod; + // mostly static getters but not in the case of generated EventArgs.g.cs + if (getter == null) + continue; + + CheckAttributes (p.FullName, p); + } + } + + if (type.HasFields) { + foreach (var f in type.Fields) { + if (!f.HasCustomAttributes || !f.IsStatic) + continue; + CheckAttributes (f.FullName, f); + } + } + } + + void CheckAttributes (string memberName, ICustomAttributeProvider p) + { + foreach (var ca in p.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name != "FieldAttribute") + continue; + + var name = ca.ConstructorArguments [0].Value as string; + + MemberReference mr; + if (!fields.TryGetValue (name, out mr)) + fields.Add (name, p as MemberReference); + else { + // not critical and quite noisy with current API profile + // Console.WriteLine ("!duplicate-field-name! {0} [Field] exists as both {1} and {2}", name, memberName, mr.FullName); + } + } + } + + public override void VisitVarDecl (VarDecl decl) + { + if (!decl.IsExternC) + return; + if (!decl.PresumedLoc.FileName.Contains (".framework")) + return; + + if (!decl.IsAvailable ()) + return; + + var name = decl.ToString (); + MemberReference mr; + if (!fields.TryGetValue (name, out mr)) { + Console.WriteLine ("!missing-field! {0} not bound", name); + return; + } else + fields.Remove (name); + } + + public override void End () + { + // at this stage anything else we have is not something we could find in Apple's headers + foreach (var extra in fields.Keys) { + Console.WriteLine ("!unknown-field! {0} bound", extra); + } + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/Helpers.cs b/tests/xtro-sharpie/Helpers.cs new file mode 100644 index 000000000000..b4f5dfd76d41 --- /dev/null +++ b/tests/xtro-sharpie/Helpers.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public static class Helpers { + + // the original name can be lost and, if not registered (e.g. enums), might not be available + static Dictionary map = new Dictionary () { + { "CFURLPathStyle", "CFUrlPathStyle" }, + { "EABluetoothAccessoryPickerErrorCode", "EABluetoothAccessoryPickerError" }, + { "EKCalendarEventAvailabilityMask", "EKCalendarEventAvailability" }, + { "GKErrorCode", "GKError" }, + { "HMCharacteristicValueAirParticulateSize", "HMCharacteristicValueAirParticulate" }, + { "HMCharacteristicValueLockMechanismLastKnownAction", "HMCharacteristicValueLockMechanism" }, + { "HMErrorCode", "HMError" }, + { "LAError", "LAStatus" }, + { "MCErrorCode", "MCError" }, + { "MIDINotificationMessageID", "MidiNotificationMessageId" }, + { "MIDIObjectType", "MidiObjectType" }, + { "MIDITransformControlType", "MidiTransformControlType" }, + { "MIDITransformType", "MidiTransformType" }, + { "MIDINetworkConnectionPolicy", "MidiNetworkConnectionPolicy" }, + { "MPMovieMediaTypeMask", "MPMovieMediaType" }, + { "MTLCPUCacheMode", "MTLCpuCacheMode" }, + { "NEVPNError", "NEVpnError" }, + { "NEVPNIKEAuthenticationMethod", "NEVpnIkeAuthenticationMethod" }, + { "NEVPNIKEv2CertificateType", "NEVpnIke2CertificateType" }, + { "NEVPNIKEv2DeadPeerDetectionRate", "NEVpnIke2DeadPeerDetectionRate" }, + { "NEVPNIKEv2DiffieHellmanGroup", "NEVpnIke2DiffieHellman" }, + { "NEVPNIKEv2EncryptionAlgorithm", "NEVpnIke2EncryptionAlgorithm" }, + { "NEVPNIKEv2IntegrityAlgorithm", "NEVpnIke2IntegrityAlgorithm" }, + { "NEVPNStatus", "NEVpnStatus" }, + { "NSAttributedStringEnumerationOptions", "NSAttributedStringEnumeration" }, + { "NSHTTPCookieAcceptPolicy", "NSHttpCookieAcceptPolicy" }, + { "NSJSONReadingOptions", "NSJsonReadingOptions" }, + { "NSJSONWritingOptions", "NSJsonWritingOptions" }, + { "NSURLBookmarkCreationOptions", "NSUrlBookmarkCreationOptions" }, + { "NSURLBookmarkResolutionOptions", "NSUrlBookmarkResolutionOptions" }, + { "NSURLCacheStoragePolicy", "NSUrlCacheStoragePolicy" }, + { "NSURLCredentialPersistence", "NSUrlCredentialPersistence" }, + { "NSURLRelationship", "NSUrlRelationship" }, + { "NSURLRequestCachePolicy", "NSUrlRequestCachePolicy" }, + { "NSURLRequestNetworkServiceType", "NSUrlRequestNetworkServiceType" }, + { "NSURLSessionAuthChallengeDisposition", "NSUrlSessionAuthChallengeDisposition" }, + { "NSURLSessionResponseDisposition", "NSUrlSessionResponseDisposition" }, + { "NSURLSessionTaskState", "NSUrlSessionTaskState" }, + { "NWTCPConnectionState", "NWTcpConnectionState" }, + { "NWUDPSessionState", "NWUdpSessionState" }, + { "RPRecordingErrorCode", "RPRecordingError" }, + { "SKErrorCode", "SKError" }, + { "SSReadingListErrorCode", "SSReadingListError" }, + { "UIDataDetectorTypes", "UIDataDetectorType" }, + { "UIControlEvents", "UIControlEvent" }, + { "UITableViewCellAccessoryType", "UITableViewCellAccessory" }, + { "UITableViewCellStateMask", "UITableViewCellState" }, + { "WatchKitErrorCode", "WKErrorCode" }, // WebKit already had that name + }; + + public static string GetManagedName (string nativeName) + { + string result; + map.TryGetValue (nativeName, out result); + return result ?? nativeName; + } + + public static string ReplaceFirstInstance (this string source, string find, string replace) + { + int index = source.IndexOf (find, StringComparison.Ordinal); + return index < 0 ? source : source.Substring (0, index) + replace + source.Substring (index + find.Length); + } + + public static string Platform { get; set; } + + public static bool IsAvailable (this Decl decl) + { + // there's no doubt we need to ask for the current platform + var result = decl.IsAvailable (Platform); + + // some categories are not decorated (as not available) but they extend types that are + if (!result.HasValue) { + var category = (decl.DeclContext as ObjCCategoryDecl); + if (category != null) + result = category.ClassInterface.IsAvailable (Platform); + } + + // but right now most frameworks consider tvOS and watchOS like iOS unless + // decorated otherwise so we must check again if we do not get a definitve answer + if ((result == null) && ((Platform == "tvos") || (Platform == "watchos"))) + result = decl.IsAvailable ("ios"); + return !result.HasValue ? true : result.Value; + } + + static bool? IsAvailable (this Decl decl, string platform) + { + bool? result = null; + foreach (var attr in decl.Attrs) { + // NS_UNAVAILABLE + if (attr is UnavailableAttr) + return false; + var avail = (attr as AvailabilityAttr); + if (avail == null) + continue; + // if the headers says it's not available then we won't report it as missing + if (avail.Unavailable && (avail.Platform.Name == platform)) + return false; + // for iOS we won't report missing members that were deprecated before 5.0 + if (!avail.Deprecated.IsEmpty && avail.Platform.Name == "ios" && avail.Deprecated.Major < 5) + return false; + // can't return true right away as it can be deprecated too + if (!avail.Introduced.IsEmpty && (avail.Platform.Name == platform)) + result = true; + } + return result; + } + + public static bool IsDesignatedInitializer (this MethodDefinition self) + { + return self.HasAttribute ("DesignatedInitializerAttribute"); + } + + public static bool IsProtocol (this TypeDefinition self) + { + return self.HasAttribute ("ProtocolAttribute"); + } + + static bool HasAttribute (this ICustomAttributeProvider self, string attributeName) + { + if (!self.HasCustomAttributes) + return false; + + foreach (var ca in self.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name == attributeName) + return true; + } + return false; + } + + static bool IsStatic (this TypeDefinition self) + { + return (self.IsSealed && self.IsAbstract); + } + + public static string GetName (this ObjCMethodDecl self) + { + if (self == null) + return null; + + var sb = new StringBuilder (); + if (self.IsClassMethod) + sb.Append ('+'); + sb.Append ((self.DeclContext as NamedDecl).Name); + sb.Append ("::"); + sb.Append (self.Selector); + return sb.ToString (); + } + + public static string GetName (this TypeDefinition self) + { + if ((self == null) || !self.HasCustomAttributes) + return null; + + if (self.IsStatic ()) { + // static types, e.g. categories, won't have a [Register] attribute + foreach (var ca in self.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name == "CategoryAttribute") { + if (ca.HasProperties) + return (ca.Properties [0].Argument.Value as string); + return self.Name; + } + } + } else { + foreach (var ca in self.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name == "RegisterAttribute") { + if (ca.HasConstructorArguments) + return (ca.ConstructorArguments [0].Value as string); + return self.Name; + } + } + } + return null; + } + + public static string GetName (this MethodDefinition self) + { + if (self == null) + return null; + + var type = self.DeclaringType; + string tname = self.DeclaringType.GetName (); + // a static type is not used for static selectors + bool is_static = !type.IsStatic () && self.IsStatic; + + // static types, e.g. categories, won't have a [Register] attribute + if (type.IsStatic ()) { + if (self.HasParameters) + tname = self.Parameters [0].ParameterType.Name; // extension method + } + if (tname == null) + return null; + + var selector = self.GetSelector (); + if (selector == null) + return null; + + var sb = new StringBuilder (); + if (is_static) + sb.Append ('+'); + sb.Append (tname); + sb.Append ("::"); + sb.Append (selector); + return sb.ToString (); + } + + public static string GetSelector (this MethodDefinition self) + { + if ((self == null) || !self.HasCustomAttributes) + return null; + + foreach (var ca in self.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name == "ExportAttribute") + return ca.ConstructorArguments [0].Value as string; + } + return null; + } + + public static string GetSelector (this ObjCMethodDecl self) + { + return self.Selector.ToString () ?? (self.IsPropertyAccessor ? self.Name : null); + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/Makefile b/tests/xtro-sharpie/Makefile new file mode 100644 index 000000000000..316ebc4636f5 --- /dev/null +++ b/tests/xtro-sharpie/Makefile @@ -0,0 +1,103 @@ +TOP=../../../xamarin-macios + +include $(TOP)/Make.config + +# a 64bits mono is required because of the clang requirement +MONO ?= /opt/mono/bin/mono --debug + +all-local:: run-ios run-osx run-watchos run-tvos classify + +sharpie: sharpie-ios sharpie-osx sharpie-watchos sharpie-tvos classify + +clean-local:: + rm -f ios.results osx.results watchos.results tvos.results *.tmp + rm -rf *os*.pch* + +bin/Debug/xtro-sharpie.exe ./bin/Debug/xtro-plugin.dll build: + xbuild + + +XIOS ?= /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/64bits/Xamarin.iOS.dll +XIOS_GL ?= /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS/OpenTK-1.0.dll +XIOS_ARCH = arm64 +XIOS_PCH = iphoneos$(IOS_SDK_VERSION)-$(XIOS_ARCH).pch + +run-ios: build $(XIOS_PCH) + $(MONO) bin/Debug/xtro-sharpie.exe $(XIOS_PCH) $(XIOS) $(XIOS_GL) | sort > ios.results + +sharpie-ios: build $(XIOS_PCH) + sharpie ./bin/Debug/xtro-plugin.dll extro $(XIOS_PCH) $(XIOS) $(XIOS_GL) | sort > ios.results + +$(XIOS_PCH): + sharpie sdk-db -s iphoneos$(IOS_SDK_VERSION) -a $(XIOS_ARCH) + + +XWATCHOS ?= /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/32bits/Xamarin.WatchOS.dll +XWATCHOS_ARCH = armv7 +XWATCHOS_PCH = watchos$(WATCH_SDK_VERSION)-$(XWATCHOS_ARCH).pch + +run-watchos: build $(XWATCHOS_PCH) + $(MONO) bin/Debug/xtro-sharpie.exe $(XWATCHOS_PCH) $(XWATCHOS) | sort > watchos.results + +sharpie-watchos: build $(XWATCHOS_PCH) + sharpie ./bin/Debug/xtro-plugin.dll extro $(XWATCHOS_PCH) $(XWATCHOS) | sort > watchos.results + +$(XWATCHOS_PCH): + sharpie sdk-db -s watchos$(WATCH_SDK_VERSION) -a $(XWATCHOS_ARCH) + + +XTVOS ?= /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll +XTVOS_GL ?= /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.TVOS/OpenTK-1.0.dll +XTVOS_ARCH = arm64 +XTVOS_PCH = appletvos$(TVOS_SDK_VERSION)-$(XTVOS_ARCH).pch + +run-tvos: build $(XTVOS_PCH) + $(MONO) bin/Debug/xtro-sharpie.exe $(XTVOS_PCH) $(XTVOS) $(XTVOS_GL) | sort > tvos.results + +sharpie-tvos: build $(XTVOS_PCH) + sharpie ./bin/Debug/xtro-plugin.dll extro $(XTVOS_PCH) $(XTVOS) $(XTVOS_GL) | sort > tvos.results + +$(XTVOS_PCH): + sharpie sdk-db -s appletvos$(TVOS_SDK_VERSION) -a $(XTVOS_ARCH) + + +XMAC ?= /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/$(XMAC_ARCH)/mobile/Xamarin.Mac.dll +XMAC_ARCH = x86_64 +XMAC_PCH = macosx$(OSX_SDK_VERSION)-$(XMAC_ARCH).pch + +run-osx: build $(XMAC_PCH) + $(MONO) bin/Debug/xtro-sharpie.exe $(XMAC_PCH) $(XMAC) | sort > osx.results + +sharpie-osx: build $(XMAC_PCH) + sharpie ./bin/Debug/xtro-plugin.dll extro $(XMAC_PCH) $(XMAC) | sort > osx.results + +$(XMAC_PCH): + sharpie sdk-db -s macosx$(OSX_SDK_VERSION) -a $(XMAC_ARCH) + +preclassify: ios.results osx.results + @comm -12 ios.results osx.results > common.unclassified.tmp + +classify-ios: preclassify + @sort ios.ignore ios.pending common.ignore common.pending > ios.skip.tmp + @comm -23 ios.results common.unclassified.tmp > ios.unclassified.tmp + @comm -23 ios.unclassified.tmp ios.skip.tmp > ios.unclassified + +classify-tvos: preclassify + @sort tvos.ignore tvos.pending ios.ignore ios.pending common.ignore common.pending > tvos.skip.tmp + @comm -23 tvos.results common.unclassified.tmp > tvos.unclassified.tmp + @comm -23 tvos.unclassified.tmp tvos.skip.tmp > tvos.unclassified + +classify-watchos: preclassify + @sort watchos.ignore watchos.pending common.ignore common.pending > watchos.skip.tmp + @comm -23 watchos.results common.unclassified.tmp > watchos.unclassified.tmp + @comm -23 watchos.unclassified.tmp watchos.skip.tmp > watchos.unclassified + +classify-osx: preclassify + @sort osx.ignore osx.pending common.ignore common.pending > osx.skip.tmp + @comm -23 osx.results common.unclassified.tmp > osx.unclassified.tmp + @comm -23 osx.unclassified.tmp osx.skip.tmp > osx.unclassified + +classify: classify-ios classify-osx classify-watchos classify-tvos + @sort common.ignore common.pending ios.skip.tmp osx.skip.tmp > common.skip.tmp + @comm -23 common.unclassified.tmp common.skip.tmp > common.unclassified + @rm *.tmp *.results diff --git a/tests/xtro-sharpie/ObjCInterfaceCheck.cs b/tests/xtro-sharpie/ObjCInterfaceCheck.cs new file mode 100644 index 000000000000..b9ff3bf7772b --- /dev/null +++ b/tests/xtro-sharpie/ObjCInterfaceCheck.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public class ObjCInterfaceCheck : BaseVisitor { + + Dictionary type_map = new Dictionary (); + + public override void VisitManagedType (TypeDefinition type) + { + if (!type.HasCustomAttributes) + return; + + string rname = null; + bool wrapper = true; + bool skip = false; + + foreach (var ca in type.CustomAttributes) { + switch (ca.Constructor.DeclaringType.Name) { + case "RegisterAttribute": + rname = type.Name; + if (ca.HasConstructorArguments) { + rname = (ca.ConstructorArguments [0].Value as string); + if (ca.ConstructorArguments.Count > 1) + wrapper = (bool)ca.ConstructorArguments [1].Value; + } + if (ca.HasProperties) { + foreach (var arg in ca.Properties) { + switch (arg.Name) { + case "Wrapper": + wrapper = (bool)arg.Argument.Value; + break; + case "SkipRegistration": + skip = (bool)arg.Argument.Value; + break; + } + } + } + break; + case "ProtocolAttribute": + // exclude protocols + return; + } + } + if (!skip && wrapper && !String.IsNullOrEmpty (rname)) { + TypeDefinition td; + if (!type_map.TryGetValue (rname, out td)) + type_map.Add (rname, type); + else { + Console.WriteLine ("!duplicate-register! {0} exists as both {1} and {2}", rname, type.FullName, td.FullName); + } + } + } + + public override void VisitObjCInterfaceDecl (ObjCInterfaceDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + if (!decl.IsDefinition) + return; + + var name = decl.Name; + if (name.EndsWith ("Internal", StringComparison.Ordinal)) + return; + + // check availability macros to see if the API is available on the OS and not deprecated + if (!decl.IsAvailable ()) + return; + + TypeDefinition td; + if (!type_map.TryGetValue (name, out td)) { + Console.WriteLine ("!missing-type! {0} not bound", name); + // other checks can't be done without an actual type to inspect + return; + } + + // check base type + var nbt = decl.SuperClass?.Name; + var mbt = td.BaseType?.Resolve ().GetName (); + if (nbt != mbt) + Console.WriteLine ("!wrong-base-type! {0} expected {1} actual {2}", name, nbt, mbt); + + // check protocols + foreach (var protocol in decl.Protocols) { + var pname = protocol.Name; + if (!ImplementProtocol (pname, td)) + Console.WriteLine ("!missing-protocol-conformance! {0} should conform to {1}", name, pname); + } + + // TODO : check for extraneous protocols + + type_map.Remove (name); + } + + public override void End () + { + // at this stage anything else we have is not something we could find in Apple's headers + foreach (var extra in type_map.Keys) { + if (extra [0] == '_') + continue; + Console.WriteLine ("!unknown-type! {0} bound", extra); + } + } + + // - version check + bool ImplementProtocol (string protocol, TypeDefinition td) + { + if (td == null) + return false; + if (td.HasInterfaces) { + foreach (var intf in td.Interfaces) { + if (protocol == GetProtocolName (intf?.Resolve ())) + return true; + } + } + return ImplementProtocol (protocol, td.BaseType?.Resolve ()); + } + + public static string GetProtocolName (TypeDefinition td) + { + if (!td.HasCustomAttributes) + return null; + + foreach (var ca in td.CustomAttributes) { + if (ca.Constructor.DeclaringType.Name == "ProtocolAttribute") { + var name = td.Name; + if (ca.HasProperties) + name = ca.Properties [0].Argument.Value as string; + return name; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/ObjCProtocolCheck.cs b/tests/xtro-sharpie/ObjCProtocolCheck.cs new file mode 100644 index 000000000000..56e957d2971c --- /dev/null +++ b/tests/xtro-sharpie/ObjCProtocolCheck.cs @@ -0,0 +1,206 @@ +// +// The rule reports +// +// !missing-protocol! +// if headers defines a protocol that we have not bound as [Protocol] +// +// !incorrect-protocol-member! +// if we have @required members without [Abstract] or @optional members with [Abstract] +// +// !missing-protocol-member! +// if we have protocol members (found in header files) but not in the interface +// +// !extra-protocol-member! +// if we have protocol members in the interface that are NOT found in header files +// +// Limitations +// +// * .NET interfaces does not allow constructors, so we cannot check for `init*` members +// +// * .NET interfaces cannot have static members, so we cannot check for [Static] members +// +// Notes: Both limitations could be _mostly_ lifted by another tests that would check types conformance to a protocol +// + +using System; +using System.Collections.Generic; +using System.Text; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public class ObjCProtocolCheck : BaseVisitor { + + Dictionary protocol_map = new Dictionary (); + + public override void VisitManagedType (TypeDefinition type) + { + if (!type.HasCustomAttributes) + return; + + string pname = null; + bool informal = false; + + foreach (var ca in type.CustomAttributes) { + switch (ca.Constructor.DeclaringType.Name) { + case "ProtocolAttribute": + if (!ca.HasProperties) + continue; + foreach (var p in ca.Properties) { + switch (p.Name) { + case "Name": + pname = p.Argument.Value as string; + break; + case "IsInformal": + informal = (bool) p.Argument.Value; + break; + } + } + break; + } + } + if (!informal && !String.IsNullOrEmpty (pname)) + protocol_map.Add (pname, type); + } + + public override void VisitObjCProtocolDecl (ObjCProtocolDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + if (!decl.IsDefinition) + return; + + // check availability macros to see if the API is available on the OS and not deprecated + if (!decl.IsAvailable ()) + return; + + var name = decl.Name; + TypeDefinition td; + if (!protocol_map.TryGetValue (name, out td)) { + Console.WriteLine ("!missing-protocol! {0} not bound", name); + // other checks can't be done without an actual protocol to inspect + return; + } + + // build type selector-required map + var map = new Dictionary (); + foreach (var ca in td.CustomAttributes) { + string export = null; + string g_export = null; + string s_export = null; + bool is_required = false; + bool is_property = false; + switch (ca.Constructor.DeclaringType.Name) { + case "ProtocolMemberAttribute": + foreach (var p in ca.Properties) { + switch (p.Name) { + case "Selector": + export = p.Argument.Value as string; + break; + case "GetterSelector": + g_export = p.Argument.Value as string; + break; + case "SetterSelector": + s_export = p.Argument.Value as string; + break; + case "IsRequired": + is_required = (bool)p.Argument.Value; + break; + case "IsProperty": + is_property = (bool)p.Argument.Value; + break; + } + } + break; + } + if (is_property) { + if (g_export != null) + map.Add (g_export, is_required); + if (s_export != null) + map.Add (s_export, is_required); + } else { + if (export != null) + map.Add (export, is_required); + } + } + + var remaining = new Dictionary (map); + + // check that required members match the [Abstract] members + foreach (ObjCMethodDecl method in decl.Methods) { + // some members might not be part of the current platform + if (!method.IsAvailable ()) + continue; + + var selector = GetSelector (method); + if (selector == null) + continue; + + // a .NET interface cannot have constructors - so we cannot enforce that on the interface + if (IsInit (selector)) + continue; + + bool is_abstract; + if (map.TryGetValue (selector, out is_abstract)) { + bool required = method.ImplementationControl == ObjCImplementationControl.Required; + if (required) { + if (!is_abstract) + Console.WriteLine ("!incorrect-protocol-member! {0} is REQUIRED and should be abstract", GetName (decl, method)); + } else { + if (is_abstract) + Console.WriteLine ("!incorrect-protocol-member! {0} is OPTIONAL and should NOT be abstract", GetName (decl, method)); + } + remaining.Remove (selector); + } else if (!method.IsClassMethod) { + // a .NET interface cannot have static methods - so we can only report missing instance methods + Console.WriteLine ("!missing-protocol-member! {0} not found", GetName (decl, method)); + remaining.Remove (selector); + } + } + + foreach (var selector in remaining.Keys) + Console.WriteLine ("!extra-protocol-member! unexpected selector {0}::{1} found", decl.Name, selector); + remaining.Clear (); + map.Clear (); + + protocol_map.Remove (name); + } + + static string GetSelector (ObjCMethodDecl method) + { + var result = method.Selector.ToString (); + if (result != null) + return result; + if (method.IsPropertyAccessor || (method.DeclContext is ObjCProtocolDecl)) + return method.Name; + return null; + } + + static string GetName (ObjCProtocolDecl decl, ObjCMethodDecl method) + { + var sb = new StringBuilder (); + if (method.IsClassMethod) + sb.Append ('+'); + sb.Append (decl.Name); + sb.Append ("::"); + sb.Append (GetSelector (method)); + return sb.ToString (); + } + + bool IsInit (string selector) + { + return selector.StartsWith ("init", StringComparison.Ordinal) && Char.IsUpper (selector [4]); + } + + public override void End () + { + // at this stage anything else we have is not something we could find in Apple's headers + foreach (var extra in protocol_map.Keys) { + Console.WriteLine ("!unknown-protocol! {0} bound", extra); + } + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/Program.cs b/tests/xtro-sharpie/Program.cs new file mode 100644 index 000000000000..6c6363872fb5 --- /dev/null +++ b/tests/xtro-sharpie/Program.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace Extrospection { + + // this is used to be executed from a custom 64bits mono + class MainClass { + + static int Main (string [] args) + { + if (args.Length < 2) { + Console.Error.WriteLine ("Usage: mono64 xtro-sharpie.exe pch-file dll-file [dll2-file]"); + return 1; + } + + try { + var assemblies = new List (); + for (int i = 1; i < args.Length; i++) + assemblies.Add (args [i]); + new Runner ().Execute (args [0], assemblies); + return 0; + } + catch (Exception e) { + Console.WriteLine (e); + return 1; + } + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/README.md b/tests/xtro-sharpie/README.md new file mode 100644 index 000000000000..9224af279802 --- /dev/null +++ b/tests/xtro-sharpie/README.md @@ -0,0 +1,44 @@ +# Extrospection Tests based on ObjectiveSharpie # + + +## Goals + +* Compare our bindings with the information available Apple's C/ObjC header files + + + +## Design + +* The runner visit the provided (managed) assembly first, then it visit the precompiled headers (pch file) for an SDK (e.g. iOS or OSX); + +* Rules can be called at any steps to gather data and or report issues. Rules are also called at the end of the visits; + +* Rules should be kept simple and the external files, e.g. `known-issues`, should be used to track special cases, along with comments with our decisions, i.e. why we tolarate them. That will ease code sharing across existing and new platforms; + + +## Rules + +### Existing + +Those should be _good enough_ to be execute on the bots on each build. + + 1) classify: takes the output from either 'sharpie' or 'all' (ios.results and osx.results files) classifies them in [ios|osx|common].[ignore|pending|unclassified] files + NOTE: to add an entry to the ignore and pending files, just copy the entire line from the unclassified file into them and add your own comments + (why we are not binding/fixing that? who is going to bind this? etc) + +### Work In Progress + +E.g. rules might be too noisy and require refinement, either in code or in external files. + +### Ideas + +Anything we do not check but for which data is available. + + +## Notes + +* To develop you need a checkout of ObjectiveSharpie + +* clang is only built for 64bits so you need a 64bits mono to execute the tool. That might change to reuse Sharpie own runtime once it's installed on every bots; + +* To be able to use XS to build/debug you need to set your runtime to a mono that was compiled with 64bits support. The currenylu shipping Mono version (4.0) does not ship with a 64bits runtime for OSX; diff --git a/tests/xtro-sharpie/Runner.cs b/tests/xtro-sharpie/Runner.cs new file mode 100644 index 000000000000..5abbf6b6960f --- /dev/null +++ b/tests/xtro-sharpie/Runner.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public class Runner { + + public Runner () + { + } + + public void Execute (string pchFile, IEnumerable assemblyNames) + { + var managed_reader = new AssemblyReader () { + new DesignatedInitializerCheck (), + new DllImportCheck (), + new EnumCheck (), + new FieldCheck (), // very noisy now, some stuff are still manually bound / harder to detect + new ObjCInterfaceCheck (), + new ObjCProtocolCheck (), + new SelectorCheck (), +// new ListNative (), // for debug + }; + foreach (var assemblyName in assemblyNames) { + var name = Path.GetFileNameWithoutExtension (assemblyName); + if (name.EndsWith (".iOS", StringComparison.Ordinal)) + Helpers.Platform = "ios"; + else if (name.EndsWith (".Mac", StringComparison.Ordinal)) + Helpers.Platform = "osx"; + else if (name.EndsWith (".WatchOS", StringComparison.Ordinal)) + Helpers.Platform = "watchos"; + else if (name.EndsWith (".TVOS", StringComparison.Ordinal)) + Helpers.Platform = "tvos"; + managed_reader.Load (assemblyName); + } + + var reader = new AstReader (); + foreach (var v in managed_reader) + reader.TranslationUnitParsed += tu => tu.Accept (v); + reader.Load (pchFile); + + managed_reader.End (); + } + } + + class AssemblyReader : IEnumerable { + + public void Load (string filename) + { + var ad = AssemblyDefinition.ReadAssembly (filename); + foreach (var v in Visitors) { + v.VisitManagedAssembly (ad); + foreach (var module in ad.Modules) { + v.VisitManagedModule (module); + if (!module.HasTypes) + continue; + foreach (var td in module.Types) + ProcessType (v, td); + } + } + } + + void ProcessType (BaseVisitor v, TypeDefinition type) + { + v.VisitManagedType (type); + if (type.HasMethods) { + foreach (var md in type.Methods) + v.VisitManagedMethod (md); + } + + if (type.HasNestedTypes) { + foreach (var nested in type.NestedTypes) + ProcessType (v, nested); + } + } + + List Visitors { get; } = new List (); + + public void Add (BaseVisitor visitor) + { + Visitors.Add (visitor); + } + + public void End () + { + foreach (var v in Visitors) + v.End (); + } + + public IEnumerator GetEnumerator () + { + return Visitors.GetEnumerator (); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + { + return Visitors.GetEnumerator (); + } + } + + public class BaseVisitor : AstVisitor { + + public virtual void VisitManagedAssembly (AssemblyDefinition assembly) + { + } + + public virtual void VisitManagedModule (ModuleDefinition module) + { + } + + public virtual void VisitManagedType (TypeDefinition type) + { + } + + public virtual void VisitManagedMethod (MethodDefinition method) + { + } + + // last chance to report errors + public virtual void End () + { + } + } + + + // debug + class ListNative : BaseVisitor { + + public override void VisitDecl (Decl decl) + { + if (decl is FunctionDecl) + ; + else if (decl is VarDecl) + ; + else if (decl is ObjCProtocolDecl) + ; + else if (decl is ObjCInterfaceDecl) + ; + else if (decl is EnumDecl) + ; + else + Console.WriteLine ("{0}\t{1}", decl, decl.GetType ().Name); + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/SelectorCheck.cs b/tests/xtro-sharpie/SelectorCheck.cs new file mode 100644 index 000000000000..5372a5904d1b --- /dev/null +++ b/tests/xtro-sharpie/SelectorCheck.cs @@ -0,0 +1,125 @@ +// +// The rule reports +// +// !missing-selector! +// if headers defines a selector for which we have no bindings +// +// !unknown-selector! +// if we have a selector that is not part of the header files +// + +using System; +using System.Collections.Generic; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection { + + public class SelectorCheck : BaseVisitor { +// Dictionary> exports = new Dictionary> (); + + // missing + // -> it's not in the type or ancestor or their interface (protocols) + // -> it's not in a category + + // unknown + // -> quick check (HashSet) to see if it's used anywhere + // -> + + // duplicate + // -> the selector is defined more than once for the same type + + HashSet known_selectors = new HashSet (); + + HashSet qualified_selectors = new HashSet (); + + //Dictionary> type_exports = new Dictionary> (); + + // most selectors will be found in [Export] attribtues + public override void VisitManagedMethod (MethodDefinition method) + { + if (!method.HasCustomAttributes) + return; + + var type = method.DeclaringType; + // we do not process protocols here + if (type.IsProtocol ()) + return; + + foreach (var ca in method.CustomAttributes) { + switch (ca.Constructor.DeclaringType.Name) { + case "ExportAttribute": + string selector = ca.ConstructorArguments [0].Value as string; + if (!known_selectors.Contains (selector)) + known_selectors.Add (selector); + + qualified_selectors.Add (method.GetName ()); +// +// TypeDefinition type = method.DeclaringType; +// HashSet list; +// if (!type_exports.TryGetValue (type, out list)) { +// list = new HashSet (); +// type_exports.Add (type, list); +// } +// list.Add (selector); + break; + } + } + } + + public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + + // protocol members are checked in ObjCProtocolCheck + if (decl.DeclContext is ObjCProtocolDecl) + return; + + // don't process methods (or types) that are unavailable for the current platform + if (!decl.IsAvailable () || !(decl.DeclContext as Decl).IsAvailable ()) + return; + + string selector = decl.GetSelector (); + if (String.IsNullOrEmpty (selector)) + return; + + var name = (decl.IsClassMethod ? "+" : String.Empty) + decl.QualifiedName; + bool found = qualified_selectors.Contains (name); + if (!found) { + // a category could be inlined into the type it extend + var category = decl.DeclContext as ObjCCategoryDecl; + if (category != null) { + var cname = category.Name; + if (cname == null) + name = GetCategoryBase (category) + name; + else + name = name.ReplaceFirstInstance (cname, GetCategoryBase (category)); + found = qualified_selectors.Contains (name); + } + } + if (!found) + Console.WriteLine ("!missing-selector! {0} not bound", name); + } + + static string GetCategoryBase (ObjCCategoryDecl category) + { + // I really dislike doing this + switch (category.Name) { + case "UIResponderStandardEditActions": + // we inlined this protocol in UIResponder but Apple has it on NSObject + return "UIResponder"; + case "UIAccessibility": + // we inlined this protocol in UIView... but Apple has it on NSObject + return "UIView"; + case "UIAccessibilityAction": + // we inlined this protocol in UIResponder but Apple has it on NSObject + return "UIResponder"; + default: + return category.ClassInterface.Name; + } + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/SharpieEntryPoint.cs b/tests/xtro-sharpie/SharpieEntryPoint.cs new file mode 100644 index 000000000000..8216c3ea79ce --- /dev/null +++ b/tests/xtro-sharpie/SharpieEntryPoint.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.IO; + +using Sharpie; +using Sharpie.Tooling; + +namespace Extrospection { + + [Tool ("extro", "Run extrospection tests", 500)] + public class SharpieEntryPoint : CommonTool { + + protected override void Run () + { + // ensure Mono.Cecil.dll will be in the directory where this is built + typeof (Mono.Cecil.AssemblyDefinition).ToString (); + + base.Run (); + + var pch = PositionalArguments.DequeueOrDefault (); + if (pch == null || !File.Exists (pch)) + throw new ExitException ("Precompiled header file (pch) must be specified"); + + var assemblies = new List (); + while (PositionalArguments.Count > 0) { + var dll = PositionalArguments.DequeueOrDefault (); + if (dll == null || !File.Exists (dll)) + throw new ExitException ("Assembly file (dll) must be specified"); + + assemblies.Add (dll); + } + new Runner ().Execute (pch, assemblies); + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/common.ignore b/tests/xtro-sharpie/common.ignore new file mode 100644 index 000000000000..dd14afedef5a --- /dev/null +++ b/tests/xtro-sharpie/common.ignore @@ -0,0 +1,54 @@ +# AVFoundation + +# We only bind "finished" as we cannot use [Bind] here as it would break compatibility with iOS 6.x +# `isFinished` was only added in iOS 7.0 SDK and cannot be called in earlier versions +!missing-selector! AVAssetResourceLoadingRequest::isFinished not bound + +# it's already defined in the base class, it's fine even if it returns mutable tracks in this case +!missing-selector! AVMutableComposition::tracks not bound + +# AVVideoCompositionInstruction is both a class and a protocol - so we have duplicate entries +# and right now only implement the type (protocol can't have the same name anyway) +!missing-selector! AVVideoCompositionInstruction::enablePostProcessing not bound +!missing-selector! AVVideoCompositionInstruction::passthroughTrackID not bound +!missing-selector! AVVideoCompositionInstruction::requiredSourceTrackIDs not bound +!missing-selector! AVVideoCompositionInstruction::timeRange not bound + + +# CoreGraphics + +## deprecated (as the name indicates) and not exposed +!missing-enum! CGGlyphDeprecatedEnum not bound + + +# CoreSpotlight + +## low value (should use OS version for any checks) +!missing-field! CoreSpotlightVersionNumber not bound +!missing-field! CoreSpotlightVersionString not bound + + +# Foundation + +## native long is same size as int (.net long is long long) +!missing-selector! NSNumber::initWithLong: not bound +!missing-selector! NSNumber::initWithUnsignedLong: not bound + + +# GameKit + +## All GKSessionError values were deprecated in iOS7 and we never bound then (no point in adding it now) +!missing-field! GKSessionErrorDomain not bound + + +# ModelIO + +## we only export the overload that expose an NSError +!missing-selector! MDLAsset::exportAssetToURL: not bound + + +# UIKit + +## no point in having p/invoke calls that can be implement with a type cast (byte vs nint) +!missing-pinvoke! NSTextAlignmentFromCTTextAlignment is not bound +!missing-pinvoke! NSTextAlignmentToCTTextAlignment is not bound diff --git a/tests/xtro-sharpie/common.pending b/tests/xtro-sharpie/common.pending new file mode 100644 index 000000000000..e8e05004e18c --- /dev/null +++ b/tests/xtro-sharpie/common.pending @@ -0,0 +1,469 @@ +# CoreData + +## https://bugzilla.xamarin.com/show_bug.cgi?id=34968 +!missing-selector! NSPropertyDescription::renamingIdentifier not bound +!missing-selector! NSPropertyDescription::setRenamingIdentifier: not bound +!missing-selector! NSEntityDescription::renamingIdentifier not bound +!missing-selector! NSEntityDescription::setRenamingIdentifier: not bound +!missing-selector! NSExpressionDescription::expression not bound +!missing-selector! NSExpressionDescription::setExpression: not bound +!missing-selector! NSExpressionDescription::expressionResultType not bound +!missing-selector! NSExpressionDescription::setExpressionResultType: not bound +!missing-selector! +NSFetchRequestExpression::expressionForFetch:context:countOnly: not bound +!missing-selector! NSFetchRequestExpression::requestExpression not bound +!missing-selector! NSFetchRequestExpression::contextExpression not bound +!missing-selector! NSFetchRequestExpression::isCountOnlyRequest not bound +!missing-selector! NSManagedObject::awakeFromSnapshotEvents: not bound +!missing-selector! NSManagedObject::faultingState not bound +!missing-selector! +NSPersistentStoreCoordinator::metadataForPersistentStoreOfType:URL:options:error: not bound +!missing-selector! +NSPersistentStoreCoordinator::setMetadata:forPersistentStoreOfType:URL:options:error: not bound +!missing-selector! +NSMappingModel::inferredMappingModelForSourceModel:destinationModel:error: not bound + + +# CoreGraphics + +## API does not exists on devices (at least for iOS, only simulator) rdar #24734681 +!missing-pinvoke! CGColorConverterCreateSimple is not bound + +## should we bother ? +!missing-pinvoke! CGColorConverterGetTypeID is not bound + + +# Foundation + +## https://bugzilla.xamarin.com/show_bug.cgi?id=35009 +!missing-selector! NSLinguisticAnalysis::linguisticTagsInRange:scheme:options:orthography:tokenRanges: not bound +!missing-selector! NSLinguisticAnalysis::enumerateLinguisticTagsInRange:scheme:options:orthography:usingBlock: not bound + +## https://bugzilla.xamarin.com/show_bug.cgi?id=35012 +!missing-selector! +NSPredicate::predicateWithFormat: not bound +!missing-selector! +NSPredicate::predicateWithFormat:arguments: not bound +!missing-selector! +NSExpression::expressionWithFormat: not bound +!missing-selector! +NSExpression::expressionWithFormat:arguments: not bound +!missing-selector! NSExpression::expressionBlock not bound + +## https://bugzilla.xamarin.com/show_bug.cgi?id=35021 +!missing-selector! NSFileWrapper::initWithSerializedRepresentation: not bound + +## the API exists but is [Sealed], until XAMCORE_4_0, to keep compatible with iOS/Mac profiles +!missing-selector! NSURLSession::getTasksWithCompletionHandler: not bound + + +# SpriteKit + +## https://bugzilla.xamarin.com/show_bug.cgi?id=34946 +!missing-selector! +SKNode::nodeWithFileNamed: not bound +!missing-selector! SKNode::isEqualToNode: not bound +!missing-selector! +SKUniform::uniformWithName: not bound +!missing-selector! +SKUniform::uniformWithName:texture: not bound +!missing-selector! +SKUniform::uniformWithName:float: not bound +!missing-selector! +SKUniform::uniformWithName:floatVector2: not bound +!missing-selector! +SKUniform::uniformWithName:floatVector3: not bound +!missing-selector! +SKUniform::uniformWithName:floatVector4: not bound +!missing-selector! +SKUniform::uniformWithName:floatMatrix2: not bound +!missing-selector! +SKUniform::uniformWithName:floatMatrix3: not bound +!missing-selector! +SKUniform::uniformWithName:floatMatrix4: not bound +!missing-selector! +SKActions::falloffTo:duration: not bound +!missing-selector! +SKVideoNode::videoNodeWithFileNamed: not bound +!missing-selector! +SKVideoNode::videoNodeWithURL: not bound + +## https://bugzilla.xamarin.com/show_bug.cgi?id=37727 +!missing-selector! SKVideoNode::initWithFileNamed: not bound +!missing-selector! SKVideoNode::initWithURL: not bound + + +# UIKit + +## https://bugzilla.xamarin.com/show_bug.cgi?id=34913 +!missing-protocol-member! UITextInput::selectionAffinity not found +!missing-protocol-member! UITextInput::setSelectionAffinity: not found + +## ctor signature conflict, dev can use colorWithHue:saturation:brightness:alpha: +!missing-selector! UIColor::initWithHue:saturation:brightness:alpha: not bound + + +# Issues we want to ignore that are common to both iOS and OSX + +## might not be usable unless our ToString output is parsable as an input (includes locale issues) +!missing-pinvoke! CFUUIDCreateFromString is not bound +!missing-pinvoke! CGAffineTransformFromString is not bound +!missing-pinvoke! CGPointFromString is not bound +!missing-pinvoke! CGRectFromString is not bound +!missing-pinvoke! CGSizeFromString is not bound +!missing-pinvoke! NSStringFromCGAffineTransform is not bound +!missing-pinvoke! NSStringFromCGPoint is not bound +!missing-pinvoke! NSStringFromCGRect is not bound +!missing-pinvoke! NSStringFromCGSize is not bound +!missing-pinvoke! NSStringFromUIOffset is not bound +!missing-pinvoke! UIOffsetFromString is not bound + + +# missing - pending decision for implementation +!missing-type! NSAssertionHandler not bound + +## collections - many are special +!missing-type! NSCountedSet not bound +!missing-type! NSHashTable not bound +!missing-type! NSMapTable not bound +!missing-type! NSPointerArray not bound +!missing-type! NSPointerFunctions not bound + +# regex +!missing-type! NSDataDetector not bound +!missing-type! NSRegularExpression not bound +!missing-enum! NSRegularExpressionOptions not bound + +!missing-type! NSDecimalNumberHandler not bound +!missing-protocol! NSDecimalNumberBehaviors not bound + +## coredata +!missing-type! NSExpressionDescription not bound +!missing-type! NSFetchRequestExpression not bound + +## stub for CFFileSecurity? +!missing-type! NSFileSecurity not bound + +## related to bound NSOperation +!missing-type! NSInvocationOperation not bound + +## not recommanded, noted as it _may_ be deprecated in 10.6 +!missing-type! NSMessagePort not bound + +## string scanning, looks helpful (porting code) +!missing-type! NSScanner not bound + +## abstract +!missing-type! NSValueTransformer not bound + + +# to be reviewed +!missing-protocol! OS_dispatch_data not bound +!missing-protocol! OS_dispatch_group not bound +!missing-protocol! OS_dispatch_io not bound +!missing-protocol! OS_dispatch_object not bound +!missing-protocol! OS_dispatch_queue not bound +!missing-protocol! OS_dispatch_queue_attr not bound +!missing-protocol! OS_dispatch_semaphore not bound +!missing-protocol! OS_dispatch_source not bound + +## there's a type of the same name (like NSObject, check what Swift did) +!missing-protocol! AVVideoCompositionInstruction not bound + + +# untyped enums (only values, not type name) + +# NSError.h +!unknown-native-enum! NSUrlErrorCancelledReason bound + + +# fixed in XAMCORE_3_0 - API break +!incorrect-protocol-member! AVAssetResourceLoaderDelegate::resourceLoader:shouldWaitForLoadingOfRequestedResource: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! GKMatchmakerViewControllerDelegate::matchmakerViewController:didFindHostedPlayers: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! GKMatchmakerViewControllerDelegate::matchmakerViewController:didFindMatch: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! GKMatchmakerViewControllerDelegate::matchmakerViewController:didFindPlayers: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! GKTurnBasedMatchmakerViewControllerDelegate::turnBasedMatchmakerViewController:didFindMatch: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! GKTurnBasedMatchmakerViewControllerDelegate::turnBasedMatchmakerViewController:playerQuitForMatch: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! AVAudioMixing::destinationForMixer:bus: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLBlitCommandEncoder::copyFromBuffer:sourceOffset:sourceBytesPerRow:sourceBytesPerImage:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:options: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLBlitCommandEncoder::copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toBuffer:destinationOffset:destinationBytesPerRow:destinationBytesPerImage:options: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLDevice::newComputePipelineStateWithDescriptor:options:completionHandler: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLDevice::newComputePipelineStateWithDescriptor:options:reflection:error: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLDevice::supportsTextureSampleCount: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLRenderCommandEncoder::setDepthClipMode: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLRenderCommandEncoder::setStencilFrontReferenceValue:backReferenceValue: is REQUIRED and should be abstract +!incorrect-protocol-member! MTLTexture::newTextureViewWithPixelFormat:textureType:levels:slices: is REQUIRED and should be abstract +!incorrect-protocol-member! SCNSceneRenderer::nodesInsideFrustumWithPointOfView: is REQUIRED and should be abstract +!incorrect-protocol-member! SCNSceneRenderer::presentScene:withTransition:incomingPointOfView:completionHandler: is REQUIRED and should be abstract +!incorrect-protocol-member! SCNSceneRenderer::setAudioListener: is REQUIRED and should be abstract +!incorrect-protocol-member! SCNSceneRenderer::setDebugOptions: is REQUIRED and should be abstract + +!incorrect-protocol-member! NSProgressReporting::progress is REQUIRED and should be abstract + + + +# not public +!missing-type! NSConstantString not bound +!missing-type! NSSimpleCString not bound + +# special case, see bug https://bugzilla.xamarin.com/show_bug.cgi?id=22940 +!missing-type! NSProxy not bound + +# Protocols we decided not to expose +!missing-protocol! NSFastEnumeration not bound +!missing-protocol-conformance! NSArray should conform to NSFastEnumeration +!missing-protocol-conformance! NSDictionary should conform to NSFastEnumeration +!missing-protocol-conformance! NSEntityDescription should conform to NSFastEnumeration +!missing-protocol-conformance! NSEnumerator should conform to NSFastEnumeration +!missing-protocol-conformance! NSManagedObjectModel should conform to NSFastEnumeration +!missing-protocol-conformance! NSOrderedSet should conform to NSFastEnumeration +!missing-protocol-conformance! NSSet should conform to NSFastEnumeration +!missing-protocol-conformance! PHFetchResult should conform to NSFastEnumeration +!missing-protocol-conformance! CMSensorDataList should conform to NSFastEnumeration +!missing-protocol-conformance! MDLAsset should conform to NSFastEnumeration +!missing-protocol-conformance! MDLMaterial should conform to NSFastEnumeration +!missing-protocol-conformance! GKBehavior should conform to NSFastEnumeration +!missing-protocol-conformance! GKComponentSystem should conform to NSFastEnumeration + +# API we decided not to bind, e.g. better alternative in .NET +!missing-enum! NSXMLParserExternalEntityResolvingPolicy not bound +!missing-enum! NSXMLParserError not bound +!missing-type! NSXMLParser not bound +!missing-selector! NSXMLParser::abortParsing is not bound +!missing-selector! NSXMLParser::allowedExternalEntityURLs is not bound +!missing-selector! NSXMLParser::delegate is not bound +!missing-selector! NSXMLParser::externalEntityResolvingPolicy is not bound +!missing-selector! NSXMLParser::initWithContentsOfURL: is not bound +!missing-selector! NSXMLParser::initWithData: is not bound +!missing-selector! NSXMLParser::initWithStream: is not bound +!missing-selector! NSXMLParser::parse is not bound +!missing-selector! NSXMLParser::parserError is not bound +!missing-selector! NSXMLParser::setAllowedExternalEntityURLs: is not bound +!missing-selector! NSXMLParser::setDelegate: is not bound +!missing-selector! NSXMLParser::setExternalEntityResolvingPolicy: is not bound +!missing-selector! NSXMLParser::setShouldProcessNamespaces: is not bound +!missing-selector! NSXMLParser::setShouldReportNamespacePrefixes: is not bound +!missing-selector! NSXMLParser::setShouldResolveExternalEntities: is not bound +!missing-selector! NSXMLParser::shouldProcessNamespaces is not bound +!missing-selector! NSXMLParser::shouldReportNamespacePrefixes is not bound +!missing-selector! NSXMLParser::shouldResolveExternalEntities is not bound +!missing-protocol! NSXMLParserDelegate not bound +!missing-selector! NSXMLParserDelegate::parser:didEndElement:namespaceURI:qualifiedName: is not bound +!missing-selector! NSXMLParserDelegate::parser:didEndMappingPrefix: is not bound +!missing-selector! NSXMLParserDelegate::parser:didStartElement:namespaceURI:qualifiedName:attributes: is not bound +!missing-selector! NSXMLParserDelegate::parser:didStartMappingPrefix:toURI: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundAttributeDeclarationWithName:forElement:type:defaultValue: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundCDATA: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundCharacters: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundComment: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundElementDeclarationWithName:model: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundExternalEntityDeclarationWithName:publicID:systemID: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundIgnorableWhitespace: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundInternalEntityDeclarationWithName:value: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundNotationDeclarationWithName:publicID:systemID: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundProcessingInstructionWithTarget:data: is not bound +!missing-selector! NSXMLParserDelegate::parser:foundUnparsedEntityDeclarationWithName:publicID:systemID:notationName: is not bound +!missing-selector! NSXMLParserDelegate::parser:parseErrorOccurred: is not bound +!missing-selector! NSXMLParserDelegate::parser:resolveExternalEntityName:systemID: is not bound +!missing-selector! NSXMLParserDelegate::parser:validationErrorOccurred: is not bound +!missing-selector! NSXMLParserDelegate::parserDidEndDocument: is not bound +!missing-selector! NSXMLParserDelegate::parserDidStartDocument: is not bound + + +# Accelerate.framework +!missing-enum! CBLAS_DIAG not bound +!missing-enum! CBLAS_ORDER not bound +!missing-enum! CBLAS_SIDE not bound +!missing-enum! CBLAS_TRANSPOSE not bound +!missing-enum! CBLAS_UPLO not bound +!missing-protocol! OS_la_object not bound + + +# Security + +## untyped enum in Security.framework/Headers/SecPolicy.h but the API use CFOptionFlags +!unknown-native-enum! SecRevocation bound + + +# internal types +!unknown-type! __MonoMac_ActionDispatcher bound +!unknown-type! __MonoMac_NSActionDispatcher bound +!unknown-type! __MonoMac_NSAsyncActionDispatcher bound +!unknown-type! __MonoTouch_UIImageStatusDispatcher bound +!unknown-type! __MonoTouch_UIVideoStatusDispatcher bound +!unknown-type! __Xamarin_NSTimerActionDispatcher bound +!unknown-type! UIControlEventProxy bound +!unknown-type! InternalNSNotificationHandler bound +!unknown-type! MonoTouch_GKSession_ReceivedObject bound + + +# internal functions +!unknown-pinvoke! xamarin_init_nsthread bound +!unknown-pinvoke! xamarin_start_wwan bound +!unknown-pinvoke! xamarin_release_managed_ref bound +!unknown-pinvoke! xamarin_create_managed_ref bound +!unknown-pinvoke! xamarin_get_block_descriptor bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr_IntPtr_UInt32 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr_IntPtr_UInt32 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr_IntPtr_UInt64 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr_IntPtr_UInt64 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr_nint_nint_nint_UInt32 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr_nint_nint_nint_UInt32 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr_nint_nint_nint_UInt64 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr_nint_nint_nint_UInt64 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr_UInt32_nint_UInt32 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr_UInt32_nint_UInt32 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSend_IntPtr_UInt64_nint_UInt64 bound +!unknown-pinvoke! xamarin_IntPtr_objc_msgSendSuper_IntPtr_UInt64_nint_UInt64 bound + + +# should we bother ? + +## *GetTypeID +!missing-pinvoke! CFAttributedStringGetTypeID is not bound +!missing-pinvoke! CFBagGetTypeID is not bound +!missing-pinvoke! CFBinaryHeapGetTypeID is not bound +!missing-pinvoke! CFBitVectorGetTypeID is not bound +!missing-pinvoke! CFBundleGetTypeID is not bound +!missing-pinvoke! CFCalendarGetTypeID is not bound +!missing-pinvoke! CFCharacterSetGetTypeID is not bound +!missing-pinvoke! CFDateFormatterGetTypeID is not bound +!missing-pinvoke! CFErrorGetTypeID is not bound +!missing-pinvoke! CFFileDescriptorGetTypeID is not bound +!missing-pinvoke! CFFileSecurityGetTypeID is not bound +!missing-pinvoke! CFHostGetTypeID is not bound +!missing-pinvoke! CFLocaleGetTypeID is not bound +!missing-pinvoke! CFMachPortGetTypeID is not bound +!missing-pinvoke! CFMessagePortGetTypeID is not bound +!missing-pinvoke! CFNetServiceBrowserGetTypeID is not bound +!missing-pinvoke! CFNetServiceGetTypeID is not bound +!missing-pinvoke! CFNetServiceMonitorGetTypeID is not bound +!missing-pinvoke! CFNotificationCenterGetTypeID is not bound +!missing-pinvoke! CFNullGetTypeID is not bound +!missing-pinvoke! CFNumberFormatterGetTypeID is not bound +!missing-pinvoke! CFPlugInGetTypeID is not bound +!missing-pinvoke! CFPlugInInstanceGetTypeID is not bound +!missing-pinvoke! CFReadStreamGetTypeID is not bound +!missing-pinvoke! CFRunLoopGetTypeID is not bound +!missing-pinvoke! CFRunLoopObserverGetTypeID is not bound +!missing-pinvoke! CFRunLoopSourceGetTypeID is not bound +!missing-pinvoke! CFRunLoopTimerGetTypeID is not bound +!missing-pinvoke! CFSetGetTypeID is not bound +!missing-pinvoke! CFSocketGetTypeID is not bound +!missing-pinvoke! CFStringTokenizerGetTypeID is not bound +!missing-pinvoke! CFTimeZoneGetTypeID is not bound +!missing-pinvoke! CFTreeGetTypeID is not bound +!missing-pinvoke! CFURLEnumeratorGetTypeID is not bound +!missing-pinvoke! CFUUIDGetTypeID is not bound +!missing-pinvoke! CFWriteStreamGetTypeID is not bound +!missing-pinvoke! CGColorGetTypeID is not bound +!missing-pinvoke! CGColorSpaceGetTypeID is not bound +!missing-pinvoke! CGContextGetTypeID is not bound +!missing-pinvoke! CGDataConsumerGetTypeID is not bound +!missing-pinvoke! CGDataProviderGetTypeID is not bound +!missing-pinvoke! CGFunctionGetTypeID is not bound +!missing-pinvoke! CGGradientGetTypeID is not bound +!missing-pinvoke! CGImageGetTypeID is not bound +!missing-pinvoke! CGLayerGetTypeID is not bound +!missing-pinvoke! CGPDFDocumentGetTypeID is not bound +!missing-pinvoke! CGPDFPageGetTypeID is not bound +!missing-pinvoke! CGPathGetTypeID is not bound +!missing-pinvoke! CGPatternGetTypeID is not bound +!missing-pinvoke! CGShadingGetTypeID is not bound +!missing-pinvoke! CMBlockBufferGetTypeID is not bound +!missing-pinvoke! CMBufferQueueGetTypeID is not bound +!missing-pinvoke! CMClockGetTypeID is not bound +!missing-pinvoke! CMMemoryPoolGetTypeID is not bound +!missing-pinvoke! CMSimpleQueueGetTypeID is not bound +!missing-pinvoke! CMTimebaseGetTypeID is not bound +!missing-pinvoke! CTFontCollectionGetTypeID is not bound +!missing-pinvoke! CTFontDescriptorGetTypeID is not bound +!missing-pinvoke! CTFrameGetTypeID is not bound +!missing-pinvoke! CTFramesetterGetTypeID is not bound +!missing-pinvoke! CTGlyphInfoGetTypeID is not bound +!missing-pinvoke! CTLineGetTypeID is not bound +!missing-pinvoke! CTParagraphStyleGetTypeID is not bound +!missing-pinvoke! CTRubyAnnotationGetTypeID is not bound +!missing-pinvoke! CTRunDelegateGetTypeID is not bound +!missing-pinvoke! CTRunGetTypeID is not bound +!missing-pinvoke! CTTextTabGetTypeID is not bound +!missing-pinvoke! CTTypesetterGetTypeID is not bound +!missing-pinvoke! GLKMatrixStackGetTypeID is not bound +!missing-pinvoke! MTAudioProcessingTapGetTypeID is not bound +!missing-pinvoke! SCNetworkReachabilityGetTypeID is not bound +!missing-pinvoke! SecAccessControlGetTypeID is not bound +!missing-pinvoke! VTCompressionSessionGetTypeID is not bound +!missing-pinvoke! VTDecompressionSessionGetTypeID is not bound +!missing-pinvoke! VTFrameSiloGetTypeID is not bound +!missing-pinvoke! VTMultiPassStorageGetTypeID is not bound + +## implemented in managed code +### ToString / we might not match the output but changing them would be a breaking change for some apps +!missing-pinvoke! NSStringFromCGAffineTransform is not bound +!missing-pinvoke! NSStringFromCGPoint is not bound +!missing-pinvoke! NSStringFromCGRect is not bound +!missing-pinvoke! NSStringFromCGSize is not bound +!missing-pinvoke! NSStringFromUIOffset is not bound +### OTOH the (missing) convertions from an NSString needs to match too +!missing-pinvoke! CGAffineTransformFromString is not bound +!missing-pinvoke! CGPointFromString is not bound +!missing-pinvoke! CGRectFromString is not bound +!missing-pinvoke! CGSizeFromString is not bound +!missing-pinvoke! UIOffsetFromString is not bound + + +## partially bound, non-framework code +## we already check that they exists, at runtime, in the introspection tests +## but we have no plan to bind the remaining of functions from those header files +!unknown-pinvoke! _Block_copy bound +!unknown-pinvoke! _Block_release bound +!unknown-pinvoke! class_addIvar bound +!unknown-pinvoke! class_addMethod bound +!unknown-pinvoke! class_addProtocol bound +!unknown-pinvoke! class_getInstanceVariable bound +!unknown-pinvoke! class_getMethodImplementation bound +!unknown-pinvoke! class_getName bound +!unknown-pinvoke! class_getSuperclass bound +!unknown-pinvoke! close bound +!unknown-pinvoke! dispatch_after_f bound +!unknown-pinvoke! dispatch_apply_f bound +!unknown-pinvoke! dispatch_async_f bound +!unknown-pinvoke! dispatch_barrier_async_f bound +!unknown-pinvoke! dispatch_get_context bound +!unknown-pinvoke! dispatch_get_current_queue bound +!unknown-pinvoke! dispatch_get_global_queue bound +!unknown-pinvoke! dispatch_group_async_f bound +!unknown-pinvoke! dispatch_group_create bound +!unknown-pinvoke! dispatch_group_enter bound +!unknown-pinvoke! dispatch_group_leave bound +!unknown-pinvoke! dispatch_group_notify_f bound +!unknown-pinvoke! dispatch_group_wait bound +!unknown-pinvoke! dispatch_queue_create bound +!unknown-pinvoke! dispatch_queue_get_label bound +!unknown-pinvoke! dispatch_release bound +!unknown-pinvoke! dispatch_resume bound +!unknown-pinvoke! dispatch_retain bound +!unknown-pinvoke! dispatch_set_context bound +!unknown-pinvoke! dispatch_set_target_queue bound +!unknown-pinvoke! dispatch_source_cancel bound +!unknown-pinvoke! dispatch_source_create bound +!unknown-pinvoke! dispatch_source_get_data bound +!unknown-pinvoke! dispatch_source_get_handle bound +!unknown-pinvoke! dispatch_source_get_mask bound +!unknown-pinvoke! dispatch_source_merge_data bound +!unknown-pinvoke! dispatch_source_set_cancel_handler bound +!unknown-pinvoke! dispatch_source_set_event_handler bound +!unknown-pinvoke! dispatch_source_set_event_handler_f bound +!unknown-pinvoke! dispatch_source_set_registration_handler bound +!unknown-pinvoke! dispatch_source_set_timer bound +!unknown-pinvoke! dispatch_source_testcancel bound +!unknown-pinvoke! dispatch_suspend bound +!unknown-pinvoke! dispatch_sync_f bound +!unknown-pinvoke! dispatch_time bound +!unknown-pinvoke! dispatch_walltime bound +!unknown-pinvoke! dlclose bound +!unknown-pinvoke! dlerror bound +!unknown-pinvoke! dlopen bound +!unknown-pinvoke! dlsym bound +!unknown-pinvoke! memcpy bound +!unknown-pinvoke! objc_allocateClassPair bound +!unknown-pinvoke! objc_allocateProtocol bound +!unknown-pinvoke! objc_getClass bound +!unknown-pinvoke! objc_getProtocol bound +!unknown-pinvoke! objc_msgSend bound +!unknown-pinvoke! objc_msgSendSuper bound +!unknown-pinvoke! objc_registerClassPair bound +!unknown-pinvoke! objc_registerProtocol bound +!unknown-pinvoke! object_getClass bound +!unknown-pinvoke! object_getInstanceVariable bound +!unknown-pinvoke! object_setInstanceVariable bound +!unknown-pinvoke! open bound +!unknown-pinvoke! protocol_addMethodDescription bound +!unknown-pinvoke! protocol_addProperty bound +!unknown-pinvoke! protocol_addProtocol bound +!unknown-pinvoke! protocol_getName bound +!unknown-pinvoke! sel_getName bound +!unknown-pinvoke! sel_isMapped bound +!unknown-pinvoke! sel_registerName bound +!unknown-pinvoke! uname bound diff --git a/tests/xtro-sharpie/ios.ignore b/tests/xtro-sharpie/ios.ignore new file mode 100644 index 000000000000..51bacd5be4fb --- /dev/null +++ b/tests/xtro-sharpie/ios.ignore @@ -0,0 +1,297 @@ +# iOS specific issues we want to (very likely forever) ignore + +# hacks around Apple - because we want better API :) + +## untyped enum, we took the prefix from values in ABPerson.h +!unknown-native-enum! ABAddressBookError bound + +## typedef is used + untyped enum in ALAssetsLibrary.h: typedef NSUInteger ALAssetsGroupType; +!unknown-native-enum! ALAssetsGroupType bound + + +# CoreImage + +## OSX-only API, rdar #22524785 +## see https://trello.com/c/kpksFWto/6-22524785-coreimage-headers-discrepancies +!missing-selector! CIKernel::setROISelector: not bound + + +## typedef is used + untyped enum in GKPeerPickerController.h: typedef NSUInteger GKPeerPickerConnectionType +!unknown-native-enum! GKPeerPickerConnectionType bound + + +# UIKit + +## typedef is used (no value) in UITextInput.h: typedef NSInteger UITextDirection +!unknown-native-enum! UITextDirection bound + +## macro is used in UIBarCommon.h: #define UIToolbarPosition UIBarPosition +!unknown-native-enum! UIToolbarPosition bound + +## we do not (need to) redefine the tintColor at every level, it will be dispatched to the right type +!missing-selector! UIButton::setTintColor: not bound +!missing-selector! UIButton::tintColor not bound +!missing-selector! UIImageView::setTintColor: not bound +!missing-selector! UIImageView::tintColor not bound +!missing-selector! UINavigationBar::setTintColor: not bound +!missing-selector! UINavigationBar::tintColor not bound +!missing-selector! UIRefreshControl::setTintColor: not bound +!missing-selector! UIRefreshControl::tintColor not bound +!missing-selector! UISearchBar::setTintColor: not bound +!missing-selector! UISearchBar::tintColor not bound +!missing-selector! UISegmentedControl::setTintColor: not bound +!missing-selector! UISegmentedControl::tintColor not bound +!missing-selector! UIStepper::setTintColor: not bound +!missing-selector! UIStepper::tintColor not bound +!missing-selector! UISwitch::setTintColor: not bound +!missing-selector! UISwitch::tintColor not bound +!missing-selector! UITabBar::setTintColor: not bound +!missing-selector! UITabBar::tintColor not bound +!missing-selector! UITableViewHeaderFooterView::setTintColor: not bound +!missing-selector! UITableViewHeaderFooterView::tintColor not bound +!missing-selector! UIToolbar::setTintColor: not bound +!missing-selector! UIToolbar::tintColor not bound + +## methods are [Sealed] so we can't reflect the selector +### Docs: This method is intended to be called, not overridden. +!missing-selector! UIGestureRecognizer::ignorePress:forEvent: not bound +### ARM ABI issue wrt variadic arguments +!missing-selector! UIAlertView::initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles: not bound + + +# XAMCORE_3_0 + +## OSX-only enums +!unknown-native-enum! AVCaptureDeviceTransportControlsPlaybackMode bound +!unknown-native-enum! AVPlayerViewControlsStyle bound +!unknown-native-enum! AVVideoFieldMode bound + +## OSX-only functions - fixed in maccore/master a0ab1a7027fb2afdd240d2bc54ca2bb048d98da4 +## they are physically in iOS but declared as N/A (so private) +!unknown-pinvoke! CGColorCreateGenericGray bound +!unknown-pinvoke! CGColorCreateGenericRGB bound +!unknown-pinvoke! CGColorGetConstantColor bound + +## fixed in maccore/master c741408048f1509fc156ab2c65d88af2dbd29830 +!unknown-selector! UICollectionViewDelegate::scrollViewDidEndDecelerating: bound +!unknown-selector! UICollectionViewDelegate::scrollViewDidEndDragging:willDecelerate: bound +!unknown-selector! UICollectionViewDelegate::scrollViewDidEndScrollingAnimation: bound +!unknown-selector! UICollectionViewDelegate::scrollViewDidEndZooming:withView:atScale: bound +!unknown-selector! UICollectionViewDelegate::scrollViewDidScroll: bound +!unknown-selector! UICollectionViewDelegate::scrollViewDidScrollToTop: bound +!unknown-selector! UICollectionViewDelegate::scrollViewDidZoom: bound +!unknown-selector! UICollectionViewDelegate::scrollViewShouldScrollToTop: bound +!unknown-selector! UICollectionViewDelegate::scrollViewWillBeginDecelerating: bound +!unknown-selector! UICollectionViewDelegate::scrollViewWillBeginDragging: bound +!unknown-selector! UICollectionViewDelegate::scrollViewWillBeginZooming:withView: bound +!unknown-selector! UICollectionViewDelegate::scrollViewWillEndDragging:withVelocity:targetContentOffset: bound +!unknown-selector! UICollectionViewDelegate::viewForZoomingInScrollView: bound + +## fixed in maccore/master +!unknown-protocol! SCNSceneExportDelegate bound +!unknown-selector! SCNLight::attributeForKey: bound +!unknown-selector! SCNLight::setAttribute:forKey: bound +!unknown-selector! SCNSceneExportDelegate::writeImage:withSceneDocumentURL:originalImageURL: bound + + +# special cases + +## defined with __Internal (which is normally ignored here) so 3rd party tools can hack it +!missing-pinvoke! UIApplicationMain is not bound + +## not part of the ARM64 API +!unknown-pinvoke! objc_msgSend_stret bound +!unknown-pinvoke! objc_msgSendSuper_stret bound + +## sys/xattr.h: used only internally (for the backup bit) +!unknown-pinvoke! getxattr bound +!unknown-pinvoke! removexattr bound +!unknown-pinvoke! setxattr bound + +## defined twice for iOS (likely to make it available to OSX) +### MKOverlayRenderer.h +### MKOverlayView.h (based on UIView so not in OSX headers list) +!missing-pinvoke! MKRoadWidthAtZoomScale is not bound + +## only on OSX (NA or unused in iOS) +!missing-enum! EKAlarmType not bound +!missing-enum! NSProcessInfoThermalState not bound + +## Xamarin (not Apple) type +!unknown-type! CADisplayLinkTimeSource bound + +## HACK (as documented in uikit.cs) +!incorrect-protocol-member! UITextInputTraits::setAutocapitalizationType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setAutocorrectionType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setEnablesReturnKeyAutomatically: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setKeyboardAppearance: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setKeyboardType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setReturnKeyType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setSecureTextEntry: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setSpellCheckingType: is OPTIONAL and should NOT be abstract + + +## OpenTK duplicates stuff accross versions +!duplicate-type-name! ActiveAttribType enum exists as both OpenTK.Graphics.ES30.ActiveAttribType and OpenTK.Graphics.ES20.ActiveAttribType +!duplicate-type-name! ActiveUniformType enum exists as both OpenTK.Graphics.ES30.ActiveUniformType and OpenTK.Graphics.ES20.ActiveUniformType +!duplicate-type-name! All enum exists as both OpenTK.Graphics.ES20.All and OpenTK.Graphics.ES11.All +!duplicate-type-name! All enum exists as both OpenTK.Graphics.ES30.All and OpenTK.Graphics.ES11.All +!duplicate-type-name! BeginMode enum exists as both OpenTK.Graphics.ES20.BeginMode and OpenTK.Graphics.ES11.BeginMode +!duplicate-type-name! BeginMode enum exists as both OpenTK.Graphics.ES30.BeginMode and OpenTK.Graphics.ES11.BeginMode +!duplicate-type-name! BlendEquationMode enum exists as both OpenTK.Graphics.ES30.BlendEquationMode and OpenTK.Graphics.ES20.BlendEquationMode +!duplicate-type-name! BlendEquationSeparate enum exists as both OpenTK.Graphics.ES30.BlendEquationSeparate and OpenTK.Graphics.ES20.BlendEquationSeparate +!duplicate-type-name! BlendSubtract enum exists as both OpenTK.Graphics.ES30.BlendSubtract and OpenTK.Graphics.ES20.BlendSubtract +!duplicate-type-name! BlendingFactorDest enum exists as both OpenTK.Graphics.ES20.BlendingFactorDest and OpenTK.Graphics.ES11.BlendingFactorDest +!duplicate-type-name! BlendingFactorDest enum exists as both OpenTK.Graphics.ES30.BlendingFactorDest and OpenTK.Graphics.ES11.BlendingFactorDest +!duplicate-type-name! BlendingFactorSrc enum exists as both OpenTK.Graphics.ES20.BlendingFactorSrc and OpenTK.Graphics.ES11.BlendingFactorSrc +!duplicate-type-name! BlendingFactorSrc enum exists as both OpenTK.Graphics.ES30.BlendingFactorSrc and OpenTK.Graphics.ES11.BlendingFactorSrc +!duplicate-type-name! Boolean enum exists as both OpenTK.Graphics.ES20.Boolean and OpenTK.Graphics.ES11.Boolean +!duplicate-type-name! Boolean enum exists as both OpenTK.Graphics.ES30.Boolean and OpenTK.Graphics.ES11.Boolean +!duplicate-type-name! BufferObjects enum exists as both OpenTK.Graphics.ES20.BufferObjects and OpenTK.Graphics.ES11.BufferObjects +!duplicate-type-name! BufferObjects enum exists as both OpenTK.Graphics.ES30.BufferObjects and OpenTK.Graphics.ES11.BufferObjects +!duplicate-type-name! BufferParameterName enum exists as both OpenTK.Graphics.ES30.BufferParameterName and OpenTK.Graphics.ES20.BufferParameterName +!duplicate-type-name! BufferTarget enum exists as both OpenTK.Graphics.ES30.BufferTarget and OpenTK.Graphics.ES20.BufferTarget +!duplicate-type-name! BufferUsage enum exists as both OpenTK.Graphics.ES30.BufferUsage and OpenTK.Graphics.ES20.BufferUsage +!duplicate-type-name! ClearBufferMask enum exists as both OpenTK.Graphics.ES20.ClearBufferMask and OpenTK.Graphics.ES11.ClearBufferMask +!duplicate-type-name! ClearBufferMask enum exists as both OpenTK.Graphics.ES30.ClearBufferMask and OpenTK.Graphics.ES11.ClearBufferMask +!duplicate-type-name! CullFaceMode enum exists as both OpenTK.Graphics.ES20.CullFaceMode and OpenTK.Graphics.ES11.CullFaceMode +!duplicate-type-name! CullFaceMode enum exists as both OpenTK.Graphics.ES30.CullFaceMode and OpenTK.Graphics.ES11.CullFaceMode +!duplicate-type-name! DataType enum exists as both OpenTK.Graphics.ES20.DataType and OpenTK.Graphics.ES11.DataType +!duplicate-type-name! DataType enum exists as both OpenTK.Graphics.ES30.DataType and OpenTK.Graphics.ES11.DataType +!duplicate-type-name! DepthFunction enum exists as both OpenTK.Graphics.ES30.DepthFunction and OpenTK.Graphics.ES20.DepthFunction +!duplicate-type-name! DrawElementsType enum exists as both OpenTK.Graphics.ES30.DrawElementsType and OpenTK.Graphics.ES20.DrawElementsType +!duplicate-type-name! EnableCap enum exists as both OpenTK.Graphics.ES20.EnableCap and OpenTK.Graphics.ES11.EnableCap +!duplicate-type-name! EnableCap enum exists as both OpenTK.Graphics.ES30.EnableCap and OpenTK.Graphics.ES11.EnableCap +!duplicate-type-name! ErrorCode enum exists as both OpenTK.Graphics.ES20.ErrorCode and OpenTK.Graphics.ES11.ErrorCode +!duplicate-type-name! ErrorCode enum exists as both OpenTK.Graphics.ES30.ErrorCode and OpenTK.Graphics.ES11.ErrorCode +!duplicate-type-name! FramebufferErrorCode enum exists as both OpenTK.Graphics.ES30.FramebufferErrorCode and OpenTK.Graphics.ES20.FramebufferErrorCode +!duplicate-type-name! FramebufferObject enum exists as both OpenTK.Graphics.ES30.FramebufferObject and OpenTK.Graphics.ES20.FramebufferObject +!duplicate-type-name! FramebufferParameterName enum exists as both OpenTK.Graphics.ES30.FramebufferParameterName and OpenTK.Graphics.ES20.FramebufferParameterName +!duplicate-type-name! FramebufferSlot enum exists as both OpenTK.Graphics.ES30.FramebufferSlot and OpenTK.Graphics.ES20.FramebufferSlot +!duplicate-type-name! FramebufferTarget enum exists as both OpenTK.Graphics.ES30.FramebufferTarget and OpenTK.Graphics.ES20.FramebufferTarget +!duplicate-type-name! FrontFaceDirection enum exists as both OpenTK.Graphics.ES20.FrontFaceDirection and OpenTK.Graphics.ES11.FrontFaceDirection +!duplicate-type-name! FrontFaceDirection enum exists as both OpenTK.Graphics.ES30.FrontFaceDirection and OpenTK.Graphics.ES11.FrontFaceDirection +!duplicate-type-name! GetPName enum exists as both OpenTK.Graphics.ES20.GetPName and OpenTK.Graphics.ES11.GetPName +!duplicate-type-name! GetPName enum exists as both OpenTK.Graphics.ES30.GetPName and OpenTK.Graphics.ES11.GetPName +!duplicate-type-name! GetTextureParameter enum exists as both OpenTK.Graphics.ES20.GetTextureParameter and OpenTK.Graphics.ES11.GetTextureParameter +!duplicate-type-name! GetTextureParameter enum exists as both OpenTK.Graphics.ES30.GetTextureParameter and OpenTK.Graphics.ES11.GetTextureParameter +!duplicate-type-name! HintMode enum exists as both OpenTK.Graphics.ES20.HintMode and OpenTK.Graphics.ES11.HintMode +!duplicate-type-name! HintMode enum exists as both OpenTK.Graphics.ES30.HintMode and OpenTK.Graphics.ES11.HintMode +!duplicate-type-name! HintTarget enum exists as both OpenTK.Graphics.ES20.HintTarget and OpenTK.Graphics.ES11.HintTarget +!duplicate-type-name! HintTarget enum exists as both OpenTK.Graphics.ES30.HintTarget and OpenTK.Graphics.ES11.HintTarget +!duplicate-type-name! OpenGlEsCoreVersions enum exists as both OpenTK.Graphics.ES20.OpenGlEsCoreVersions and OpenTK.Graphics.ES11.OpenGlEsCoreVersions +!duplicate-type-name! OpenGlEsCoreVersions enum exists as both OpenTK.Graphics.ES30.OpenGlEsCoreVersions and OpenTK.Graphics.ES11.OpenGlEsCoreVersions +!duplicate-type-name! OpenGlescoreVersions enum exists as both OpenTK.Graphics.ES20.OpenGlescoreVersions and OpenTK.Graphics.ES11.OpenGlescoreVersions +!duplicate-type-name! PixelFormat enum exists as both OpenTK.Graphics.ES20.PixelFormat and OpenTK.Graphics.ES11.PixelFormat +!duplicate-type-name! PixelFormat enum exists as both OpenTK.Graphics.ES30.PixelFormat and OpenTK.Graphics.ES11.PixelFormat +!duplicate-type-name! PixelInternalFormat enum exists as both OpenTK.Graphics.ES20.PixelInternalFormat and OpenTK.Graphics.ES11.PixelInternalFormat +!duplicate-type-name! PixelInternalFormat enum exists as both OpenTK.Graphics.ES30.PixelInternalFormat and OpenTK.Graphics.ES11.PixelInternalFormat +!duplicate-type-name! PixelStoreParameter enum exists as both OpenTK.Graphics.ES20.PixelStoreParameter and OpenTK.Graphics.ES11.PixelStoreParameter +!duplicate-type-name! PixelStoreParameter enum exists as both OpenTK.Graphics.ES30.PixelStoreParameter and OpenTK.Graphics.ES11.PixelStoreParameter +!duplicate-type-name! PixelType enum exists as both OpenTK.Graphics.ES20.PixelType and OpenTK.Graphics.ES11.PixelType +!duplicate-type-name! PixelType enum exists as both OpenTK.Graphics.ES30.PixelType and OpenTK.Graphics.ES11.PixelType +!duplicate-type-name! ProgramParameter enum exists as both OpenTK.Graphics.ES30.ProgramParameter and OpenTK.Graphics.ES20.ProgramParameter +!duplicate-type-name! ReadFormat enum exists as both OpenTK.Graphics.ES30.ReadFormat and OpenTK.Graphics.ES20.ReadFormat +!duplicate-type-name! RenderbufferInternalFormat enum exists as both OpenTK.Graphics.ES30.RenderbufferInternalFormat and OpenTK.Graphics.ES20.RenderbufferInternalFormat +!duplicate-type-name! RenderbufferParameterName enum exists as both OpenTK.Graphics.ES30.RenderbufferParameterName and OpenTK.Graphics.ES20.RenderbufferParameterName +!duplicate-type-name! RenderbufferTarget enum exists as both OpenTK.Graphics.ES30.RenderbufferTarget and OpenTK.Graphics.ES20.RenderbufferTarget +!duplicate-type-name! SeparateBlendFunctions enum exists as both OpenTK.Graphics.ES30.SeparateBlendFunctions and OpenTK.Graphics.ES20.SeparateBlendFunctions +!duplicate-type-name! ShaderBinary enum exists as both OpenTK.Graphics.ES30.ShaderBinary and OpenTK.Graphics.ES20.ShaderBinary +!duplicate-type-name! ShaderBinaryFormat enum exists as both OpenTK.Graphics.ES30.ShaderBinaryFormat and OpenTK.Graphics.ES20.ShaderBinaryFormat +!duplicate-type-name! ShaderParameter enum exists as both OpenTK.Graphics.ES30.ShaderParameter and OpenTK.Graphics.ES20.ShaderParameter +!duplicate-type-name! ShaderPrecision enum exists as both OpenTK.Graphics.ES30.ShaderPrecision and OpenTK.Graphics.ES20.ShaderPrecision +!duplicate-type-name! ShaderPrecisionSpecifiedTypes enum exists as both OpenTK.Graphics.ES30.ShaderPrecisionSpecifiedTypes and OpenTK.Graphics.ES20.ShaderPrecisionSpecifiedTypes +!duplicate-type-name! ShaderSource enum exists as both OpenTK.Graphics.ES30.ShaderSource and OpenTK.Graphics.ES20.ShaderSource +!duplicate-type-name! ShaderType enum exists as both OpenTK.Graphics.ES30.ShaderType and OpenTK.Graphics.ES20.ShaderType +!duplicate-type-name! Shaders enum exists as both OpenTK.Graphics.ES30.Shaders and OpenTK.Graphics.ES20.Shaders +!duplicate-type-name! StencilFunction enum exists as both OpenTK.Graphics.ES30.StencilFunction and OpenTK.Graphics.ES20.StencilFunction +!duplicate-type-name! StencilOp enum exists as both OpenTK.Graphics.ES20.StencilOp and OpenTK.Graphics.ES11.StencilOp +!duplicate-type-name! StencilOp enum exists as both OpenTK.Graphics.ES30.StencilOp and OpenTK.Graphics.ES11.StencilOp +!duplicate-type-name! StringName enum exists as both OpenTK.Graphics.ES20.StringName and OpenTK.Graphics.ES11.StringName +!duplicate-type-name! StringName enum exists as both OpenTK.Graphics.ES30.StringName and OpenTK.Graphics.ES11.StringName +!duplicate-type-name! TextureMagFilter enum exists as both OpenTK.Graphics.ES20.TextureMagFilter and OpenTK.Graphics.ES11.TextureMagFilter +!duplicate-type-name! TextureMagFilter enum exists as both OpenTK.Graphics.ES30.TextureMagFilter and OpenTK.Graphics.ES11.TextureMagFilter +!duplicate-type-name! TextureMinFilter enum exists as both OpenTK.Graphics.ES20.TextureMinFilter and OpenTK.Graphics.ES11.TextureMinFilter +!duplicate-type-name! TextureMinFilter enum exists as both OpenTK.Graphics.ES30.TextureMinFilter and OpenTK.Graphics.ES11.TextureMinFilter +!duplicate-type-name! TextureParameterName enum exists as both OpenTK.Graphics.ES20.TextureParameterName and OpenTK.Graphics.ES11.TextureParameterName +!duplicate-type-name! TextureParameterName enum exists as both OpenTK.Graphics.ES30.TextureParameterName and OpenTK.Graphics.ES11.TextureParameterName +!duplicate-type-name! TextureTarget enum exists as both OpenTK.Graphics.ES30.TextureTarget and OpenTK.Graphics.ES20.TextureTarget +!duplicate-type-name! TextureUnit enum exists as both OpenTK.Graphics.ES20.TextureUnit and OpenTK.Graphics.ES11.TextureUnit +!duplicate-type-name! TextureUnit enum exists as both OpenTK.Graphics.ES30.TextureUnit and OpenTK.Graphics.ES11.TextureUnit +!duplicate-type-name! TextureWrapMode enum exists as both OpenTK.Graphics.ES20.TextureWrapMode and OpenTK.Graphics.ES11.TextureWrapMode +!duplicate-type-name! TextureWrapMode enum exists as both OpenTK.Graphics.ES30.TextureWrapMode and OpenTK.Graphics.ES11.TextureWrapMode +!duplicate-type-name! UniformTypes enum exists as both OpenTK.Graphics.ES30.UniformTypes and OpenTK.Graphics.ES20.UniformTypes +!duplicate-type-name! Unknown enum exists as both OpenTK.Graphics.ES20.Unknown and OpenTK.Graphics.ES11.Unknown +!duplicate-type-name! Unknown enum exists as both OpenTK.Graphics.ES30.Unknown and OpenTK.Graphics.ES11.Unknown +!duplicate-type-name! VertexArrays enum exists as both OpenTK.Graphics.ES30.VertexArrays and OpenTK.Graphics.ES20.VertexArrays +!duplicate-type-name! VertexAttribParameter enum exists as both OpenTK.Graphics.ES30.VertexAttribParameter and OpenTK.Graphics.ES20.VertexAttribParameter +!duplicate-type-name! VertexAttribPointerParameter enum exists as both OpenTK.Graphics.ES30.VertexAttribPointerParameter and OpenTK.Graphics.ES20.VertexAttribPointerParameter +!duplicate-type-name! VertexAttribPointerType enum exists as both OpenTK.Graphics.ES30.VertexAttribPointerType and OpenTK.Graphics.ES20.VertexAttribPointerType + + +# old deprecated - old enough that we don't provide bindings for them + +## deprecated in iOS 3 +!missing-selector! UIWebView::detectsPhoneNumbers is not bound +!missing-selector! UIWebView::setDetectsPhoneNumbers: is not bound +!unknown-selector! UITableViewDelegate::tableView:accessoryTypeForRowWithIndexPath: bound + +## deprecated in iOS 3.2 +!missing-selector! CLLocation::getDistanceFrom: is not bound + +# from docs: Important: UIActionSheetDelegate is deprecated in iOS 8. +!missing-protocol-conformance! UIApplication should conform to UIActionSheetDelegate +!missing-protocol-conformance! UIDocumentInteractionController should conform to UIActionSheetDelegate + +# from iOS 4.0 to 5.1 +!unknown-field! AVMediaTypeTimedMetadata bound + +# !XAMCORE_2_0 [Availability (Deprecated = Platform.iOS_3_2, Message = "Use DistanceFrom instead")] +!missing-selector! CLLocation::getDistanceFrom: not bound + +# Deprecated in iOS 3.0. +!missing-selector! UIWebView::detectsPhoneNumbers not bound +!missing-selector! UIWebView::setDetectsPhoneNumbers: not bound + +# Apple UIPrintPaper.h -> UIPrintPaper(Deprecated_Nonfunctional) +!missing-selector! UIPrintPaper::printRect not bound + +# Apple docs: Available in iOS 3.0 through iOS 7.1 +!unknown-selector! NSManagedObject::observationInfo bound +!unknown-selector! NSManagedObject::setObservationInfo: bound + +# Apple docs: deprecated in iOS 3.1 +!unknown-selector! UIImagePickerController::allowsImageEditing bound +!unknown-selector! UIImagePickerController::setAllowsImageEditing: bound + +# Apple docs: Available in iOS 8.0 through iOS 8.2. +!unknown-field! SCNSceneSourceConvertToYUpKey bound +!unknown-field! SCNSceneSourceConvertUnitsToMetersKey bound + +# Apple docs: Deprecated in iOS 4.2. +!unknown-field! ADBannerContentSizeIdentifier320x50 bound +!unknown-field! ADBannerContentSizeIdentifier480x32 bound + +# Apple docs: Deprecated in iOS 3.2 +!unknown-field! UIKeyboardBoundsUserInfoKey bound +!unknown-field! UIKeyboardCenterBeginUserInfoKey bound +!unknown-field! UIKeyboardCenterEndUserInfoKey bound + +# Apple headers: Deprecated in iOS 9 +!unknown-native-enum! ABPersonImageFormat bound + +# Apple headers: Deprecated in iOS 7 +!missing-enum! GKSessionError not bound + +# deprecated in iOS 3.0 +!unknown-selector! UIImagePickerControllerDelegate::imagePickerController:didFinishPickingImage:editingInfo: bound + +# obsoleted in iOS 9 (removed from header files) +!unknown-field! CBUUIDAppearanceString bound +!unknown-field! CBUUIDDeviceNameString bound +!unknown-field! CBUUIDGenericAccessProfileString bound +!unknown-field! CBUUIDGenericAttributeProfileString bound +!unknown-field! CBUUIDPeripheralPreferredConnectionParametersString bound +!unknown-field! CBUUIDPeripheralPrivacyFlagString bound +!unknown-field! CBUUIDReconnectionAddressString bound +!unknown-field! CBUUIDServiceChangedString bound diff --git a/tests/xtro-sharpie/ios.pending b/tests/xtro-sharpie/ios.pending new file mode 100644 index 000000000000..7f6baf0be828 --- /dev/null +++ b/tests/xtro-sharpie/ios.pending @@ -0,0 +1,119 @@ +# iOS specific issues we need to look into + +# CoreMedia + +!missing-field! kCMMetadataKeySpace_HLSDateRange not bound + + +# CoreVideo + +!missing-field! kCVOpenGLESTextureCacheMaximumTextureAgeKey not bound + + +# GameplayKit + +## Apple introduced those types in Xcode 7.1 and removed them afterward !?! +## they do work (intro tests checks them) but thy are not part of the header files +!unknown-type! GKHybridStrategist bound +!unknown-type! GKMonteCarloStrategist bound +!unknown-type! GKQuadTree bound +!unknown-type! GKQuadTreeNode bound + + +# OpenGLES + +!missing-field! kEAGLColorFormatRGB565 not bound +!missing-field! kEAGLColorFormatRGBA8 not bound +!missing-field! kEAGLColorFormatSRGBA8 not bound +!missing-field! kEAGLDrawablePropertyColorFormat not bound +!missing-field! kEAGLDrawablePropertyRetainedBacking not bound + + +# VideoToolbox + +## Apple headers bug, header file VTPixelTransferProperties.h not included by default (!TARGET_OS_IPHONE) +## but API are mentioned as available (and our intro tests results concurs) +!unknown-field! kVTDownsamplingMode_Average bound +!unknown-field! kVTDownsamplingMode_Decimate bound +!unknown-field! kVTPixelTransferPropertyKey_DestinationCleanAperture bound +!unknown-field! kVTPixelTransferPropertyKey_DestinationPixelAspectRatio bound +!unknown-field! kVTPixelTransferPropertyKey_DestinationYCbCrMatrix bound +!unknown-field! kVTPixelTransferPropertyKey_DownsamplingMode bound +!unknown-field! kVTPixelTransferPropertyKey_ScalingMode bound +!unknown-field! kVTScalingMode_CropSourceToCleanAperture bound +!unknown-field! kVTScalingMode_Letterbox bound +!unknown-field! kVTScalingMode_Normal bound +!unknown-field! kVTScalingMode_Trim bound + + +# static methods in protocols are problematic +!missing-selector! +UIViewControllerRestoration::viewControllerWithRestorationIdentifierPath:coder: not bound + +## added in iOS 8.0 +!missing-pinvoke! SecAddSharedWebCredential is not bound +!missing-pinvoke! SecCreateSharedWebCredentialPassword is not bound +!missing-pinvoke! SecRequestSharedWebCredential is not bound +!missing-field! kSecSharedPassword not bound + +# the only member exists in OSX 10.11 - but there are empty protocols so it must be reported (and ignored) +!missing-protocol! AVFragmentMinding not bound + +# Apple docs: This property is inherited from the UIView parent class. This class changes the default value of this property to NO. +!missing-selector! UIImageView::isUserInteractionEnabled not bound +!missing-selector! UIImageView::setUserInteractionEnabled: not bound +!missing-selector! UILabel::isUserInteractionEnabled not bound +!missing-selector! UILabel::setUserInteractionEnabled: not bound + +# added in iOS7 but there was another way to get this ending up with the same name +# so current code works better (before 7.0) but can't be overridden (likely a good thing) +!missing-selector! MPMediaEntity::persistentID not bound + +## UIBarButtonItem.Callback nested type, [UI|NS]*GestureRecognizer.Callback nested types +!unknown-type! Callback bound + +## Implemented in managed code +!missing-selector! UIColor::getHue:saturation:brightness:alpha: not bound +!missing-selector! UIColor::getRed:green:blue:alpha: not bound + + +# does not exists in iOS as a type - but some API refers to it (messy) +!unknown-type! NSPortMessage bound + +# untyped enum but used as a NSInteger in the API, forcing us to use [Native] +!unknown-native-enum! TWRequestMethod bound + +# unfortunate (but required for API compatibility) it also means one seems to be missing (same key) +!duplicate-type-name! WKErrorCode enum exists as both WatchKit.WKErrorCode and WebKit.WKErrorCode +!missing-enum! WKErrorCode not bound + +# Apple renamed it from UILineBreakMode and we kept the old name +!missing-enum! NSLineBreakMode not bound + +# Apple renamed it from NSTextAlignment and we kept the old name +!missing-enum! NSTextAlignment not bound + + +# fixed in XAMCORE_4_0 - API break +!incorrect-protocol-member! ADInterstitialAdDelegate::interstitialAdActionDidFinish: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! ADInterstitialAdDelegate::interstitialAdActionShouldBegin:willLeaveApplication: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! ADInterstitialAdDelegate::interstitialAdDidLoad: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! PKPaymentAuthorizationViewControllerDelegate::paymentAuthorizationViewControllerWillAuthorizePayment: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UIDocumentMenuDelegate::documentMenuWasCancelled: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UIDynamicAnimatorDelegate::dynamicAnimatorDidPause: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UIDynamicAnimatorDelegate::dynamicAnimatorWillResume: is OPTIONAL and should NOT be abstract + + +# should we bother ? + +## *GetTypeID +!missing-pinvoke! CVMetalTextureCacheGetTypeID is not bound +!missing-pinvoke! CVMetalTextureGetTypeID is not bound +!missing-pinvoke! CVOpenGLESTextureCacheGetTypeID is not bound +!missing-pinvoke! CVOpenGLESTextureGetTypeID is not bound + +## availability macro says iOS 8.0 but constants are under a #if !TARGET_OS_IPHONE define. +## introspection does not report them as missing... +!unknown-field! kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder bound +!unknown-field! kVTDecompressionPropertyKey_UsingHardwareAcceleratedVideoDecoder bound +!unknown-field! kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder bound +!unknown-field! kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder bound diff --git a/tests/xtro-sharpie/osx.ignore b/tests/xtro-sharpie/osx.ignore new file mode 100644 index 000000000000..5b63a23942fe --- /dev/null +++ b/tests/xtro-sharpie/osx.ignore @@ -0,0 +1,46 @@ + +# fixed in XAMCORE_3_0 + +## 8a6099b8027fa8e1ad1e032c731c7f750619303e +!duplicate-type-name! NSFileWrapperReadingOptions enum exists as both AppKit.NSFileWrapperReadingOptions and Foundation.NSFileWrapperReadingOptions +!duplicate-type-name! NSWritingDirection enum exists as both AppKit.NSWritingDirection and Foundation.NSWritingDirection + +# Defined in NSObject (NSDeprecatedTextStorageDelegateInterface +!extra-protocol-member! unexpected selector NSTextStorageDelegate::textStorageDidProcessEditing: found +!extra-protocol-member! unexpected selector NSTextStorageDelegate::textStorageWillProcessEditing: found + +# Defined in NSControlTextEditingDelegate - NSTextFieldDelegate +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:didFailToFormatString:errorDescription: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:didFailToValidatePartialString:errorDescription: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:isValidObject: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:textShouldBeginEditing: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:textShouldEndEditing: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:textView:completions:forPartialWordRange:indexOfSelectedItem: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::control:textView:doCommandBySelector: found + +# From header - This method is invoked when the user begins editing text in a control such as a text field or a form field. +# The control posts a NSControlTextDidBeginEditingNotification notification, and if the control’s delegate implements this method, +# it is automatically registered to receive the notification. +!extra-protocol-member! unexpected selector NSRuleEditorDelegate::controlTextDidBeginEditing: found +!extra-protocol-member! unexpected selector NSRuleEditorDelegate::controlTextDidChange: found +!extra-protocol-member! unexpected selector NSRuleEditorDelegate::controlTextDidEndEditing: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::controlTextDidBeginEditing: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::controlTextDidChange: found +!extra-protocol-member! unexpected selector NSTextFieldDelegate::controlTextDidEndEditing: found + +# Defined in NSObject(NSDraggingSourceDeprecated) +!extra-protocol-member! unexpected selector NSDraggingSource::draggingSourceOperationMaskForLocal: found +!extra-protocol-member! unexpected selector NSDraggingSource::draggedImage:beganAt: found +!extra-protocol-member! unexpected selector NSDraggingSource::draggedImage:endedAt:operation: found +!extra-protocol-member! unexpected selector NSDraggingSource::draggedImage:movedTo: found +!extra-protocol-member! unexpected selector NSDraggingSource::ignoreModifierKeysWhileDragging found +!extra-protocol-member! unexpected selector NSDraggingSource::draggedImage:endedAt:deposited: found + +# Defined in NSObject(NSDraggingSourceDeprecated) +!extra-protocol-member! unexpected selector NSDraggingSource::namesOfPromisedFilesDroppedAtDestination: found + +# Defined in NSObject(NSSavePanelDelegateDeprecated) +!extra-protocol-member! unexpected selector NSOpenSavePanelDelegate::panel:compareFilename:with:caseSensitive: found +!extra-protocol-member! unexpected selector NSOpenSavePanelDelegate::panel:directoryDidChange: found +!extra-protocol-member! unexpected selector NSOpenSavePanelDelegate::panel:isValidFilename: found +!extra-protocol-member! unexpected selector NSOpenSavePanelDelegate::panel:shouldShowFilename: found diff --git a/tests/xtro-sharpie/osx.pending b/tests/xtro-sharpie/osx.pending new file mode 100644 index 000000000000..5dd8469e9341 --- /dev/null +++ b/tests/xtro-sharpie/osx.pending @@ -0,0 +1,130 @@ +# OSX specific issues we want to ignore + + +# OSX only - API not exposed in XI even if it's in the header files +!missing-selector! NEVPNProtocol::identityReference is not bound +!missing-selector! NEVPNProtocol::setIdentityReference: is not bound + +# https://bugzilla.xamarin.com/show_bug.cgi?id=30717 +!duplicate-register! _NSDatePickerCellDelegate exists as both AppKit.NSDatePickerCell/_NSDatePickerCellDelegate and AppKit.NSDatePicker/_NSDatePickerCellDelegate + + +# should we bother ? + +## *GetTypeID +!missing-pinvoke! AXObserverGetTypeID is not bound +!missing-pinvoke! AXUIElementGetTypeID is not bound +!missing-pinvoke! AXValueGetTypeID is not bound +!missing-pinvoke! CFUserNotificationGetTypeID is not bound +!missing-pinvoke! CFXMLNodeGetTypeID is not bound +!missing-pinvoke! CFXMLParserGetTypeID is not bound +!missing-pinvoke! CGDisplayModeGetTypeID is not bound +!missing-pinvoke! CGDisplayStreamGetTypeID is not bound +!missing-pinvoke! CGDisplayStreamUpdateGetTypeID is not bound +!missing-pinvoke! CGEventGetTypeID is not bound +!missing-pinvoke! CGEventSourceGetTypeID is not bound +!missing-pinvoke! CGPSConverterGetTypeID is not bound +!missing-pinvoke! CMSDecoderGetTypeID is not bound +!missing-pinvoke! CMSEncoderGetTypeID is not bound +!missing-pinvoke! CSIdentityAuthorityGetTypeID is not bound +!missing-pinvoke! CSIdentityGetTypeID is not bound +!missing-pinvoke! CSIdentityQueryGetTypeID is not bound +!missing-pinvoke! CVDisplayLinkGetTypeID is not bound +!missing-pinvoke! CVOpenGLBufferGetTypeID is not bound +!missing-pinvoke! CVOpenGLBufferPoolGetTypeID is not bound +!missing-pinvoke! CVOpenGLTextureCacheGetTypeID is not bound +!missing-pinvoke! CVOpenGLTextureGetTypeID is not bound +!missing-pinvoke! ColorSyncCMMGetTypeID is not bound +!missing-pinvoke! ColorSyncProfileGetTypeID is not bound +!missing-pinvoke! ColorSyncTransformGetTypeID is not bound +!missing-pinvoke! DAApprovalSessionGetTypeID is not bound +!missing-pinvoke! DADiskGetTypeID is not bound +!missing-pinvoke! DASessionGetTypeID is not bound +!missing-pinvoke! DRBurnGetTypeID is not bound +!missing-pinvoke! DRBurnSessionGetTypeID is not bound +!missing-pinvoke! DRCDTextBlockGetTypeID is not bound +!missing-pinvoke! DRDeviceGetTypeID is not bound +!missing-pinvoke! DREraseGetTypeID is not bound +!missing-pinvoke! DREraseSessionGetTypeID is not bound +!missing-pinvoke! DRFileGetTypeID is not bound +!missing-pinvoke! DRFolderGetTypeID is not bound +!missing-pinvoke! DRNotificationCenterGetTypeID is not bound +!missing-pinvoke! DRTrackGetTypeID is not bound +!missing-pinvoke! FSFileOperationGetTypeID is not bound +!missing-pinvoke! FSFileSecurityGetTypeID is not bound +!missing-pinvoke! HIShapeGetTypeID is not bound +!missing-pinvoke! IOHIDDeviceGetTypeID is not bound +!missing-pinvoke! IOHIDElementGetTypeID is not bound +!missing-pinvoke! IOHIDManagerGetTypeID is not bound +!missing-pinvoke! IOHIDQueueGetTypeID is not bound +!missing-pinvoke! IOHIDTransactionGetTypeID is not bound +!missing-pinvoke! IOHIDValueGetTypeID is not bound +!missing-pinvoke! IOSurfaceGetTypeID is not bound +!missing-pinvoke! InkStrokeGetTypeID is not bound +!missing-pinvoke! InkTextGetTypeID is not bound +!missing-pinvoke! LSMMapGetTypeID is not bound +!missing-pinvoke! LSMResultGetTypeID is not bound +!missing-pinvoke! LSMTextGetTypeID is not bound +!missing-pinvoke! LSSharedFileListGetTypeID is not bound +!missing-pinvoke! LSSharedFileListItemGetTypeID is not bound +!missing-pinvoke! MDItemGetTypeID is not bound +!missing-pinvoke! MDLabelGetTypeID is not bound +!missing-pinvoke! MDQueryGetTypeID is not bound +!missing-pinvoke! ODContextGetTypeID is not bound +!missing-pinvoke! ODNodeGetTypeID is not bound +!missing-pinvoke! ODQueryGetTypeID is not bound +!missing-pinvoke! ODRecordGetTypeID is not bound +!missing-pinvoke! ODSessionGetTypeID is not bound +!missing-pinvoke! PasteboardGetTypeID is not bound +!missing-pinvoke! QLPreviewRequestGetTypeID is not bound +!missing-pinvoke! QLThumbnailGetTypeID is not bound +!missing-pinvoke! QLThumbnailRequestGetTypeID is not bound +!missing-pinvoke! SCBondStatusGetTypeID is not bound +!missing-pinvoke! SCDynamicStoreGetTypeID is not bound +!missing-pinvoke! SCNetworkConnectionGetTypeID is not bound +!missing-pinvoke! SCNetworkInterfaceGetTypeID is not bound +!missing-pinvoke! SCNetworkProtocolGetTypeID is not bound +!missing-pinvoke! SCNetworkServiceGetTypeID is not bound +!missing-pinvoke! SCNetworkSetGetTypeID is not bound +!missing-pinvoke! SCPreferencesGetTypeID is not bound +!missing-pinvoke! SKDocumentGetTypeID is not bound +!missing-pinvoke! SKIndexDocumentIteratorGetTypeID is not bound +!missing-pinvoke! SKIndexGetTypeID is not bound +!missing-pinvoke! SKSearchGetTypeID is not bound +!missing-pinvoke! SKSearchGroupGetTypeID is not bound +!missing-pinvoke! SKSearchResultsGetTypeID is not bound +!missing-pinvoke! SKSummaryGetTypeID is not bound +!missing-pinvoke! SecACLGetTypeID is not bound +!missing-pinvoke! SecAccessGetTypeID is not bound +!missing-pinvoke! SecCodeGetTypeID is not bound +!missing-pinvoke! SecDecryptTransformGetTypeID is not bound +!missing-pinvoke! SecDigestTransformGetTypeID is not bound +!missing-pinvoke! SecEncryptTransformGetTypeID is not bound +!missing-pinvoke! SecGroupTransformGetTypeID is not bound +!missing-pinvoke! SecIdentitySearchGetTypeID is not bound +!missing-pinvoke! SecKeychainGetTypeID is not bound +!missing-pinvoke! SecKeychainItemGetTypeID is not bound +!missing-pinvoke! SecKeychainSearchGetTypeID is not bound +!missing-pinvoke! SecPolicySearchGetTypeID is not bound +!missing-pinvoke! SecRequirementGetTypeID is not bound +!missing-pinvoke! SecStaticCodeGetTypeID is not bound +!missing-pinvoke! SecTaskGetTypeID is not bound +!missing-pinvoke! SecTransformGetTypeID is not bound +!missing-pinvoke! SecTrustedApplicationGetTypeID is not bound +!missing-pinvoke! TISInputSourceGetTypeID is not bound +!missing-pinvoke! TranslationGetTypeID is not bound +!missing-pinvoke! VTPixelTransferSessionGetTypeID is not bound +!missing-pinvoke! WSMethodInvocationGetTypeID is not bound +!missing-pinvoke! WSProtocolHandlerGetTypeID is not bound + +# Used to remove hard to kill delegate API until XAMCORE_4_0 +!extra-protocol-member! unexpected selector CBPeripheralDelegate::xamarin:selector:removed: found +!extra-protocol-member! unexpected selector GKMatchDelegate::xamarin:selector:removed: found +!extra-protocol-member! unexpected selector NSGestureRecognizerDelegate::xamarinselector:removed: found +!extra-protocol-member! unexpected selector NSPasteboardReading::xamarinselector:removed: found +!extra-protocol-member! unexpected selector NSApplicationDelegate::orderFrontStandardAboutPanel: found +!extra-protocol-member! unexpected selector NSApplicationDelegate::orderFrontStandardAboutPanelWithOptions: found +!extra-protocol-member! unexpected selector NSApplicationDelegate::readSelectionFromPasteboard: found +!extra-protocol-member! unexpected selector NSApplicationDelegate::registerServicesMenuSendTypes:returnTypes: found +!extra-protocol-member! unexpected selector NSApplicationDelegate::writeSelectionToPasteboard:types: found + diff --git a/tests/xtro-sharpie/packages.config b/tests/xtro-sharpie/packages.config new file mode 100644 index 000000000000..e304cab94ecf --- /dev/null +++ b/tests/xtro-sharpie/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tests/xtro-sharpie/tvos.ignore b/tests/xtro-sharpie/tvos.ignore new file mode 100644 index 000000000000..31f97fd8b019 --- /dev/null +++ b/tests/xtro-sharpie/tvos.ignore @@ -0,0 +1,353 @@ +# AVFoundation + +## OSX only - but only the member is marked (not the protocol itself) +!missing-protocol! AVFragmentMinding not bound + +## OSX only - category "AVFragmentedAsset (AVFragmentedAssetTrackInspection)" is not decorated +## but AVFragmentedAsset is only available on 10.11 (so it does not build) +!missing-selector! AVFragmentedAsset::trackWithTrackID: not bound +!missing-selector! AVFragmentedAsset::tracksWithMediaCharacteristic: not bound +!missing-selector! AVFragmentedAsset::tracksWithMediaType: not bound + + +# CloudKit + +## shown as available in iOS 9.3 in tvOS header files (from Xcode 7.3) so normally available in tvOS 9.2 +## In reality the selectors only answer in the simulator, not on AppleTV devices +!missing-selector! CKContainer::fetchAllLongLivedOperationIDsWithCompletionHandler: not bound +!missing-selector! CKContainer::fetchLongLivedOperationWithID:completionHandler: not bound + + +# CoreImage + +## Apple bug (mac only) - https://trello.com/c/kpksFWto/6-22524785-coreimage-headers-discrepancies +!missing-selector! CIKernel::setROISelector: not bound + + +# Foundation + +## does not exists in iOS (or watchOS) as a type - but some API refers to it (messy) +!unknown-type! NSPortMessage bound + +## shown as available in iOS 9.3 in tvOS header files (from Xcode 7.3) so normally available in tvOS 9.2 +## In reality it's only available in the simulator, not on AppleTV devices (all fields are null) +!missing-field! NSUbiquitousUserDefaultsCompletedInitialSyncNotification not bound +!missing-field! NSUbiquitousUserDefaultsDidChangeAccountsNotification not bound +!missing-field! NSUserDefaultsSizeLimitExceededNotification not bound + + +# GameKit + +## all members are not available so the protocol is empty +## however this is confusing because some protocols have no members (so it can't just be ignored) +!missing-protocol! GKFriendRequestComposeViewControllerDelegate not bound +!missing-protocol! GKSavedGameListener not bound + +## GKSession is not in the tvOS API but the GKSessionDelegate is not marked +## looks like mistakes as the API is not used anywhere else +## easier to add later, if needed, than remove +!missing-protocol! GKSessionDelegate not bound +!missing-selector! GKSessionDelegate::session:connectionWithPeerFailed:withError: not bound +!missing-selector! GKSessionDelegate::session:didFailWithError: not bound +!missing-selector! GKSessionDelegate::session:didReceiveConnectionRequestFromPeer: not bound +!missing-selector! GKSessionDelegate::session:peer:didChangeState: not bound + +## GKVoiceChatService is not in tvOS so nothing uses GKVoiceChatClient +!missing-protocol! GKVoiceChatClient not bound +!missing-selector! GKVoiceChatClient::participantID not bound +!missing-selector! GKVoiceChatClient::voiceChatService:didNotStartWithParticipantID:error: not bound +!missing-selector! GKVoiceChatClient::voiceChatService:didReceiveInvitationFromParticipantID:callID: not bound +!missing-selector! GKVoiceChatClient::voiceChatService:didStartWithParticipantID: not bound +!missing-selector! GKVoiceChatClient::voiceChatService:didStopWithParticipantID:error: not bound +!missing-selector! GKVoiceChatClient::voiceChatService:sendData:toParticipantID: not bound +!missing-selector! GKVoiceChatClient::voiceChatService:sendRealTimeData:toParticipantID: not bound + + +# MediaPlayer + +## the "owner" type MPMediaEntity is marked with __TVOS_PROHIBITED +## but in reality fields' parents are not the type (DeclContext) +## so the xtro tests cannot know they are not really available +!missing-field! MPMediaEntityPropertyPersistentID not bound + +## the "owner" type MPMediaItem is marked with __TVOS_PROHIBITED +!missing-field! MPMediaItemPropertyAlbumArtist not bound +!missing-field! MPMediaItemPropertyAlbumArtistPersistentID not bound +!missing-field! MPMediaItemPropertyAlbumPersistentID not bound +!missing-field! MPMediaItemPropertyAlbumTitle not bound +!missing-field! MPMediaItemPropertyAlbumTrackCount not bound +!missing-field! MPMediaItemPropertyAlbumTrackNumber not bound +!missing-field! MPMediaItemPropertyArtist not bound +!missing-field! MPMediaItemPropertyArtistPersistentID not bound +!missing-field! MPMediaItemPropertyArtwork not bound +!missing-field! MPMediaItemPropertyAssetURL not bound +!missing-field! MPMediaItemPropertyBeatsPerMinute not bound +!missing-field! MPMediaItemPropertyBookmarkTime not bound +!missing-field! MPMediaItemPropertyComments not bound +!missing-field! MPMediaItemPropertyComposer not bound +!missing-field! MPMediaItemPropertyComposerPersistentID not bound +!missing-field! MPMediaItemPropertyDiscCount not bound +!missing-field! MPMediaItemPropertyDiscNumber not bound +!missing-field! MPMediaItemPropertyGenre not bound +!missing-field! MPMediaItemPropertyGenrePersistentID not bound +!missing-field! MPMediaItemPropertyHasProtectedAsset not bound +!missing-field! MPMediaItemPropertyIsCloudItem not bound +!missing-field! MPMediaItemPropertyIsCompilation not bound +!missing-field! MPMediaItemPropertyLastPlayedDate not bound +!missing-field! MPMediaItemPropertyLyrics not bound +!missing-field! MPMediaItemPropertyMediaType not bound +!missing-field! MPMediaItemPropertyPersistentID not bound +!missing-field! MPMediaItemPropertyPlayCount not bound +!missing-field! MPMediaItemPropertyPlaybackDuration not bound +!missing-field! MPMediaItemPropertyPodcastPersistentID not bound +!missing-field! MPMediaItemPropertyPodcastTitle not bound +!missing-field! MPMediaItemPropertyRating not bound +!missing-field! MPMediaItemPropertyReleaseDate not bound +!missing-field! MPMediaItemPropertySkipCount not bound +!missing-field! MPMediaItemPropertyTitle not bound +!missing-field! MPMediaItemPropertyUserGrouping not bound + +## shown as available in iOS 9.3 in tvOS header files (from Xcode 7.3) so normally available in tvOS 9.2 +## In reality it's only available in the simulator, not on AppleTV devices (all fields are null) +!missing-field! MPMediaPlaylistPropertyAuthorDisplayName not bound +!missing-field! MPMediaPlaylistPropertyDescriptionText not bound + + +## the enum is only used in API marked with __TVOS_PROHIBITED +!missing-enum! MPMediaLibraryAuthorizationStatus not bound + +## in tvOS 9.2 MPContentItem is not marked with __TVOS_PROHIBITED anymore +## however it expose a type that is still marked with __TVOS_PROHIBITED !?! +## and it's also not used by other, available, API +## we're not risking it into our public API until Apple replies to the radar +## https://trello.com/c/2gxuFbeS/38-24982126-mpmediaitemartwork-is-not-available-on-tvos-9-3b5 +!missing-type! MPContentItem not bound +!missing-selector! MPContentItem::artwork not bound +!missing-selector! MPContentItem::identifier not bound +!missing-selector! MPContentItem::initWithIdentifier: not bound +!missing-selector! MPContentItem::isContainer not bound +!missing-selector! MPContentItem::isPlayable not bound +!missing-selector! MPContentItem::playbackProgress not bound +!missing-selector! MPContentItem::setArtwork: not bound +!missing-selector! MPContentItem::setContainer: not bound +!missing-selector! MPContentItem::setPlayable: not bound +!missing-selector! MPContentItem::setPlaybackProgress: not bound +!missing-selector! MPContentItem::setSubtitle: not bound +!missing-selector! MPContentItem::setTitle: not bound +!missing-selector! MPContentItem::subtitle not bound +!missing-selector! MPContentItem::title not bound + + +## Deprecated in iOS 9.0 (in favor of AVKit) and the related type +## MPMoviePlayerController is marked with __TVOS_PROHIBITED +!missing-field! MPMovieDurationAvailableNotification not bound +!missing-field! MPMovieMediaTypesAvailableNotification not bound +!missing-field! MPMovieNaturalSizeAvailableNotification not bound +!missing-field! MPMoviePlayerDidEnterFullscreenNotification not bound +!missing-field! MPMoviePlayerDidExitFullscreenNotification not bound +!missing-field! MPMoviePlayerFullscreenAnimationCurveUserInfoKey not bound +!missing-field! MPMoviePlayerFullscreenAnimationDurationUserInfoKey not bound +!missing-field! MPMoviePlayerIsAirPlayVideoActiveDidChangeNotification not bound +!missing-field! MPMoviePlayerLoadStateDidChangeNotification not bound +!missing-field! MPMoviePlayerNowPlayingMovieDidChangeNotification not bound +!missing-field! MPMoviePlayerPlaybackDidFinishNotification not bound +!missing-field! MPMoviePlayerPlaybackDidFinishReasonUserInfoKey not bound +!missing-field! MPMoviePlayerPlaybackStateDidChangeNotification not bound +!missing-field! MPMoviePlayerReadyForDisplayDidChangeNotification not bound +!missing-field! MPMoviePlayerScalingModeDidChangeNotification not bound +!missing-field! MPMoviePlayerThumbnailErrorKey not bound +!missing-field! MPMoviePlayerThumbnailImageKey not bound +!missing-field! MPMoviePlayerThumbnailImageRequestDidFinishNotification not bound +!missing-field! MPMoviePlayerThumbnailTimeKey not bound +!missing-field! MPMoviePlayerTimedMetadataKeyDataType not bound +!missing-field! MPMoviePlayerTimedMetadataKeyInfo not bound +!missing-field! MPMoviePlayerTimedMetadataKeyLanguageCode not bound +!missing-field! MPMoviePlayerTimedMetadataKeyMIMEType not bound +!missing-field! MPMoviePlayerTimedMetadataKeyName not bound +!missing-field! MPMoviePlayerTimedMetadataUpdatedNotification not bound +!missing-field! MPMoviePlayerTimedMetadataUserInfoKey not bound +!missing-field! MPMoviePlayerWillEnterFullscreenNotification not bound +!missing-field! MPMoviePlayerWillExitFullscreenNotification not bound +!missing-field! MPMovieSourceTypeAvailableNotification not bound + + +# StoreKit + +## SKStoreProductViewController is not in tvOS and the only member of the delegate is not either +## but the delegate itself is not marked (so it's reported as missing) +!missing-protocol! SKStoreProductViewControllerDelegate not bound + + +# UIKit + +## Apple renamed it from UILineBreakMode and we kept the old name +!missing-enum! NSLineBreakMode not bound +!unknown-native-enum! UILineBreakMode bound + +## Apple renamed it from NSTextAlignment and we kept the old name +!missing-enum! NSTextAlignment not bound +!unknown-native-enum! UITextAlignment bound + +## headers uses a NSInteger, we provide an enum +!unknown-native-enum! UITextDirection bound + +## UIBarButtonItem.Callback nested type, [UI|NS]*GestureRecognizer.Callback nested types +!unknown-type! Callback bound + +## Implemented in managed code +!missing-selector! UIColor::getHue:saturation:brightness:alpha: not bound +!missing-selector! UIColor::getRed:green:blue:alpha: not bound + +## the UIActivityItemSource protocol is not marked as unavailable but all it's members use +## UIActivityViewController which is not allowed on tvOS +!missing-protocol! UIActivityItemSource not bound +!missing-selector! UIActivityItemSource::activityViewController:dataTypeIdentifierForActivityType: not bound +!missing-selector! UIActivityItemSource::activityViewController:itemForActivityType: not bound +!missing-selector! UIActivityItemSource::activityViewController:subjectForActivityType: not bound +!missing-selector! UIActivityItemSource::activityViewController:thumbnailImageForActivityType:suggestedSize: not bound +!missing-selector! UIActivityItemSource::activityViewControllerPlaceholderItem: not bound + +## HACK (as documented in uikit.cs) +!incorrect-protocol-member! UITextInputTraits::setAutocapitalizationType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setAutocorrectionType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setEnablesReturnKeyAutomatically: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setKeyboardAppearance: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setKeyboardType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setReturnKeyType: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setSecureTextEntry: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::setSpellCheckingType: is OPTIONAL and should NOT be abstract + +## We only define tintColor on UIView, not on the subclasses (not needed for us) +!missing-selector! UIButton::setTintColor: not bound +!missing-selector! UIButton::tintColor not bound +!missing-selector! UIImageView::setTintColor: not bound +!missing-selector! UIImageView::tintColor not bound +!missing-selector! UINavigationBar::setTintColor: not bound +!missing-selector! UINavigationBar::tintColor not bound +!missing-selector! UISearchBar::setTintColor: not bound +!missing-selector! UISearchBar::tintColor not bound +!missing-selector! UISegmentedControl::setTintColor: not bound +!missing-selector! UISegmentedControl::tintColor not bound +!missing-selector! UITabBar::setTintColor: not bound +!missing-selector! UITabBar::tintColor not bound +!missing-selector! UITableViewHeaderFooterView::setTintColor: not bound +!missing-selector! UITableViewHeaderFooterView::tintColor not bound + + +# OpenTK + +## never been exposed in XI either +!missing-pinvoke! CVOpenGLESTextureCacheGetTypeID is not bound +!missing-pinvoke! CVOpenGLESTextureGetTypeID is not bound + +## duplicates by design +!duplicate-type-name! ActiveAttribType enum exists as both OpenTK.Graphics.ES30.ActiveAttribType and OpenTK.Graphics.ES20.ActiveAttribType +!duplicate-type-name! ActiveUniformType enum exists as both OpenTK.Graphics.ES30.ActiveUniformType and OpenTK.Graphics.ES20.ActiveUniformType +!duplicate-type-name! All enum exists as both OpenTK.Graphics.ES20.All and OpenTK.Graphics.ES11.All +!duplicate-type-name! All enum exists as both OpenTK.Graphics.ES30.All and OpenTK.Graphics.ES11.All +!duplicate-type-name! BeginMode enum exists as both OpenTK.Graphics.ES20.BeginMode and OpenTK.Graphics.ES11.BeginMode +!duplicate-type-name! BeginMode enum exists as both OpenTK.Graphics.ES30.BeginMode and OpenTK.Graphics.ES11.BeginMode +!duplicate-type-name! BlendEquationMode enum exists as both OpenTK.Graphics.ES30.BlendEquationMode and OpenTK.Graphics.ES20.BlendEquationMode +!duplicate-type-name! BlendEquationSeparate enum exists as both OpenTK.Graphics.ES30.BlendEquationSeparate and OpenTK.Graphics.ES20.BlendEquationSeparate +!duplicate-type-name! BlendSubtract enum exists as both OpenTK.Graphics.ES30.BlendSubtract and OpenTK.Graphics.ES20.BlendSubtract +!duplicate-type-name! BlendingFactorDest enum exists as both OpenTK.Graphics.ES20.BlendingFactorDest and OpenTK.Graphics.ES11.BlendingFactorDest +!duplicate-type-name! BlendingFactorDest enum exists as both OpenTK.Graphics.ES30.BlendingFactorDest and OpenTK.Graphics.ES11.BlendingFactorDest +!duplicate-type-name! BlendingFactorSrc enum exists as both OpenTK.Graphics.ES20.BlendingFactorSrc and OpenTK.Graphics.ES11.BlendingFactorSrc +!duplicate-type-name! BlendingFactorSrc enum exists as both OpenTK.Graphics.ES30.BlendingFactorSrc and OpenTK.Graphics.ES11.BlendingFactorSrc +!duplicate-type-name! Boolean enum exists as both OpenTK.Graphics.ES20.Boolean and OpenTK.Graphics.ES11.Boolean +!duplicate-type-name! Boolean enum exists as both OpenTK.Graphics.ES30.Boolean and OpenTK.Graphics.ES11.Boolean +!duplicate-type-name! BufferObjects enum exists as both OpenTK.Graphics.ES20.BufferObjects and OpenTK.Graphics.ES11.BufferObjects +!duplicate-type-name! BufferObjects enum exists as both OpenTK.Graphics.ES30.BufferObjects and OpenTK.Graphics.ES11.BufferObjects +!duplicate-type-name! BufferParameterName enum exists as both OpenTK.Graphics.ES30.BufferParameterName and OpenTK.Graphics.ES20.BufferParameterName +!duplicate-type-name! BufferTarget enum exists as both OpenTK.Graphics.ES30.BufferTarget and OpenTK.Graphics.ES20.BufferTarget +!duplicate-type-name! BufferUsage enum exists as both OpenTK.Graphics.ES30.BufferUsage and OpenTK.Graphics.ES20.BufferUsage +!duplicate-type-name! ClearBufferMask enum exists as both OpenTK.Graphics.ES20.ClearBufferMask and OpenTK.Graphics.ES11.ClearBufferMask +!duplicate-type-name! ClearBufferMask enum exists as both OpenTK.Graphics.ES30.ClearBufferMask and OpenTK.Graphics.ES11.ClearBufferMask +!duplicate-type-name! CullFaceMode enum exists as both OpenTK.Graphics.ES20.CullFaceMode and OpenTK.Graphics.ES11.CullFaceMode +!duplicate-type-name! CullFaceMode enum exists as both OpenTK.Graphics.ES30.CullFaceMode and OpenTK.Graphics.ES11.CullFaceMode +!duplicate-type-name! DataType enum exists as both OpenTK.Graphics.ES20.DataType and OpenTK.Graphics.ES11.DataType +!duplicate-type-name! DataType enum exists as both OpenTK.Graphics.ES30.DataType and OpenTK.Graphics.ES11.DataType +!duplicate-type-name! DepthFunction enum exists as both OpenTK.Graphics.ES30.DepthFunction and OpenTK.Graphics.ES20.DepthFunction +!duplicate-type-name! DrawElementsType enum exists as both OpenTK.Graphics.ES30.DrawElementsType and OpenTK.Graphics.ES20.DrawElementsType +!duplicate-type-name! EnableCap enum exists as both OpenTK.Graphics.ES20.EnableCap and OpenTK.Graphics.ES11.EnableCap +!duplicate-type-name! EnableCap enum exists as both OpenTK.Graphics.ES30.EnableCap and OpenTK.Graphics.ES11.EnableCap +!duplicate-type-name! ErrorCode enum exists as both OpenTK.Graphics.ES20.ErrorCode and OpenTK.Graphics.ES11.ErrorCode +!duplicate-type-name! ErrorCode enum exists as both OpenTK.Graphics.ES30.ErrorCode and OpenTK.Graphics.ES11.ErrorCode +!duplicate-type-name! FramebufferErrorCode enum exists as both OpenTK.Graphics.ES30.FramebufferErrorCode and OpenTK.Graphics.ES20.FramebufferErrorCode +!duplicate-type-name! FramebufferObject enum exists as both OpenTK.Graphics.ES30.FramebufferObject and OpenTK.Graphics.ES20.FramebufferObject +!duplicate-type-name! FramebufferParameterName enum exists as both OpenTK.Graphics.ES30.FramebufferParameterName and OpenTK.Graphics.ES20.FramebufferParameterName +!duplicate-type-name! FramebufferSlot enum exists as both OpenTK.Graphics.ES30.FramebufferSlot and OpenTK.Graphics.ES20.FramebufferSlot +!duplicate-type-name! FramebufferTarget enum exists as both OpenTK.Graphics.ES30.FramebufferTarget and OpenTK.Graphics.ES20.FramebufferTarget +!duplicate-type-name! FrontFaceDirection enum exists as both OpenTK.Graphics.ES20.FrontFaceDirection and OpenTK.Graphics.ES11.FrontFaceDirection +!duplicate-type-name! FrontFaceDirection enum exists as both OpenTK.Graphics.ES30.FrontFaceDirection and OpenTK.Graphics.ES11.FrontFaceDirection +!duplicate-type-name! GetPName enum exists as both OpenTK.Graphics.ES20.GetPName and OpenTK.Graphics.ES11.GetPName +!duplicate-type-name! GetPName enum exists as both OpenTK.Graphics.ES30.GetPName and OpenTK.Graphics.ES11.GetPName +!duplicate-type-name! GetTextureParameter enum exists as both OpenTK.Graphics.ES20.GetTextureParameter and OpenTK.Graphics.ES11.GetTextureParameter +!duplicate-type-name! GetTextureParameter enum exists as both OpenTK.Graphics.ES30.GetTextureParameter and OpenTK.Graphics.ES11.GetTextureParameter +!duplicate-type-name! HintMode enum exists as both OpenTK.Graphics.ES20.HintMode and OpenTK.Graphics.ES11.HintMode +!duplicate-type-name! HintMode enum exists as both OpenTK.Graphics.ES30.HintMode and OpenTK.Graphics.ES11.HintMode +!duplicate-type-name! HintTarget enum exists as both OpenTK.Graphics.ES20.HintTarget and OpenTK.Graphics.ES11.HintTarget +!duplicate-type-name! HintTarget enum exists as both OpenTK.Graphics.ES30.HintTarget and OpenTK.Graphics.ES11.HintTarget +!duplicate-type-name! OpenGlEsCoreVersions enum exists as both OpenTK.Graphics.ES20.OpenGlEsCoreVersions and OpenTK.Graphics.ES11.OpenGlEsCoreVersions +!duplicate-type-name! OpenGlEsCoreVersions enum exists as both OpenTK.Graphics.ES30.OpenGlEsCoreVersions and OpenTK.Graphics.ES11.OpenGlEsCoreVersions +!duplicate-type-name! OpenGlescoreVersions enum exists as both OpenTK.Graphics.ES20.OpenGlescoreVersions and OpenTK.Graphics.ES11.OpenGlescoreVersions +!duplicate-type-name! PixelFormat enum exists as both OpenTK.Graphics.ES20.PixelFormat and OpenTK.Graphics.ES11.PixelFormat +!duplicate-type-name! PixelFormat enum exists as both OpenTK.Graphics.ES30.PixelFormat and OpenTK.Graphics.ES11.PixelFormat +!duplicate-type-name! PixelInternalFormat enum exists as both OpenTK.Graphics.ES20.PixelInternalFormat and OpenTK.Graphics.ES11.PixelInternalFormat +!duplicate-type-name! PixelInternalFormat enum exists as both OpenTK.Graphics.ES30.PixelInternalFormat and OpenTK.Graphics.ES11.PixelInternalFormat +!duplicate-type-name! PixelStoreParameter enum exists as both OpenTK.Graphics.ES20.PixelStoreParameter and OpenTK.Graphics.ES11.PixelStoreParameter +!duplicate-type-name! PixelStoreParameter enum exists as both OpenTK.Graphics.ES30.PixelStoreParameter and OpenTK.Graphics.ES11.PixelStoreParameter +!duplicate-type-name! PixelType enum exists as both OpenTK.Graphics.ES20.PixelType and OpenTK.Graphics.ES11.PixelType +!duplicate-type-name! PixelType enum exists as both OpenTK.Graphics.ES30.PixelType and OpenTK.Graphics.ES11.PixelType +!duplicate-type-name! ProgramParameter enum exists as both OpenTK.Graphics.ES30.ProgramParameter and OpenTK.Graphics.ES20.ProgramParameter +!duplicate-type-name! ReadFormat enum exists as both OpenTK.Graphics.ES30.ReadFormat and OpenTK.Graphics.ES20.ReadFormat +!duplicate-type-name! RenderbufferInternalFormat enum exists as both OpenTK.Graphics.ES30.RenderbufferInternalFormat and OpenTK.Graphics.ES20.RenderbufferInternalFormat +!duplicate-type-name! RenderbufferParameterName enum exists as both OpenTK.Graphics.ES30.RenderbufferParameterName and OpenTK.Graphics.ES20.RenderbufferParameterName +!duplicate-type-name! RenderbufferTarget enum exists as both OpenTK.Graphics.ES30.RenderbufferTarget and OpenTK.Graphics.ES20.RenderbufferTarget +!duplicate-type-name! SeparateBlendFunctions enum exists as both OpenTK.Graphics.ES30.SeparateBlendFunctions and OpenTK.Graphics.ES20.SeparateBlendFunctions +!duplicate-type-name! ShaderBinary enum exists as both OpenTK.Graphics.ES30.ShaderBinary and OpenTK.Graphics.ES20.ShaderBinary +!duplicate-type-name! ShaderBinaryFormat enum exists as both OpenTK.Graphics.ES30.ShaderBinaryFormat and OpenTK.Graphics.ES20.ShaderBinaryFormat +!duplicate-type-name! ShaderParameter enum exists as both OpenTK.Graphics.ES30.ShaderParameter and OpenTK.Graphics.ES20.ShaderParameter +!duplicate-type-name! ShaderPrecision enum exists as both OpenTK.Graphics.ES30.ShaderPrecision and OpenTK.Graphics.ES20.ShaderPrecision +!duplicate-type-name! ShaderPrecisionSpecifiedTypes enum exists as both OpenTK.Graphics.ES30.ShaderPrecisionSpecifiedTypes and OpenTK.Graphics.ES20.ShaderPrecisionSpecifiedTypes +!duplicate-type-name! ShaderSource enum exists as both OpenTK.Graphics.ES30.ShaderSource and OpenTK.Graphics.ES20.ShaderSource +!duplicate-type-name! ShaderType enum exists as both OpenTK.Graphics.ES30.ShaderType and OpenTK.Graphics.ES20.ShaderType +!duplicate-type-name! Shaders enum exists as both OpenTK.Graphics.ES30.Shaders and OpenTK.Graphics.ES20.Shaders +!duplicate-type-name! StencilFunction enum exists as both OpenTK.Graphics.ES30.StencilFunction and OpenTK.Graphics.ES20.StencilFunction +!duplicate-type-name! StencilOp enum exists as both OpenTK.Graphics.ES20.StencilOp and OpenTK.Graphics.ES11.StencilOp +!duplicate-type-name! StencilOp enum exists as both OpenTK.Graphics.ES30.StencilOp and OpenTK.Graphics.ES11.StencilOp +!duplicate-type-name! StringName enum exists as both OpenTK.Graphics.ES20.StringName and OpenTK.Graphics.ES11.StringName +!duplicate-type-name! StringName enum exists as both OpenTK.Graphics.ES30.StringName and OpenTK.Graphics.ES11.StringName +!duplicate-type-name! TextureMagFilter enum exists as both OpenTK.Graphics.ES20.TextureMagFilter and OpenTK.Graphics.ES11.TextureMagFilter +!duplicate-type-name! TextureMagFilter enum exists as both OpenTK.Graphics.ES30.TextureMagFilter and OpenTK.Graphics.ES11.TextureMagFilter +!duplicate-type-name! TextureMinFilter enum exists as both OpenTK.Graphics.ES20.TextureMinFilter and OpenTK.Graphics.ES11.TextureMinFilter +!duplicate-type-name! TextureMinFilter enum exists as both OpenTK.Graphics.ES30.TextureMinFilter and OpenTK.Graphics.ES11.TextureMinFilter +!duplicate-type-name! TextureParameterName enum exists as both OpenTK.Graphics.ES20.TextureParameterName and OpenTK.Graphics.ES11.TextureParameterName +!duplicate-type-name! TextureParameterName enum exists as both OpenTK.Graphics.ES30.TextureParameterName and OpenTK.Graphics.ES11.TextureParameterName +!duplicate-type-name! TextureTarget enum exists as both OpenTK.Graphics.ES30.TextureTarget and OpenTK.Graphics.ES20.TextureTarget +!duplicate-type-name! TextureUnit enum exists as both OpenTK.Graphics.ES20.TextureUnit and OpenTK.Graphics.ES11.TextureUnit +!duplicate-type-name! TextureUnit enum exists as both OpenTK.Graphics.ES30.TextureUnit and OpenTK.Graphics.ES11.TextureUnit +!duplicate-type-name! TextureWrapMode enum exists as both OpenTK.Graphics.ES20.TextureWrapMode and OpenTK.Graphics.ES11.TextureWrapMode +!duplicate-type-name! TextureWrapMode enum exists as both OpenTK.Graphics.ES30.TextureWrapMode and OpenTK.Graphics.ES11.TextureWrapMode +!duplicate-type-name! UniformTypes enum exists as both OpenTK.Graphics.ES30.UniformTypes and OpenTK.Graphics.ES20.UniformTypes +!duplicate-type-name! Unknown enum exists as both OpenTK.Graphics.ES20.Unknown and OpenTK.Graphics.ES11.Unknown +!duplicate-type-name! Unknown enum exists as both OpenTK.Graphics.ES30.Unknown and OpenTK.Graphics.ES11.Unknown +!duplicate-type-name! VertexArrays enum exists as both OpenTK.Graphics.ES30.VertexArrays and OpenTK.Graphics.ES20.VertexArrays +!duplicate-type-name! VertexAttribParameter enum exists as both OpenTK.Graphics.ES30.VertexAttribParameter and OpenTK.Graphics.ES20.VertexAttribParameter +!duplicate-type-name! VertexAttribPointerParameter enum exists as both OpenTK.Graphics.ES30.VertexAttribPointerParameter and OpenTK.Graphics.ES20.VertexAttribPointerParameter +!duplicate-type-name! VertexAttribPointerType enum exists as both OpenTK.Graphics.ES30.VertexAttribPointerType and OpenTK.Graphics.ES20.VertexAttribPointerType + + +# Security + +## added in iOS 8.0 +!missing-pinvoke! SecAddSharedWebCredential is not bound +!missing-pinvoke! SecCreateSharedWebCredentialPassword is not bound +!missing-pinvoke! SecRequestSharedWebCredential is not bound +!missing-field! kSecSharedPassword not bound + + +# Non-Apple + +## Xamarin (not Apple) type +!unknown-type! CADisplayLinkTimeSource bound diff --git a/tests/xtro-sharpie/tvos.pending b/tests/xtro-sharpie/tvos.pending new file mode 100644 index 000000000000..0e84726e7959 --- /dev/null +++ b/tests/xtro-sharpie/tvos.pending @@ -0,0 +1,116 @@ +# AVFoundation + +## there's no *Capture* possibility on AppleTV - looks like an Apple mistake +!missing-field! AVCaptureExposureDurationCurrent not bound +!missing-field! AVCaptureExposureTargetBiasCurrent not bound +!missing-field! AVCaptureISOCurrent not bound +!missing-field! AVCaptureLensPositionCurrent not bound +!missing-field! AVCaptureMaxAvailableTorchLevel not bound +!missing-field! AVCaptureWhiteBalanceGainsCurrent not bound + +## inside AVPlayerViewControllerDeprecated +!missing-selector! AVPlayerItem::externalSubtitleOptionLanguages not bound +!missing-selector! AVPlayerItem::selectedExternalSubtitleOptionLanguage not bound +!missing-selector! AVPlayerItem::setExternalSubtitleOptionLanguages: not bound +!missing-selector! AVPlayerItem::setSelectedExternalSubtitleOptionLanguage: not bound + +## AVAudioPlayer INTERRUPTION NOTIFICATIONS ARE DEPRECATED - Use AVAudioSession instead. + +### deprecated in iOS8 +!missing-protocol-member! AVAudioPlayerDelegate::audioPlayerEndInterruption:withFlags: not found + +### deprecated in iOS6, replaced by above +!missing-protocol-member! AVAudioPlayerDelegate::audioPlayerEndInterruption:withOptions: not found + + +# CloudKit + +## Apple added the API / headers but they are not included by default (so xtro do not have it) +!unknown-type! CKFetchWebAuthTokenOperation bound + + +# CoreMedia + +## kCMFormatDescription* are not bound for iOS either (common.unclassified) +!missing-field! kCMFormatDescriptionYCbCrMatrix_DCI_P3 not bound +!missing-field! kCMFormatDescriptionYCbCrMatrix_P3_D65 not bound + + +# GameplayKit + +## Xcode 7.1 added those types - but they are not in Xcode 7.2 SDK ??? Apple merge conflict +!unknown-type! GKHybridStrategist bound +!unknown-type! GKMonteCarloStrategist bound +!unknown-type! GKQuadTree bound +!unknown-type! GKQuadTreeNode bound + + +# UIKit + +## Apple docs: This property is inherited from the UIView parent class. This class changes the default value of this property to NO. +!missing-selector! UIImageView::isUserInteractionEnabled not bound +!missing-selector! UIImageView::setUserInteractionEnabled: not bound +!missing-selector! UILabel::isUserInteractionEnabled not bound +!missing-selector! UILabel::setUserInteractionEnabled: not bound + +## headers are unclear (added in iOS9.1) but Apple web documentation does not show those members +## and several only make sense for the stylus touches +!missing-selector! UITouch::altitudeAngle not bound +!missing-selector! UITouch::azimuthAngleInView: not bound +!missing-selector! UITouch::azimuthUnitVectorInView: not bound +!missing-selector! UITouch::estimatedProperties not bound +!missing-selector! UITouch::estimatedPropertiesExpectingUpdates not bound +!missing-selector! UITouch::estimationUpdateIndex not bound +!missing-selector! UITouch::preciseLocationInView: not bound +!missing-selector! UITouch::precisePreviousLocationInView: not bound + +## confusing header wrt categories, defined in: UIAdaptivePresentations (UIViewController) +## UIPopoverPresentationController, the returned type, is not available in tvOS +!missing-selector! UIViewController::popoverPresentationController not bound + +## property not decorated as unavailable but +## UIPinchGestureRecognizer, the returned type, is not available in tvOS +!missing-selector! UIScrollView::pinchGestureRecognizer not bound + +## the signature use UILexicon which is not part of tvOS +!missing-selector! UIInputViewController::requestSupplementaryLexiconWithCompletion: not bound + +## the [Sealed] attributes removes the [Export] one so it seems missing (but it's not) +!missing-selector! UIGestureRecognizer::ignorePress:forEvent: not bound + +## UIAccessibilityContainer is an informal protocol +## that we bound as a protocol but is (objc encoding) a category +!missing-selector! NSObject::accessibilityElementAtIndex: not bound +!missing-selector! NSObject::accessibilityElements not bound +!missing-selector! NSObject::indexOfAccessibilityElement: not bound +!missing-selector! NSObject::setAccessibilityElements: not bound + +## It's a ObjC Category / .NET static type so it's assumed the selector is for an instance +## and as it's a really static (both ways). That fails at xtro verification (can't know it's +## static). That's weird construct with managed helper method (so it looks ok) +!missing-selector! +NSAttributedString::attributedStringWithAttachment: not bound + +## fixed in XAMCORE_4_0 - API break +!incorrect-protocol-member! UIDynamicAnimatorDelegate::dynamicAnimatorDidPause: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UIDynamicAnimatorDelegate::dynamicAnimatorWillResume: is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UILayoutSupport::bottomAnchor is REQUIRED and should be abstract +!incorrect-protocol-member! UILayoutSupport::heightAnchor is REQUIRED and should be abstract +!incorrect-protocol-member! UILayoutSupport::topAnchor is REQUIRED and should be abstract + +## it's technically optional but there's no point in adopting the protocol if you do not provide the implemenation +!incorrect-protocol-member! UIInputViewAudioFeedback::enableInputClicksWhenVisible is OPTIONAL and should NOT be abstract + +## static method cannot be overriden "normally" they must be re-exposed with [Export] +!incorrect-protocol-member! +UIPopoverBackgroundViewMethods::arrowBase is REQUIRED and should be abstract +!incorrect-protocol-member! +UIPopoverBackgroundViewMethods::arrowHeight is REQUIRED and should be abstract +!incorrect-protocol-member! +UIPopoverBackgroundViewMethods::contentViewInsets is REQUIRED and should be abstract + +## hack to get them inlined into UITextView and UITextField +!incorrect-protocol-member! UITextInputTraits::autocapitalizationType is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::autocorrectionType is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::enablesReturnKeyAutomatically is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::isSecureTextEntry is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::keyboardAppearance is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::keyboardType is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::returnKeyType is OPTIONAL and should NOT be abstract +!incorrect-protocol-member! UITextInputTraits::spellCheckingType is OPTIONAL and should NOT be abstract diff --git a/tests/xtro-sharpie/watchos.ignore b/tests/xtro-sharpie/watchos.ignore new file mode 100644 index 000000000000..8e4f343d6a3e --- /dev/null +++ b/tests/xtro-sharpie/watchos.ignore @@ -0,0 +1,53 @@ +# UNLIKELY TO BE EVER FIXED + +# Foundation + +## does not exists in iOS (or watchOS) as a type - but some API refers to it (messy) +!unknown-type! NSPortMessage bound + +## deprecated in 9.0 but still visible (for watchOS) from `NSDeprecatedKitAdditions (NSAttributedString)` +## not part of tvOS and we provide the replacement selector with the same managed API +!missing-selector! NSAttributedString::initWithFileURL:options:documentAttributes:error: not bound + +# Deprecated in iOS 9.0 (so watch 2.0) with an alternative (NSWritingDirectionFormatType in UIKit) +# better not expose the deprecated enum since it's not available in tvOS either +!missing-enum! NSTextWritingDirection not bound + + +# UIKit + +## Implemented in managed code +!missing-selector! UIColor::getHue:saturation:brightness:alpha: not bound +!missing-selector! UIColor::getRed:green:blue:alpha: not bound +!missing-field! UIEdgeInsetsZero not bound +!missing-field! UIOffsetZero not bound + +## Not implemented (ctor signature conflict) but there's a static method available that does the job +!missing-selector! UIColor::initWithHue:saturation:brightness:alpha: not bound + +## deprecated +!missing-selector! UIImageDeprecated::leftCapWidth not bound +!missing-selector! UIImageDeprecated::stretchableImageWithLeftCapWidth:topCapHeight: not bound +!missing-selector! UIImageDeprecated::topCapHeight not bound + + +# Apple internals (we do not expose them) + +!missing-field! _NSConstantStringClassReference not bound + + +# Non-Apple + +## Xamarin (not Apple) type +!unknown-type! CADisplayLinkTimeSource bound +!unknown-type! InternalNSNotificationHandler bound + +## Xamarin generic collection subclasses +!unknown-type! NSArray`1 bound +!unknown-type! NSDictionary`2 bound +!unknown-type! NSMutableArray`1 bound +!unknown-type! NSMutableDictionary`2 bound +!unknown-type! NSMutableOrderedSet`1 bound +!unknown-type! NSMutableSet`1 bound +!unknown-type! NSOrderedSet`1 bound +!unknown-type! NSSet`1 bound diff --git a/tests/xtro-sharpie/watchos.pending b/tests/xtro-sharpie/watchos.pending new file mode 100644 index 000000000000..176db2df0792 --- /dev/null +++ b/tests/xtro-sharpie/watchos.pending @@ -0,0 +1,35 @@ +# TO BE FIXED - but maybe only in the far future / profiles + + +# CoreMotion + +## NSFastEnumeration - see bug https://bugzilla.xamarin.com/show_bug.cgi?id=34555 +!missing-protocol-conformance! CMSensorDataList should conform to NSFastEnumeration + + +# UIKit + +## Apple renamed it from UILineBreakMode and we kept the old name +!missing-enum! NSLineBreakMode not bound +!unknown-native-enum! UILineBreakMode bound + +## Apple renamed it from NSTextAlignment and we kept the old name +!missing-enum! NSTextAlignment not bound +!unknown-native-enum! UITextAlignment bound + + +# others + +## might not be usable unless our ToString output is parsable as an input (includes locale issues) +!missing-pinvoke! CFUUIDCreateFromString is not bound +!missing-pinvoke! CGAffineTransformFromString is not bound +!missing-pinvoke! CGPointFromString is not bound +!missing-pinvoke! CGRectFromString is not bound +!missing-pinvoke! CGSizeFromString is not bound +!missing-pinvoke! NSStringFromCGAffineTransform is not bound +!missing-pinvoke! NSStringFromCGPoint is not bound +!missing-pinvoke! NSStringFromCGRect is not bound +!missing-pinvoke! NSStringFromCGSize is not bound +!missing-pinvoke! NSStringFromUIOffset is not bound +!missing-pinvoke! UIOffsetFromString is not bound + diff --git a/tests/xtro-sharpie/xtro-plugin.csproj b/tests/xtro-sharpie/xtro-plugin.csproj new file mode 100644 index 000000000000..d9f0128be570 --- /dev/null +++ b/tests/xtro-sharpie/xtro-plugin.csproj @@ -0,0 +1,51 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6CBA2C3C-2EC7-42A0-8AA7-85FC62252A18} + Library + xtroplugin + xtro-plugin + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + \Library\Frameworks\ObjectiveSharpie.framework\Versions\Current\Sharpie.Core.dll + + + packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll + + + + + + + + + {D890A042-93C2-4B4B-ABF8-7ECBCBF059D8} + xtro-sharpie + + + \ No newline at end of file diff --git a/tests/xtro-sharpie/xtro-sharpie.csproj b/tests/xtro-sharpie/xtro-sharpie.csproj new file mode 100644 index 000000000000..d8469a0fcc31 --- /dev/null +++ b/tests/xtro-sharpie/xtro-sharpie.csproj @@ -0,0 +1,58 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {D890A042-93C2-4B4B-ABF8-7ECBCBF059D8} + Exe + xtrosharpie + xtro-sharpie + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + ../../iphoneos9.2-arm64.pch /Library/Frameworks/Xamarin.iOS.framework/Versions/Current//lib/64bits/Xamarin.iOS.dll + + + full + true + bin\Release + prompt + 4 + true + + + + + \Library\Frameworks\ObjectiveSharpie.framework\Versions\Current\Clang.dll + + + packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/xtro-sharpie/xtro-sharpie.sln b/tests/xtro-sharpie/xtro-sharpie.sln new file mode 100644 index 000000000000..9f73655d58c3 --- /dev/null +++ b/tests/xtro-sharpie/xtro-sharpie.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xtro-sharpie", "xtro-sharpie.csproj", "{D890A042-93C2-4B4B-ABF8-7ECBCBF059D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xtro-plugin", "xtro-plugin.csproj", "{6CBA2C3C-2EC7-42A0-8AA7-85FC62252A18}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6CBA2C3C-2EC7-42A0-8AA7-85FC62252A18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CBA2C3C-2EC7-42A0-8AA7-85FC62252A18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CBA2C3C-2EC7-42A0-8AA7-85FC62252A18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CBA2C3C-2EC7-42A0-8AA7-85FC62252A18}.Release|Any CPU.Build.0 = Release|Any CPU + {D890A042-93C2-4B4B-ABF8-7ECBCBF059D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D890A042-93C2-4B4B-ABF8-7ECBCBF059D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D890A042-93C2-4B4B-ABF8-7ECBCBF059D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D890A042-93C2-4B4B-ABF8-7ECBCBF059D8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal