oreorenasass 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +11 -0
  3. data/CONTRIBUTING +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +221 -0
  6. data/Rakefile +370 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/sass +13 -0
  10. data/bin/sass-convert +12 -0
  11. data/bin/scss +13 -0
  12. data/extra/update_watch.rb +13 -0
  13. data/init.rb +18 -0
  14. data/lib/sass/cache_stores/base.rb +88 -0
  15. data/lib/sass/cache_stores/chain.rb +34 -0
  16. data/lib/sass/cache_stores/filesystem.rb +60 -0
  17. data/lib/sass/cache_stores/memory.rb +47 -0
  18. data/lib/sass/cache_stores/null.rb +25 -0
  19. data/lib/sass/cache_stores.rb +15 -0
  20. data/lib/sass/callbacks.rb +67 -0
  21. data/lib/sass/css.rb +407 -0
  22. data/lib/sass/engine.rb +1181 -0
  23. data/lib/sass/environment.rb +191 -0
  24. data/lib/sass/error.rb +198 -0
  25. data/lib/sass/exec/base.rb +187 -0
  26. data/lib/sass/exec/sass_convert.rb +264 -0
  27. data/lib/sass/exec/sass_scss.rb +424 -0
  28. data/lib/sass/exec.rb +9 -0
  29. data/lib/sass/features.rb +47 -0
  30. data/lib/sass/importers/base.rb +182 -0
  31. data/lib/sass/importers/filesystem.rb +211 -0
  32. data/lib/sass/importers.rb +22 -0
  33. data/lib/sass/logger/base.rb +30 -0
  34. data/lib/sass/logger/log_level.rb +45 -0
  35. data/lib/sass/logger.rb +12 -0
  36. data/lib/sass/media.rb +210 -0
  37. data/lib/sass/plugin/compiler.rb +565 -0
  38. data/lib/sass/plugin/configuration.rb +118 -0
  39. data/lib/sass/plugin/generic.rb +15 -0
  40. data/lib/sass/plugin/merb.rb +48 -0
  41. data/lib/sass/plugin/rack.rb +60 -0
  42. data/lib/sass/plugin/rails.rb +47 -0
  43. data/lib/sass/plugin/staleness_checker.rb +199 -0
  44. data/lib/sass/plugin.rb +133 -0
  45. data/lib/sass/railtie.rb +10 -0
  46. data/lib/sass/repl.rb +57 -0
  47. data/lib/sass/root.rb +7 -0
  48. data/lib/sass/script/css_lexer.rb +33 -0
  49. data/lib/sass/script/css_parser.rb +34 -0
  50. data/lib/sass/script/functions.rb +2626 -0
  51. data/lib/sass/script/lexer.rb +449 -0
  52. data/lib/sass/script/parser.rb +637 -0
  53. data/lib/sass/script/tree/funcall.rb +306 -0
  54. data/lib/sass/script/tree/interpolation.rb +118 -0
  55. data/lib/sass/script/tree/list_literal.rb +77 -0
  56. data/lib/sass/script/tree/literal.rb +45 -0
  57. data/lib/sass/script/tree/map_literal.rb +64 -0
  58. data/lib/sass/script/tree/node.rb +109 -0
  59. data/lib/sass/script/tree/operation.rb +103 -0
  60. data/lib/sass/script/tree/selector.rb +26 -0
  61. data/lib/sass/script/tree/string_interpolation.rb +104 -0
  62. data/lib/sass/script/tree/unary_operation.rb +69 -0
  63. data/lib/sass/script/tree/variable.rb +57 -0
  64. data/lib/sass/script/tree.rb +16 -0
  65. data/lib/sass/script/value/arg_list.rb +36 -0
  66. data/lib/sass/script/value/base.rb +240 -0
  67. data/lib/sass/script/value/bool.rb +35 -0
  68. data/lib/sass/script/value/color.rb +680 -0
  69. data/lib/sass/script/value/helpers.rb +262 -0
  70. data/lib/sass/script/value/list.rb +113 -0
  71. data/lib/sass/script/value/map.rb +70 -0
  72. data/lib/sass/script/value/null.rb +44 -0
  73. data/lib/sass/script/value/number.rb +530 -0
  74. data/lib/sass/script/value/string.rb +97 -0
  75. data/lib/sass/script/value.rb +11 -0
  76. data/lib/sass/script.rb +66 -0
  77. data/lib/sass/scss/css_parser.rb +42 -0
  78. data/lib/sass/scss/parser.rb +1209 -0
  79. data/lib/sass/scss/rx.rb +141 -0
  80. data/lib/sass/scss/script_lexer.rb +15 -0
  81. data/lib/sass/scss/script_parser.rb +25 -0
  82. data/lib/sass/scss/static_parser.rb +368 -0
  83. data/lib/sass/scss.rb +16 -0
  84. data/lib/sass/selector/abstract_sequence.rb +109 -0
  85. data/lib/sass/selector/comma_sequence.rb +175 -0
  86. data/lib/sass/selector/pseudo.rb +256 -0
  87. data/lib/sass/selector/sequence.rb +600 -0
  88. data/lib/sass/selector/simple.rb +117 -0
  89. data/lib/sass/selector/simple_sequence.rb +325 -0
  90. data/lib/sass/selector.rb +326 -0
  91. data/lib/sass/shared.rb +76 -0
  92. data/lib/sass/source/map.rb +210 -0
  93. data/lib/sass/source/position.rb +39 -0
  94. data/lib/sass/source/range.rb +41 -0
  95. data/lib/sass/stack.rb +120 -0
  96. data/lib/sass/supports.rb +227 -0
  97. data/lib/sass/tree/at_root_node.rb +83 -0
  98. data/lib/sass/tree/charset_node.rb +22 -0
  99. data/lib/sass/tree/comment_node.rb +82 -0
  100. data/lib/sass/tree/content_node.rb +9 -0
  101. data/lib/sass/tree/css_import_node.rb +60 -0
  102. data/lib/sass/tree/debug_node.rb +18 -0
  103. data/lib/sass/tree/directive_node.rb +59 -0
  104. data/lib/sass/tree/each_node.rb +24 -0
  105. data/lib/sass/tree/error_node.rb +18 -0
  106. data/lib/sass/tree/extend_node.rb +43 -0
  107. data/lib/sass/tree/for_node.rb +36 -0
  108. data/lib/sass/tree/function_node.rb +39 -0
  109. data/lib/sass/tree/if_node.rb +52 -0
  110. data/lib/sass/tree/import_node.rb +74 -0
  111. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  112. data/lib/sass/tree/media_node.rb +48 -0
  113. data/lib/sass/tree/mixin_def_node.rb +38 -0
  114. data/lib/sass/tree/mixin_node.rb +52 -0
  115. data/lib/sass/tree/node.rb +238 -0
  116. data/lib/sass/tree/prop_node.rb +171 -0
  117. data/lib/sass/tree/return_node.rb +19 -0
  118. data/lib/sass/tree/root_node.rb +44 -0
  119. data/lib/sass/tree/rule_node.rb +145 -0
  120. data/lib/sass/tree/supports_node.rb +38 -0
  121. data/lib/sass/tree/trace_node.rb +33 -0
  122. data/lib/sass/tree/variable_node.rb +36 -0
  123. data/lib/sass/tree/visitors/base.rb +72 -0
  124. data/lib/sass/tree/visitors/check_nesting.rb +177 -0
  125. data/lib/sass/tree/visitors/convert.rb +334 -0
  126. data/lib/sass/tree/visitors/cssize.rb +369 -0
  127. data/lib/sass/tree/visitors/deep_copy.rb +107 -0
  128. data/lib/sass/tree/visitors/extend.rb +68 -0
  129. data/lib/sass/tree/visitors/perform.rb +539 -0
  130. data/lib/sass/tree/visitors/set_options.rb +139 -0
  131. data/lib/sass/tree/visitors/to_css.rb +381 -0
  132. data/lib/sass/tree/warn_node.rb +18 -0
  133. data/lib/sass/tree/while_node.rb +18 -0
  134. data/lib/sass/util/cross_platform_random.rb +19 -0
  135. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  136. data/lib/sass/util/normalized_map.rb +130 -0
  137. data/lib/sass/util/ordered_hash.rb +192 -0
  138. data/lib/sass/util/subset_map.rb +110 -0
  139. data/lib/sass/util/test.rb +9 -0
  140. data/lib/sass/util.rb +1318 -0
  141. data/lib/sass/version.rb +124 -0
  142. data/lib/sass.rb +102 -0
  143. data/rails/init.rb +1 -0
  144. data/test/sass/cache_test.rb +131 -0
  145. data/test/sass/callbacks_test.rb +61 -0
  146. data/test/sass/compiler_test.rb +232 -0
  147. data/test/sass/conversion_test.rb +2054 -0
  148. data/test/sass/css2sass_test.rb +477 -0
  149. data/test/sass/data/hsl-rgb.txt +319 -0
  150. data/test/sass/encoding_test.rb +219 -0
  151. data/test/sass/engine_test.rb +3301 -0
  152. data/test/sass/exec_test.rb +86 -0
  153. data/test/sass/extend_test.rb +1661 -0
  154. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  155. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  156. data/test/sass/functions_test.rb +1926 -0
  157. data/test/sass/importer_test.rb +412 -0
  158. data/test/sass/logger_test.rb +58 -0
  159. data/test/sass/mock_importer.rb +49 -0
  160. data/test/sass/more_results/more1.css +9 -0
  161. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  162. data/test/sass/more_results/more_import.css +29 -0
  163. data/test/sass/more_templates/_more_partial.sass +2 -0
  164. data/test/sass/more_templates/more1.sass +23 -0
  165. data/test/sass/more_templates/more_import.sass +11 -0
  166. data/test/sass/plugin_test.rb +554 -0
  167. data/test/sass/results/alt.css +4 -0
  168. data/test/sass/results/basic.css +9 -0
  169. data/test/sass/results/cached_import_option.css +3 -0
  170. data/test/sass/results/compact.css +5 -0
  171. data/test/sass/results/complex.css +86 -0
  172. data/test/sass/results/compressed.css +1 -0
  173. data/test/sass/results/expanded.css +19 -0
  174. data/test/sass/results/filename_fn.css +3 -0
  175. data/test/sass/results/if.css +3 -0
  176. data/test/sass/results/import.css +31 -0
  177. data/test/sass/results/import_charset.css +5 -0
  178. data/test/sass/results/import_charset_1_8.css +5 -0
  179. data/test/sass/results/import_charset_ibm866.css +5 -0
  180. data/test/sass/results/import_content.css +1 -0
  181. data/test/sass/results/line_numbers.css +49 -0
  182. data/test/sass/results/mixins.css +95 -0
  183. data/test/sass/results/multiline.css +24 -0
  184. data/test/sass/results/nested.css +22 -0
  185. data/test/sass/results/options.css +1 -0
  186. data/test/sass/results/parent_ref.css +13 -0
  187. data/test/sass/results/script.css +16 -0
  188. data/test/sass/results/scss_import.css +31 -0
  189. data/test/sass/results/scss_importee.css +2 -0
  190. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  191. data/test/sass/results/subdir/subdir.css +3 -0
  192. data/test/sass/results/units.css +11 -0
  193. data/test/sass/results/warn.css +0 -0
  194. data/test/sass/results/warn_imported.css +0 -0
  195. data/test/sass/script_conversion_test.rb +328 -0
  196. data/test/sass/script_test.rb +1054 -0
  197. data/test/sass/scss/css_test.rb +1215 -0
  198. data/test/sass/scss/rx_test.rb +156 -0
  199. data/test/sass/scss/scss_test.rb +3900 -0
  200. data/test/sass/scss/test_helper.rb +37 -0
  201. data/test/sass/source_map_test.rb +977 -0
  202. data/test/sass/superselector_test.rb +191 -0
  203. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  204. data/test/sass/templates/_double_import_loop2.sass +1 -0
  205. data/test/sass/templates/_filename_fn_import.scss +11 -0
  206. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  207. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  208. data/test/sass/templates/_imported_content.sass +3 -0
  209. data/test/sass/templates/_partial.sass +2 -0
  210. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  211. data/test/sass/templates/alt.sass +16 -0
  212. data/test/sass/templates/basic.sass +23 -0
  213. data/test/sass/templates/bork1.sass +2 -0
  214. data/test/sass/templates/bork2.sass +2 -0
  215. data/test/sass/templates/bork3.sass +2 -0
  216. data/test/sass/templates/bork4.sass +2 -0
  217. data/test/sass/templates/bork5.sass +3 -0
  218. data/test/sass/templates/cached_import_option.scss +3 -0
  219. data/test/sass/templates/compact.sass +17 -0
  220. data/test/sass/templates/complex.sass +305 -0
  221. data/test/sass/templates/compressed.sass +15 -0
  222. data/test/sass/templates/double_import_loop1.sass +1 -0
  223. data/test/sass/templates/expanded.sass +17 -0
  224. data/test/sass/templates/filename_fn.scss +18 -0
  225. data/test/sass/templates/if.sass +11 -0
  226. data/test/sass/templates/import.sass +12 -0
  227. data/test/sass/templates/import_charset.sass +9 -0
  228. data/test/sass/templates/import_charset_1_8.sass +6 -0
  229. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  230. data/test/sass/templates/import_content.sass +4 -0
  231. data/test/sass/templates/importee.less +2 -0
  232. data/test/sass/templates/importee.sass +19 -0
  233. data/test/sass/templates/line_numbers.sass +13 -0
  234. data/test/sass/templates/mixin_bork.sass +5 -0
  235. data/test/sass/templates/mixins.sass +76 -0
  236. data/test/sass/templates/multiline.sass +20 -0
  237. data/test/sass/templates/nested.sass +25 -0
  238. data/test/sass/templates/nested_bork1.sass +2 -0
  239. data/test/sass/templates/nested_bork2.sass +2 -0
  240. data/test/sass/templates/nested_bork3.sass +2 -0
  241. data/test/sass/templates/nested_bork4.sass +2 -0
  242. data/test/sass/templates/nested_import.sass +2 -0
  243. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  244. data/test/sass/templates/options.sass +2 -0
  245. data/test/sass/templates/parent_ref.sass +25 -0
  246. data/test/sass/templates/same_name_different_ext.sass +2 -0
  247. data/test/sass/templates/same_name_different_ext.scss +1 -0
  248. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  249. data/test/sass/templates/script.sass +101 -0
  250. data/test/sass/templates/scss_import.scss +12 -0
  251. data/test/sass/templates/scss_importee.scss +1 -0
  252. data/test/sass/templates/single_import_loop.sass +1 -0
  253. data/test/sass/templates/subdir/import_up1.scss +1 -0
  254. data/test/sass/templates/subdir/import_up2.scss +1 -0
  255. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  256. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  257. data/test/sass/templates/subdir/subdir.sass +6 -0
  258. data/test/sass/templates/units.sass +11 -0
  259. data/test/sass/templates/warn.sass +3 -0
  260. data/test/sass/templates/warn_imported.sass +4 -0
  261. data/test/sass/test_helper.rb +8 -0
  262. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  263. data/test/sass/util/normalized_map_test.rb +51 -0
  264. data/test/sass/util/subset_map_test.rb +91 -0
  265. data/test/sass/util_test.rb +467 -0
  266. data/test/sass/value_helpers_test.rb +179 -0
  267. data/test/test_helper.rb +109 -0
  268. metadata +386 -0
@@ -0,0 +1,12 @@
1
+ $preconst: hello;
2
+
3
+ @mixin premixin {pre-mixin: here}
4
+
5
+ @import "importee.sass", "scss_importee", "basic.sass", "basic.css", "../results/complex.css";
6
+ @import "part\
7
+ ial.sass";
8
+
9
+ nonimported {
10
+ myconst: $preconst;
11
+ otherconst: $postconst;
12
+ @include postmixin; }
@@ -0,0 +1 @@
1
+ scss {imported: yes}
@@ -0,0 +1 @@
1
+ @import "single_import_loop"
@@ -0,0 +1 @@
1
+ @import "../subdir/import_up2.scss";
@@ -0,0 +1 @@
1
+ @import "../subdir/import_up3.scss";
@@ -0,0 +1,2 @@
1
+ #nested
2
+ :relative true
@@ -0,0 +1,3 @@
1
+ #pi
2
+ :width 314px
3
+
@@ -0,0 +1,6 @@
1
+ @import nested_subdir/nested_partial.sass
2
+
3
+ #subdir
4
+ :font
5
+ :size 20px
6
+ :weight bold
@@ -0,0 +1,11 @@
1
+ b
2
+ :foo 0.5 * 10px
3
+ :bar 10zzz * 12px / 5zzz
4
+ :baz percentage(12.0px / 18px)
5
+ :many-units 10.0zzz / 3yyy * 12px / 5zzz * 3yyy / 3px * 4em
6
+ :mm 5mm + 1cm
7
+ :pc 1pc + 12pt
8
+ :pt 72pt - 2in
9
+ :inches 1in + 2.54cm
10
+ :more-inches 1in + ((72pt * 2in) + (36pt * 1in)) / 2.54cm
11
+ :mixed (1 + (1em * 6px / 3in)) * 4in / 2em
@@ -0,0 +1,3 @@
1
+ @warn "In the main file"
2
+ @import warn_imported.sass
3
+ +emits-a-warning
@@ -0,0 +1,4 @@
1
+ @warn "Imported"
2
+
3
+ =emits-a-warning
4
+ @warn "In an imported mixin"
@@ -0,0 +1,8 @@
1
+ test_dir = File.dirname(__FILE__)
2
+ $:.unshift test_dir unless $:.include?(test_dir)
3
+
4
+ class MiniTest::Test
5
+ def absolutize(file)
6
+ File.expand_path("#{File.dirname(__FILE__)}/#{file}")
7
+ end
8
+ end
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/../../test_helper'
4
+
5
+ unless Sass::Util.ruby1_8?
6
+ class MultibyteStringScannerTest < MiniTest::Test
7
+ def setup
8
+ @scanner = Sass::Util::MultibyteStringScanner.new("cölorfül")
9
+ end
10
+
11
+ def test_initial
12
+ assert_scanner_state 0, 0, nil, nil
13
+ end
14
+
15
+ def test_check
16
+ assert_equal 'cö', @scanner.check(/../)
17
+ assert_scanner_state 0, 0, 2, 3
18
+ assert_equal 0, @scanner.pos
19
+ assert_equal 0, @scanner.pos
20
+ assert_equal 2, @scanner.matched_size
21
+ assert_equal 3, @scanner.byte_matched_size
22
+ end
23
+
24
+ def test_check_until
25
+ assert_equal 'cölorfü', @scanner.check_until(/f./)
26
+ assert_scanner_state 0, 0, 2, 3
27
+ end
28
+
29
+ def test_getch
30
+ assert_equal 'c', @scanner.getch
31
+ assert_equal 'ö', @scanner.getch
32
+ assert_scanner_state 2, 3, 1, 2
33
+ end
34
+
35
+ def test_match?
36
+ assert_equal 2, @scanner.match?(/../)
37
+ assert_scanner_state 0, 0, 2, 3
38
+ end
39
+
40
+ def test_peek
41
+ assert_equal 'cö', @scanner.peek(2)
42
+ assert_scanner_state 0, 0, nil, nil
43
+ end
44
+
45
+ def test_rest_size
46
+ assert_equal 'cö', @scanner.scan(/../)
47
+ assert_equal 6, @scanner.rest_size
48
+ end
49
+
50
+ def test_scan
51
+ assert_equal 'cö', @scanner.scan(/../)
52
+ assert_scanner_state 2, 3, 2, 3
53
+ end
54
+
55
+ def test_scan_until
56
+ assert_equal 'cölorfü', @scanner.scan_until(/f./)
57
+ assert_scanner_state 7, 9, 2, 3
58
+ end
59
+
60
+ def test_skip
61
+ assert_equal 2, @scanner.skip(/../)
62
+ assert_scanner_state 2, 3, 2, 3
63
+ end
64
+
65
+ def test_skip_until
66
+ assert_equal 7, @scanner.skip_until(/f./)
67
+ assert_scanner_state 7, 9, 2, 3
68
+ end
69
+
70
+ def test_set_pos
71
+ @scanner.pos = 7
72
+ assert_scanner_state 7, 9, nil, nil
73
+ @scanner.pos = 6
74
+ assert_scanner_state 6, 7, nil, nil
75
+ @scanner.pos = 1
76
+ assert_scanner_state 1, 1, nil, nil
77
+ end
78
+
79
+ def test_reset
80
+ @scanner.scan(/../)
81
+ @scanner.reset
82
+ assert_scanner_state 0, 0, nil, nil
83
+ end
84
+
85
+ def test_scan_full
86
+ assert_equal 'cö', @scanner.scan_full(/../, true, true)
87
+ assert_scanner_state 2, 3, 2, 3
88
+
89
+ @scanner.reset
90
+ assert_equal 'cö', @scanner.scan_full(/../, false, true)
91
+ assert_scanner_state 0, 0, 2, 3
92
+
93
+ @scanner.reset
94
+ assert_nil @scanner.scan_full(/../, true, false)
95
+ assert_scanner_state 2, 3, 2, 3
96
+
97
+ @scanner.reset
98
+ assert_nil @scanner.scan_full(/../, false, false)
99
+ assert_scanner_state 0, 0, 2, 3
100
+ end
101
+
102
+ def test_search_full
103
+ assert_equal 'cölorfü', @scanner.search_full(/f./, true, true)
104
+ assert_scanner_state 7, 9, 2, 3
105
+
106
+ @scanner.reset
107
+ assert_equal 'cölorfü', @scanner.search_full(/f./, false, true)
108
+ assert_scanner_state 0, 0, 2, 3
109
+
110
+ @scanner.reset
111
+ assert_nil @scanner.search_full(/f./, true, false)
112
+ assert_scanner_state 7, 9, 2, 3
113
+
114
+ @scanner.reset
115
+ assert_nil @scanner.search_full(/f./, false, false)
116
+ assert_scanner_state 0, 0, 2, 3
117
+ end
118
+
119
+ def test_set_string
120
+ @scanner.scan(/../)
121
+ @scanner.string = 'föóbâr'
122
+ assert_scanner_state 0, 0, nil, nil
123
+ end
124
+
125
+ def test_terminate
126
+ @scanner.scan(/../)
127
+ @scanner.terminate
128
+ assert_scanner_state 8, 10, nil, nil
129
+ end
130
+
131
+ def test_unscan
132
+ @scanner.scan(/../)
133
+ @scanner.scan_until(/f./)
134
+ @scanner.unscan
135
+ assert_scanner_state 2, 3, nil, nil
136
+ end
137
+
138
+ private
139
+
140
+ def assert_scanner_state(pos, byte_pos, matched_size, byte_matched_size)
141
+ assert_equal pos, @scanner.pos, 'pos'
142
+ assert_equal byte_pos, @scanner.byte_pos, 'byte_pos'
143
+ assert_equal matched_size, @scanner.matched_size, 'matched_size'
144
+ assert_equal byte_matched_size, @scanner.byte_matched_size, 'byte_matched_size'
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../test_helper'
3
+ require 'sass/util/normalized_map'
4
+
5
+ class NormalizedMapTest < MiniTest::Test
6
+ extend PublicApiLinter
7
+
8
+ lint_api Hash, Sass::Util::NormalizedMap
9
+
10
+ def lint_instance
11
+ Sass::Util::NormalizedMap.new
12
+ end
13
+
14
+ def test_normalized_map_errors_unless_explicitly_implemented
15
+ assert Sass.tests_running
16
+ assert_raise_message(ArgumentError, "The method invert must be implemented explicitly") do
17
+ Sass::Util::NormalizedMap.new.invert
18
+ end
19
+ end
20
+
21
+ def test_normalized_map_does_not_error_when_released
22
+ Sass.tests_running = false
23
+ assert_equal({}, Sass::Util::NormalizedMap.new.invert)
24
+ ensure
25
+ Sass.tests_running = true
26
+ end
27
+
28
+ def test_basic_lifecycle
29
+ m = Sass::Util::NormalizedMap.new
30
+ m["a-b"] = 1
31
+ assert_equal ["a_b"], m.keys
32
+ assert_equal 1, m["a_b"]
33
+ assert_equal 1, m["a-b"]
34
+ assert m.has_key?("a_b")
35
+ assert m.has_key?("a-b")
36
+ assert_equal({"a-b" => 1}, m.as_stored)
37
+ assert_equal 1, m.delete("a-b")
38
+ assert !m.has_key?("a-b")
39
+ m["a_b"] = 2
40
+ assert_equal({"a_b" => 2}, m.as_stored)
41
+ end
42
+
43
+ def test_dup
44
+ m = Sass::Util::NormalizedMap.new
45
+ m["a-b"] = 1
46
+ m2 = m.dup
47
+ m.delete("a-b")
48
+ assert !m.has_key?("a-b")
49
+ assert m2.has_key?("a-b")
50
+ end
51
+ end
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../test_helper'
3
+
4
+ class SubsetMapTest < MiniTest::Test
5
+ def setup
6
+ @ssm = Sass::Util::SubsetMap.new
7
+ @ssm[Set[1, 2]] = "Foo"
8
+ @ssm[Set["fizz", "fazz"]] = "Bar"
9
+
10
+ @ssm[Set[:foo, :bar]] = "Baz"
11
+ @ssm[Set[:foo, :bar, :baz]] = "Bang"
12
+
13
+ @ssm[Set[:bip, :bop, :blip]] = "Qux"
14
+ @ssm[Set[:bip, :bop]] = "Thram"
15
+ end
16
+
17
+ def test_equal_keys
18
+ assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2])
19
+ assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"])
20
+ end
21
+
22
+ def test_subset_keys
23
+ assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"])
24
+ assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3])
25
+ end
26
+
27
+ def test_superset_keys
28
+ assert_equal [], @ssm.get(Set[1])
29
+ assert_equal [], @ssm.get(Set[2])
30
+ assert_equal [], @ssm.get(Set["fizz"])
31
+ assert_equal [], @ssm.get(Set["fazz"])
32
+ end
33
+
34
+ def test_disjoint_keys
35
+ assert_equal [], @ssm.get(Set[3, 4])
36
+ assert_equal [], @ssm.get(Set["fuzz", "frizz"])
37
+ assert_equal [], @ssm.get(Set["gran", 15])
38
+ end
39
+
40
+ def test_semi_disjoint_keys
41
+ assert_equal [], @ssm.get(Set[2, 3])
42
+ assert_equal [], @ssm.get(Set["fizz", "fuzz"])
43
+ assert_equal [], @ssm.get(Set[1, "fazz"])
44
+ end
45
+
46
+ def test_empty_key_set
47
+ assert_raises(ArgumentError) {@ssm[Set[]] = "Fail"}
48
+ end
49
+
50
+ def test_empty_key_get
51
+ assert_equal [], @ssm.get(Set[])
52
+ end
53
+
54
+ def test_multiple_subsets
55
+ assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"])
56
+ assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", "fuzz"])
57
+
58
+ assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar])
59
+ assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz])
60
+ end
61
+
62
+ def test_bracket_bracket
63
+ assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]]
64
+ assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]]
65
+ end
66
+
67
+ def test_order_preserved
68
+ @ssm[Set[10, 11, 12]] = 1
69
+ @ssm[Set[10, 11]] = 2
70
+ @ssm[Set[11]] = 3
71
+ @ssm[Set[11, 12]] = 4
72
+ @ssm[Set[9, 10, 11, 12, 13]] = 5
73
+ @ssm[Set[10, 13]] = 6
74
+
75
+ assert_equal(
76
+ [[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]],
77
+ [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]],
78
+ @ssm.get(Set[9, 10, 11, 12, 13]))
79
+ end
80
+
81
+ def test_multiple_equal_values
82
+ @ssm[Set[11, 12]] = 1
83
+ @ssm[Set[12, 13]] = 2
84
+ @ssm[Set[13, 14]] = 1
85
+ @ssm[Set[14, 15]] = 1
86
+
87
+ assert_equal(
88
+ [[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]],
89
+ @ssm.get(Set[11, 12, 13, 14, 15]))
90
+ end
91
+ end
@@ -0,0 +1,467 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+ require 'pathname'
4
+ require 'tmpdir'
5
+
6
+ class UtilTest < MiniTest::Test
7
+ include Sass::Util
8
+
9
+ def test_scope
10
+ assert(File.exist?(scope("Rakefile")))
11
+ end
12
+
13
+ def test_to_hash
14
+ assert_equal({
15
+ :foo => 1,
16
+ :bar => 2,
17
+ :baz => 3
18
+ }, to_hash([[:foo, 1], [:bar, 2], [:baz, 3]]))
19
+ end
20
+
21
+ def test_map_keys
22
+ assert_equal({
23
+ "foo" => 1,
24
+ "bar" => 2,
25
+ "baz" => 3
26
+ }, map_keys({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
27
+ end
28
+
29
+ def test_map_vals
30
+ assert_equal({
31
+ :foo => "1",
32
+ :bar => "2",
33
+ :baz => "3"
34
+ }, map_vals({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
35
+ end
36
+
37
+ def test_map_hash
38
+ assert_equal({
39
+ "foo" => "1",
40
+ "bar" => "2",
41
+ "baz" => "3"
42
+ }, map_hash({:foo => 1, :bar => 2, :baz => 3}) {|k, v| [k.to_s, v.to_s]})
43
+ end
44
+
45
+ def test_map_hash_with_normalized_map
46
+ map = NormalizedMap.new("foo-bar" => 1, "baz_bang" => 2)
47
+ result = map_hash(map) {|k, v| [k, v.to_s]}
48
+ assert_equal("1", result["foo-bar"])
49
+ assert_equal("1", result["foo_bar"])
50
+ assert_equal("2", result["baz-bang"])
51
+ assert_equal("2", result["baz_bang"])
52
+ end
53
+
54
+ def test_powerset
55
+ return unless Set[Set[]] == Set[Set[]] # There's a bug in Ruby 1.8.6 that breaks nested set equality
56
+ assert_equal([[].to_set].to_set,
57
+ powerset([]))
58
+ assert_equal([[].to_set, [1].to_set].to_set,
59
+ powerset([1]))
60
+ assert_equal([[].to_set, [1].to_set, [2].to_set, [1, 2].to_set].to_set,
61
+ powerset([1, 2]))
62
+ assert_equal([[].to_set, [1].to_set, [2].to_set, [3].to_set,
63
+ [1, 2].to_set, [2, 3].to_set, [1, 3].to_set, [1, 2, 3].to_set].to_set,
64
+ powerset([1, 2, 3]))
65
+ end
66
+
67
+ def test_restrict
68
+ assert_equal(0.5, restrict(0.5, 0..1))
69
+ assert_equal(1, restrict(2, 0..1))
70
+ assert_equal(1.3, restrict(2, 0..1.3))
71
+ assert_equal(0, restrict(-1, 0..1))
72
+ end
73
+
74
+ def test_merge_adjacent_strings
75
+ assert_equal(["foo bar baz", :bang, "biz bop", 12],
76
+ merge_adjacent_strings(["foo ", "bar ", "baz", :bang, "biz", " bop", 12]))
77
+ str = "foo"
78
+ assert_equal(["foo foo foo", :bang, "foo foo", 12],
79
+ merge_adjacent_strings([str, " ", str, " ", str, :bang, str, " ", str, 12]))
80
+ end
81
+
82
+ def test_replace_subseq
83
+ assert_equal([1, 2, :a, :b, 5],
84
+ replace_subseq([1, 2, 3, 4, 5], [3, 4], [:a, :b]))
85
+ assert_equal([1, 2, 3, 4, 5],
86
+ replace_subseq([1, 2, 3, 4, 5], [3, 4, 6], [:a, :b]))
87
+ assert_equal([1, 2, 3, 4, 5],
88
+ replace_subseq([1, 2, 3, 4, 5], [4, 5, 6], [:a, :b]))
89
+ end
90
+
91
+ def test_intersperse
92
+ assert_equal(["foo", " ", "bar", " ", "baz"],
93
+ intersperse(%w[foo bar baz], " "))
94
+ assert_equal([], intersperse([], " "))
95
+ end
96
+
97
+ def test_substitute
98
+ assert_equal(["foo", "bar", "baz", 3, 4],
99
+ substitute([1, 2, 3, 4], [1, 2], ["foo", "bar", "baz"]))
100
+ assert_equal([1, "foo", "bar", "baz", 4],
101
+ substitute([1, 2, 3, 4], [2, 3], ["foo", "bar", "baz"]))
102
+ assert_equal([1, 2, "foo", "bar", "baz"],
103
+ substitute([1, 2, 3, 4], [3, 4], ["foo", "bar", "baz"]))
104
+
105
+ assert_equal([1, "foo", "bar", "baz", 2, 3, 4],
106
+ substitute([1, 2, 2, 2, 3, 4], [2, 2], ["foo", "bar", "baz"]))
107
+ end
108
+
109
+ def test_strip_string_array
110
+ assert_equal(["foo ", " bar ", " baz"],
111
+ strip_string_array([" foo ", " bar ", " baz "]))
112
+ assert_equal([:foo, " bar ", " baz"],
113
+ strip_string_array([:foo, " bar ", " baz "]))
114
+ assert_equal(["foo ", " bar ", :baz],
115
+ strip_string_array([" foo ", " bar ", :baz]))
116
+ end
117
+
118
+ def test_paths
119
+ assert_equal([[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5]],
120
+ paths([[1, 2], [3, 4], [5]]))
121
+ assert_equal([[]], paths([]))
122
+ assert_equal([[1, 2, 3]], paths([[1], [2], [3]]))
123
+ end
124
+
125
+ def test_lcs
126
+ assert_equal([1, 2, 3], lcs([1, 2, 3], [1, 2, 3]))
127
+ assert_equal([], lcs([], [1, 2, 3]))
128
+ assert_equal([], lcs([1, 2, 3], []))
129
+ assert_equal([1, 2, 3], lcs([5, 1, 4, 2, 3, 17], [0, 0, 1, 2, 6, 3]))
130
+
131
+ assert_equal([1], lcs([1, 2, 3, 4], [4, 3, 2, 1]))
132
+ assert_equal([1, 2], lcs([1, 2, 3, 4], [3, 4, 1, 2]))
133
+ end
134
+
135
+ def test_lcs_with_block
136
+ assert_equal(["1", "2", "3"],
137
+ lcs([1, 4, 2, 5, 3], [1, 2, 3]) {|a, b| a == b && a.to_s})
138
+ assert_equal([-4, 2, 8],
139
+ lcs([-5, 3, 2, 8], [-4, 1, 8]) {|a, b| (a - b).abs <= 1 && [a, b].max})
140
+ end
141
+
142
+ def test_group_by_to_a
143
+ assert_equal([[1, [1, 3, 5, 7]], [0, [2, 4, 6, 8]]],
144
+ group_by_to_a(1..8) {|i| i % 2})
145
+ assert_equal([[1, [1, 4, 7, 10]], [2, [2, 5, 8, 11]], [0, [3, 6, 9, 12]]],
146
+ group_by_to_a(1..12) {|i| i % 3})
147
+ end
148
+
149
+ def test_subsequence
150
+ assert(subsequence?([1, 2, 3], [1, 2, 3]))
151
+ assert(subsequence?([1, 2, 3], [1, :a, 2, :b, 3]))
152
+ assert(subsequence?([1, 2, 3], [:a, 1, :b, :c, 2, :d, 3, :e, :f]))
153
+
154
+ assert(!subsequence?([1, 2, 3], [1, 2]))
155
+ assert(!subsequence?([1, 2, 3], [1, 3, 2]))
156
+ assert(!subsequence?([1, 2, 3], [3, 2, 1]))
157
+ end
158
+
159
+ def test_silence_warnings
160
+ old_stderr, $stderr = $stderr, StringIO.new
161
+ warn "Out"
162
+ assert_equal("Out\n", $stderr.string)
163
+ silence_warnings {warn "In"}
164
+ assert_equal("Out\n", $stderr.string)
165
+ ensure
166
+ $stderr = old_stderr
167
+ end
168
+
169
+ def test_sass_warn
170
+ assert_warning("Foo!") {sass_warn "Foo!"}
171
+ end
172
+
173
+ def test_silence_sass_warnings
174
+ old_stderr, $stderr = $stderr, StringIO.new
175
+ silence_sass_warnings {warn "Out"}
176
+ assert_equal("Out\n", $stderr.string)
177
+ silence_sass_warnings {sass_warn "In"}
178
+ assert_equal("Out\n", $stderr.string)
179
+ ensure
180
+ $stderr = old_stderr
181
+ end
182
+
183
+ def test_has
184
+ assert(has?(:instance_method, String, :chomp!))
185
+ assert(has?(:private_instance_method, Sass::Engine, :parse_interp))
186
+ end
187
+
188
+ def test_enum_with_index
189
+ assert_equal(%w[foo0 bar1 baz2],
190
+ enum_with_index(%w[foo bar baz]).map {|s, i| "#{s}#{i}"})
191
+ end
192
+
193
+ def test_enum_cons
194
+ assert_equal(%w[foobar barbaz],
195
+ enum_cons(%w[foo bar baz], 2).map {|s1, s2| "#{s1}#{s2}"})
196
+ end
197
+
198
+ def test_extract
199
+ arr = [1, 2, 3, 4, 5]
200
+ assert_equal([1, 3, 5], extract!(arr) {|e| e % 2 == 1})
201
+ assert_equal([2, 4], arr)
202
+ end
203
+
204
+ def test_ord
205
+ assert_equal(102, ord("f"))
206
+ assert_equal(98, ord("bar"))
207
+ end
208
+
209
+ def test_flatten
210
+ assert_equal([1, 2, 3], flatten([1, 2, 3], 0))
211
+ assert_equal([1, 2, 3], flatten([1, 2, 3], 1))
212
+ assert_equal([1, 2, 3], flatten([1, 2, 3], 2))
213
+
214
+ assert_equal([[1, 2], 3], flatten([[1, 2], 3], 0))
215
+ assert_equal([1, 2, 3], flatten([[1, 2], 3], 1))
216
+ assert_equal([1, 2, 3], flatten([[1, 2], 3], 2))
217
+
218
+ assert_equal([[[1], 2], [3], 4], flatten([[[1], 2], [3], 4], 0))
219
+ assert_equal([[1], 2, 3, 4], flatten([[[1], 2], [3], 4], 1))
220
+ assert_equal([1, 2, 3, 4], flatten([[[1], 2], [3], 4], 2))
221
+ end
222
+
223
+ def test_flatten_vertically
224
+ assert_equal([1, 2, 3], flatten_vertically([1, 2, 3]))
225
+ assert_equal([1, 3, 5, 2, 4, 6], flatten_vertically([[1, 2], [3, 4], [5, 6]]))
226
+ assert_equal([1, 2, 4, 3, 5, 6], flatten_vertically([1, [2, 3], [4, 5, 6]]))
227
+ assert_equal([1, 4, 6, 2, 5, 3], flatten_vertically([[1, 2, 3], [4, 5], 6]))
228
+ end
229
+
230
+ def test_set_hash
231
+ assert(set_hash(Set[1, 2, 3]) == set_hash(Set[3, 2, 1]))
232
+ assert(set_hash(Set[1, 2, 3]) == set_hash(Set[1, 2, 3]))
233
+
234
+ s1 = Set[]
235
+ s1 << 1
236
+ s1 << 2
237
+ s1 << 3
238
+ s2 = Set[]
239
+ s2 << 3
240
+ s2 << 2
241
+ s2 << 1
242
+ assert(set_hash(s1) == set_hash(s2))
243
+ end
244
+
245
+ def test_set_eql
246
+ assert(set_eql?(Set[1, 2, 3], Set[3, 2, 1]))
247
+ assert(set_eql?(Set[1, 2, 3], Set[1, 2, 3]))
248
+
249
+ s1 = Set[]
250
+ s1 << 1
251
+ s1 << 2
252
+ s1 << 3
253
+ s2 = Set[]
254
+ s2 << 3
255
+ s2 << 2
256
+ s2 << 1
257
+ assert(set_eql?(s1, s2))
258
+ end
259
+
260
+ def test_extract_and_inject_values
261
+ test = lambda {|arr| assert_equal(arr, with_extracted_values(arr) {|str| str})}
262
+
263
+ test[['foo bar']]
264
+ test[['foo {12} bar']]
265
+ test[['foo {{12} bar']]
266
+ test[['foo {{1', 12, '2} bar']]
267
+ test[['foo 1', 2, '{3', 4, 5, 6, '{7}', 8]]
268
+ test[['foo 1', [2, 3, 4], ' bar']]
269
+ test[['foo ', 1, "\n bar\n", [2, 3, 4], "\n baz"]]
270
+ end
271
+
272
+ def nested_caller_info_fn
273
+ caller_info
274
+ end
275
+
276
+ def double_nested_caller_info_fn
277
+ nested_caller_info_fn
278
+ end
279
+
280
+ def test_caller_info
281
+ assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle'"))
282
+ assert_equal(["/tmp/foo.rb", 12, nil], caller_info("/tmp/foo.rb:12"))
283
+ assert_equal(["(sass)", 12, "blah"], caller_info("(sass):12: in `blah'"))
284
+ assert_equal(["", 12, "boop"], caller_info(":12: in `boop'"))
285
+ assert_equal(["/tmp/foo.rb", -12, "fizzle"], caller_info("/tmp/foo.rb:-12: in `fizzle'"))
286
+ assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle {}'"))
287
+
288
+ info = nested_caller_info_fn
289
+ assert_equal(__FILE__, info[0])
290
+ assert_equal("test_caller_info", info[2])
291
+
292
+ info = proc {nested_caller_info_fn}.call
293
+ assert_equal(__FILE__, info[0])
294
+ assert_match(/^(block in )?test_caller_info$/, info[2])
295
+
296
+ info = double_nested_caller_info_fn
297
+ assert_equal(__FILE__, info[0])
298
+ assert_equal("double_nested_caller_info_fn", info[2])
299
+
300
+ info = proc {double_nested_caller_info_fn}.call
301
+ assert_equal(__FILE__, info[0])
302
+ assert_equal("double_nested_caller_info_fn", info[2])
303
+ end
304
+
305
+ def test_version_gt
306
+ assert_version_gt("2.0.0", "1.0.0")
307
+ assert_version_gt("1.1.0", "1.0.0")
308
+ assert_version_gt("1.0.1", "1.0.0")
309
+ assert_version_gt("1.0.0", "1.0.0.rc")
310
+ assert_version_gt("1.0.0.1", "1.0.0.rc")
311
+ assert_version_gt("1.0.0.rc", "0.9.9")
312
+ assert_version_gt("1.0.0.beta", "1.0.0.alpha")
313
+
314
+ assert_version_eq("1.0.0", "1.0.0")
315
+ assert_version_eq("1.0.0", "1.0.0.0")
316
+ end
317
+
318
+ def assert_version_gt(v1, v2)
319
+ #assert(version_gt(v1, v2), "Expected #{v1} > #{v2}")
320
+ assert(!version_gt(v2, v1), "Expected #{v2} < #{v1}")
321
+ end
322
+
323
+ def assert_version_eq(v1, v2)
324
+ assert(!version_gt(v1, v2), "Expected #{v1} = #{v2}")
325
+ assert(!version_gt(v2, v1), "Expected #{v2} = #{v1}")
326
+ end
327
+
328
+ class FooBar
329
+ def foo
330
+ Sass::Util.abstract(self)
331
+ end
332
+ def old_method
333
+ Sass::Util.deprecated(self)
334
+ end
335
+ def old_method_with_custom_message
336
+ Sass::Util.deprecated(self, "Call FooBar#new_method instead.")
337
+ end
338
+ def self.another_old_method
339
+ Sass::Util.deprecated(self)
340
+ end
341
+ end
342
+
343
+ def test_abstract
344
+ assert_raise_message(NotImplementedError,
345
+ "UtilTest::FooBar must implement #foo") {FooBar.new.foo}
346
+ end
347
+
348
+ def test_deprecated
349
+ assert_warning("DEPRECATION WARNING: UtilTest::FooBar#old_method will be removed in a future version of Sass.") { FooBar.new.old_method }
350
+ assert_warning(<<WARNING) { FooBar.new.old_method_with_custom_message }
351
+ DEPRECATION WARNING: UtilTest::FooBar#old_method_with_custom_message will be removed in a future version of Sass.
352
+ Call FooBar#new_method instead.
353
+ WARNING
354
+ assert_warning("DEPRECATION WARNING: UtilTest::FooBar.another_old_method will be removed in a future version of Sass.") { FooBar.another_old_method }
355
+ end
356
+
357
+ def test_json_escape_string
358
+ assert_json_string "", ""
359
+ alphanum = (("0".."9").to_a).concat(("a".."z").to_a).concat(("A".."Z").to_a).join
360
+ assert_json_string alphanum, alphanum
361
+ assert_json_string "'\"\\'", "'\\\"\\\\'"
362
+ assert_json_string "\b\f\n\r\t", "\\b\\f\\n\\r\\t"
363
+ end
364
+
365
+ def assert_json_string(source, target)
366
+ assert_equal target, json_escape_string(source)
367
+ end
368
+
369
+ def test_json_value_of
370
+ assert_json_value 0, "0"
371
+ assert_json_value(-42, "-42")
372
+ assert_json_value 42, "42"
373
+ assert_json_value true, "true"
374
+ assert_json_value false, "false"
375
+ assert_json_value "", "\"\""
376
+ assert_json_value "\"\"", "\"\\\"\\\"\""
377
+ assert_json_value "Multi\nLine\rString", "\"Multi\\nLine\\rString\""
378
+ assert_json_value [1, "some\nstr,ing", false, nil], "[1,\"some\\nstr,ing\",false,null]"
379
+ end
380
+
381
+ def assert_json_value(source, target)
382
+ assert_equal target, json_value_of(source)
383
+ end
384
+
385
+ def test_vlq
386
+ assert_equal "A", encode_vlq(0)
387
+ assert_equal "e", encode_vlq(15)
388
+ assert_equal "gB", encode_vlq(16)
389
+ assert_equal "wH", encode_vlq(120)
390
+ end
391
+
392
+ def assert_vlq_encodes(int, vlq)
393
+ vlq_from_decimal_array = decimal_array.map {|d| encode_vlq(d)}.join
394
+ decimal_array_from_vlq = decode_vlq(vlq)
395
+ assert_equal vlq, vlq_from_decimal_array
396
+ assert_equal decimal_array, decimal_array_from_vlq
397
+ end
398
+
399
+ def test_atomic_writes
400
+ # when using normal writes, this test fails about 90% of the time.
401
+ filename = File.join(Dir.tmpdir, "test_atomic")
402
+ 5.times do
403
+ writes_to_perform = %w(1 2 3 4 5 6 7 8 9).map {|i| "#{i}\n" * 100_000}
404
+ threads = writes_to_perform.map do |to_write|
405
+ Thread.new do
406
+ # To see this test fail with a normal write,
407
+ # change to the standard file open mechanism:
408
+ # open(filename, "w") do |f|
409
+ atomic_create_and_write_file(filename) do |f|
410
+ f.write(to_write)
411
+ end
412
+ end
413
+ end
414
+ loop do
415
+ contents = File.exist?(filename) ? File.read(filename) : nil
416
+ next if contents.nil? || contents.size == 0
417
+ unless writes_to_perform.include?(contents)
418
+ if contents.size != writes_to_perform.first.size
419
+ fail "Incomplete write detected: was #{contents.size} characters, " +
420
+ "should have been #{writes_to_perform.first.size}"
421
+ else
422
+ fail "Corrupted read/write detected"
423
+ end
424
+ end
425
+ break if threads.all? {|t| !t.alive?}
426
+ end
427
+ threads.each {|t| t.join}
428
+ end
429
+ end
430
+
431
+ def test_atomic_write_permissions
432
+ atomic_filename = File.join(Dir.tmpdir, "test_atomic_perms.atomic")
433
+ normal_filename = File.join(Dir.tmpdir, "test_atomic_perms.normal")
434
+ atomic_create_and_write_file(atomic_filename) {|f| f.write("whatever\n") }
435
+ open(normal_filename, "wb") {|f| f.write("whatever\n") }
436
+ assert_equal File.stat(normal_filename).mode.to_s(8), File.stat(atomic_filename).mode.to_s(8)
437
+ ensure
438
+ File.unlink(atomic_filename) rescue nil
439
+ File.unlink(normal_filename) rescue nil
440
+ end
441
+
442
+ def test_atomic_writes_respect_umask
443
+ atomic_filename = File.join(Dir.tmpdir, "test_atomic_perms.atomic")
444
+ atomic_create_and_write_file(atomic_filename) do |f|
445
+ f.write("whatever\n")
446
+ end
447
+ assert_equal 0, File.stat(atomic_filename).mode & File.umask
448
+ ensure
449
+ File.unlink(atomic_filename)
450
+ end
451
+
452
+ class FakeError < RuntimeError; end
453
+
454
+ def test_atomic_writes_handles_exceptions
455
+ filename = File.join(Dir.tmpdir, "test_atomic_exception")
456
+ FileUtils.rm_f(filename)
457
+ tmp_filename = nil
458
+ assert_raises FakeError do
459
+ atomic_create_and_write_file(filename) do |f|
460
+ tmp_filename = f.path
461
+ raise FakeError.new "Borken"
462
+ end
463
+ end
464
+ assert !File.exist?(filename)
465
+ assert !File.exist?(tmp_filename)
466
+ end
467
+ end