diff --git a/tests/large.rs b/tests/large.rs new file mode 100644 index 0000000..78a9994 --- /dev/null +++ b/tests/large.rs @@ -0,0 +1,242 @@ +//! Large tests that exercise many features at once + +#[macro_use] +mod macros; + +test!( + /// https://github.com/kaj/rsass/issues/41 + issue_41, + "@function str-replace($string, $search, $replace: \"\") { + $index: str-index($string, $search); + + @if $index { + @return str-slice($string, 1, $index - 1)+$replace+str-replace(str-slice($string, $index + str-length($search)), $search, $replace); + } + + @return $index; + } + + $x: str-replace(url(\"a#b#c\"), \"#\", \":\"); + + a { + color: $x; + }", + "a {\n color: url(\"a:b:;\n}\n" +); + +test!( + base64_decode, + r##" +@use "sass:math"; +@use "sass:map"; + +@function char-at($s, $idx) { + @return str-slice($s, $idx, $idx); +} + +@function bitwise-and($a, $b) { + $x: null; + $y: null; + + @if $a > $b { + $x: $a; + $y: $b; + } @else { + $x: $b; + $y: $a; + } + + $limit: math.floor(math.log($x, 2)); + $result: 0; + + @for $n from 0 through $limit { + $two-pow-n: math.pow(2, $n); + $result: $result + + $two-pow-n * + (math.floor(math.div($x, $two-pow-n)) % 2) * + (math.floor(math.div($y, $two-pow-n)) % 2); + } + + @return $result; +} + +@function bitwise-shift-left($n, $amt) { + @return math.floor($n * math.pow(2, $amt)); +} + +@function bitwise-shift-right($n, $amt) { + @return math.floor(math.div($n, math.pow(2, $amt))); +} + +@function bitwise-or($a, $b) { + $x: null; + $y: null; + + @if $a > $b { + $x: $a; + $y: $b; + } @else { + $x: $b; + $y: $a; + } + + $limit: math.floor(math.log($x, 2)); + $result: 0; + + @for $n from 0 through $limit { + $two-pow-n: math.pow(2, $n); + $x-div-two-pow-n: math.floor(math.div($x, $two-pow-n)) % 2; + $y-div-two-pow-n: math.floor(math.div($y, $two-pow-n)) % 2; + + $result: $result + + $two-pow-n * + ( + ( + ($x-div-two-pow-n + $y-div-two-pow-n) + + $x-div-two-pow-n * + $y-div-two-pow-n + ) + % + 2 + ); + } + + @return $result; +} + +@function letter-index-map() { + $map: (); + + $chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + + @for $i from 1 through str-length($chars) { + $char: char-at($chars, $i); + + $map: map.set($map, $char, $i - 1); + $map: map.set($map, $i - 1, $char); + } + + @return $map; +} + +@function ascii-map() { + $map: (); + + $chars-upper: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + @for $i from 1 through str-length($chars-upper) { + $char: char-at($chars-upper, $i); + + $map: map.set($map, $char, $i - 1 + 65); + $map: map.set($map, $i - 1 + 65, $char); + } + + $chars-lower: "abcdefghijklmnopqrstuvwxyz"; + + @for $i from 1 through str-length($chars-lower) { + $char: char-at($chars-lower, $i); + + $map: map.set($map, $char, $i - 1 + 97); + $map: map.set($map, $i - 1 + 97, $char); + } + + @return $map; +} + +$letter-index-map: letter-index-map(); +$ascii-map: ascii-map(); + +@function byte-at($str, $idx) { + @return map-get($letter-index-map, char-at($str, $idx)); +} + +@function chunk-string($str) { + $chunks: []; + + @for $i from 1 through str-length($str) { + @if ($i - 1) % 4 == 0 { + $chunk: byte-at($str, $i) + byte-at($str, $i + 1) + byte-at($str, $i + 2) + byte-at($str, $i + 3); + + $chunks: append($chunks, $chunk); + } + } + + @return $chunks; +} + +@function decode-base64($str) { + $result: ""; + + @if str-length($str) % 4 != 0 { + @error "Invalid base64 string length"; + } + + $chunks: chunk-string($str); + + @each $chunk in $chunks { + $start: bitwise-or( + bitwise-shift-left(nth($chunk, 1), 18), + bitwise-shift-left(nth($chunk, 2), 12) + ); + + @if bitwise-and(nth($chunk, 3), nth($chunk, 4)) == 64 { + $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 16), 255))}"; + } @else if nth($chunk, 4) == 64 { + $start: bitwise-or($start, bitwise-shift-left(nth($chunk, 3), 6)); + + $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 16), 255))}"; + $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 8), 255))}"; + } @else { + $val: bitwise-or(bitwise-shift-left(nth($chunk, 3), 6), nth($chunk, 4)); + $start: bitwise-or($start, $val); + + $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 16), 255))}"; + $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 8), 255))}"; + $result: "#{$result}#{map-get($ascii-map, bitwise-and(bitwise-shift-right($start, 0), 255))}"; + } + } + + @return $result; +} + +a { + color: decode-base64("SGVsbG8="); +} + "##, + "a {\n color: \"Hello\";\n}\n" +); + +test!( + two_sum, + r#" +@use "sass:map"; + +@function two-sum($nums, $target) { + $map: (); + + @for $i from 1 through length($nums) { + $num: nth($nums, $i); + + $diff: $target - $num; + + @if map-get($map, $diff) { + @return map-get($map, $diff) - 1 $i - 1; + } @else { + $map: map.set($map, $num, $i); + } + } + + @return null; +} + +a { + color: two-sum(2 7 11 15, 9); + color: two-sum(3 2 4, 6); + color: two-sum(3 3, 6); + color: two-sum(3 2, 6); +}"#, + "a {\n color: 0 1;\n color: 1 2;\n color: 0 1;\n}\n" +); diff --git a/tests/rsass_issues.rs b/tests/rsass_issues.rs deleted file mode 100644 index 8d8ce3c..0000000 --- a/tests/rsass_issues.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Test cases adapted verbatim from the rsass issue tracker -//! https://github.com/kaj/rsass/issues?q=is%3Aissue - -#[macro_use] -mod macros; - -test!( - /// https://github.com/kaj/rsass/issues/41 - issue_41, - "@function str-replace($string, $search, $replace: \"\") { - $index: str-index($string, $search); - - @if $index { - @return str-slice($string, 1, $index - 1)+$replace+str-replace(str-slice($string, $index + str-length($search)), $search, $replace); - } - - @return $index; - } - - $x: str-replace(url(\"a#b#c\"), \"#\", \":\"); - - a { - color: $x; - }", - "a {\n color: url(\"a:b:;\n}\n" -);