You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
12KB

  1. Option Explicit
  2. Dim fso, logDir, viewsDir, testViewsDir, pass
  3. pass = True
  4. Set fso = CreateObject("Scripting.FileSystemObject")
  5. logDir = fso.GetParentFolderName(WScript.ScriptFullName) & "\test-logs"
  6. If fso.FolderExists(logDir) Then
  7. fso.DeleteFolder logDir, True
  8. End If
  9. ' Real Views/ used for the /hello integration path (proves the end-to-end
  10. ' rendering pipeline, not just the ViewRenderer component in isolation).
  11. viewsDir = fso.GetParentFolderName(WScript.ScriptFullName) & "\..\Views"
  12. ' Disposable fixture directory for direct ViewRenderer contract tests below.
  13. testViewsDir = fso.GetParentFolderName(WScript.ScriptFullName) & "\test-views"
  14. If fso.FolderExists(testViewsDir) Then
  15. fso.DeleteFolder testViewsDir, True
  16. End If
  17. fso.CreateFolder testViewsDir
  18. Function NewContext(path, httpMethod)
  19. Dim ctx
  20. Set ctx = CreateObject("WscMvc.RequestContext")
  21. ctx.Initialize path, httpMethod, logDir
  22. Set NewContext = ctx
  23. End Function
  24. Sub RunApplication(app, path, httpMethod, applicationName, statusLine, contentType, body, allowHeader)
  25. Dim ctx
  26. Set ctx = NewContext(path, httpMethod)
  27. statusLine = "" : contentType = "" : body = "" : allowHeader = ""
  28. app.Run ctx, applicationName, viewsDir, statusLine, contentType, body, allowHeader
  29. Set ctx = Nothing
  30. End Sub
  31. Sub WriteFixture(fileName, content)
  32. Dim stream
  33. Set stream = fso.CreateTextFile(testViewsDir & "\" & fileName, True)
  34. stream.Write content
  35. stream.Close
  36. Set stream = Nothing
  37. End Sub
  38. Sub CheckEqual(actual, expected, label)
  39. If actual = expected Then
  40. WScript.Echo "PASS: " & label
  41. Else
  42. WScript.Echo "FAIL: " & label & " -> expected [" & expected & "] got [" & actual & "]"
  43. pass = False
  44. End If
  45. End Sub
  46. ' --- RequestContext contract ---
  47. Dim ctx1
  48. On Error Resume Next
  49. Set ctx1 = NewContext("/hello", "GET")
  50. If Err.Number <> 0 Then
  51. WScript.Echo "FAIL: could not create/initialize WscMvc.RequestContext - " & Err.Description
  52. pass = False
  53. Err.Clear
  54. End If
  55. On Error Goto 0
  56. If pass Then
  57. CheckEqual ctx1.Path, "/hello", "RequestContext.Path"
  58. CheckEqual ctx1.HttpMethod, "GET", "RequestContext.HttpMethod"
  59. If Len(ctx1.CorrelationId) > 0 Then
  60. WScript.Echo "PASS: RequestContext.CorrelationId non-empty (" & ctx1.CorrelationId & ")"
  61. Else
  62. WScript.Echo "FAIL: RequestContext.CorrelationId empty"
  63. pass = False
  64. End If
  65. If ctx1.ElapsedMs() >= 0 Then
  66. WScript.Echo "PASS: RequestContext.ElapsedMs non-negative (" & ctx1.ElapsedMs() & ")"
  67. Else
  68. WScript.Echo "FAIL: RequestContext.ElapsedMs negative"
  69. pass = False
  70. End If
  71. End If
  72. ' --- Two independent contexts must not share correlation IDs or state ---
  73. Dim ctx2
  74. If pass Then
  75. Set ctx2 = NewContext("/does-not-exist", "GET")
  76. If ctx1.CorrelationId <> ctx2.CorrelationId Then
  77. WScript.Echo "PASS: two RequestContext instances have distinct CorrelationIds"
  78. Else
  79. WScript.Echo "FAIL: two RequestContext instances produced the same CorrelationId - " & ctx1.CorrelationId
  80. pass = False
  81. End If
  82. End If
  83. ' --- Application.Run happy path via ctx ---
  84. Dim app, statusLine, contentType, body, allowHeader
  85. If pass Then
  86. On Error Resume Next
  87. Set app = CreateObject("WscMvc.Application")
  88. If Err.Number <> 0 Then
  89. WScript.Echo "FAIL: could not create WscMvc.Application - " & Err.Description
  90. pass = False
  91. Err.Clear
  92. End If
  93. On Error Goto 0
  94. End If
  95. If pass Then
  96. On Error Resume Next
  97. RunApplication app, "/hello", "GET", "production", statusLine, contentType, body, allowHeader
  98. If Err.Number <> 0 Then
  99. WScript.Echo "FAIL: Application.Run raised error on /hello - " & Err.Description
  100. pass = False
  101. Err.Clear
  102. End If
  103. On Error Goto 0
  104. End If
  105. If pass Then
  106. CheckEqual statusLine, "200 OK", "Application.Run(/hello) statusLine"
  107. CheckEqual contentType, "text/html; charset=utf-8", "Application.Run(/hello) contentType"
  108. CheckEqual body, "Hello from WSC-MVC!", "Application.Run(/hello) body"
  109. CheckEqual allowHeader, "", "Application.Run(/hello) Allow header"
  110. End If
  111. ' --- Application.Run unknown route via ctx (expected 404, not an error) ---
  112. If pass Then
  113. On Error Resume Next
  114. RunApplication app, "/does-not-exist", "GET", "production", statusLine, contentType, body, allowHeader
  115. If Err.Number <> 0 Then
  116. WScript.Echo "FAIL: Application.Run raised error on unknown route - " & Err.Description
  117. pass = False
  118. Err.Clear
  119. End If
  120. On Error Goto 0
  121. End If
  122. If pass Then
  123. CheckEqual statusLine, "404 Not Found", "Application.Run(unknown route) statusLine"
  124. CheckEqual allowHeader, "", "Application.Run(unknown route) Allow header"
  125. End If
  126. ' --- Router method contract: existing route with unsupported method is 405 + Allow ---
  127. If pass Then
  128. On Error Resume Next
  129. RunApplication app, "/hello", "POST", "production", statusLine, contentType, body, allowHeader
  130. If Err.Number <> 0 Then
  131. WScript.Echo "FAIL: Application.Run raised error on method mismatch - " & Err.Description
  132. pass = False
  133. Err.Clear
  134. End If
  135. On Error Goto 0
  136. End If
  137. If pass Then
  138. CheckEqual statusLine, "405 Method Not Allowed", "Application.Run(POST /hello) statusLine"
  139. CheckEqual contentType, "text/plain; charset=utf-8", "Application.Run(POST /hello) contentType"
  140. CheckEqual body, "Method Not Allowed", "Application.Run(POST /hello) body"
  141. CheckEqual allowHeader, "GET", "Application.Run(POST /hello) Allow header"
  142. End If
  143. ' --- Router app isolation and POST support for test app route ---
  144. If pass Then
  145. On Error Resume Next
  146. RunApplication app, "/self-test", "POST", "tests", statusLine, contentType, body, allowHeader
  147. If Err.Number <> 0 Then
  148. WScript.Echo "FAIL: Application.Run raised error on POST /self-test - " & Err.Description
  149. pass = False
  150. Err.Clear
  151. End If
  152. On Error Goto 0
  153. End If
  154. If pass Then
  155. CheckEqual statusLine, "200 OK", "Application.Run(POST /self-test tests) statusLine"
  156. CheckEqual contentType, "application/json; charset=utf-8", "Application.Run(POST /self-test tests) contentType"
  157. CheckEqual allowHeader, "", "Application.Run(POST /self-test tests) Allow header"
  158. End If
  159. ' --- Router malformed path contract ---
  160. If pass Then
  161. On Error Resume Next
  162. RunApplication app, "/hello/../secret", "GET", "production", statusLine, contentType, body, allowHeader
  163. If Err.Number <> 0 Then
  164. WScript.Echo "FAIL: Application.Run raised error on malformed path - " & Err.Description
  165. pass = False
  166. Err.Clear
  167. End If
  168. On Error Goto 0
  169. End If
  170. If pass Then
  171. CheckEqual statusLine, "400 Bad Request", "Application.Run(malformed path) statusLine"
  172. CheckEqual contentType, "text/plain; charset=utf-8", "Application.Run(malformed path) contentType"
  173. CheckEqual body, "Bad Request", "Application.Run(malformed path) body"
  174. CheckEqual allowHeader, "", "Application.Run(malformed path) Allow header"
  175. End If
  176. ' --- ViewRenderer contract: substitution + HTML-encoding ---
  177. Dim renderer
  178. On Error Resume Next
  179. Set renderer = CreateObject("WscMvc.ViewRenderer")
  180. If Err.Number <> 0 Then
  181. WScript.Echo "FAIL: could not create WscMvc.ViewRenderer - " & Err.Description
  182. pass = False
  183. Err.Clear
  184. End If
  185. On Error Goto 0
  186. If pass Then
  187. WriteFixture "Sample.html", "<p>{{Name}}</p>"
  188. Dim dataSample, outSample
  189. Set dataSample = CreateObject("Scripting.Dictionary")
  190. dataSample.Add "Name", "<script>alert(1)</script>"
  191. outSample = ""
  192. On Error Resume Next
  193. renderer.Render testViewsDir, "Sample", dataSample, outSample
  194. If Err.Number <> 0 Then
  195. WScript.Echo "FAIL: ViewRenderer.Render raised error on Sample - " & Err.Description
  196. pass = False
  197. Err.Clear
  198. End If
  199. On Error Goto 0
  200. If pass Then
  201. CheckEqual outSample, "<p>&lt;script&gt;alert(1)&lt;/script&gt;</p>", "ViewRenderer HTML-encodes placeholder value"
  202. End If
  203. Set dataSample = Nothing
  204. End If
  205. ' --- ViewRenderer contract: template with no placeholders passes through unchanged, data = Nothing ---
  206. If pass Then
  207. WriteFixture "Plain.html", "Plain text, no placeholders."
  208. Dim outPlain
  209. outPlain = ""
  210. On Error Resume Next
  211. renderer.Render testViewsDir, "Plain", Nothing, outPlain
  212. If Err.Number <> 0 Then
  213. WScript.Echo "FAIL: ViewRenderer.Render raised error on Plain (data=Nothing) - " & Err.Description
  214. pass = False
  215. Err.Clear
  216. End If
  217. On Error Goto 0
  218. If pass Then
  219. CheckEqual outPlain, "Plain text, no placeholders.", "ViewRenderer passes through template with no placeholders (data=Nothing)"
  220. End If
  221. End If
  222. ' --- ViewRenderer contract: missing template file is a safe, path-free error ---
  223. If pass Then
  224. Dim outMissing, missingOk, missingDetail
  225. missingOk = False
  226. outMissing = ""
  227. On Error Resume Next
  228. renderer.Render testViewsDir, "DoesNotExist", Nothing, outMissing
  229. If Err.Number <> 0 Then
  230. missingDetail = Err.Description
  231. If InStr(1, missingDetail, testViewsDir, 1) = 0 Then
  232. missingOk = True
  233. End If
  234. Err.Clear
  235. End If
  236. On Error Goto 0
  237. If missingOk Then
  238. WScript.Echo "PASS: ViewRenderer.Render on missing template raises a path-free error"
  239. Else
  240. WScript.Echo "FAIL: ViewRenderer.Render on missing template -> Err.Number after call, detail=[" & missingDetail & "]"
  241. pass = False
  242. End If
  243. End If
  244. ' --- ViewRenderer contract: unresolved placeholder (no matching dictionary key) is a safe error ---
  245. If pass Then
  246. WriteFixture "Missing.html", "{{Unknown}}"
  247. Dim dataEmpty, outMissingKey, unresolvedOk
  248. Set dataEmpty = CreateObject("Scripting.Dictionary")
  249. unresolvedOk = False
  250. outMissingKey = ""
  251. On Error Resume Next
  252. renderer.Render testViewsDir, "Missing", dataEmpty, outMissingKey
  253. If Err.Number <> 0 Then
  254. unresolvedOk = True
  255. Err.Clear
  256. End If
  257. On Error Goto 0
  258. If unresolvedOk Then
  259. WScript.Echo "PASS: ViewRenderer.Render raises on unresolved placeholder"
  260. Else
  261. WScript.Echo "FAIL: ViewRenderer.Render did not raise on unresolved placeholder -> got [" & outMissingKey & "]"
  262. pass = False
  263. End If
  264. Set dataEmpty = Nothing
  265. End If
  266. ' --- ViewRenderer contract: invalid view name (path traversal attempt) is rejected ---
  267. If pass Then
  268. Dim outTraversal, traversalOk
  269. traversalOk = False
  270. outTraversal = ""
  271. On Error Resume Next
  272. renderer.Render testViewsDir, "../secret", Nothing, outTraversal
  273. If Err.Number <> 0 Then
  274. traversalOk = True
  275. Err.Clear
  276. End If
  277. On Error Goto 0
  278. If traversalOk Then
  279. WScript.Echo "PASS: ViewRenderer.Render rejects an invalid view name"
  280. Else
  281. WScript.Echo "FAIL: ViewRenderer.Render did not reject invalid view name -> got [" & outTraversal & "]"
  282. pass = False
  283. End If
  284. End If
  285. Set renderer = Nothing
  286. ' --- Logging: best-effort log file was written with both outcomes ---
  287. If pass Then
  288. Dim logPath, logContent
  289. logPath = logDir & "\app.log"
  290. If fso.FileExists(logPath) Then
  291. Dim logStream
  292. Set logStream = fso.OpenTextFile(logPath, 1)
  293. logContent = logStream.ReadAll
  294. logStream.Close
  295. If InStr(logContent, "200 OK") > 0 And InStr(logContent, "404 Not Found") > 0 Then
  296. WScript.Echo "PASS: app.log contains both 200 OK and 404 Not Found outcomes"
  297. Else
  298. WScript.Echo "FAIL: app.log missing expected outcomes -> " & logContent
  299. pass = False
  300. End If
  301. Else
  302. WScript.Echo "FAIL: app.log was not created at " & logPath
  303. pass = False
  304. End If
  305. End If
  306. Set app = Nothing
  307. Set ctx1 = Nothing
  308. Set ctx2 = Nothing
  309. If fso.FolderExists(logDir) Then
  310. fso.DeleteFolder logDir, True
  311. End If
  312. If fso.FolderExists(testViewsDir) Then
  313. fso.DeleteFolder testViewsDir, True
  314. End If
  315. Set fso = Nothing
  316. If pass Then
  317. WScript.Echo "RESULT: ALL PASS"
  318. WScript.Quit 0
  319. Else
  320. WScript.Echo "RESULT: FAILURE"
  321. WScript.Quit 1
  322. End If

Powered by TurnKey Linux.