PageRenderTime 61ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/SodaUtils.rb

https://github.com/trampus/SODA
Ruby | 756 lines | 415 code | 96 blank | 245 comment | 58 complexity | 9dcbfbcbc7dae775c0eaf7155625c4c7 MD5 | raw file
  1. ###############################################################################
  2. # Copyright (c) 2010, SugarCRM, Inc.
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are met:
  7. # * Redistributions of source code must retain the above copyright
  8. # notice, this list of conditions and the following disclaimer.
  9. # * Redistributions in binary form must reproduce the above copyright
  10. # notice, this list of conditions and the following disclaimer in the
  11. # documentation and/or other materials provided with the distribution.
  12. # * Neither the name of SugarCRM, Inc. nor the
  13. # names of its contributors may be used to endorse or promote products
  14. # derived from this software without specific prior written permission.
  15. #
  16. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. # ARE DISCLAIMED. IN NO EVENT SHALL SugarCRM, Inc. BE LIABLE FOR ANY
  20. # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. ###############################################################################
  27. ###############################################################################
  28. # Needed Ruby libs:
  29. ###############################################################################
  30. require 'rbconfig'
  31. require 'time'
  32. require 'rubygems'
  33. require 'libxml'
  34. ###############################################################################
  35. # SodaUtils -- Module
  36. # This module is to provide useful functions for soda that do not need
  37. # to create an object to use this functionality. The whole point to this
  38. # module is to be fast, simple, and useful.
  39. #
  40. ###############################################################################
  41. module SodaUtils
  42. ###############################################################################
  43. # Module global data:
  44. ###############################################################################
  45. VERSION = "1.0"
  46. LOG = 0
  47. ERROR = 1
  48. WARN = 2
  49. EVENT = 3
  50. FIREFOX_JS_ERROR_CHECK_SRC = <<JS
  51. var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
  52. var msg = {};
  53. var msg_count = {};
  54. aConsoleService.getMessageArray(msg, {});
  55. msg.value.forEach(function(m) {
  56. if (m instanceof Components.interfaces.nsIScriptError) {
  57. m.QueryInterface(Components.interfaces.nsIScriptError);
  58. var txt = "--Error::" + m.errorMessage +
  59. "--Line::" + m.lineNumber +
  60. "--Col::" + m.columnNumber +
  61. "--Flags::" + m.flags +
  62. "--Cat::" + m.category+
  63. "--SrcName::" + m.sourceName;
  64. print("######" + txt);
  65. }
  66. });
  67. aConsoleService.reset();
  68. JS
  69. FIREFOX_JS_ERROR_CLEAR = <<JS
  70. var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
  71. aConsoleService.reset();
  72. JS
  73. ###############################################################################
  74. # GetOsType --
  75. # This function checks the internal ruby config to see what os we are
  76. # running on. We should never use the RUBY_PLATFORM as it will not aways
  77. # give us the info we need.
  78. #
  79. # Currently this function only checks for supported OS's and will return
  80. # and error if run on an unsupported os.
  81. #
  82. # Params:
  83. # None.
  84. #
  85. # Results:
  86. # returns nil on error, or one of the supported os names in generic
  87. # format.
  88. #
  89. # Supported OS return values:
  90. # 1.) WINDOWS
  91. # 2.) LINUX
  92. # 3.) OSX
  93. #
  94. ###############################################################################
  95. def SodaUtils.GetOsType
  96. os = ""
  97. if Config::CONFIG['host_os'] =~ /mswin/i
  98. os = "WINDOWS"
  99. elsif Config::CONFIG['host_os'] =~ /linux/i
  100. os = "LINUX"
  101. elsif Config::CONFIG['host_os'] =~ /darwin/i
  102. os = "OSX"
  103. else
  104. os = Config::CONFIG['host_os'];
  105. PrintSoda("Found unsupported OS: #{os}!\n", 1)
  106. os = nil
  107. end
  108. return os
  109. end
  110. ###############################################################################
  111. # PrintSoda --
  112. # This is a print function that creates standard formatting when printing
  113. # Soda message.
  114. #
  115. # Params:
  116. # str: This is the user message that will be printed after being formatted.
  117. #
  118. # error: If set to 1 then all message will start "(!)" to note an error
  119. # is being reported. Anything passed other then 1 will result in a
  120. # "(*)" being used for the message start.
  121. #
  122. # file: A valid open writable file handle. If this isn't nil then all
  123. # this message will be writen to the file. Passing nil will bypass
  124. # this and cause all message to go to STDOUT.
  125. #
  126. # debug: This will print the caller stack before the message so you can
  127. # have more useful info for debugging. Also a datetime stamp will be
  128. # added to the beginning of the message.
  129. #
  130. # notime: Setting this to anything other then 0 will remove the datetime
  131. # stamp from the stdout message, but never from the file message.
  132. #
  133. # Results:
  134. # Always returns the message that is printed.
  135. #
  136. ###############################################################################
  137. def SodaUtils.PrintSoda (str, error = 0, file = nil, debug = 0, notime = 0,
  138. callback = nil)
  139. header = ""
  140. error_header = ""
  141. msg = nil
  142. datetime = nil
  143. stackmsg = ""
  144. now = nil
  145. now = Time.now().strftime("%m/%d/%Y-%H:%M:%S")
  146. header = "[#{now}]"
  147. if (debug != 0)
  148. cstak = caller()
  149. stackmsg = "[Call Stack]:\n"
  150. cstak.each do |stack|
  151. stackmsg = stackmsg + "--#{stack}"
  152. end
  153. stackmsg = stackmsg + "\n"
  154. end
  155. case error
  156. when SodaUtils::LOG
  157. error_header = "(*)"
  158. when SodaUtils::ERROR
  159. error_header = "(!)"
  160. when SodaUtils::WARN
  161. error_header = "(W)"
  162. when SodaUtils::EVENT
  163. error_header = "(E)"
  164. else
  165. error_header = "(*)"
  166. end
  167. if ( (debug != 1) && (error != 1) )
  168. msg = header + "#{error_header}#{str}"
  169. elsif (debug != 0)
  170. msg = header + "#{error_header}#{str}#{stackmsg}\n"
  171. else
  172. msg = "#{header}#{error_header}#{str}"
  173. end
  174. if (file)
  175. file.write(msg)
  176. else
  177. if (notime != 0)
  178. msg = msg.gsub("[#{now}]", "")
  179. end
  180. print "#{msg}"
  181. end
  182. if (callback != nil)
  183. callback.call("#{msg}")
  184. end
  185. return msg
  186. end
  187. ###############################################################################
  188. # DumpEvent -- Function
  189. # This function dumps a Soda event into a nice log format that can be
  190. # parsed by our friendly SodaLogReporter class into html.
  191. #
  192. # Params:
  193. # event: This is the soda event to dump. Really this can be an ruby hash.
  194. #
  195. # Results:
  196. # returns a formatted string on success, or an empty string when there is
  197. # no hash pairs.
  198. #
  199. # Notes:
  200. # The formatted string results will look like this:
  201. # str = "--do=>puts--text=>Closing browser"
  202. #
  203. ###############################################################################
  204. def SodaUtils.DumpEvent(event)
  205. str = ""
  206. if (event.length < 1)
  207. return str
  208. end
  209. event.each do |key, val|
  210. str << "--#{key}=>#{val}"
  211. end
  212. return str
  213. end
  214. ###############################################################################
  215. # Base64FileEncode - function
  216. # This function encodes a file in base64 encoding, without modifying the
  217. # source file. So a new file is created that is the encoded version of
  218. # the source file.
  219. #
  220. # Params:
  221. # inputfile: The file to encode.
  222. # outputfile: The dest for the encoded file.
  223. # tostream: Setting this to true will cause this function to notw write to
  224. # a file, but to return an encoded stream of bytes insted.
  225. #
  226. # Results:
  227. # When tostream is set, will return a stream of encoded bytes.
  228. #
  229. ###############################################################################
  230. def SodaUtils.Base64FileEncode(inputfile, outputfile, tostream = false)
  231. buffer = ""
  232. stream = ""
  233. base64_stream = ""
  234. src_file = File.new(inputfile, "r")
  235. if (tostream != true)
  236. out_file = File.new(outputfile, "w+")
  237. out_file.binmode
  238. out_file.sync = true
  239. end
  240. src_file.sync = true
  241. src_file.binmode
  242. while (src_file.read(1024, buffer) != nil)
  243. stream << buffer
  244. end
  245. buffer = nil
  246. src_file.close
  247. base64_stream = [stream].pack('m')
  248. stream = nil
  249. if (tostream != true)
  250. out_file.write(base64_stream)
  251. base64_stream = nil
  252. out_file.close
  253. base64_stream = nil
  254. end
  255. return base64_stream
  256. end
  257. ###############################################################################
  258. # Base64FileDecode - function
  259. # This function decodes a file from base64 encoding, without modifying the
  260. # source file. So a new file is created that is the decoded version of
  261. # the source file.
  262. #
  263. # Params:
  264. # inputfile: The file to decode.
  265. # outputfile: The dest for the decoded file.
  266. #
  267. # Results:
  268. # None.
  269. #
  270. ###############################################################################
  271. def SodaUtils.Base64FileDecode(inputfile, outputfile)
  272. src_file = File.new(inputfile, "r")
  273. out_file = File.new(outputfile, "w+")
  274. buffer = ""
  275. base64_stream = ""
  276. stream = ""
  277. src_file.sync = true
  278. out_file.sync = true
  279. src_file.binmode
  280. out_file.binmode
  281. while (src_file.read(1024, buffer) != nil)
  282. base64_stream << buffer
  283. end
  284. buffer = nil
  285. src_file.close
  286. stream = base64_stream.unpack('m')
  287. out_file.write(stream)
  288. stream = nil
  289. out_file.close
  290. end
  291. ###############################################################################
  292. # ParseBlockFile -- Function
  293. # This function parses Soda block xml files.
  294. #
  295. # Params:
  296. # block_file: The xml file with blocks
  297. #
  298. # Results:
  299. # returns an array of hashs.
  300. #
  301. ###############################################################################
  302. def SodaUtils.ParseBlockFile(block_file)
  303. parser = nil
  304. error = false
  305. data = []
  306. doc = nil
  307. begin
  308. parser = LibXML::XML::Parser.file(block_file)
  309. doc = parser.parse()
  310. rescue Exception => e
  311. error = true
  312. data = []
  313. print "Error: #{e.message}!\n"
  314. print "BackTrace: #{e.backtrace}!\n"
  315. ensure
  316. if (error != false)
  317. return data
  318. end
  319. end
  320. doc.root.each do |node|
  321. hash = Hash.new
  322. if (node.name != "block")
  323. next
  324. end
  325. for child in node.children()
  326. hash[child.name] = "#{child.content}"
  327. end
  328. if (hash['testfile'].empty?)
  329. next
  330. end
  331. data.push(hash)
  332. end
  333. return data
  334. end
  335. ###############################################################################
  336. # ParseWhiteFile -- Function
  337. # This function parses Soda white xml files.
  338. #
  339. # Params:
  340. # white_file: The xml file with white list.
  341. #
  342. # Results:
  343. # returns an array of hashs.
  344. #
  345. ###############################################################################
  346. def SodaUtils.ParseWhiteFile(white_file)
  347. parser = nil
  348. error = false
  349. data = []
  350. doc = nil
  351. begin
  352. parser = LibXML::XML::Parser.file(white_file)
  353. doc = parser.parse()
  354. rescue Exception => e
  355. error = true
  356. data = []
  357. print "Error: #{e.message}!\n"
  358. print "BackTrace: #{e.backtrace}!\n"
  359. ensure
  360. if (error != false)
  361. return data
  362. end
  363. end
  364. doc.root.each do |node|
  365. hash = Hash.new
  366. if (node.name != "white")
  367. next
  368. end
  369. for child in node.children()
  370. hash[child.name] = "#{child.content}"
  371. end
  372. data.push(hash)
  373. end
  374. return data
  375. end
  376. ###############################################################################
  377. # ParseOldBlockListFile -- Function
  378. # This function parses the old style txt blocklist files.
  379. #
  380. # Params:
  381. # block_file: This is the blocklist file to parse.
  382. #
  383. # Results:
  384. # Returns an array of all the files to block, or an empty array on error.
  385. #
  386. ###############################################################################
  387. def SodaUtils.ParseOldBlockListFile(block_file)
  388. result = []
  389. block_file = File.expand_path(block_file)
  390. if (FileTest.exist?(block_file))
  391. file_array = IO.readlines(block_file)
  392. file_array.each do |line|
  393. line = line.chomp
  394. bfiles = line.split(',')
  395. for bf in bfiles
  396. if (bf == "")
  397. next
  398. end
  399. result.push(bf)
  400. end
  401. end
  402. else
  403. result = []
  404. end
  405. return result
  406. end
  407. ###############################################################################
  408. # ConvertOldBrowserClose -- Function
  409. # This function converts all the old style soda browser closes to the
  410. # new proper way to close the browser as an action.
  411. #
  412. # Params:
  413. # event: a soda event.
  414. # reportobj: The soda report object.
  415. # testfile: The file with the issue.
  416. #
  417. # Results:
  418. # Always returns a soda event.
  419. #
  420. ###############################################################################
  421. def SodaUtils.ConvertOldBrowserClose(event, reportobj, testfile)
  422. if (event.key?('close'))
  423. event['action'] = "close"
  424. event.delete('close')
  425. reportobj.log("You are using a deprecated Soda feature: <browser close" +
  426. "=\"true\" /> Test file: \"#{testfile}\", Line: "+
  427. "#{event['line_number']}!\n",
  428. SodaUtils::WARN)
  429. reportobj.log("Use <browser action=\"close\" />.\n", SodaUtils::WARN)
  430. end
  431. return event
  432. end
  433. ###############################################################################
  434. # ConvertOldAssert -- function
  435. # This function is to handle all the old tests that use the old way to
  436. # assertnot, which was a total hack! So this function just looks for the
  437. # old style assert & exist=false code and converts it to a proper
  438. # assertnot call.
  439. #
  440. # Params:
  441. # event: This is a soda event.
  442. # reportobj: This is soda's report object for logging.
  443. # testfile: This is the test file that the event came from.
  444. #
  445. # Results:
  446. # Always returns a soda event.
  447. #
  448. ###############################################################################
  449. def SodaUtils.ConvertOldAssert(event, reportobj, testfile)
  450. msg = nil
  451. if ( (event.key?('exist')) && (event.key?('assert')) )
  452. event['exist'] = getStringBool(event['exist'])
  453. if (event['exist'] == false)
  454. event['assertnot'] = event['assert']
  455. end
  456. msg = "You are using a deprecated Soda feature: " +
  457. "< assert=\"something\" exist=\"false\" />" +
  458. " Test file: \"#{testfile}\", Line: #{event['line_number']}\n."
  459. reportobj.log(msg, SodaUtils::WARN)
  460. msg = "Use: < assertnot=\"something\" />\n"
  461. reportobj.log(msg, SodaUtils::WARN)
  462. event.delete('exist')
  463. event.delete('assert')
  464. end
  465. return event
  466. end
  467. ###############################################################################
  468. # isRegex -- Function
  469. # This function checks to see if a string is a perl looking regex.
  470. #
  471. # Input:
  472. # str: The string to check.
  473. #
  474. # Output:
  475. # returns true if it is a regex, else false.
  476. #
  477. ###############################################################################
  478. def SodaUtils.isRegex(str)
  479. result = false
  480. if ( (str =~ /^\//) && (str =~ /\/$|\/\w+$/) )
  481. result = true
  482. else
  483. result = false
  484. end
  485. return result
  486. end
  487. ###############################################################################
  488. # CreateRegexFromStr -- Function
  489. # This function creates a regexp object from a string.
  490. #
  491. # Input:
  492. # str: This is the regex string.
  493. #
  494. # Output:
  495. # returns nil on error, or a Regexp object on success.
  496. #
  497. ###############################################################################
  498. def SodaUtils.CreateRegexFromStr(str)
  499. options = 0
  500. items = ""
  501. return nil if (!isRegex(str))
  502. str = str.gsub(/^\//,"")
  503. str =~ /\/(\w+)$/
  504. items = $1
  505. str = str.gsub(/\/#{items}$/, "")
  506. if ((items != nil) && (!items.empty?))
  507. items = items.split(//)
  508. items.each do |i|
  509. case (i)
  510. when "i"
  511. options = options | Regexp::IGNORECASE
  512. when "m"
  513. options = options | Regexp::MULTILINE
  514. when "x"
  515. options = options | Regexp::EXTENDED
  516. end
  517. end
  518. end
  519. reg = Regexp.new(str, options)
  520. return reg
  521. end
  522. ###############################################################################
  523. # XmlSafeStr -- Function
  524. #
  525. #
  526. ###############################################################################
  527. def SodaUtils.XmlSafeStr(str)
  528. str = str.gsub(/&/, "&amp;")
  529. str = str.gsub(/"/, "&quot;")
  530. str = str.gsub(/'/, "&apos;")
  531. str = str.gsub(/</, "&lt;")
  532. str = str.gsub(/>/, "&gt;")
  533. return str
  534. end
  535. ###############################################################################
  536. # getStringBool -- Function
  537. # This function checks to see of the value passed to it proves to be
  538. # positive in most any way.
  539. #
  540. # Params:
  541. # value: This is a string that will prove something true or false.
  542. #
  543. # Results:
  544. # returns true if the value is a form of being 'positive', or false.
  545. # If the value isn't a string then the value is just returned....
  546. #
  547. # Notes:
  548. # This is a total hack, we should be throw an exception if the value is
  549. # something other then a string... Will come back to this later...
  550. #
  551. ###############################################################################
  552. def SodaUtils.getStringBool(value)
  553. results = nil
  554. if (value.is_a?(String))
  555. value.downcase!
  556. if (value == 'true' or value == 'yes' or value == '1')
  557. results = true
  558. else
  559. results = false
  560. end
  561. end
  562. return results
  563. end
  564. ###############################################################################
  565. # ReadSodaConfig - function
  566. # This functions reads the soda config file into a hash.
  567. #
  568. # Params:
  569. # configfile: This is the config xml file to read.
  570. #
  571. # Results:
  572. # Returns a hash containing the config file parsed into sub hashes and
  573. # arrays.
  574. #
  575. ###############################################################################
  576. def SodaUtils.ReadSodaConfig(configfile)
  577. parser = nil
  578. doc = nil
  579. data = {
  580. "gvars" => {},
  581. "cmdopts" => [],
  582. "errorskip" => []
  583. }
  584. parser = LibXML::XML::Parser.file(configfile)
  585. doc = parser.parse()
  586. doc.root.each do |node|
  587. attrs = node.attributes()
  588. attrs = attrs.to_h()
  589. name = attrs['name']
  590. content = node.content()
  591. case node.name
  592. when "errorskip"
  593. data['errorskip'].push("#{attrs['type']}")
  594. when "gvar"
  595. data['gvars']["#{name}"] = "#{content}"
  596. when "cmdopt"
  597. data['cmdopts'].push({"#{name}" => "#{content}"})
  598. when "text"
  599. next
  600. else
  601. SodaUtils.PrintSoda("Found unknown xml tag: \"#{node.name}\"!\n",
  602. SodaUtils::ERROR)
  603. end
  604. end
  605. return data
  606. end
  607. ###############################################################################
  608. ###############################################################################
  609. def SodaUtils.getSodaJS()
  610. return <<JSCode
  611. (function() {
  612. var Dom = YAHOO.util.Dom, DDM = YAHOO.util.DDM;
  613. SUGAR.soda = {
  614. fakeDrag : function(fromEl, toEl)
  615. {
  616. if(typeof fromEl == "string") {
  617. fromEl = Dom.get(fromEl);
  618. }
  619. if(typeof toEl == "string") {
  620. toEl = Dom.get(toEl);
  621. }
  622. var dd = DDM.getDDById(fromEl.id);
  623. var startXY = Dom.getXY(fromEl);
  624. var endXY = Dom.getXY(toEl);
  625. var startEvent = {
  626. target : fromEl,
  627. pageX : startXY[0],
  628. pageY : startXY[1],
  629. clientX : startXY[0],
  630. clientY : startXY[1],
  631. button : 0
  632. };
  633. var enterEvent = {
  634. target : fromEl,
  635. pageX : endXY[0],
  636. pageY : endXY[1],
  637. clientX : endXY[0],
  638. clientY : endXY[1],
  639. button : 0
  640. };
  641. var endEvent = {
  642. target : fromEl,
  643. pageX : endXY[0] + 1,
  644. pageY : endXY[1] + 1,
  645. clientX : endXY[0] + 1,
  646. clientY : endXY[1] + 1,
  647. button : 0
  648. };
  649. DDM.handleMouseDown(startEvent, dd);
  650. DDM.handleMouseMove(enterEvent);
  651. DDM.handleMouseMove(endEvent);
  652. DDM.handleMouseUp(endEvent);
  653. }
  654. };
  655. })();
  656. JSCode
  657. end
  658. end