A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections;
3using System.Linq;
4using System.Threading.Tasks;
5using NUnit.Framework;
6using NUnit.Framework.Interfaces;
7using NUnit.Framework.Internal;
8using NUnit.Framework.Internal.Commands;
9using UnityEngine.TestTools;
10using SetUpTearDownCommand = UnityEngine.TestTools.SetUpTearDownCommand;
11using TestActionCommand = UnityEngine.TestTools.TestActionCommand;
12
13namespace UnityEngine.TestRunner.NUnitExtensions.Runner
14{
15 internal static class TestCommandBuilder
16 {
17 public static TestCommand BuildTestCommand(TestMethod test, ITestFilter filter)
18 {
19 if (test.RunState != RunState.Runnable &&
20 !(test.RunState == RunState.Explicit && filter.IsExplicitMatch(test)))
21 {
22 return new SkipCommand(test);
23 }
24
25 var testReturnsIEnumerator = test.Method.ReturnType.Type == typeof(IEnumerator);
26 var testReturnsTask = test.Method.ReturnType.Type == typeof(Task);
27
28 TestCommand command;
29 if (testReturnsTask)
30 {
31 command = new TaskTestMethodCommand(test);
32 }
33 else if (testReturnsIEnumerator)
34 {
35 command = new EnumerableTestMethodCommand(test);
36 }
37 else
38 {
39 command = new UnityTestMethodCommand(test);
40 }
41
42 command = new UnityLogCheckDelegatingCommand(command);
43 foreach (var wrapper in test.Method.GetCustomAttributes<IWrapTestMethod>(true))
44 {
45 command = wrapper.Wrap(command);
46 if (command == null)
47 {
48 var message = String.Format("IWrapTestMethod implementation '{0}' returned null as command.",
49 wrapper.GetType().FullName);
50 return new FailCommand(test, ResultState.Failure, message);
51 }
52
53 if (testReturnsIEnumerator && !(command is IEnumerableTestMethodCommand))
54 {
55 command = TryReplaceWithEnumerableCommand(command);
56 if (command != null)
57 {
58 continue;
59 }
60
61 var message = String.Format("'{0}' is not supported on {1} as it does not handle returning IEnumerator.",
62 wrapper.GetType().FullName,
63 GetTestBuilderName(test));
64 return new FailCommand(test, ResultState.Failure, message);
65 }
66 }
67
68 command = new TestActionCommand(command);
69
70 if (!testReturnsIEnumerator && !testReturnsTask)
71 {
72 command = new ImmediateEnumerableCommand(command);
73 }
74
75 command = new SetUpTearDownCommand(command);
76
77 foreach (var wrapper in test.Method.GetCustomAttributes<IWrapSetUpTearDown>(true))
78 {
79 if (command is SetUpTearDownCommand && !testReturnsIEnumerator && !testReturnsTask)
80 {
81 // Ensure that we can use the immediate execute on the setup/teardown
82 command = new ImmediateEnumerableCommand(command);
83 }
84
85 command = wrapper.Wrap(command);
86 if (command == null)
87 {
88 var message = String.Format("IWrapSetUpTearDown implementation '{0}' returned null as command.",
89 wrapper.GetType().FullName);
90 return new FailCommand(test, ResultState.Failure, message);
91 }
92
93 if ((testReturnsIEnumerator || testReturnsTask) && !(command is IEnumerableTestMethodCommand))
94 {
95 command = TryReplaceWithEnumerableCommand(command);
96 if (command != null)
97 {
98 continue;
99 }
100
101 var message = String.Format("'{0}' is not supported on {1} as it does not handle returning IEnumerator.",
102 wrapper.GetType().FullName,
103 GetTestBuilderName(test));
104 return new FailCommand(test, ResultState.Failure, message);
105 }
106 }
107
108 command = new EnumerableSetUpTearDownCommand(command);
109 command = new OuterUnityTestActionCommand(command);
110 command = new RetryCommand(command);
111 command = new RepeatCommand(command);
112
113 IApplyToContext[] changes = test.Method.GetCustomAttributes<IApplyToContext>(true);
114 if (changes.Length > 0)
115 {
116 command = new EnumerableApplyChangesToContextCommand(command, changes);
117 }
118
119 command = new TimeoutCommand(command);
120 command = new IgnoreTestCommand(command, test);
121 command = new StrictCheckCommand(command);
122 return command;
123 }
124
125 private static string GetTestBuilderName(TestMethod testMethod)
126 {
127 return new[]
128 {
129 testMethod.Method.GetCustomAttributes<ITestBuilder>(true).Select(attribute => attribute.GetType().Name),
130 testMethod.Method.GetCustomAttributes<ISimpleTestBuilder>(true).Select(attribute => attribute.GetType().Name)
131 }.SelectMany(v => v).FirstOrDefault();
132 }
133
134 private static TestCommand TryReplaceWithEnumerableCommand(TestCommand command)
135 {
136 switch (command.GetType().Name)
137 {
138 case nameof(RepeatAttribute.RepeatedTestCommand):
139 return new EnumerableRepeatedTestCommand(command as RepeatAttribute.RepeatedTestCommand);
140 case nameof(RetryAttribute.RetryCommand):
141 return new EnumerableRetryTestCommand(command as RetryAttribute.RetryCommand);
142 case nameof(MaxTimeCommand):
143 return new EnumerableMaxTimeCommand(command as MaxTimeCommand);
144 default:
145 return null;
146 }
147 }
148 }
149}