-
Notifications
You must be signed in to change notification settings - Fork 56
/
RemoteFacade.cfc
executable file
·211 lines (174 loc) · 8.98 KB
/
RemoteFacade.cfc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
<cfcomponent name="mxunit.framework.RemoteFacade" hint="Main default interface into MXUnit framework from the MXUnit Ecplise Plugin." wsversion="1">
<cfset cu = createObject("component","mxunit.framework.ComponentUtils")>
<cfset cache = createObject("component","mxunit.framework.RemoteFacadeObjectCache")>
<cfset ConfigManager = createObject("component","mxunit.framework.ConfigManager")>
<cffunction name="ping" output="false" access="remote" returntype="boolean" hint="returns true">
<cfreturn true>
</cffunction>
<cffunction name="initializeSuitePool" access="remote" returntype="void">
<cfset cache.initializeSuitePool()>
</cffunction>
<cffunction name="purgeSuitePool" access="remote" returntype="numeric">
<cfreturn cache.purgeSuitePool()>
</cffunction>
<cffunction name="getServerType" output="false" access="remote" returntype="String" hint="returns the server type, whether coldfusion or bluedragon">
<cfreturn server.ColdFusion.ProductName>
</cffunction>
<cffunction name="getFrameworkVersion" output="false" access="remote" returntype="String" hint="returns the current framework version in form of major.minor.buildnum">
<cfreturn createObject("component","mxunit.framework.VersionReader").getVersionInfo().VersionNumber>
</cffunction>
<cffunction name="getFrameworkDate" output="false" access="remote" returntype="Date" hint="returns the current framework version date in form of mm/dd/yyyy">
<cfreturn createObject("component","mxunit.framework.VersionReader").getVersionInfo().VersionDate>
</cffunction>
<cffunction name="startTestRun" access="remote" returntype="string">
<cfset var useCache = false>
<cfset ConfigManager.ConfigManager()>
<cfset useCache = configManager.getConfigElementValue("pluginControl","UseRemoteFacadeObjectCache")>
<cfif useCache>
<cfreturn cache.startTestRun()>
<cfelse>
<cfreturn "">
</cfif>
</cffunction>
<cffunction name="getObject" access="package" returntype="any">
<cfargument name="componentName" type="String" required="true">
<cfargument name="testRunKey" type="string" required="true" hint="the key returned from startTestRun; used for managing the pool of components">
<cfreturn cache.getObject(componentName, testRunKey)>
</cffunction>
<cffunction name="endTestRun" access="remote" returntype="string" hint="ensures proper cleanup">
<cfargument name="TestRunKey" type="string" required="true" hint="the key returned from startTestRun; used for managing the pool of components">
<!---run all components' afterTests() --->
<cfset var pool = cache.getSuitePool()>
<cfset var componentName = "">
<cfset var testCase = "">
<cfif structKeyExists( pool, testRunKey )>
<cfloop collection="#pool[testRunKey].components#" item="componentName">
<cftry>
<cfset testCase = pool[testRunKey].components[componentName]>
<cfset testCase.enableAfterTests()>
<cfset testCase.afterTests()>
<cfcatch>
<cflog text="MXUnit afterTests() Exception from Eclipse Remote Facade. Component Name: #componentName#. Error: #cfcatch.message#; #cfcatch.detail#">
</cfcatch>
</cftry>
</cfloop>
</cfif>
<cfreturn cache.endTestRun(TestRunKey)>
</cffunction>
<cffunction name="executeTestCase" access="remote" returntype="struct">
<cfargument name="componentName" type="String" required="true">
<cfargument name="methodNames" type="String" required="true" hint="pass empty string to run all methods. pass list of valid method names to run individual methods">
<cfargument name="TestRunKey" type="string" required="true" hint="the key returned from startTestRun; used for managing the pool of components">
<cfset var s_results = structNew()>
<cfset var key = "">
<cfset var suite = createObject("component","mxunit.framework.TestSuite")>
<cfset var testResult = "">
<!--- the "baseTarget" is the actual test case, underneath its layers of test decorators. When we start the test case, we want the pure object, not the decorated object --->
<cfset var obj = getObject(componentName, TestRunKey).getBaseTarget()>
<cfset var componentPath = getMetadata(obj).path>
<cfset suite.enableRequestScopeDebugging()>
<cfset actOnTestCase(obj)>
<!--- disable afterTests... we'll run them all during endTestRun --->
<cfset obj.disableAfterTests()>
<cfif len(methodNames)>
<cfset suite.add(componentName, methodNames, obj)>
<cfelse>
<cfset suite.addAll(componentName, obj)>
</cfif>
<cfset testResult = suite.run()>
<cfset s_results = testResultToStructs(testResult, componentPath)>
<cfreturn s_results>
</cffunction>
<cffunction name="getComponentMethods" access="remote" returntype="array">
<cfargument name="componentName" required="true" type="string" hint="">
<cfset var methods = arrayNew(1)>
<cfset var obj = "">
<!--- by doing this instead of letting it throw an error
we ensure that the error (most likely a parse error)
continues to show up when they run the test. --->
<cftry>
<cfset obj = createObject("component", ComponentName).TestCase()>
<cfset methods = obj.getRunnableMethods()>
<cfcatch>
<cfset ArrayAppend(methods, listLast(arguments.ComponentName, ".") & " <ERROR: #cfcatch.Message#>")>
</cfcatch>
</cftry>
<cfreturn methods>
</cffunction>
<!--- <cffunction name="getComponentMethodsRich2" access="remote" returntype="array">
<cfset var bean = {dataprovidertype="excel", rows=50}>
<cfreturn [bean]>
</cffunction>--->
<cffunction name="actOnTestCase" access="public" hint="an 'Interceptor' for custom remote facades. This will enable you to act on each test case object, possibly injecting additional data, etc" output="false">
<cfargument name="testCase" required="true" hint="">
</cffunction>
<cffunction name="testResultToStructs" hint="turns the TestResult item into a struct for passing to eclipse. It will only ever process a single component under test, although I did build it to loop over the array of tests returned from the TestResult, although currently there is no condition under which that will ever be more than a single-element array" access="public">
<cfargument name="testResult" required="true">
<cfargument name="componentPath" required="true" hint="the full filesystem path to the component under test">
<cfset var s_results = structNew()>
<cfset var a_tests = TestResult.Results>
<cfset var s_test = structNew()>
<cfset var test = 1>
<cfset var tag = 1>
<cfset var i = 1>
<cfset var t = "">
<cfset var iDebug = 1>
<cfset var debugString = "">
<cfset var isFrameworkTest = cu.isFrameworkTemplate(ComponentPath)>
<cfloop from="1" to="#ArrayLen(a_tests)#" index="test">
<cfset s_test = a_tests[test]>
<cfif not StructKeyExists(s_results,s_test.component)>
<cfset s_results[s_test.component] = structNew()>
</cfif>
<cfset s_results[s_test.component][s_test.TestName] = structNew()>
<cfset t = s_results[s_test.component][s_test.TestName]>
<cfif ArrayLen(s_test.debug)>
<cfsavecontent variable="debugString">
<cfloop from="1" to="#ArrayLen(s_test.debug)#" index="iDebug">
<cfdump attributecollection="#s_test.debug[iDebug]#">
</cfloop>
</cfsavecontent>
<cfelse>
<cfset debugString = "<p class='nodebugresults'>No calls made to debug().</p> ">
</cfif>
<cfset t.OUTPUT = s_test.content & debugString>
<cfset t.MESSAGE = "">
<cfset t.RESULT = s_test.TestStatus>
<cfset t.TIME = s_test.Time>
<cfset t.EXPECTED = s_test.expected>
<cfset t.ACTUAL = s_test.actual>
<!--- <cfset t.httprequestdata = getHTTPRequestData()> --->
<cfif not isSimpleValue(s_test.error)>
<cfset t.EXCEPTION = formatExceptionKey(s_test.error.type)>
<cfset t.MESSAGE = s_test.error.message>
<cfif len(s_test.error.detail)>
<cfset t.MESSAGE = t.MESSAGE & " " & s_test.error.detail>
</cfif>
<!--- <cfset t.TagContext = s_test.error.tagcontext> --->
<cfset t.TAGCONTEXT = ArrayNew(1)>
<cfset i = 1>
<!--- --->
<cfloop from="1" to="#ArrayLen(s_test.error.tagcontext)#" index="tag">
<cfif FileExists(s_test.error.tagcontext[tag].template)>
<!---<cflog text=" #s_test.error.tagcontext[tag].template# #isFrameworkTest# OR NOT #cu.isFrameworkTemplate(s_test.error.tagcontext[tag].template)#" >--->
<cfif isFrameworkTest OR NOT cu.isFrameworkTemplate(s_test.error.tagcontext[tag].template)>
<cfset t.TAGCONTEXT[i] = structNew()>
<cfset t.TAGCONTEXT[i].FILE = s_test.error.tagcontext[tag].template>
<cfset t.TAGCONTEXT[i].LINE = s_test.error.tagcontext[tag].line>
<cfset i = i + 1>
</cfif>
</cfif>
</cfloop>
</cfif>
</cfloop>
<cfreturn s_results>
</cffunction>
<cffunction name="formatExceptionKey" access="package" hint="ensures a string in the EXCEPTION key. This is necessitated by a weirdo bug in CF with NonArrayExceptions" returntype="string">
<cfargument name="ErrorType" required="true" type="any" hint="the TYPE key from the cfcatch struct">
<cfif isSimpleValue(ErrorType)>
<cfreturn ErrorType>
<cfelse>
<cfreturn "Exception[ComplexValue]: " & ErrorType.toString()>
</cfif>
</cffunction>
</cfcomponent>