build.gradle 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. import groovy.io.FileType
  2. import org.apache.tools.ant.taskdefs.condition.Os
  3. import org.gradle.api.tasks.Exec
  4. buildscript {
  5. repositories {
  6. mavenCentral()
  7. jcenter()
  8. }
  9. dependencies {
  10. classpath 'com.eriwen:gradle-js-plugin:1.8.0'
  11. classpath 'com.moowork.gradle:gradle-grunt-plugin:0.2'
  12. }
  13. }
  14. apply plugin: 'js'
  15. apply plugin: 'grunt'
  16. repositories {
  17. mavenCentral()
  18. }
  19. configurations {
  20. rhino
  21. }
  22. dependencies {
  23. rhino 'org.mozilla:rhino:1.7R4'
  24. }
  25. project.ext {
  26. packageProps = new groovy.json.JsonSlurper().parseText(new File("package.json").toURL().text)
  27. failures = 0;
  28. rhinoTestSrc = "out/rhino-test-${packageProps.version}.js"
  29. testSrc = 'test/less'
  30. testOut = 'out/test'
  31. }
  32. task runGruntRhino(type: GruntTask) {
  33. gruntArgs = "rhino"
  34. }
  35. combineJs {
  36. dependsOn runGruntRhino
  37. source = ["dist/less-rhino-${packageProps.version}.js", "test/rhino/test-header.js","dist/lessc-rhino-${packageProps.version}.js"]
  38. dest = file(rhinoTestSrc)
  39. }
  40. task testRhino(type: AllRhinoTests) {
  41. // dependsOn 'testRhinoBase'
  42. dependsOn 'testRhinoBase', 'testRhinoErrors', 'testRhinoLegacy', 'testRhinoStaticUrls', 'testRhinoCompression', 'testRhinoDebugAll', 'testRhinoDebugComments', 'testRhinoDebugMediaquery', 'testRhinoNoJsError', 'testRhinoSourceMap'
  43. }
  44. task testRhinoBase(type: RhinoTest) {
  45. options = [ '--strict-math=true', '--relative-urls' ]
  46. }
  47. task testRhinoDebugAll(type: DebugRhinoTest) {
  48. options = [ '--strict-math=true', '--line-numbers=all' ]
  49. testDir = 'debug' + fs
  50. suffix = "-all"
  51. }
  52. task testRhinoDebugComments(type: DebugRhinoTest) {
  53. options = [ '--strict-math=true', '--line-numbers=comments' ]
  54. testDir = 'debug' + fs
  55. suffix = "-comments"
  56. }
  57. task testRhinoDebugMediaquery(type: DebugRhinoTest) {
  58. options = [ '--strict-math=true', '--line-numbers=mediaquery' ]
  59. testDir = 'debug' + fs
  60. suffix = "-mediaquery"
  61. }
  62. task testRhinoErrors(type: RhinoTest) {
  63. options = [ '--strict-math=true', '--strict-units=true' ]
  64. testDir = 'errors/'
  65. expectErrors = true
  66. }
  67. task testRhinoChyby(type: RhinoTest) {
  68. options = [ '--strict-math=true', '--strict-units=true' ]
  69. testDir = 'chyby/'
  70. // expectErrors = true
  71. }
  72. task testRhinoNoJsError(type: RhinoTest) {
  73. options = [ '--strict-math=true', '--strict-units=true', '--no-js' ]
  74. testDir = 'no-js-errors/'
  75. expectErrors = true
  76. }
  77. task testRhinoLegacy(type: RhinoTest) {
  78. testDir = 'legacy/'
  79. }
  80. task testRhinoStaticUrls(type: RhinoTest) {
  81. options = [ '--strict-math=true', '--rootpath=folder (1)/' ]
  82. testDir = 'static-urls/'
  83. }
  84. task testRhinoCompression(type: RhinoTest) {
  85. options = [ '--compress=true' ]
  86. testDir = 'compression/'
  87. }
  88. task testRhinoSourceMap(type: SourceMapRhinoTest) {
  89. options = [ '--strict-math=true', '--strict-units=true']
  90. testDir = 'sourcemaps/'
  91. }
  92. task setupTest {
  93. dependsOn combineJs
  94. doLast {
  95. file(testOut).deleteDir()
  96. }
  97. }
  98. task clean << {
  99. file(rhinoTestSrc).delete()
  100. file(testOut).deleteDir()
  101. }
  102. class SourceMapRhinoTest extends RhinoTest {
  103. // helper to get the output map file
  104. def getOutputMap(lessFile) {
  105. def outFile = project.file(lessFile.path.replace('test/less', project.testOut).replace('.less', '.css'))
  106. return project.file(outFile.path + ".map");
  107. }
  108. // callback to add SourceMap options to the options list
  109. def postProcessOptions(options, lessFile) {
  110. def outFile = getOutputMap(lessFile)
  111. project.file(outFile.parent).mkdirs()
  112. options << "--source-map=${testDir}${lessFile.name.replace('.less','.css')}"
  113. options << "--source-map-basepath=${lessRootDir}"
  114. options << "--source-map-rootpath=testweb/"
  115. options << "--source-map-output-map-file=${outFile}"
  116. options
  117. }
  118. // Callback to validate output
  119. def handleResult(exec, out, lessFile) {
  120. def actualFile = getOutputMap(lessFile)
  121. def expectedFile = project.file(projectDir + fs + "test" + fs + testDir + fs + lessFile.name.replace(".less", ".json"))
  122. assert actualFile.text == expectedFile.text
  123. }
  124. }
  125. class DebugRhinoTest extends RhinoTest {
  126. def escapeIt(it) {
  127. return it.replaceAll("\\\\", "\\\\\\\\").replaceAll("/", "\\\\/").replaceAll(":", "\\\\:").replaceAll("\\.", "\\\\.");
  128. }
  129. def globalReplacements(input, directory) {
  130. def pDirectory = toPlatformFs(directory)
  131. def p = lessRootDir + fs + pDirectory
  132. def pathimport = p + toPlatformFs("import/")
  133. def pathesc = escapeIt(p)
  134. def pathimportesc = escapeIt(pathimport)
  135. def result = input.replace("{path}", p).replace("{pathesc}", pathesc).replace("{pathimport}", pathimport)
  136. return result.replace("{pathimportesc}", pathimportesc).replace("\r\n", "\n")
  137. }
  138. }
  139. class RhinoTest extends DefaultTask {
  140. RhinoTest() {
  141. dependsOn 'setupTest'
  142. }
  143. def suffix = ""
  144. def testDir = ''
  145. def options = []
  146. def expectErrors = false
  147. def fs = File.separator;
  148. def projectDir = toUpperCaseDriveLetter(System.getProperty("user.dir"));
  149. def lessRootDir = projectDir + fs + "test" + fs + "less"
  150. def toUpperCaseDriveLetter(path) {
  151. if (path.charAt(1)==':' && path.charAt(2)=='\\') {
  152. return path.substring(0,1).toUpperCase() + path.substring(1);
  153. }
  154. return path;
  155. }
  156. def toPlatformFs(path) {
  157. return path.replace('\\', fs).replace('/', fs);
  158. }
  159. def expectedCssPath(lessFilePath) {
  160. lessFilePath.replace('.less', "${suffix}.css").replace("${fs}less${fs}", "${fs}css${fs}");
  161. }
  162. def globalReplacements(input, directory) {
  163. return input;
  164. }
  165. def stylize(str, style) {
  166. def styles = [
  167. reset : [0, 0],
  168. bold : [1, 22],
  169. inverse : [7, 27],
  170. underline : [4, 24],
  171. yellow : [33, 39],
  172. green : [32, 39],
  173. red : [31, 39],
  174. grey : [90, 39]
  175. ];
  176. return '\033[' + styles[style][0] + 'm' + str +
  177. '\033[' + styles[style][1] + 'm';
  178. }
  179. // Callback for subclasses to make any changes to the options
  180. def postProcessOptions(options, lessFile) {
  181. options
  182. }
  183. // Callback to validate output
  184. def handleResult(exec, out, lessFile) {
  185. def actual = out.toString().trim()
  186. def actualResult = project.file(lessFile.path.replace('test/less', project.testOut).replace('.less', '.css'))
  187. project.file(actualResult.parent).mkdirs()
  188. actualResult << actual
  189. def expected
  190. if (expectErrors) {
  191. assert exec.exitValue != 0
  192. expected = project.file(lessFile.path.replace('.less', '.txt')).text.trim().
  193. replace('{path}', lessFile.parent + '/').
  194. replace('{pathhref}', '').
  195. replace('{404status}', '')
  196. } else {
  197. assert exec.exitValue == 0
  198. def expectedFile = expectedCssPath(lessFile.path)
  199. expected = project.file(expectedFile).text.trim()
  200. expected = globalReplacements(expected, testDir)
  201. }
  202. actual=actual.trim()
  203. actual = actual.replace('\r\n', '\n')
  204. expected = expected.replace('\r\n', '\n')
  205. actual = actual.replace("/","\\")
  206. expected = expected.replace("/","\\")
  207. // println "* actual *"
  208. // println actual
  209. // new File("actual.txt").write(actual)
  210. // println "* expected *"
  211. // println expected
  212. // new File("expected.txt").write(expected)
  213. assert actual == expected
  214. actualResult.delete()
  215. }
  216. @TaskAction
  217. def runTest() {
  218. int testSuccesses = 0, testFailures = 0, testErrors = 0
  219. project.file('test/less/' + testDir).eachFileMatch(FileType.FILES, ~/.*\.less/) { lessFile ->
  220. println "lessfile: $lessFile"
  221. if (!project.hasProperty('test') || lessFile.name.startsWith(project.test)) {
  222. def out = new java.io.ByteArrayOutputStream()
  223. def processedOptions = postProcessOptions([project.rhinoTestSrc, lessFile] + options, lessFile)
  224. def execOptions = {
  225. main = 'org.mozilla.javascript.tools.shell.Main'
  226. // main = 'org.mozilla.javascript.tools.debugger.Main'
  227. classpath = project.configurations.rhino
  228. args = processedOptions
  229. standardOutput = out
  230. ignoreExitValue = true
  231. }
  232. println "rhinoTestSrc: ${project.rhinoTestSrc}"
  233. try {
  234. def exec = project.javaexec(execOptions)
  235. handleResult(exec, out, lessFile)
  236. testSuccesses++
  237. println stylize(' ok', 'green')
  238. }
  239. catch (ex) {
  240. println ex
  241. println()
  242. testErrors++;
  243. }
  244. catch (AssertionError ae) {
  245. println stylize(' failed', 'red')
  246. println ae
  247. testFailures++
  248. }
  249. } else {
  250. println stylize(' skipped', 'yellow')
  251. }
  252. }
  253. println stylize(testSuccesses + ' ok', 'green')
  254. println stylize(testFailures + ' assertion failed', testFailures == 0 ? 'green' : 'red')
  255. println stylize(testErrors + ' errors', testErrors == 0 ? 'green' : 'red')
  256. if (testFailures != 0 || testErrors != 0) {
  257. project.failures++;
  258. }
  259. }
  260. }
  261. class AllRhinoTests extends DefaultTask {
  262. AllRhinoTests() {
  263. }
  264. @TaskAction
  265. def runTest() {
  266. println stylize(project.failures + ' test suites failed', project.failures == 0 ? 'green' : 'red')
  267. }
  268. def stylize(str, style) {
  269. def styles = [
  270. reset : [0, 0],
  271. bold : [1, 22],
  272. inverse : [7, 27],
  273. underline : [4, 24],
  274. yellow : [33, 39],
  275. green : [32, 39],
  276. red : [31, 39],
  277. grey : [90, 39]
  278. ];
  279. return '\033[' + styles[style][0] + 'm' + str +
  280. '\033[' + styles[style][1] + 'm';
  281. }
  282. }
  283. class GruntTask extends Exec {
  284. private String gruntExecutable = Os.isFamily(Os.FAMILY_WINDOWS) ? "grunt.cmd" : "grunt"
  285. private String switches = "--no-color"
  286. String gruntArgs = ""
  287. public GruntTask() {
  288. super()
  289. this.setExecutable(gruntExecutable)
  290. }
  291. public void setGruntArgs(String gruntArgs) {
  292. this.args = "$switches $gruntArgs".trim().split(" ") as List
  293. }
  294. }