Compare commits

..

No commits in common. "master" and "1.3.0" have entirely different histories.

622 changed files with 14570 additions and 83877 deletions

120
.circleci/config.yml Normal file
View File

@ -0,0 +1,120 @@
version: 2.1
executors:
unity:
# https://hub.docker.com/r/gableroux/unity3d/tags
parameters:
version: {type: string}
docker:
- image: gableroux/unity3d:<< parameters.version >>
go:
docker:
- image: circleci/golang
commands:
unity_activate:
parameters:
unity_version: {type: string}
unity_license: {type: string}
steps:
# get activation file, if fail to activate unity, use this key and activate from https://license.unity3d.com/manual
- run: apt update && apt install libunwind8 -y
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -logFile -createManualActivationFile || exit 0
- run: cat Unity_v<< parameters.unity_version >>.alf
# get from UNITY_LICENSE envvar(base64 encoded(cat foo.ulf | base64 )), this file is generated from above manual activation
- run: echo << parameters.unity_license >> | base64 -di >> .circleci/Unity.ulf
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .circleci/Unity.ulf || exit 0
jobs:
build-and-test:
parameters:
unity_version: {type: string}
unity_license: {type: string}
executor:
name: unity
version: << parameters.unity_version >>
steps:
- checkout
- unity_activate:
unity_version: << parameters.unity_version >>
unity_license: << parameters.unity_license >>
- run:
name: Build Linux(Mono)
command: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend Mono2x /BuildTarget StandaloneLinux64
working_directory: .
# TODO:check unity version and packages...
# - run: ./bin/UnitTest/StandaloneLinux64_Mono2x/test
build-and-create-package:
parameters:
unity_version: {type: string}
unity_license: {type: string}
executor:
name: unity
version: << parameters.unity_version >>
steps:
- checkout
- unity_activate:
unity_version: << parameters.unity_version >>
unity_license: << parameters.unity_license >>
- run:
name: Export unitypackage
command: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
working_directory: .
- store_artifacts:
path: ./UniRx.Async.unitypackage
destination: /UniRx.Async.unitypackage
# upload to github by ghr
upload-github:
executor: go
steps:
- attach_workspace:
at: .
- run: go get github.com/tcnksm/ghr
- run: ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} ${CIRCLE_TAG} .
- store_artifacts:
path: UniRx.Async.unitypackage
destination: UniRx.Async.unitypackage
workflows:
version: 2
build-unity:
jobs:
# does not exists yet.
# - build-and-test:
# unity_version: 2019.3.0a2
# unity_license: ${UNITY_LICENSE_2019_3}
# - build-and-test:
# unity_version: 2019.2.0b2
# unity_license: ${UNITY_LICENSE_2019_2}
- build-and-create-package:
unity_version: 2019.1.2f1
unity_license: ${UNITY_LICENSE_2019_1}
filters:
tags:
only: /.*/
- build-and-test:
unity_version: 2019.1.2f1
unity_license: ${UNITY_LICENSE_2019_1}
filters:
tags:
only: /.*/
# test asmdef will not found.
# - build-and-test:
# unity_version: 2018.4.0f1
# unity_license: ${UNITY_LICENSE_2018_4}
# # UniTask minimum support version is 2018.3(C# 7.x)
# - build-and-test:
# unity_version: 2018.3.12f1
# unity_license: ${UNITY_LICENSE_2018_3}
- build-and-create-package-release:
unity_version: 2019.1.2f1
unity_license: ${UNITY_LICENSE_2019_1}
filters:
tags:
only: /^\d\.\d\.\d.*/
branches:
ignore: /.*/
- upload-github:
requires:
- build-and-create-package-release
filters:
tags:
only: /^\d\.\d\.\d.*/
branches:
ignore: /.*/

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
github: [neuecc]

View File

@ -1,73 +0,0 @@
name: Build-Debug
on:
push:
branches:
- "master"
pull_request:
branches:
- "master"
jobs:
build-dotnet:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
with:
dotnet-version: |
6.0.x
7.0.x
- run: dotnet build -c Debug
- run: dotnet test -c Debug
build-unity:
if: "((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:'))"
strategy:
matrix:
unity: ["2019.3.9f1", "2019.4.13f1", "2020.1.12f1"]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
# Execute scripts: RuntimeUnitTestToolkit
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
- name: Build UnitTest(Linux64, mono)
uses: Cysharp/Actions/.github/actions/unity-builder@main
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
projectPath: src/UniTask
unityVersion: ${{ matrix.unity }}
targetPlatform: StandaloneLinux64
buildMethod: UnitTestBuilder.BuildUnitTest
customParameters: /headless /ScriptBackend mono
- name: Execute UnitTest
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
# Execute scripts: Export Package
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
- name: Build Unity (.unitypacakge)
uses: Cysharp/Actions/.github/actions/unity-builder@main
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
projectPath: src/UniTask
unityVersion: ${{ matrix.unity }}
targetPlatform: StandaloneLinux64
buildMethod: PackageExporter.Export
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
with:
directory: src/UniTask
# Store artifacts.
- uses: actions/upload-artifact@v2
with:
name: UniTask.unitypackage-${{ matrix.unity }}.zip
path: ./src/UniTask/*.unitypackage

View File

@ -1,31 +0,0 @@
name: build-docs
on:
push:
branches:
- master
- feature/docs
jobs:
run-docfx:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: Cysharp/DocfxTemplate
path: docs/_DocfxTemplate
- uses: Kirbyrawr/docfx-action@master
name: Docfx metadata
with:
args: metadata docs/docfx.json
- uses: Kirbyrawr/docfx-action@master
name: Docfx build
with:
args: build docs/docfx.json
- name: Publish to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/_site

View File

@ -1,124 +0,0 @@
name: build-release
on:
workflow_dispatch:
inputs:
tag:
description: "tag: git tag you want create. (sample 1.0.0)"
required: true
dry-run:
description: "dry-run: true will never create relase/nuget."
required: true
default: false
type: boolean
env:
GIT_TAG: ${{ github.event.inputs.tag }}
DRY_RUN: ${{ github.event.inputs.dry-run }}
jobs:
update-packagejson:
uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main
with:
file-path: ./src/UniTask/Assets/Plugins/UniTask/package.json
tag: ${{ github.event.inputs.tag }}
dry-run: ${{ fromJson(github.event.inputs.dry-run) }}
build-dotnet:
needs: [update-packagejson]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- run: echo ${{ needs.update-packagejson.outputs.sha }}
- uses: actions/checkout@v3
with:
ref: ${{ needs.update-packagejson.outputs.sha }}
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
with:
dotnet-version: |
3.1.x
6.0.x
# build and pack
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
- run: dotnet test -c Release --no-build
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ env.GIT_TAG }} -o ./publish
# Store artifacts.
- uses: actions/upload-artifact@v2
with:
name: nuget
path: ./publish/
build-unity:
needs: [update-packagejson]
strategy:
matrix:
unity: ["2019.3.9f1"]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- run: echo ${{ needs.update-packagejson.outputs.sha }}
- uses: actions/checkout@v3
with:
ref: ${{ needs.update-packagejson.outputs.sha }}
# Execute scripts: Export Package
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
- name: Build Unity (.unitypacakge)
uses: Cysharp/Actions/.github/actions/unity-builder@main
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
projectPath: src/UniTask
unityVersion: ${{ matrix.unity }}
targetPlatform: StandaloneLinux64
buildMethod: PackageExporter.Export
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
with:
directory: src/UniTask
# Store artifacts.
- uses: actions/upload-artifact@v2
with:
name: UniTask.${{ env.GIT_TAG }}.unitypackage
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
create-release:
if: github.event.inputs.dry-run == 'false'
needs: [update-packagejson, build-dotnet, build-unity]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
# Create Releases
- uses: actions/create-release@v1
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.GIT_TAG }}
release_name: Ver.${{ env.GIT_TAG }}
commitish: ${{ needs.update-packagejson.outputs.sha }}
draft: true
prerelease: false
# Download(All) Artifacts to current directory
- uses: actions/download-artifact@v2
# Upload to NuGet
- run: dotnet nuget push "./nuget/*.nupkg" --skip-duplicate -s https://www.nuget.org/api/v2/package -k ${{ secrets.NUGET_KEY }}
# Upload to Releases(unitypackage)
- uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./UniTask.${{ env.GIT_TAG }}.unitypackage/UniTask.${{ env.GIT_TAG }}.unitypackage
asset_name: UniTask.${{ env.GIT_TAG }}.unitypackage
asset_content_type: application/octet-stream
cleanup:
if: needs.update-packagejson.outputs.is-branch-created == 'true'
needs: [update-packagejson, build-dotnet, build-unity]
uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
with:
branch: ${{ needs.update-packagejson.outputs.branch-name }}

View File

@ -1,10 +0,0 @@
name: Prevent github change
on:
pull_request:
paths:
- ".github/**/*.yaml"
- ".github/**/*.yml"
jobs:
detect:
uses: Cysharp/Actions/.github/workflows/prevent-github-change.yaml@main

View File

@ -1,10 +0,0 @@
name: "Close stale issues"
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
uses: Cysharp/Actions/.github/workflows/stale-issue.yaml@main

View File

@ -1,15 +0,0 @@
name: TOC Generator
on:
push:
paths:
- 'README.md'
jobs:
generateTOC:
name: TOC Generator
runs-on: ubuntu-latest
steps:
- uses: technote-space/toc-generator@v2.4.0
with:
TOC_TITLE: "## Table of Contents"

114
.gitignore vendored
View File

@ -147,117 +147,3 @@ Assembly-CSharp-Editor\.csproj
UniRx\.Async\.unitypackage UniRx\.Async\.unitypackage
UniRx.Async.Tests.Editor.csproj UniRx.Async.Tests.Editor.csproj
src/UniTask/UniTask.csproj
src/UniTask/UniTask.Editor.csproj
src/UniTask/UniTask.Tests.csproj
src/UniTask/UniTask.Tests.Editor.csproj
src/UniTask/UniTask.*.unitypackage
src/UniTask/UniTask.Linq.csproj
src/UniTask/DOTween.Modules.csproj
src/UniTask/Unity.Addressables.csproj
src/UniTask/Unity.Addressables.Editor.csproj
src/UniTask/Unity.Analytics.DataPrivacy.csproj
src/UniTask/Unity.Recorder.csproj
src/UniTask/Unity.Recorder.Editor.csproj
src/UniTask/Unity.ResourceManager.csproj
src/UniTask/Unity.Rider.Editor.csproj
src/UniTask/Unity.ScriptableBuildPipeline.csproj
src/UniTask/Unity.ScriptableBuildPipeline.Editor.csproj
src/UniTask/Unity.TextMeshPro.csproj
src/UniTask/Unity.TextMeshPro.Editor.csproj
src/UniTask/Unity.Timeline.csproj
src/UniTask/Unity.Timeline.Editor.csproj
src/UniTask/Unity.VisualStudio.Editor.csproj
src/UniTask/Unity.VSCode.Editor.csproj
src/UniTask/UnityEditor.CacheServer.csproj
src/UniTask/UnityEditor.TestRunner.csproj
src/UniTask/UnityEditor.UI.csproj
src/UniTask/UnityEngine.Advertisements.csproj
src/UniTask/UnityEngine.Monetization.csproj
src/UniTask/UnityEngine.TestRunner.csproj
src/UniTask/UnityEngine.UI.csproj
src/UniTask/TempAsm.csproj
src/UniTask/UniTask.Addressables.csproj
src/UniTask/UniTask.DOTween.csproj
src/UniTask/UniTask.TextMeshPro.csproj
src/UniTask/RuntimeUnitTestToolkit.Player.csproj
src/UniTask/TempAsm.Player.csproj
src/UniTask/UniTask.Addressables.Player.csproj
src/UniTask/UniTask.DOTween.Player.csproj
src/UniTask/UniTask.Linq.Player.csproj
src/UniTask/UniTask.Player.csproj
src/UniTask/UniTask.Tests.Player.csproj
src/UniTask/UniTask.TextMeshPro.Player.csproj
src/UniTask/Unity.Addressables.Player.csproj
src/UniTask/Unity.Analytics.DataPrivacy.Player.csproj
src/UniTask/Unity.ResourceManager.Player.csproj
src/UniTask/Unity.ScriptableBuildPipeline.Player.csproj
src/UniTask/Unity.TextMeshPro.Player.csproj
src/UniTask/Unity.Timeline.Player.csproj
src/UniTask/UnityEngine.Advertisements.Player.csproj
src/UniTask/UnityEngine.Monetization.Player.csproj
src/UniTask/UnityEngine.TestRunner.Player.csproj
src/UniTask/UnityEngine.UI.Player.csproj
src/UniTask/DOTween.Modules.Player.csproj
src/UniTask/Assembly-CSharp.Player.csproj
src/UniTask/Unity.EditorCoroutines.Editor.csproj
src/UniTask/.vsconfig
src/UniTask/Logs/ApiUpdaterCheck.txt
src/UniTask/Assembly-CSharp-firstpass.csproj

View File

@ -0,0 +1,35 @@
#if UNITY_EDITOR
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public static class PackageExporter
{
[MenuItem("Tools/Export Unitypackage")]
public static void Export()
{
// configure
var root = "UniRx.Async";
var exportPath = "./UniRx.Async.unitypackage";
var path = Path.Combine(Application.dataPath, root);
var assets = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories)
.Where(x => Path.GetExtension(x) == ".cs" || Path.GetExtension(x) == ".asmdef" || Path.GetExtension(x) == ".json" || Path.GetExtension(x) == ".meta")
.Select(x => "Assets" + x.Replace(Application.dataPath, "").Replace(@"\", "/"))
.ToArray();
UnityEngine.Debug.Log("Export below files" + Environment.NewLine + string.Join(Environment.NewLine, assets));
AssetDatabase.ExportPackage(
assets,
exportPath,
ExportPackageOptions.Default);
UnityEngine.Debug.Log("Export complete: " + Path.GetFullPath(exportPath));
}
}
#endif

View File

@ -169,25 +169,21 @@ Switch,
SaveSettings(settings); SaveSettings(settings);
} }
#if !UNITY_2019_2_OR_NEWER //[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = true, priority = 3)]
//static bool ValidateBuildTargetStandaloneLinux()
//{
// Menu.SetChecked("Test/Settings/BuildTarget/StandaloneLinux", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneLinux);
// return true;
//}
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = true, priority = 3)] //[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = false, priority = 3)]
static bool ValidateBuildTargetStandaloneLinux() //static void BuildTargetStandaloneLinux()
{ //{
Menu.SetChecked("Test/Settings/BuildTarget/StandaloneLinux", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneLinux); // var settings = LoadOrGetDefaultSettings();
return true; // settings.UseCurrentBuildTarget = false;
} // settings.BuildTarget = BuildTarget.StandaloneLinux;
// SaveSettings(settings);
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = false, priority = 3)] //}
static void BuildTargetStandaloneLinux()
{
var settings = LoadOrGetDefaultSettings();
settings.UseCurrentBuildTarget = false;
settings.BuildTarget = BuildTarget.StandaloneLinux;
SaveSettings(settings);
}
#endif
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux64", validate = true, priority = 4)] [MenuItem("Test/Settings/BuildTarget/StandaloneLinux64", validate = true, priority = 4)]
static bool ValidateBuildTargetStandaloneLinux64() static bool ValidateBuildTargetStandaloneLinux64()

View File

@ -1,4 +1,4 @@
#if UNITY_EDITOR #if UNITY_EDITOR
using RuntimeUnitTestToolkit; using RuntimeUnitTestToolkit;
using RuntimeUnitTestToolkit.Editor; using RuntimeUnitTestToolkit.Editor;
@ -118,7 +118,7 @@ public static partial class UnitTestBuilder
if (buildPath == null) if (buildPath == null)
{ {
buildPath = $"bin/UnitTest/{settings.BuildTarget}_{settings.ScriptBackend}/test" + GetExtensionForBuildTarget(settings.BuildTarget); buildPath = $"bin/UnitTest/{settings.BuildTarget}_{settings.ScriptBackend}/test" + (IsWindows(settings.BuildTarget) ? ".exe" : "");
} }
var originalScene = SceneManager.GetActiveScene().path; var originalScene = SceneManager.GetActiveScene().path;
@ -136,15 +136,6 @@ public static partial class UnitTestBuilder
} }
} }
[MenuItem("Test/LoadUnitTestScene")]
public static void LoadUnitTestScene()
{
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
BuildUnitTestRunnerScene();
EditorSceneManager.MarkSceneDirty(scene);
}
static RuntimeUnitTestSettings LoadOrGetDefaultSettings() static RuntimeUnitTestSettings LoadOrGetDefaultSettings()
{ {
var key = SettingsKeyBase + Application.productName; var key = SettingsKeyBase + Application.productName;
@ -457,42 +448,20 @@ public static partial class UnitTestBuilder
} }
} }
static string GetExtensionForBuildTarget(BuildTarget buildTarget)
{
switch (buildTarget)
{
case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64:
case BuildTarget.WSAPlayer:
return ".exe";
case BuildTarget.StandaloneOSX:
return ".app";
case BuildTarget.Android:
return ".apk";
default:
return "";
}
}
static BuildTargetGroup ToBuildTargetGroup(BuildTarget buildTarget) static BuildTargetGroup ToBuildTargetGroup(BuildTarget buildTarget)
{ {
#pragma warning disable CS0618 #pragma warning disable CS0618
switch (buildTarget) switch (buildTarget)
{ {
#if UNITY_2017_3_OR_NEWER
case BuildTarget.StandaloneOSX: case BuildTarget.StandaloneOSX:
#else case (BuildTarget)3:
case BuildTarget.StandaloneOSXIntel: case BuildTarget.StandaloneOSXIntel:
case BuildTarget.StandaloneOSXIntel64: case BuildTarget.StandaloneOSXIntel64:
case BuildTarget.StandaloneOSXUniversal:
#endif // UNITY_2017_3_OR_NEWER
case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64: case BuildTarget.StandaloneWindows64:
case BuildTarget.StandaloneLinux64:
#if !UNITY_2019_2_OR_NEWER
case BuildTarget.StandaloneLinux: case BuildTarget.StandaloneLinux:
case BuildTarget.StandaloneLinux64:
case BuildTarget.StandaloneLinuxUniversal: case BuildTarget.StandaloneLinuxUniversal:
#endif // !UNITY_2019_2_OR_NEWER
return BuildTargetGroup.Standalone; return BuildTargetGroup.Standalone;
case (BuildTarget)6: case (BuildTarget)6:
case (BuildTarget)7: case (BuildTarget)7:
@ -543,4 +512,4 @@ public static partial class UnitTestBuilder
} }
} }
#endif #endif

View File

@ -0,0 +1,450 @@
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.TestTools;
using UnityEngine.UI;
namespace RuntimeUnitTestToolkit
{
public class UnitTestRunner : MonoBehaviour
{
// object is IEnumerator or Func<IEnumerator>
Dictionary<string, List<KeyValuePair<string, object>>> tests = new Dictionary<string, List<KeyValuePair<string, object>>>();
List<Pair> additionalActionsOnFirst = new List<Pair>();
public Button clearButton;
public RectTransform list;
public Scrollbar listScrollBar;
public Text logText;
public Scrollbar logScrollBar;
readonly Color passColor = new Color(0f, 1f, 0f, 1f); // green
readonly Color failColor = new Color(1f, 0f, 0f, 1f); // red
readonly Color normalColor = new Color(1f, 1f, 1f, 1f); // white
bool allTestGreen = true;
void Start()
{
try
{
UnityEngine.Application.logMessageReceived += (a, b, c) =>
{
logText.text += "[" + c + "]" + a + "\n";
};
// register all test types
foreach (var item in GetTestTargetTypes())
{
RegisterAllMethods(item);
}
var executeAll = new List<Func<Coroutine>>();
foreach (var ___item in tests)
{
var actionList = ___item; // be careful, capture in lambda
executeAll.Add(() => StartCoroutine(RunTestInCoroutine(actionList)));
Add(actionList.Key, () => StartCoroutine(RunTestInCoroutine(actionList)));
}
var executeAllButton = Add("Run All Tests", () => StartCoroutine(ExecuteAllInCoroutine(executeAll)));
clearButton.gameObject.GetComponent<Image>().color = new Color(170 / 255f, 170 / 255f, 170 / 255f, 1);
executeAllButton.gameObject.GetComponent<Image>().color = new Color(250 / 255f, 150 / 255f, 150 / 255f, 1);
executeAllButton.transform.SetSiblingIndex(1);
additionalActionsOnFirst.Reverse();
foreach (var item in additionalActionsOnFirst)
{
var newButton = GameObject.Instantiate(clearButton);
newButton.name = item.Name;
newButton.onClick.RemoveAllListeners();
newButton.GetComponentInChildren<Text>().text = item.Name;
newButton.onClick.AddListener(item.Action);
newButton.transform.SetParent(list);
newButton.transform.SetSiblingIndex(1);
}
clearButton.onClick.AddListener(() =>
{
logText.text = "";
foreach (var btn in list.GetComponentsInChildren<Button>())
{
btn.interactable = true;
btn.GetComponent<Image>().color = normalColor;
}
executeAllButton.gameObject.GetComponent<Image>().color = new Color(250 / 255f, 150 / 255f, 150 / 255f, 1);
});
listScrollBar.value = 1;
logScrollBar.value = 1;
if (Application.isBatchMode)
{
// run immediately in player
StartCoroutine(ExecuteAllInCoroutine(executeAll));
}
}
catch (Exception ex)
{
if (Application.isBatchMode)
{
// when failed(can not start runner), quit immediately.
WriteToConsole(ex.ToString());
Application.Quit(1);
}
else
{
throw;
}
}
}
Button Add(string title, UnityAction test)
{
var newButton = GameObject.Instantiate(clearButton);
newButton.name = title;
newButton.onClick.RemoveAllListeners();
newButton.GetComponentInChildren<Text>().text = title;
newButton.onClick.AddListener(test);
newButton.transform.SetParent(list);
return newButton;
}
static IEnumerable<Type> GetTestTargetTypes()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var n = assembly.FullName;
if (n.StartsWith("UnityEngine")) continue;
if (n.StartsWith("mscorlib")) continue;
if (n.StartsWith("System")) continue;
foreach (var item in assembly.GetTypes())
{
foreach (var method in item.GetMethods())
{
var t1 = method.GetCustomAttribute<TestAttribute>(true);
if (t1 != null)
{
yield return item;
break;
}
var t2 = method.GetCustomAttribute<UnityTestAttribute>(true);
if (t2 != null)
{
yield return item;
break;
}
}
}
}
}
public void AddTest(string group, string title, Action test)
{
List<KeyValuePair<string, object>> list;
if (!tests.TryGetValue(group, out list))
{
list = new List<KeyValuePair<string, object>>();
tests[group] = list;
}
list.Add(new KeyValuePair<string, object>(title, test));
}
public void AddAsyncTest(string group, string title, Func<IEnumerator> asyncTestCoroutine)
{
List<KeyValuePair<string, object>> list;
if (!tests.TryGetValue(group, out list))
{
list = new List<KeyValuePair<string, object>>();
tests[group] = list;
}
list.Add(new KeyValuePair<string, object>(title, asyncTestCoroutine));
}
public void AddCutomAction(string name, UnityAction action)
{
additionalActionsOnFirst.Add(new Pair { Name = name, Action = action });
}
public void RegisterAllMethods<T>()
where T : new()
{
RegisterAllMethods(typeof(T));
}
public void RegisterAllMethods(Type testType)
{
try
{
var test = Activator.CreateInstance(testType);
var methods = testType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
foreach (var item in methods)
{
try
{
var iteratorTest = item.GetCustomAttribute<UnityEngine.TestTools.UnityTestAttribute>(true);
if (iteratorTest != null)
{
if (item.GetParameters().Length == 0 && item.ReturnType == typeof(IEnumerator))
{
var factory = (Func<IEnumerator>)Delegate.CreateDelegate(typeof(Func<IEnumerator>), test, item);
AddAsyncTest(factory.Target.GetType().Name, factory.Method.Name, factory);
}
else
{
UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter or return type is invalid).");
}
}
var standardTest = item.GetCustomAttribute<NUnit.Framework.TestAttribute>(true);
if (standardTest != null)
{
if (item.GetParameters().Length == 0 && item.ReturnType == typeof(void))
{
var invoke = (Action)Delegate.CreateDelegate(typeof(Action), test, item);
AddTest(invoke.Target.GetType().Name, invoke.Method.Name, invoke);
}
else
{
UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter or return type is invalid).");
}
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(testType.Name + "." + item.Name + " failed to register method, exception: " + e.ToString());
}
}
}
catch (Exception ex)
{
Debug.LogException(ex);
}
}
System.Collections.IEnumerator ScrollLogToEndNextFrame()
{
yield return null;
yield return null;
logScrollBar.value = 0;
}
IEnumerator RunTestInCoroutine(KeyValuePair<string, List<KeyValuePair<string, object>>> actionList)
{
Button self = null;
foreach (var btn in list.GetComponentsInChildren<Button>())
{
btn.interactable = false;
if (btn.name == actionList.Key) self = btn;
}
if (self != null)
{
self.GetComponent<Image>().color = normalColor;
}
var allGreen = true;
logText.text += "<color=yellow>" + actionList.Key + "</color>\n";
WriteToConsole("Begin Test Class: " + actionList.Key);
yield return null;
var totalExecutionTime = new List<double>();
foreach (var item2 in actionList.Value)
{
// before start, cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
logText.text += "<color=teal>" + item2.Key + "</color>\n";
yield return null;
var v = item2.Value;
var methodStopwatch = System.Diagnostics.Stopwatch.StartNew();
Exception exception = null;
if (v is Action)
{
try
{
((Action)v).Invoke();
}
catch (Exception ex)
{
exception = ex;
}
}
else
{
var coroutineFactory = (Func<IEnumerator>)v;
IEnumerator coroutine = null;
try
{
coroutine = coroutineFactory();
}
catch (Exception ex)
{
exception = ex;
}
if (exception == null)
{
yield return StartCoroutine(UnwrapEnumerator(coroutine, ex =>
{
exception = ex;
}));
}
}
methodStopwatch.Stop();
totalExecutionTime.Add(methodStopwatch.Elapsed.TotalMilliseconds);
if (exception == null)
{
logText.text += "OK, " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms\n";
WriteToConsoleResult(item2.Key + ", " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms", true);
}
else
{
// found match line...
var line = string.Join("\n", exception.StackTrace.Split('\n').Where(x => x.Contains(actionList.Key) || x.Contains(item2.Key)).ToArray());
logText.text += "<color=red>" + exception.Message + "\n" + line + "</color>\n";
WriteToConsoleResult(item2.Key + ", " + exception.Message, false);
WriteToConsole(line);
allGreen = false;
allTestGreen = false;
}
}
logText.text += "[" + actionList.Key + "]" + totalExecutionTime.Sum().ToString("0.00") + "ms\n\n";
foreach (var btn in list.GetComponentsInChildren<Button>()) btn.interactable = true;
if (self != null)
{
self.GetComponent<Image>().color = allGreen ? passColor : failColor;
}
yield return StartCoroutine(ScrollLogToEndNextFrame());
}
IEnumerator ExecuteAllInCoroutine(List<Func<Coroutine>> tests)
{
allTestGreen = true;
foreach (var item in tests)
{
yield return item();
}
if (Application.isBatchMode)
{
var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
bool disableAutoClose = (scene.name.Contains("DisableAutoClose"));
if (allTestGreen)
{
WriteToConsole("Test Complete Successfully");
if (!disableAutoClose)
{
Application.Quit();
}
}
else
{
WriteToConsole("Test Failed, please see [NG] log.");
if (!disableAutoClose)
{
Application.Quit(1);
}
}
}
}
IEnumerator UnwrapEnumerator(IEnumerator enumerator, Action<Exception> exceptionCallback)
{
var hasNext = true;
while (hasNext)
{
try
{
hasNext = enumerator.MoveNext();
}
catch (Exception ex)
{
exceptionCallback(ex);
hasNext = false;
}
if (hasNext)
{
// unwrap self for bug of Unity
// https://issuetracker.unity3d.com/issues/does-not-stop-coroutine-when-it-throws-exception-in-movenext-at-first-frame
var moreCoroutine = enumerator.Current as IEnumerator;
if (moreCoroutine != null)
{
yield return StartCoroutine(UnwrapEnumerator(moreCoroutine, ex =>
{
exceptionCallback(ex);
hasNext = false;
}));
}
else
{
yield return enumerator.Current;
}
}
}
}
static void WriteToConsole(string msg)
{
if (Application.isBatchMode)
{
Console.WriteLine(msg);
}
}
static void WriteToConsoleResult(string msg, bool green)
{
if (Application.isBatchMode)
{
if (!green)
{
var currentForeground = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("[NG]");
Console.ForegroundColor = currentForeground;
}
else
{
var currentForeground = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("[OK]");
Console.ForegroundColor = currentForeground;
}
System.Console.WriteLine(msg);
}
}
struct Pair
{
public string Name;
public UnityAction Action;
}
}
}

View File

@ -1,7 +1,7 @@
{ {
"name": "com.cysharp.runtimeunittesttoolkit", "name": "jp.cysharp.runtimeunittesttoolkit",
"displayName": "RuntimeUnitTestToolkit", "displayName": "RuntimeUnitTestToolkit",
"version": "2.3.0", "version": "2.0.0",
"unity": "2018.3", "unity": "2018.3",
"description": "CLI/GUI Frontend of Unity Test Runner to test on any platform.", "description": "CLI/GUI Frontend of Unity Test Runner to test on any platform.",
"keywords": ["test"], "keywords": ["test"],

View File

@ -0,0 +1,26 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using UniRx.Async;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class SandboxMain : MonoBehaviour
{
public Button okButton;
public Button cancelButton;
CancellationTokenSource cts;
async void Start()
{
UnityEngine.Debug.Log("DOWNLOAD START:" + Time.frameCount);
var req = await UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, "test.txt")).SendWebRequest();
UnityEngine.Debug.Log("DOWNLOAD RESULT:" + Time.frameCount + ", " + req.downloadHandler.text);
}
}

View File

@ -96,7 +96,6 @@ LightmapSettings:
m_PVRFilteringAtrousPositionSigmaAO: 1 m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0 m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0} m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1 m_UseShadowmask: 1
--- !u!196 &4 --- !u!196 &4
@ -169,7 +168,7 @@ MonoBehaviour:
m_GameObject: {fileID: 16537670} m_GameObject: {fileID: 16537670}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Navigation: m_Navigation:
@ -203,6 +202,8 @@ MonoBehaviour:
m_OnClick: m_OnClick:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null
--- !u!114 &16537673 --- !u!114 &16537673
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -212,7 +213,7 @@ MonoBehaviour:
m_GameObject: {fileID: 16537670} m_GameObject: {fileID: 16537670}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Material: {fileID: 0} m_Material: {fileID: 0}
@ -221,6 +222,8 @@ MonoBehaviour:
m_OnCullStateChanged: m_OnCullStateChanged:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1 m_Type: 1
m_PreserveAspect: 0 m_PreserveAspect: 0
@ -230,7 +233,6 @@ MonoBehaviour:
m_FillClockwise: 1 m_FillClockwise: 1
m_FillOrigin: 0 m_FillOrigin: 0
m_UseSpriteMesh: 0 m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &16537674 --- !u!222 &16537674
CanvasRenderer: CanvasRenderer:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -239,80 +241,6 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 16537670} m_GameObject: {fileID: 16537670}
m_CullTransparentMesh: 0 m_CullTransparentMesh: 0
--- !u!1 &518730348
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 518730350}
- component: {fileID: 518730349}
m_Layer: 0
m_Name: Camera
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!20 &518730349
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 518730348}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &518730350
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 518730348}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 488, y: 418, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &519420028 --- !u!1 &519420028
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -352,11 +280,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f0bc6c75abb2e0b47a25aa49bfd488ed, type: 3} m_Script: {fileID: 11500000, guid: f0bc6c75abb2e0b47a25aa49bfd488ed, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
camera: {fileID: 518730349}
okButton: {fileID: 16537672} okButton: {fileID: 16537672}
cancelButton: {fileID: 628393011} cancelButton: {fileID: 628393011}
text: {fileID: 2101290655}
button: {fileID: 0}
--- !u!20 &519420031 --- !u!20 &519420031
Camera: Camera:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -462,7 +387,7 @@ MonoBehaviour:
m_GameObject: {fileID: 628393009} m_GameObject: {fileID: 628393009}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Navigation: m_Navigation:
@ -496,6 +421,8 @@ MonoBehaviour:
m_OnClick: m_OnClick:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null
--- !u!114 &628393012 --- !u!114 &628393012
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -505,7 +432,7 @@ MonoBehaviour:
m_GameObject: {fileID: 628393009} m_GameObject: {fileID: 628393009}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Material: {fileID: 0} m_Material: {fileID: 0}
@ -514,6 +441,8 @@ MonoBehaviour:
m_OnCullStateChanged: m_OnCullStateChanged:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1 m_Type: 1
m_PreserveAspect: 0 m_PreserveAspect: 0
@ -523,7 +452,6 @@ MonoBehaviour:
m_FillClockwise: 1 m_FillClockwise: 1
m_FillOrigin: 0 m_FillOrigin: 0
m_UseSpriteMesh: 0 m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &628393013 --- !u!222 &628393013
CanvasRenderer: CanvasRenderer:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -578,7 +506,7 @@ MonoBehaviour:
m_GameObject: {fileID: 865871444} m_GameObject: {fileID: 865871444}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Material: {fileID: 0} m_Material: {fileID: 0}
@ -587,6 +515,8 @@ MonoBehaviour:
m_OnCullStateChanged: m_OnCullStateChanged:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData: m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14 m_FontSize: 14
@ -636,7 +566,7 @@ MonoBehaviour:
m_GameObject: {fileID: 872009839} m_GameObject: {fileID: 872009839}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal m_HorizontalAxis: Horizontal
@ -655,7 +585,7 @@ MonoBehaviour:
m_GameObject: {fileID: 872009839} m_GameObject: {fileID: 872009839}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0} m_FirstSelected: {fileID: 0}
@ -673,7 +603,7 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 2 m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1556045504 --- !u!1 &1556045504
GameObject: GameObject:
@ -703,7 +633,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1556045504} m_GameObject: {fileID: 1556045504}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1 m_IgnoreReversedGraphics: 1
@ -720,7 +650,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1556045504} m_GameObject: {fileID: 1556045504}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_UiScaleMode: 0 m_UiScaleMode: 0
@ -767,9 +697,8 @@ RectTransform:
m_Children: m_Children:
- {fileID: 16537671} - {fileID: 16537671}
- {fileID: 628393010} - {fileID: 628393010}
- {fileID: 2101290654}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 3 m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0} m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0}
@ -822,7 +751,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1584557231} m_GameObject: {fileID: 1584557231}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Material: {fileID: 0} m_Material: {fileID: 0}
@ -831,6 +760,8 @@ MonoBehaviour:
m_OnCullStateChanged: m_OnCullStateChanged:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData: m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14 m_FontSize: 14
@ -855,80 +786,3 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1584557231} m_GameObject: {fileID: 1584557231}
m_CullTransparentMesh: 0 m_CullTransparentMesh: 0
--- !u!1 &2101290653
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2101290654}
- component: {fileID: 2101290656}
- component: {fileID: 2101290655}
m_Layer: 0
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2101290654
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2101290653}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1556045508}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 1.5, y: -61.4}
m_SizeDelta: {x: 588.7, y: 398.7}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2101290655
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2101290653}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: New Text
--- !u!222 &2101290656
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2101290653}
m_CullTransparentMesh: 0

View File

@ -9,7 +9,8 @@ using System.Linq;
using System.Text; using System.Text;
using UnityEngine.UI; using UnityEngine.UI;
using UnityEngine.Scripting; using UnityEngine.Scripting;
using Cysharp.Threading.Tasks; using UniRx;
using UniRx.Async;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System.Threading.Tasks; using System.Threading.Tasks;
@ -31,7 +32,7 @@ using NUnit.Framework;
using UnityEngine.TestTools; using UnityEngine.TestTools;
using FluentAssertions; using FluentAssertions;
namespace Cysharp.Threading.TasksTests namespace UniRx.AsyncTests
{ {
public class AsyncTest public class AsyncTest
{ {
@ -55,8 +56,6 @@ namespace Cysharp.Threading.TasksTests
} }
} }
#if !UNITY_WEBGL
[UnityTest] [UnityTest]
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () => public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
{ {
@ -78,8 +77,6 @@ namespace Cysharp.Threading.TasksTests
} }
}); });
#endif
[UnityTest] [UnityTest]
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () => public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
{ {
@ -104,12 +101,12 @@ namespace Cysharp.Threading.TasksTests
{ {
var a = UniTask.FromResult(999); var a = UniTask.FromResult(999);
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask(); var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask(); var c = UniTask.DelayFrame(99);
var (a2, b2, c2) = await UniTask.WhenAll(a, b, c); var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
a2.Should().Be(999); a2.Should().Be(999);
b2.Should().Be(AsyncUnit.Default); b2.Should().Be(AsyncUnit.Default);
c2.Should().Be(AsyncUnit.Default); c2.Should().Be(99);
}); });
[UnityTest] [UnityTest]
@ -117,28 +114,32 @@ namespace Cysharp.Threading.TasksTests
{ {
var a = UniTask.FromResult(999); var a = UniTask.FromResult(999);
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask(); var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask(); var c = UniTask.DelayFrame(99);
var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c); var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
win.Should().Be(0); win.Should().Be(0);
a2.Should().Be(999); a2.hasResult.Should().Be(true);
a2.result0.Should().Be(999);
b2.hasResult.Should().Be(false);
c2.hasResult.Should().Be(false);
}); });
[UnityTest] [UnityTest]
public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () => public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
{ {
await ToaruCoroutineEnumerator(); // wait 5 frame:) await ToaruCoroutineEnumerator(); // wait 5 frame:)
await ToaruCoroutineEnumerator().ConfigureAwait(PlayerLoopTiming.PostLateUpdate);
}); });
//[UnityTest] [UnityTest]
//public IEnumerator JobSystem() => UniTask.ToCoroutine(async () => public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
//{ {
// var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) }; var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
// JobHandle.ScheduleBatchedJobs(); JobHandle.ScheduleBatchedJobs();
// await job.Schedule(); await job.Schedule();
// job.inOut[0].Should().Be(999); job.inOut[0].Should().Be(999);
// job.inOut.Dispose(); job.inOut.Dispose();
//}); });
class MyMyClass class MyMyClass
{ {
@ -150,7 +151,7 @@ namespace Cysharp.Threading.TasksTests
{ {
bool t = false; bool t = false;
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget(); UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(_ => t = true).Forget();
var startFrame = Time.frameCount; var startFrame = Time.frameCount;
await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate); await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
@ -164,7 +165,7 @@ namespace Cysharp.Threading.TasksTests
{ {
bool t = true; bool t = true;
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget(); UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(_ => t = false).Forget();
var startFrame = Time.frameCount; var startFrame = Time.frameCount;
await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate); await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
@ -178,7 +179,7 @@ namespace Cysharp.Threading.TasksTests
{ {
var v = new MyMyClass { MyProperty = 99 }; var v = new MyMyClass { MyProperty = 99 };
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget(); UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(_ => v.MyProperty = 1000).Forget();
var startFrame = Time.frameCount; var startFrame = Time.frameCount;
await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate); await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
@ -187,8 +188,6 @@ namespace Cysharp.Threading.TasksTests
diff.Should().Be(11); diff.Should().Be(11);
}); });
#if !UNITY_WEBGL
[UnityTest] [UnityTest]
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () => public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
{ {
@ -203,7 +202,7 @@ namespace Cysharp.Threading.TasksTests
//await UniTask.SwitchToThreadPool(); //await UniTask.SwitchToThreadPool();
@ -221,8 +220,6 @@ namespace Cysharp.Threading.TasksTests
currentThreadId.Should().Be(switchedThreadId2); currentThreadId.Should().Be(switchedThreadId2);
}); });
#endif
//[UnityTest] //[UnityTest]
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () => //public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
//{ //{
@ -272,13 +269,12 @@ namespace Cysharp.Threading.TasksTests
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget(); UniTask.DelayFrame(10).ContinueWith(_ => cts.Cancel()).Forget();
var first = Time.frameCount; var first = Time.frameCount;
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow(); var (canceled, value) = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
var r = (Time.frameCount - first); (Time.frameCount - first).Should().Be(11); // 10 frame canceled
(9 < r && r < 11).Should().BeTrue();
canceled.Should().Be(true); canceled.Should().Be(true);
}); });
@ -287,12 +283,12 @@ namespace Cysharp.Threading.TasksTests
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget(); UniTask.DelayFrame(10).ContinueWith(_ => cts.Cancel()).Forget();
bool occur = false; bool occur = false;
try try
{ {
await UniTask.DelayFrame(100, cancellationToken: cts.Token); var value = await UniTask.DelayFrame(100, cancellationToken: cts.Token);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
@ -310,33 +306,33 @@ namespace Cysharp.Threading.TasksTests
yield return null; yield return null;
} }
//[UnityTest] [UnityTest]
//public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () => public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
//{ {
// bool calledEx = false; bool calledEx = false;
// Action<Exception> action = exx => Action<Exception> action = exx =>
// { {
// calledEx = true; calledEx = true;
// exx.Message.Should().Be("MyException"); exx.Message.Should().Be("MyException");
// }; };
// UniTaskScheduler.UnobservedTaskException += action; UniTaskScheduler.UnobservedTaskException += action;
// var ex = InException1(); var ex = InException1();
// ex = default(UniTask); ex = default(UniTask);
// await UniTask.DelayFrame(3); await UniTask.DelayFrame(3);
// GC.Collect(); GC.Collect();
// GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();
// GC.Collect(); GC.Collect();
// await UniTask.DelayFrame(1); await UniTask.DelayFrame(1);
// calledEx.Should().BeTrue(); calledEx.Should().BeTrue();
// UniTaskScheduler.UnobservedTaskException -= action; UniTaskScheduler.UnobservedTaskException -= action;
//}); });
[UnityTest] [UnityTest]
public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () => public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
@ -366,29 +362,6 @@ namespace Cysharp.Threading.TasksTests
UniTaskScheduler.UnobservedTaskException -= action; UniTaskScheduler.UnobservedTaskException -= action;
}); });
// can not run on RuntimeUnitTestToolkit so ignore...
// [UnityTest]
// public IEnumerator ThrowExceptionUnawaited() => UniTask.ToCoroutine(async () =>
// {
// LogAssert.Expect(LogType.Exception, "Exception: MyException");
//#pragma warning disable 1998
// async UniTask Throw() => throw new Exception("MyException");
//#pragma warning restore 1998
//#pragma warning disable 4014
// Throw();
//#pragma warning restore 4014
// await UniTask.DelayFrame(3);
// GC.Collect();
// GC.WaitForPendingFinalizers();
// GC.Collect();
// await UniTask.DelayFrame(1);
// });
async UniTask InException1() async UniTask InException1()
{ {
await UniTask.Yield(); await UniTask.Yield();
@ -401,24 +374,6 @@ namespace Cysharp.Threading.TasksTests
throw new Exception("MyException"); throw new Exception("MyException");
} }
[UnityTest]
public IEnumerator NextFrame1() => UniTask.ToCoroutine(async () =>
{
await UniTask.Yield(PlayerLoopTiming.LastUpdate);
var frame = Time.frameCount;
await UniTask.NextFrame();
Time.frameCount.Should().Be(frame + 1);
});
[UnityTest]
public IEnumerator NextFrame2() => UniTask.ToCoroutine(async () =>
{
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
var frame = Time.frameCount;
await UniTask.NextFrame();
Time.frameCount.Should().Be(frame + 1);
});
[UnityTest] [UnityTest]
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () => public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
{ {
@ -452,7 +407,7 @@ namespace Cysharp.Threading.TasksTests
completedTaskObserver.OnCompletedCalled.Should().BeTrue(); completedTaskObserver.OnCompletedCalled.Should().BeTrue();
completedTaskObserver.OnErrorCalled.Should().BeFalse(); completedTaskObserver.OnErrorCalled.Should().BeFalse();
var delayFrameTaskObserver = new ToObservableObserver<AsyncUnit>(); var delayFrameTaskObserver = new ToObservableObserver<int>();
UniTask.DelayFrame(1).ToObservable().Subscribe(delayFrameTaskObserver); UniTask.DelayFrame(1).ToObservable().Subscribe(delayFrameTaskObserver);
delayFrameTaskObserver.OnNextCalled.Should().BeFalse(); delayFrameTaskObserver.OnNextCalled.Should().BeFalse();
delayFrameTaskObserver.OnCompletedCalled.Should().BeFalse(); delayFrameTaskObserver.OnCompletedCalled.Should().BeFalse();
@ -474,7 +429,6 @@ namespace Cysharp.Threading.TasksTests
public void OnError(Exception error) => OnErrorCalled = true; public void OnError(Exception error) => OnErrorCalled = true;
} }
#endif #endif
#endif #endif
} }

View File

@ -0,0 +1,405 @@
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.UI;
using UnityEngine.Scripting;
using UniRx;
using UniRx.Async;
using UnityEngine.SceneManagement;
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System.Threading.Tasks;
#endif
using UnityEngine.Networking;
#if !UNITY_2019_3_OR_NEWER
using UnityEngine.Experimental.LowLevel;
#else
using UnityEngine.LowLevel;
#endif
#if !UNITY_WSA
using Unity.Jobs;
#endif
using Unity.Collections;
using System.Threading;
using NUnit.Framework;
using UnityEngine.TestTools;
using FluentAssertions;
namespace UniRx.AsyncTests
{
public class AsyncTest
{
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#if !UNITY_WSA
public struct MyJob : IJob
{
public int loopCount;
public NativeArray<int> inOut;
public int result;
public void Execute()
{
result = 0;
for (int i = 0; i < loopCount; i++)
{
result++;
}
inOut[0] = result;
}
}
[UnityTest]
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
{
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
var time = Time.realtimeSinceStartup;
Time.timeScale = 0.5f;
try
{
await UniTask.Delay(TimeSpan.FromSeconds(3));
var elapsed = Time.realtimeSinceStartup - time;
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6);
}
finally
{
Time.timeScale = 1.0f;
}
});
[UnityTest]
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
{
var time = Time.realtimeSinceStartup;
Time.timeScale = 0.5f;
try
{
await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true);
var elapsed = Time.realtimeSinceStartup - time;
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
}
finally
{
Time.timeScale = 1.0f;
}
});
[UnityTest]
public IEnumerator WhenAll() => UniTask.ToCoroutine(async () =>
{
var a = UniTask.FromResult(999);
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
var c = UniTask.DelayFrame(99);
var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
a2.Should().Be(999);
b2.Should().Be(AsyncUnit.Default);
c2.Should().Be(99);
});
[UnityTest]
public IEnumerator WhenAny() => UniTask.ToCoroutine(async () =>
{
var a = UniTask.FromResult(999);
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
var c = UniTask.DelayFrame(99);
var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
win.Should().Be(0);
a2.hasResult.Should().Be(true);
a2.result0.Should().Be(999);
b2.hasResult.Should().Be(false);
c2.hasResult.Should().Be(false);
});
[UnityTest]
public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
{
await ToaruCoroutineEnumerator(); // wait 5 frame:)
await ToaruCoroutineEnumerator().ConfigureAwait(PlayerLoopTiming.PostLateUpdate);
});
[UnityTest]
public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
{
var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
JobHandle.ScheduleBatchedJobs();
await job.Schedule();
job.inOut[0].Should().Be(999);
job.inOut.Dispose();
});
class MyMyClass
{
public int MyProperty { get; set; }
}
[UnityTest]
public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
{
bool t = false;
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(_ => t = true).Forget();
var startFrame = Time.frameCount;
await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
var diff = Time.frameCount - startFrame;
diff.Should().Be(11);
});
[UnityTest]
public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
{
bool t = true;
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(_ => t = false).Forget();
var startFrame = Time.frameCount;
await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
var diff = Time.frameCount - startFrame;
diff.Should().Be(11);
});
[UnityTest]
public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
{
var v = new MyMyClass { MyProperty = 99 };
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(_ => v.MyProperty = 1000).Forget();
var startFrame = Time.frameCount;
await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
var diff = Time.frameCount - startFrame;
diff.Should().Be(11);
});
[UnityTest]
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
{
await UniTask.Yield();
var currentThreadId = Thread.CurrentThread.ManagedThreadId;
await UniTask.SwitchToThreadPool();
//await UniTask.SwitchToThreadPool();
//await UniTask.SwitchToThreadPool();
var switchedThreadId = Thread.CurrentThread.ManagedThreadId;
currentThreadId.Should().NotBe(switchedThreadId);
await UniTask.Yield();
var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId;
currentThreadId.Should().Be(switchedThreadId2);
});
//[UnityTest]
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
//{
// var v = await Observable.Range(1, 10).ToUniTask();
// v.Is(10);
// v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true);
// v.Is(1);
// v = await UniTask.DelayFrame(10).ToObservable().ToTask();
// v.Is(10);
// v = await UniTask.FromResult(99).ToObservable();
// v.Is(99);
//});
//[UnityTest]
//public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () =>
//{
// var rp1 = new ReactiveProperty<int>(99);
// UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget();
// await rp1;
// rp1.Value.Is(100);
// // var delay2 = UniTask.DelayFrame(10);
// // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2);
//});
//[UnityTest]
//public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () =>
//{
// var rc = new ReactiveCommand<int>();
// UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget();
// var v = await rc;
// v.Is(100);
//});
[UnityTest]
public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () =>
{
var cts = new CancellationTokenSource();
UniTask.DelayFrame(10).ContinueWith(_ => cts.Cancel()).Forget();
var first = Time.frameCount;
var (canceled, value) = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
(Time.frameCount - first).Should().Be(11); // 10 frame canceled
canceled.Should().Be(true);
});
[UnityTest]
public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () =>
{
var cts = new CancellationTokenSource();
UniTask.DelayFrame(10).ContinueWith(_ => cts.Cancel()).Forget();
bool occur = false;
try
{
var value = await UniTask.DelayFrame(100, cancellationToken: cts.Token);
}
catch (OperationCanceledException)
{
occur = true;
}
occur.Should().BeTrue();
});
IEnumerator ToaruCoroutineEnumerator()
{
yield return null;
yield return null;
yield return null;
yield return null;
yield return null;
}
[UnityTest]
public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
{
bool calledEx = false;
Action<Exception> action = exx =>
{
calledEx = true;
exx.Message.Should().Be("MyException");
};
UniTaskScheduler.UnobservedTaskException += action;
var ex = InException1();
ex = default(UniTask);
await UniTask.DelayFrame(3);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
await UniTask.DelayFrame(1);
calledEx.Should().BeTrue();
UniTaskScheduler.UnobservedTaskException -= action;
});
[UnityTest]
public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
{
bool calledEx = false;
Action<Exception> action = exx =>
{
calledEx = true;
exx.Message.Should().Be("MyException");
};
UniTaskScheduler.UnobservedTaskException += action;
var ex = InException2();
ex = default(UniTask<int>);
await UniTask.DelayFrame(3);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
await UniTask.DelayFrame(1);
calledEx.Should().BeTrue();
UniTaskScheduler.UnobservedTaskException -= action;
});
async UniTask InException1()
{
await UniTask.Yield();
throw new Exception("MyException");
}
async UniTask<int> InException2()
{
await UniTask.Yield();
throw new Exception("MyException");
}
[UnityTest]
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
{
var time = Time.realtimeSinceStartup;
await ParentCoroutineEnumerator();
var elapsed = Time.realtimeSinceStartup - time;
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
});
IEnumerator ParentCoroutineEnumerator()
{
yield return ChildCoroutineEnumerator();
}
IEnumerator ChildCoroutineEnumerator()
{
yield return new WaitForSeconds(3);
}
#endif
#endif
}
}
#endif

View File

@ -0,0 +1,96 @@
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.UI;
using UnityEngine.Scripting;
using UniRx;
using UniRx.Async;
using UnityEngine.SceneManagement;
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System.Threading.Tasks;
#endif
using UnityEngine.Networking;
#if !UNITY_2019_3_OR_NEWER
using UnityEngine.Experimental.LowLevel;
#else
using UnityEngine.LowLevel;
#endif
#if !UNITY_WSA
using Unity.Jobs;
#endif
using Unity.Collections;
using System.Threading;
using NUnit.Framework;
using UnityEngine.TestTools;
using FluentAssertions;
namespace UniRx.AsyncTests
{
public class RunTest
{
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#if !UNITY_WSA
//[UnityTest]
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
//{
// var main = Thread.CurrentThread.ManagedThreadId;
// var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false);
// UnityEngine.Debug.Log("Ret Value is:" + v);
// UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
// //v.Should().Be(3);
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
//});
[UnityTest]
public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () =>
{
var main = Thread.CurrentThread.ManagedThreadId;
var v = await UniTask.Run(() => 3, true);
v.Should().Be(3);
main.Should().Be(Thread.CurrentThread.ManagedThreadId);
});
//[UnityTest]
//public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () =>
//{
// var main = Thread.CurrentThread.ManagedThreadId;
// try
// {
// await UniTask.Run<int>(() => throw new Exception(), false);
// }
// catch
// {
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
// }
//});
[UnityTest]
public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () =>
{
var main = Thread.CurrentThread.ManagedThreadId;
try
{
await UniTask.Run<int>(() => throw new Exception(), true);
}
catch
{
main.Should().Be(Thread.CurrentThread.ManagedThreadId);
}
});
#endif
#endif
}
}
#endif

View File

@ -1,12 +1,10 @@
{ {
"name": "UniTask.Tests.Editor", "name": "UniRx.Async.Tests.Editor",
"references": [ "references": [
"UnityEngine.TestRunner", "UnityEngine.TestRunner",
"UnityEditor.TestRunner", "UnityEditor.TestRunner",
"UniTask.Tests", "UniRx.Async",
"UniTask", "UniRx.Async.Tests"
"Unity.ResourceManager",
"DOTween.Modules"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"
@ -15,13 +13,11 @@
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": true, "overrideReferences": true,
"precompiledReferences": [ "precompiledReferences": [
"nunit.framework.dll", "nunit.framework.dll"
"DOTween.dll"
], ],
"autoReferenced": false, "autoReferenced": false,
"defineConstraints": [ "defineConstraints": [
"UNITY_INCLUDE_TESTS" "UNITY_INCLUDE_TESTS"
], ],
"versionDefines": [], "versionDefines": []
"noEngineReferences": false
} }

View File

@ -0,0 +1,44 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.UI;
using UnityEngine.Scripting;
using UniRx;
using UniRx.Async;
using Unity.Collections;
using System.Threading;
using NUnit.Framework;
using UnityEngine.TestTools;
using FluentAssertions;
namespace UniRx.AsyncTests
{
public class WhenAnyTest
{
[UnityTest]
public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () =>
{
var cts = new CancellationTokenSource();
var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1));
var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token);
cts.CancelAfterSlim(200);
try
{
var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask });
}
catch (Exception ex)
{
ex.Should().BeAssignableTo<OperationCanceledException>();
}
});
}
}
#endif

View File

@ -9,7 +9,8 @@ using System.Linq;
using System.Text; using System.Text;
using UnityEngine.UI; using UnityEngine.UI;
using UnityEngine.Scripting; using UnityEngine.Scripting;
using Cysharp.Threading.Tasks; using UniRx;
using UniRx.Async;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System.Threading.Tasks; using System.Threading.Tasks;
@ -31,13 +32,12 @@ using NUnit.Framework;
using UnityEngine.TestTools; using UnityEngine.TestTools;
using FluentAssertions; using FluentAssertions;
namespace Cysharp.Threading.TasksTests namespace UniRx.AsyncTests
{ {
public class RunTest public class RunTest
{ {
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#if !UNITY_WSA #if !UNITY_WSA
#if !UNITY_WEBGL
//[UnityTest] //[UnityTest]
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () => //public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
@ -79,9 +79,7 @@ namespace Cysharp.Threading.TasksTests
var main = Thread.CurrentThread.ManagedThreadId; var main = Thread.CurrentThread.ManagedThreadId;
try try
{ {
#pragma warning disable CS1998 await UniTask.Run<int>(() => throw new Exception(), true);
await UniTask.Run<int>(async () => throw new Exception(), true);
#pragma warning restore CS1998
} }
catch catch
{ {
@ -89,7 +87,7 @@ namespace Cysharp.Threading.TasksTests
} }
}); });
#endif
#endif #endif
#endif #endif
} }

View File

@ -1,25 +1,20 @@
{ {
"name": "UniTask.Tests", "name": "UniRx.Async.Tests",
"references": [ "references": [
"UnityEngine.TestRunner", "UnityEngine.TestRunner",
"UnityEditor.TestRunner", "UnityEditor.TestRunner",
"UniTask", "UniRx.Async"
"Unity.ResourceManager",
"DOTween.Modules",
"UniTask.Linq"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": true, "overrideReferences": true,
"precompiledReferences": [ "precompiledReferences": [
"nunit.framework.dll", "nunit.framework.dll"
"DOTween.dll"
], ],
"autoReferenced": false, "autoReferenced": false,
"defineConstraints": [ "defineConstraints": [
"UNITY_INCLUDE_TESTS" "UNITY_INCLUDE_TESTS"
], ],
"versionDefines": [], "versionDefines": []
"noEngineReferences": false
} }

View File

@ -9,14 +9,15 @@ using System.Linq;
using System.Text; using System.Text;
using UnityEngine.UI; using UnityEngine.UI;
using UnityEngine.Scripting; using UnityEngine.Scripting;
using Cysharp.Threading.Tasks; using UniRx;
using UniRx.Async;
using Unity.Collections; using Unity.Collections;
using System.Threading; using System.Threading;
using NUnit.Framework; using NUnit.Framework;
using UnityEngine.TestTools; using UnityEngine.TestTools;
using FluentAssertions; using FluentAssertions;
namespace Cysharp.Threading.TasksTests namespace UniRx.AsyncTests
{ {
public class WhenAnyTest public class WhenAnyTest
{ {

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a3e874acee8398745b1dc3eddac09eaa guid: 38249c6f05d584f44a219b4c97790f99
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@ -1,10 +1,11 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or
using System; using System;
namespace Cysharp.Threading.Tasks namespace UniRx.Async
{ {
public readonly struct AsyncUnit : IEquatable<AsyncUnit> public struct AsyncUnit : IEquatable<AsyncUnit>
{ {
public static readonly AsyncUnit Default = new AsyncUnit(); public static readonly AsyncUnit Default = new AsyncUnit();
@ -24,3 +25,4 @@ namespace Cysharp.Threading.Tasks
} }
} }
} }
#endif

View File

@ -1,9 +1,10 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
namespace Cysharp.Threading.Tasks namespace UniRx.Async
{ {
public class CancellationTokenEqualityComparer : IEqualityComparer<CancellationToken> public class CancellationTokenEqualityComparer : IEqualityComparer<CancellationToken>
{ {
@ -21,3 +22,4 @@ namespace Cysharp.Threading.Tasks
} }
} }
#endif

View File

@ -0,0 +1,76 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Threading;
namespace UniRx.Async
{
public static class CancellationTokenExtensions
{
static readonly Action<object> cancellationTokenCallback = Callback;
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cts)
{
if (cts.IsCancellationRequested)
{
return (UniTask.FromCanceled(cts), default(CancellationTokenRegistration));
}
var promise = new UniTaskCompletionSource<AsyncUnit>();
return (promise.Task, cts.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise));
}
static void Callback(object state)
{
var promise = (UniTaskCompletionSource<AsyncUnit>)state;
promise.TrySetResult(AsyncUnit.Default);
}
public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback)
{
var restoreFlow = false;
if (!ExecutionContext.IsFlowSuppressed())
{
ExecutionContext.SuppressFlow();
restoreFlow = true;
}
try
{
return cancellationToken.Register(callback, false);
}
finally
{
if (restoreFlow)
{
ExecutionContext.RestoreFlow();
}
}
}
public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action<object> callback, object state)
{
var restoreFlow = false;
if (!ExecutionContext.IsFlowSuppressed())
{
ExecutionContext.SuppressFlow();
restoreFlow = true;
}
try
{
return cancellationToken.Register(callback, state, false);
}
finally
{
if (restoreFlow)
{
ExecutionContext.RestoreFlow();
}
}
}
}
}
#endif

View File

@ -0,0 +1,48 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Threading;
using UnityEngine;
using UniRx.Async.Triggers;
using System;
namespace UniRx.Async
{
public static class CancellationTokenSourceExtensions
{
public static void CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
{
var delay = UniTask.Delay(millisecondsDelay, ignoreTimeScale, delayTiming, cts.Token);
CancelAfterCore(cts, delay).Forget();
}
public static void CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
{
var delay = UniTask.Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cts.Token);
CancelAfterCore(cts, delay).Forget();
}
static async UniTaskVoid CancelAfterCore(CancellationTokenSource cts, UniTask delayTask)
{
var alreadyCanceled = await delayTask.SuppressCancellationThrow();
if (!alreadyCanceled)
{
cts.Cancel();
cts.Dispose();
}
}
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component)
{
RegisterRaiseCancelOnDestroy(cts, component.gameObject);
}
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject)
{
var trigger = gameObject.GetAsyncDestroyTrigger();
trigger.AddCancellationTriggerOnDestroy(cts);
}
}
}
#endif

View File

@ -1,4 +1,5 @@
 #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#pragma warning disable CS0436 #pragma warning disable CS0436
@ -15,3 +16,4 @@ namespace System.Runtime.CompilerServices
} }
} }
#endif

View File

@ -1,110 +1,130 @@
 #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security; using System.Security;
namespace Cysharp.Threading.Tasks.CompilerServices namespace UniRx.Async.CompilerServices
{ {
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder public struct AsyncUniTaskMethodBuilder
{ {
IStateMachineRunnerPromise runnerPromise; UniTaskCompletionSource promise;
Exception ex; Action moveNext;
// 1. Static Create method. // 1. Static Create method.
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskMethodBuilder Create() public static AsyncUniTaskMethodBuilder Create()
{ {
return default; var builder = new AsyncUniTaskMethodBuilder();
return builder;
} }
// 2. TaskLike Task property. // 2. TaskLike Task property.
[DebuggerHidden]
public UniTask Task public UniTask Task
{ {
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get get
{ {
if (runnerPromise != null) if (promise != null)
{ {
return runnerPromise.Task; return promise.Task;
} }
else if (ex != null)
if (moveNext == null)
{ {
return UniTask.FromException(ex); return UniTask.CompletedTask;
} }
else else
{ {
return UniTask.CompletedTask; promise = new UniTaskCompletionSource();
return promise.Task;
} }
} }
} }
// 3. SetException // 3. SetException
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception exception) public void SetException(Exception exception)
{ {
if (runnerPromise == null) if (promise == null)
{ {
ex = exception; promise = new UniTaskCompletionSource();
}
if (exception is OperationCanceledException ex)
{
promise.TrySetCanceled(ex);
} }
else else
{ {
runnerPromise.SetException(exception); promise.TrySetException(exception);
} }
} }
// 4. SetResult // 4. SetResult
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetResult() public void SetResult()
{ {
if (runnerPromise != null) if (moveNext == null)
{ {
runnerPromise.SetResult(); }
else
{
if (promise == null)
{
promise = new UniTaskCompletionSource();
}
promise.TrySetResult();
} }
} }
// 5. AwaitOnCompleted // 5. AwaitOnCompleted
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
if (runnerPromise == null) if (moveNext == null)
{ {
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise); if (promise == null)
{
promise = new UniTaskCompletionSource(); // built future.
}
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
} }
awaiter.OnCompleted(runnerPromise.MoveNext); awaiter.OnCompleted(moveNext);
} }
// 6. AwaitUnsafeOnCompleted // 6. AwaitUnsafeOnCompleted
[DebuggerHidden] [DebuggerHidden]
[SecuritySafeCritical] [SecuritySafeCritical]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
if (runnerPromise == null) if (moveNext == null)
{ {
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise); if (promise == null)
{
promise = new UniTaskCompletionSource(); // built future.
}
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
} }
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); awaiter.UnsafeOnCompleted(moveNext);
} }
// 7. Start // 7. Start
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine) public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
@ -115,127 +135,128 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[DebuggerHidden] [DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine) public void SetStateMachine(IAsyncStateMachine stateMachine)
{ {
// don't use boxed stateMachine.
} }
#if DEBUG || !UNITY_2018_3_OR_NEWER
// Important for IDE debugger.
object debuggingId;
private object ObjectIdForDebugger
{
get
{
if (debuggingId == null)
{
debuggingId = new object();
}
return debuggingId;
}
}
#endif
} }
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder<T> public struct AsyncUniTaskMethodBuilder<T>
{ {
IStateMachineRunnerPromise<T> runnerPromise;
Exception ex;
T result; T result;
UniTaskCompletionSource<T> promise;
Action moveNext;
// 1. Static Create method. // 1. Static Create method.
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskMethodBuilder<T> Create() public static AsyncUniTaskMethodBuilder<T> Create()
{ {
return default; var builder = new AsyncUniTaskMethodBuilder<T>();
return builder;
} }
// 2. TaskLike Task property. // 2. TaskLike Task property.
[DebuggerHidden]
public UniTask<T> Task public UniTask<T> Task
{ {
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get get
{ {
if (runnerPromise != null) if (promise != null)
{ {
return runnerPromise.Task; return new UniTask<T>(promise);
} }
else if (ex != null)
if (moveNext == null)
{ {
return UniTask.FromException<T>(ex); return new UniTask<T>(result);
} }
else else
{ {
return UniTask.FromResult(result); promise = new UniTaskCompletionSource<T>();
return new UniTask<T>(promise);
} }
} }
} }
// 3. SetException // 3. SetException
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception exception) public void SetException(Exception exception)
{ {
if (runnerPromise == null) if (promise == null)
{ {
ex = exception; promise = new UniTaskCompletionSource<T>();
}
if (exception is OperationCanceledException ex)
{
promise.TrySetCanceled(ex);
} }
else else
{ {
runnerPromise.SetException(exception); promise.TrySetException(exception);
} }
} }
// 4. SetResult // 4. SetResult
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetResult(T result) public void SetResult(T result)
{ {
if (runnerPromise == null) if (moveNext == null)
{ {
this.result = result; this.result = result;
} }
else else
{ {
runnerPromise.SetResult(result); if (promise == null)
{
promise = new UniTaskCompletionSource<T>();
}
promise.TrySetResult(result);
} }
} }
// 5. AwaitOnCompleted // 5. AwaitOnCompleted
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
if (runnerPromise == null) if (moveNext == null)
{ {
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise); if (promise == null)
{
promise = new UniTaskCompletionSource<T>(); // built future.
}
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
} }
awaiter.OnCompleted(runnerPromise.MoveNext); awaiter.OnCompleted(moveNext);
} }
// 6. AwaitUnsafeOnCompleted // 6. AwaitUnsafeOnCompleted
[DebuggerHidden] [DebuggerHidden]
[SecuritySafeCritical] [SecuritySafeCritical]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
if (runnerPromise == null) if (moveNext == null)
{ {
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise); if (promise == null)
{
promise = new UniTaskCompletionSource<T>(); // built future.
}
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
} }
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); awaiter.UnsafeOnCompleted(moveNext);
} }
// 7. Start // 7. Start
[DebuggerHidden] [DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine) public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine where TStateMachine : IAsyncStateMachine
{ {
@ -246,24 +267,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[DebuggerHidden] [DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine) public void SetStateMachine(IAsyncStateMachine stateMachine)
{ {
// don't use boxed stateMachine.
} }
#if DEBUG || !UNITY_2018_3_OR_NEWER
// Important for IDE debugger.
object debuggingId;
private object ObjectIdForDebugger
{
get
{
if (debuggingId == null)
{
debuggingId = new object();
}
return debuggingId;
}
}
#endif
} }
} }
#endif

View File

@ -0,0 +1,90 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security;
namespace UniRx.Async.CompilerServices
{
public struct AsyncUniTaskVoidMethodBuilder
{
Action moveNext;
// 1. Static Create method.
[DebuggerHidden]
public static AsyncUniTaskVoidMethodBuilder Create()
{
var builder = new AsyncUniTaskVoidMethodBuilder();
return builder;
}
// 2. TaskLike Task property(void)
public UniTaskVoid Task => default(UniTaskVoid);
// 3. SetException
[DebuggerHidden]
public void SetException(Exception exception)
{
UniTaskScheduler.PublishUnobservedTaskException(exception);
}
// 4. SetResult
[DebuggerHidden]
public void SetResult()
{
// do nothing
}
// 5. AwaitOnCompleted
[DebuggerHidden]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (moveNext == null)
{
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
}
awaiter.OnCompleted(moveNext);
}
// 6. AwaitUnsafeOnCompleted
[DebuggerHidden]
[SecuritySafeCritical]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (moveNext == null)
{
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
}
awaiter.UnsafeOnCompleted(moveNext);
}
// 7. Start
[DebuggerHidden]
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
// 8. SetStateMachine
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
}
}
}
#endif

View File

@ -0,0 +1,23 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace UniRx.Async.CompilerServices
{
internal class MoveNextRunner<TStateMachine>
where TStateMachine : IAsyncStateMachine
{
public TStateMachine StateMachine;
[DebuggerHidden]
public void Run()
{
StateMachine.MoveNext();
}
}
}
#endif

View File

@ -1,4 +1,5 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,11 +13,10 @@ using System.Security;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEngine;
namespace Cysharp.Threading.Tasks.Internal namespace UniRx.Async
{ {
internal static class DiagnosticsExtensions public static class DiagnosticsExtensions
{ {
static bool displayFilenames = true; static bool displayFilenames = true;
@ -45,6 +45,36 @@ namespace Cysharp.Threading.Tasks.Internal
{ typeof(UniTaskVoid), "UniTaskVoid" } { typeof(UniTaskVoid), "UniTaskVoid" }
}; };
public static string ToStringWithCleanupAsyncStackTrace(this Exception exception)
{
if (exception == null) return "";
String message = exception.Message;
String s;
if (message == null || message.Length <= 0)
{
s = exception.GetType().ToString();
}
else
{
s = exception.GetType().ToString() + ": " + message;
}
if (exception.InnerException != null)
{
s = s + " ---> " + exception.InnerException.ToString() + Environment.NewLine + " Exception_EndOfInnerExceptionStack";
}
string stackTrace = new StackTrace(exception).CleanupAsyncStackTrace();
if (stackTrace != null)
{
s += Environment.NewLine + stackTrace;
}
return s;
}
public static string CleanupAsyncStackTrace(this StackTrace stackTrace) public static string CleanupAsyncStackTrace(this StackTrace stackTrace)
{ {
if (stackTrace == null) return ""; if (stackTrace == null) return "";
@ -113,7 +143,7 @@ namespace Cysharp.Threading.Tasks.Internal
if (fileName != null) if (fileName != null)
{ {
sb.Append(' '); sb.Append(' ');
sb.AppendFormat(CultureInfo.InvariantCulture, "(at {0})", AppendHyperLink(fileName, sf.GetFileLineNumber().ToString())); sb.AppendFormat(CultureInfo.InvariantCulture, "in {0}:{1}", SimplifyPath(fileName), sf.GetFileLineNumber());
} }
} }
@ -148,7 +178,7 @@ namespace Cysharp.Threading.Tasks.Internal
foreach (var candidateMethod in methods) foreach (var candidateMethod in methods)
{ {
var attributes = candidateMethod.GetCustomAttributes<StateMachineAttribute>(false); var attributes = candidateMethod.GetCustomAttributes<StateMachineAttribute>();
if (attributes == null) if (attributes == null)
{ {
continue; continue;
@ -182,7 +212,7 @@ namespace Cysharp.Threading.Tasks.Internal
{ {
return "(" + string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true))) + ")"; return "(" + string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true))) + ")";
} }
if (!t.IsGenericType) return shortName ? t.Name : t.FullName.Replace("Cysharp.Threading.Tasks.Triggers.", "").Replace("Cysharp.Threading.Tasks.Internal.", "").Replace("Cysharp.Threading.Tasks.", "") ?? t.Name; if (!t.IsGenericType) return shortName ? t.Name : t.FullName ?? t.Name;
var innerFormat = string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true))); var innerFormat = string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true)));
@ -192,7 +222,7 @@ namespace Cysharp.Threading.Tasks.Internal
genericType = "Task"; genericType = "Task";
} }
return typeBeautifyRegex.Replace(genericType, "").Replace("Cysharp.Threading.Tasks.Triggers.", "").Replace("Cysharp.Threading.Tasks.Internal.", "").Replace("Cysharp.Threading.Tasks.", "") + "<" + innerFormat + ">"; return typeBeautifyRegex.Replace(genericType, "") + "<" + innerFormat + ">";
} }
static bool IgnoreLine(MethodBase methodInfo) static bool IgnoreLine(MethodBase methodInfo)
@ -206,7 +236,7 @@ namespace Cysharp.Threading.Tasks.Internal
{ {
return true; return true;
} }
else if (declareType.StartsWith("Cysharp.Threading.Tasks.CompilerServices")) else if (declareType.StartsWith("UniRx.Async.CompilerServices"))
{ {
return true; return true;
} }
@ -218,19 +248,11 @@ namespace Cysharp.Threading.Tasks.Internal
{ {
return true; return true;
} }
else if (declareType.StartsWith("Cysharp.Threading.Tasks.UniTaskCompletionSourceCore"))
{
return true;
}
else if (declareType.StartsWith("Cysharp.Threading.Tasks.AwaiterActions"))
{
return true;
}
return false; return false;
} }
static string AppendHyperLink(string path, string line) static string SimplifyPath(string path)
{ {
var fi = new FileInfo(path); var fi = new FileInfo(path);
if (fi.Directory == null) if (fi.Directory == null)
@ -239,11 +261,10 @@ namespace Cysharp.Threading.Tasks.Internal
} }
else else
{ {
var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(PlayerLoopHelper.ApplicationDataPath, ""); return fi.Directory.Name + "/" + fi.Name;
var withAssetsPath = "Assets/" + fname;
return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
} }
} }
} }
} }
#endif

View File

@ -1,4 +1,5 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Linq; using System.Linq;
@ -6,7 +7,7 @@ using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace Cysharp.Threading.Tasks.Editor namespace UniRx.Async.Editor
{ {
// reflection call of UnityEditor.SplitterGUILayout // reflection call of UnityEditor.SplitterGUILayout
internal static class SplitterGUILayout internal static class SplitterGUILayout
@ -60,3 +61,4 @@ namespace Cysharp.Threading.Tasks.Editor
} }
} }
#endif

View File

@ -1,7 +1,7 @@
{ {
"name": "UniTask.Editor", "name": "UniRx.Async.Editor",
"references": [ "references": [
"UniTask" "UniRx.Async"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"
@ -10,8 +10,7 @@
"allowUnsafeCode": false, "allowUnsafeCode": false,
"overrideReferences": false, "overrideReferences": false,
"precompiledReferences": [], "precompiledReferences": [],
"autoReferenced": false, "autoReferenced": true,
"defineConstraints": [], "defineConstraints": [],
"versionDefines": [], "versionDefines": []
"noEngineReferences": false
} }

View File

@ -1,4 +1,5 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine; using UnityEngine;
using UnityEditor; using UnityEditor;
@ -7,16 +8,13 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System; using System;
using UnityEditor.IMGUI.Controls; using UnityEditor.IMGUI.Controls;
using Cysharp.Threading.Tasks.Internal; using UniRx.Async.Internal;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
namespace Cysharp.Threading.Tasks.Editor namespace UniRx.Async.Editor
{ {
public class UniTaskTrackerViewItem : TreeViewItem public class UniTaskTrackerViewItem : TreeViewItem
{ {
static Regex removeHref = new Regex("<a href.+>(.+)</a>", RegexOptions.Compiled);
public string TaskType { get; set; } public string TaskType { get; set; }
public string Elapsed { get; set; } public string Elapsed { get; set; }
public string Status { get; set; } public string Status { get; set; }
@ -45,8 +43,7 @@ namespace Cysharp.Threading.Tasks.Editor
} }
sb.Append(str[i]); sb.Append(str[i]);
} }
return sb.ToString();
return removeHref.Replace(sb.ToString(), "$1");
} }
public UniTaskTrackerViewItem(int id) : base(id) public UniTaskTrackerViewItem(int id) : base(id)
@ -180,3 +177,4 @@ namespace Cysharp.Threading.Tasks.Editor
} }
#endif

View File

@ -1,4 +1,5 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine; using UnityEngine;
using UnityEditor; using UnityEditor;
@ -7,9 +8,9 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System; using System;
using UnityEditor.IMGUI.Controls; using UnityEditor.IMGUI.Controls;
using Cysharp.Threading.Tasks.Internal; using UniRx.Async.Internal;
namespace Cysharp.Threading.Tasks.Editor namespace UniRx.Async.Editor
{ {
public class UniTaskTrackerWindow : EditorWindow public class UniTaskTrackerWindow : EditorWindow
{ {
@ -173,7 +174,7 @@ namespace Cysharp.Threading.Tasks.Editor
{ {
if (detailsStyle == null) if (detailsStyle == null)
{ {
detailsStyle = new GUIStyle("CN Message"); detailsStyle = new GUIStyle(EditorStyles.wordWrappedLabel);
detailsStyle.wordWrap = false; detailsStyle.wordWrap = false;
detailsStyle.stretchHeight = true; detailsStyle.stretchHeight = true;
detailsStyle.margin.right = 15; detailsStyle.margin.right = 15;
@ -207,3 +208,4 @@ namespace Cysharp.Threading.Tasks.Editor
} }
} }
#endif

View File

@ -1,9 +1,10 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Cysharp.Threading.Tasks namespace UniRx.Async
{ {
public static class EnumerableAsyncExtensions public static class EnumerableAsyncExtensions
{ {
@ -32,3 +33,4 @@ namespace Cysharp.Threading.Tasks
} }
#endif

View File

@ -0,0 +1,246 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading;
using UniRx.Async.Internal;
using UnityEngine;
namespace UniRx.Async
{
public static class EnumeratorAsyncExtensions
{
public static IAwaiter GetAwaiter(this IEnumerator enumerator)
{
var awaiter = new EnumeratorAwaiter(enumerator, CancellationToken.None);
if (!awaiter.IsCompleted)
{
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, awaiter);
}
return awaiter;
}
public static UniTask ToUniTask(this IEnumerator enumerator)
{
var awaiter = new EnumeratorAwaiter(enumerator, CancellationToken.None);
if (!awaiter.IsCompleted)
{
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, awaiter);
}
return new UniTask(awaiter);
}
public static UniTask ConfigureAwait(this IEnumerator enumerator, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
{
var awaiter = new EnumeratorAwaiter(enumerator, cancellationToken);
if (!awaiter.IsCompleted)
{
PlayerLoopHelper.AddAction(timing, awaiter);
}
return new UniTask(awaiter);
}
class EnumeratorAwaiter : IAwaiter, IPlayerLoopItem
{
IEnumerator innerEnumerator;
CancellationToken cancellationToken;
Action continuation;
AwaiterStatus status;
ExceptionDispatchInfo exception;
public EnumeratorAwaiter(IEnumerator innerEnumerator, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
status = AwaiterStatus.Canceled;
return;
}
this.innerEnumerator = ConsumeEnumerator(innerEnumerator);
this.status = AwaiterStatus.Pending;
this.cancellationToken = cancellationToken;
this.continuation = null;
TaskTracker.TrackActiveTask(this, 2);
}
public bool IsCompleted => status.IsCompleted();
public AwaiterStatus Status => status;
public void GetResult()
{
switch (status)
{
case AwaiterStatus.Succeeded:
break;
case AwaiterStatus.Pending:
Error.ThrowNotYetCompleted();
break;
case AwaiterStatus.Faulted:
exception.Throw();
break;
case AwaiterStatus.Canceled:
Error.ThrowOperationCanceledException();
break;
default:
break;
}
}
public bool MoveNext()
{
if (cancellationToken.IsCancellationRequested)
{
InvokeContinuation(AwaiterStatus.Canceled);
return false;
}
var success = false;
try
{
if (innerEnumerator.MoveNext())
{
return true;
}
else
{
success = true;
}
}
catch (Exception ex)
{
exception = ExceptionDispatchInfo.Capture(ex);
}
InvokeContinuation(success ? AwaiterStatus.Succeeded : AwaiterStatus.Faulted);
return false;
}
void InvokeContinuation(AwaiterStatus status)
{
this.status = status;
var cont = this.continuation;
// cleanup
TaskTracker.RemoveTracking(this);
this.continuation = null;
this.cancellationToken = CancellationToken.None;
this.innerEnumerator = null;
if (cont != null) cont.Invoke();
}
public void OnCompleted(Action continuation)
{
UnsafeOnCompleted(continuation);
}
public void UnsafeOnCompleted(Action continuation)
{
Error.ThrowWhenContinuationIsAlreadyRegistered(this.continuation);
this.continuation = continuation;
}
// Unwrap YieldInstructions
static IEnumerator ConsumeEnumerator(IEnumerator enumerator)
{
while (enumerator.MoveNext())
{
var current = enumerator.Current;
if (current == null)
{
yield return null;
}
else if (current is CustomYieldInstruction)
{
// WWW, WaitForSecondsRealtime
var e2 = UnwrapWaitCustomYieldInstruction((CustomYieldInstruction)current);
while (e2.MoveNext())
{
yield return null;
}
}
else if (current is YieldInstruction)
{
IEnumerator innerCoroutine = null;
switch (current)
{
case AsyncOperation ao:
innerCoroutine = UnwrapWaitAsyncOperation(ao);
break;
case WaitForSeconds wfs:
innerCoroutine = UnwrapWaitForSeconds(wfs);
break;
}
if (innerCoroutine != null)
{
while (innerCoroutine.MoveNext())
{
yield return null;
}
}
else
{
yield return null;
}
}
else if (current is IEnumerator e3)
{
var e4 = ConsumeEnumerator(e3);
while (e4.MoveNext())
{
yield return null;
}
}
else
{
// WaitForEndOfFrame, WaitForFixedUpdate, others.
yield return null;
}
}
}
// WWW and others as CustomYieldInstruction.
static IEnumerator UnwrapWaitCustomYieldInstruction(CustomYieldInstruction yieldInstruction)
{
while (yieldInstruction.keepWaiting)
{
yield return null;
}
}
static readonly FieldInfo waitForSeconds_Seconds = typeof(WaitForSeconds).GetField("m_Seconds", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic);
static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
{
var second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
var startTime = DateTimeOffset.UtcNow;
while (true)
{
yield return null;
var elapsed = (DateTimeOffset.UtcNow - startTime).TotalSeconds;
if (elapsed >= second)
{
break;
}
};
}
static IEnumerator UnwrapWaitAsyncOperation(AsyncOperation asyncOperation)
{
while (!asyncOperation.isDone)
{
yield return null;
}
}
}
}
}
#endif

View File

@ -1,7 +1,8 @@
 #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System; using System;
namespace Cysharp.Threading.Tasks namespace UniRx.Async
{ {
public static class ExceptionExtensions public static class ExceptionExtensions
{ {
@ -12,3 +13,4 @@ namespace Cysharp.Threading.Tasks
} }
} }
#endif

View File

@ -0,0 +1,64 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591
using System.Runtime.CompilerServices;
namespace UniRx.Async
{
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
Pending = 0,
/// <summary>The operation completed successfully.</summary>
Succeeded = 1,
/// <summary>The operation completed with an error.</summary>
Faulted = 2,
/// <summary>The operation completed due to cancellation.</summary>
Canceled = 3
}
public interface IAwaiter : ICriticalNotifyCompletion
{
AwaiterStatus Status { get; }
bool IsCompleted { get; }
void GetResult();
}
public interface IAwaiter<out T> : IAwaiter
{
new T GetResult();
}
public static class AwaiterStatusExtensions
{
/// <summary>!= Pending.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsCompleted(this AwaiterStatus status)
{
return status != AwaiterStatus.Pending;
}
/// <summary>== Succeeded.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsCompletedSuccessfully(this AwaiterStatus status)
{
return status == AwaiterStatus.Succeeded;
}
/// <summary>== Canceled.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsCanceled(this AwaiterStatus status)
{
return status == AwaiterStatus.Canceled;
}
/// <summary>== Faulted.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsFaulted(this AwaiterStatus status)
{
return status == AwaiterStatus.Faulted;
}
}
}
#endif

View File

@ -1,9 +1,10 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Threading; using System.Threading;
namespace Cysharp.Threading.Tasks.Internal namespace UniRx.Async.Internal
{ {
// Same interface as System.Buffers.ArrayPool<T> but only provides Shared. // Same interface as System.Buffers.ArrayPool<T> but only provides Shared.
@ -148,3 +149,4 @@ namespace Cysharp.Threading.Tasks.Internal
} }
} }
} }
#endif

View File

@ -1,10 +1,11 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Cysharp.Threading.Tasks.Internal namespace UniRx.Async.Internal
{ {
internal static class ArrayPoolUtil internal static class ArrayPoolUtil
{ {
@ -39,14 +40,9 @@ namespace Cysharp.Threading.Tasks.Internal
return new RentArray<T>(array, array.Length, null); return new RentArray<T>(array, array.Length, null);
} }
var defaultCount = 32; var defaultCount = 4;
if (source is ICollection<T> coll) if (source is ICollection<T> coll)
{ {
if (coll.Count == 0)
{
return new RentArray<T>(Array.Empty<T>(), 0, null);
}
defaultCount = coll.Count; defaultCount = coll.Count;
var pool = ArrayPool<T>.Shared; var pool = ArrayPool<T>.Shared;
var buffer = pool.Rent(defaultCount); var buffer = pool.Rent(defaultCount);
@ -113,3 +109,4 @@ namespace Cysharp.Threading.Tasks.Internal
} }
} }
#endif

View File

@ -1,10 +1,11 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Cysharp.Threading.Tasks.Internal namespace UniRx.Async.Internal
{ {
internal static class ArrayUtil internal static class ArrayUtil
{ {
@ -71,3 +72,4 @@ namespace Cysharp.Threading.Tasks.Internal
} }
} }
#endif

View File

@ -0,0 +1,32 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Threading;
namespace UniRx.Async.Internal
{
internal static class CancellationTokenHelper
{
public static bool TrySetOrLinkCancellationToken(ref CancellationToken field, CancellationToken newCancellationToken)
{
if (newCancellationToken == CancellationToken.None)
{
return false;
}
else if (field == CancellationToken.None)
{
field = newCancellationToken;
return true;
}
else if (field == newCancellationToken)
{
return false;
}
field = CancellationTokenSource.CreateLinkedTokenSource(field, newCancellationToken).Token;
return true;
}
}
}
#endif

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: e51b78c06cb410f42b36e0af9de3b065 guid: 53d1b536fc7e2d4458294ee2c7d9b743
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

Some files were not shown because too many files have changed in this diff Show More