From 48ee47d88a51b3a0cdf0edcfcd683b5f01222ffd Mon Sep 17 00:00:00 2001 From: Mike Welsh Date: Wed, 11 Nov 2020 02:32:23 -0800 Subject: [PATCH] tests: Add test for AVM2 Math Also allow specifying relative epsilon for swf_tests_approx. --- core/tests/regression_tests.rs | 46 ++- core/tests/swfs/avm2/math/Test.as | 94 +++++ core/tests/swfs/avm2/math/output.txt | 498 +++++++++++++++++++++++++++ core/tests/swfs/avm2/math/test.fla | Bin 0 -> 4570 bytes core/tests/swfs/avm2/math/test.swf | Bin 0 -> 1859 bytes 5 files changed, 621 insertions(+), 17 deletions(-) create mode 100644 core/tests/swfs/avm2/math/Test.as create mode 100644 core/tests/swfs/avm2/math/output.txt create mode 100644 core/tests/swfs/avm2/math/test.fla create mode 100644 core/tests/swfs/avm2/math/test.swf diff --git a/core/tests/regression_tests.rs b/core/tests/regression_tests.rs index 3c5288de3..9880b8fb1 100644 --- a/core/tests/regression_tests.rs +++ b/core/tests/regression_tests.rs @@ -2,7 +2,7 @@ //! //! Trace output can be compared with correct output from the official Flash Payer. -use approx::assert_abs_diff_eq; +use approx::assert_relative_eq; use ruffle_core::backend::locale::NullLocaleBackend; use ruffle_core::backend::log::LogBackend; use ruffle_core::backend::navigator::{NullExecutor, NullNavigatorBackend}; @@ -45,7 +45,7 @@ macro_rules! swf_tests { // This macro generates test cases for a given list of SWFs using `test_swf_approx`. macro_rules! swf_tests_approx { - ($($(#[$attr:meta])* ($name:ident, $path:expr, $num_frames:literal, $epsilon:literal),)*) => { + ($($(#[$attr:meta])* ($name:ident, $path:expr, $num_frames:literal $(, $opt:ident = $val:expr)*),)*) => { $( #[test] $(#[$attr])* @@ -54,7 +54,8 @@ macro_rules! swf_tests_approx { concat!("tests/swfs/", $path, "/test.swf"), $num_frames, concat!("tests/swfs/", $path, "/output.txt"), - $epsilon, + |actual, expected| assert_relative_eq!(actual, expected $(, $opt = $val)*), + //$relative_epsilon, |_| Ok(()), |_| Ok(()), ) @@ -414,18 +415,19 @@ swf_tests! { // Eventually we can hopefully make some of these match exactly (see #193). // Some will probably always need to be approx. (if they rely on trig functions, etc.) swf_tests_approx! { - (local_to_global, "avm1/local_to_global", 1, 0.051), - (stage_object_properties, "avm1/stage_object_properties", 5, 0.051), - (stage_object_properties_swf6, "avm1/stage_object_properties_swf6", 4, 0.051), - (movieclip_getbounds, "avm1/movieclip_getbounds", 1, 0.051), - (edittext_letter_spacing, "avm1/edittext_letter_spacing", 1, 15.0), // TODO: Discrepancy in wrapping in letterSpacing = 0.1 test. - (edittext_align, "avm1/edittext_align", 1, 3.0), - (edittext_margins, "avm1/edittext_margins", 1, 5.0), // TODO: Discrepancy in wrapping. - (edittext_tab_stops, "avm1/edittext_tab_stops", 1, 5.0), - (edittext_bullet, "avm1/edittext_bullet", 1, 3.0), - (edittext_underline, "avm1/edittext_underline", 1, 4.0), - (as3_coerce_string_precision, "avm2/coerce_string_precision", 1, 10_000_000.0), - (as3_divide, "avm2/divide", 1, 0.0), // TODO: Discrepancy in float formatting. + (local_to_global, "avm1/local_to_global", 1, epsilon = 0.051), + (stage_object_properties, "avm1/stage_object_properties", 5, epsilon = 0.051), + (stage_object_properties_swf6, "avm1/stage_object_properties_swf6", 4, epsilon = 0.051), + (movieclip_getbounds, "avm1/movieclip_getbounds", 1, epsilon = 0.051), + (edittext_letter_spacing, "avm1/edittext_letter_spacing", 1, epsilon = 15.0), // TODO: Discrepancy in wrapping in letterSpacing = 0.1 test. + (edittext_align, "avm1/edittext_align", 1, epsilon = 3.0), + (edittext_margins, "avm1/edittext_margins", 1, epsilon = 5.0), // TODO: Discrepancy in wrapping. + (edittext_tab_stops, "avm1/edittext_tab_stops", 1, epsilon = 5.0), + (edittext_bullet, "avm1/edittext_bullet", 1, epsilon = 3.0), + (edittext_underline, "avm1/edittext_underline", 1, epsilon = 4.0), + (as3_coerce_string_precision, "avm2/coerce_string_precision", 1, max_relative = 30.0 * std::f64::EPSILON), + (as3_divide, "avm2/divide", 1, epsilon = 0.0), // TODO: Discrepancy in float formatting. + (as3_math, "avm2/math", 1, max_relative = 30.0 * std::f64::EPSILON), } #[test] @@ -558,7 +560,7 @@ fn test_swf_approx( swf_path: &str, num_frames: u32, expected_output_path: &str, - epsilon: f64, + approx_assert_fn: impl Fn(f64, f64), before_start: impl FnOnce(Arc>) -> Result<(), Error>, before_end: impl FnOnce(Arc>) -> Result<(), Error>, ) -> Result<(), Error> { @@ -585,7 +587,17 @@ fn test_swf_approx( } // TODO: Lower this epsilon as the accuracy of the properties improves. - assert_abs_diff_eq!(actual, expected, epsilon = epsilon); + // if let Some(relative_epsilon) = relative_epsilon { + // assert_relative_eq!( + // actual, + // expected, + // epsilon = absolute_epsilon, + // max_relative = relative_epsilon + // ); + // } else { + // assert_abs_diff_eq!(actual, expected, epsilon = absolute_epsilon); + // } + approx_assert_fn(actual, expected); } else { assert_eq!(actual, expected); } diff --git a/core/tests/swfs/avm2/math/Test.as b/core/tests/swfs/avm2/math/Test.as new file mode 100644 index 000000000..ea3632db6 --- /dev/null +++ b/core/tests/swfs/avm2/math/Test.as @@ -0,0 +1,94 @@ +package { + public class Test {} +} + +// Constants +trace("Math.E =", Math.E); +trace("Math.LN10 =", Math.LN10); +trace("Math.LN2 =", Math.LN2); +trace("Math.LOG10E =", Math.LOG10E); +trace("Math.LOG2E =", Math.LOG2E); +trace("Math.PI =", Math.PI); +trace("Math.SQRT1_2 =", Math.SQRT1_2); +trace("Math.SQRT2 =", Math.SQRT2); +trace(); + +var obj = {valueOf: function():Number { return 10.1; }}; + +function runTest(name, func, val) { + trace(name + "(" + val + ") ="); + trace(func(val)); +} + +function test(name, func) { + runTest(name, func, 0); + runTest(name, func, 1); + runTest(name, func, -1); + runTest(name, func, 1234.5); + runTest(name, func, -1234.5); + runTest(name, func, Infinity); + runTest(name, func, -Infinity); + runTest(name, func, NaN); + runTest(name, func, true); + runTest(name, func, false); + runTest(name, func, undefined); + runTest(name, func, null); + runTest(name, func, "55.5"); + runTest(name, func, obj); + trace(); +} + +function runTest2(name, func, val1, val2) { + trace(name + "(" + val1 + ", " + val2 + ") ="); + trace(func(val1, val2)); +} + +function test2(name, func) { + runTest2(name, func, 0, 0); + runTest2(name, func, 1, 2); + runTest2(name, func, 2, -4); + runTest2(name, func, 4, -2); + runTest2(name, func, -99, -100); + runTest2(name, func, Infinity, -Infinity); + runTest2(name, func, NaN, 100); + runTest2(name, func, 999, NaN); + runTest2(name, func, true, false); + runTest2(name, func, undefined, null); + runTest2(name, func, "55.5", "-1234"); + runTest2(name, func, obj, obj); + trace(); +} + +test("Math.abs", Math.abs); +test("Math.acos", Math.acos); +test("Math.asin", Math.asin); +test("Math.atan", Math.atan); +test2("Math.atan2", Math.atan2); +test("Math.ceil", Math.ceil); +test("Math.cos", Math.cos); +test("Math.exp", Math.exp); +test("Math.floor", Math.floor); +test("Math.log", Math.log); +test2("Math.max", Math.max); +test2("Math.min", Math.min); +test2("Math.pow", Math.pow); +test("Math.round", Math.round); +test("Math.sin", Math.sin); +test("Math.sqrt", Math.sqrt); +test("Math.tan", Math.tan); + +// Test varargs in min/max +trace("Math.min() =", Math.min()); +trace("Math.min(0) =", Math.min(0)); +trace("Math.min(1, 2, 3) =", Math.min(1, 2, 3)); +trace("Math.min(-1.1, -2.2, -3.3) =", Math.min(-1.1, -2.2, -3.3)); +trace("Math.min(9, NaN, false, true, Infinity, undefined) =", Math.min(9, NaN, false, true, Infinity, undefined)); +trace(); + +trace("Math.max() =", Math.max()); +trace("Math.max(0) =", Math.max(0)); +trace("Math.max(1, 2, 3) =", Math.max(1, 2, 3)); +trace("Math.max(-1.1, -2.2, -3.3) =", Math.max(-1.1, -2.2, -3.3)); +trace("Math.max(9, NaN, false, true, Infinity, undefined) =", Math.max(9, NaN, false, true, Infinity, undefined)); +trace(); + diff --git a/core/tests/swfs/avm2/math/output.txt b/core/tests/swfs/avm2/math/output.txt new file mode 100644 index 000000000..f905503e6 --- /dev/null +++ b/core/tests/swfs/avm2/math/output.txt @@ -0,0 +1,498 @@ +Math.E = 2.718281828459045 +Math.LN10 = 2.302585092994046 +Math.LN2 = 0.6931471805599453 +Math.LOG10E = 0.4342944819032518 +Math.LOG2E = 1.4426950408889634 +Math.PI = 3.141592653589793 +Math.SQRT1_2 = 0.7071067811865476 +Math.SQRT2 = 1.4142135623730951 + +Math.abs(0) = +0 +Math.abs(1) = +1 +Math.abs(-1) = +1 +Math.abs(1234.5) = +1234.5 +Math.abs(-1234.5) = +1234.5 +Math.abs(Infinity) = +Infinity +Math.abs(-Infinity) = +Infinity +Math.abs(NaN) = +NaN +Math.abs(true) = +1 +Math.abs(false) = +0 +Math.abs(undefined) = +NaN +Math.abs(null) = +0 +Math.abs(55.5) = +55.5 +Math.abs([object Object]) = +10.1 + +Math.acos(0) = +1.5707963267948966 +Math.acos(1) = +0 +Math.acos(-1) = +3.141592653589793 +Math.acos(1234.5) = +NaN +Math.acos(-1234.5) = +NaN +Math.acos(Infinity) = +NaN +Math.acos(-Infinity) = +NaN +Math.acos(NaN) = +NaN +Math.acos(true) = +0 +Math.acos(false) = +1.5707963267948966 +Math.acos(undefined) = +NaN +Math.acos(null) = +1.5707963267948966 +Math.acos(55.5) = +NaN +Math.acos([object Object]) = +NaN + +Math.asin(0) = +0 +Math.asin(1) = +1.5707963267948966 +Math.asin(-1) = +-1.5707963267948966 +Math.asin(1234.5) = +NaN +Math.asin(-1234.5) = +NaN +Math.asin(Infinity) = +NaN +Math.asin(-Infinity) = +NaN +Math.asin(NaN) = +NaN +Math.asin(true) = +1.5707963267948966 +Math.asin(false) = +0 +Math.asin(undefined) = +NaN +Math.asin(null) = +0 +Math.asin(55.5) = +NaN +Math.asin([object Object]) = +NaN + +Math.atan(0) = +0 +Math.atan(1) = +0.7853981633974483 +Math.atan(-1) = +-0.7853981633974483 +Math.atan(1234.5) = +1.5699862824196225 +Math.atan(-1234.5) = +-1.5699862824196225 +Math.atan(Infinity) = +1.5707963267948966 +Math.atan(-Infinity) = +-1.5707963267948966 +Math.atan(NaN) = +NaN +Math.atan(true) = +0.7853981633974483 +Math.atan(false) = +0 +Math.atan(undefined) = +NaN +Math.atan(null) = +0 +Math.atan(55.5) = +1.5527802582408412 +Math.atan([object Object]) = +1.47210806614649 + +Math.atan2(0, 0) = +0 +Math.atan2(1, 2) = +0.4636476090008061 +Math.atan2(2, -4) = +2.677945044588987 +Math.atan2(4, -2) = +2.0344439357957027 +Math.atan2(-99, -100) = +-2.361219573523157 +Math.atan2(Infinity, -Infinity) = +2.356194490192345 +Math.atan2(NaN, 100) = +NaN +Math.atan2(999, NaN) = +NaN +Math.atan2(true, false) = +1.5707963267948966 +Math.atan2(undefined, null) = +NaN +Math.atan2(55.5, -1234) = +3.096647253816438 +Math.atan2([object Object], [object Object]) = +0.7853981633974483 + +Math.ceil(0) = +0 +Math.ceil(1) = +1 +Math.ceil(-1) = +-1 +Math.ceil(1234.5) = +1235 +Math.ceil(-1234.5) = +-1234 +Math.ceil(Infinity) = +Infinity +Math.ceil(-Infinity) = +-Infinity +Math.ceil(NaN) = +NaN +Math.ceil(true) = +1 +Math.ceil(false) = +0 +Math.ceil(undefined) = +NaN +Math.ceil(null) = +0 +Math.ceil(55.5) = +56 +Math.ceil([object Object]) = +11 + +Math.cos(0) = +1 +Math.cos(1) = +0.5403023058681398 +Math.cos(-1) = +0.5403023058681398 +Math.cos(1234.5) = +-0.989373592132422 +Math.cos(-1234.5) = +-0.989373592132422 +Math.cos(Infinity) = +NaN +Math.cos(-Infinity) = +NaN +Math.cos(NaN) = +NaN +Math.cos(true) = +0.5403023058681398 +Math.cos(false) = +1 +Math.cos(undefined) = +NaN +Math.cos(null) = +1 +Math.cos(55.5) = +0.49872621790648564 +Math.cos([object Object]) = +-0.7805681801691837 + +Math.exp(0) = +1 +Math.exp(1) = +2.718281828459045 +Math.exp(-1) = +0.36787944117144233 +Math.exp(1234.5) = +Infinity +Math.exp(-1234.5) = +0 +Math.exp(Infinity) = +Infinity +Math.exp(-Infinity) = +0 +Math.exp(NaN) = +NaN +Math.exp(true) = +2.718281828459045 +Math.exp(false) = +1 +Math.exp(undefined) = +NaN +Math.exp(null) = +1 +Math.exp(55.5) = +1.26865561401095e+24 +Math.exp([object Object]) = +24343.00942440837 + +Math.floor(0) = +0 +Math.floor(1) = +1 +Math.floor(-1) = +-1 +Math.floor(1234.5) = +1234 +Math.floor(-1234.5) = +-1235 +Math.floor(Infinity) = +Infinity +Math.floor(-Infinity) = +-Infinity +Math.floor(NaN) = +NaN +Math.floor(true) = +1 +Math.floor(false) = +0 +Math.floor(undefined) = +NaN +Math.floor(null) = +0 +Math.floor(55.5) = +55 +Math.floor([object Object]) = +10 + +Math.log(0) = +-Infinity +Math.log(1) = +0 +Math.log(-1) = +NaN +Math.log(1234.5) = +7.118421308785234 +Math.log(-1234.5) = +NaN +Math.log(Infinity) = +Infinity +Math.log(-Infinity) = +NaN +Math.log(NaN) = +NaN +Math.log(true) = +0 +Math.log(false) = +-Infinity +Math.log(undefined) = +NaN +Math.log(null) = +-Infinity +Math.log(55.5) = +4.0163830207523885 +Math.log([object Object]) = +2.312535423847214 + +Math.max(0, 0) = +0 +Math.max(1, 2) = +2 +Math.max(2, -4) = +2 +Math.max(4, -2) = +4 +Math.max(-99, -100) = +-99 +Math.max(Infinity, -Infinity) = +Infinity +Math.max(NaN, 100) = +NaN +Math.max(999, NaN) = +NaN +Math.max(true, false) = +1 +Math.max(undefined, null) = +NaN +Math.max(55.5, -1234) = +55.5 +Math.max([object Object], [object Object]) = +10.1 + +Math.min(0, 0) = +0 +Math.min(1, 2) = +1 +Math.min(2, -4) = +-4 +Math.min(4, -2) = +-2 +Math.min(-99, -100) = +-100 +Math.min(Infinity, -Infinity) = +-Infinity +Math.min(NaN, 100) = +NaN +Math.min(999, NaN) = +NaN +Math.min(true, false) = +0 +Math.min(undefined, null) = +NaN +Math.min(55.5, -1234) = +-1234 +Math.min([object Object], [object Object]) = +10.1 + +Math.pow(0, 0) = +1 +Math.pow(1, 2) = +1 +Math.pow(2, -4) = +0.0625 +Math.pow(4, -2) = +0.0625 +Math.pow(-99, -100) = +2.73199902642903e-200 +Math.pow(Infinity, -Infinity) = +0 +Math.pow(NaN, 100) = +NaN +Math.pow(999, NaN) = +NaN +Math.pow(true, false) = +1 +Math.pow(undefined, null) = +1 +Math.pow(55.5, -1234) = +0 +Math.pow([object Object], [object Object]) = +13920212824.565006 + +Math.round(0) = +0 +Math.round(1) = +1 +Math.round(-1) = +-1 +Math.round(1234.5) = +1235 +Math.round(-1234.5) = +-1234 +Math.round(Infinity) = +Infinity +Math.round(-Infinity) = +-Infinity +Math.round(NaN) = +NaN +Math.round(true) = +1 +Math.round(false) = +0 +Math.round(undefined) = +NaN +Math.round(null) = +0 +Math.round(55.5) = +56 +Math.round([object Object]) = +10 + +Math.sin(0) = +0 +Math.sin(1) = +0.8414709848078965 +Math.sin(-1) = +-0.8414709848078965 +Math.sin(1234.5) = +0.14539565052293643 +Math.sin(-1234.5) = +-0.14539565052293643 +Math.sin(Infinity) = +NaN +Math.sin(-Infinity) = +NaN +Math.sin(NaN) = +NaN +Math.sin(true) = +0.8414709848078965 +Math.sin(false) = +0 +Math.sin(undefined) = +NaN +Math.sin(null) = +0 +Math.sin(55.5) = +-0.8667595742607592 +Math.sin([object Object]) = +-0.6250706488928821 + +Math.sqrt(0) = +0 +Math.sqrt(1) = +1 +Math.sqrt(-1) = +NaN +Math.sqrt(1234.5) = +35.13545218152173 +Math.sqrt(-1234.5) = +NaN +Math.sqrt(Infinity) = +Infinity +Math.sqrt(-Infinity) = +NaN +Math.sqrt(NaN) = +NaN +Math.sqrt(true) = +1 +Math.sqrt(false) = +0 +Math.sqrt(undefined) = +NaN +Math.sqrt(null) = +0 +Math.sqrt(55.5) = +7.44983221287567 +Math.sqrt([object Object]) = +3.1780497164141406 + +Math.tan(0) = +0 +Math.tan(1) = +1.5574077246549023 +Math.tan(-1) = +-1.5574077246549023 +Math.tan(1234.5) = +-0.14695727850342305 +Math.tan(-1234.5) = +0.14695727850342305 +Math.tan(Infinity) = +NaN +Math.tan(-Infinity) = +NaN +Math.tan(NaN) = +NaN +Math.tan(true) = +1.5574077246549023 +Math.tan(false) = +0 +Math.tan(undefined) = +NaN +Math.tan(null) = +0 +Math.tan(55.5) = +-1.7379466792405172 +Math.tan([object Object]) = +0.8007893029375109 + +Math.min() = Infinity +Math.min(0) = 0 +Math.min(1, 2, 3) = 1 +Math.min(-1.1, -2.2, -3.3) = -3.3 +Math.min(9, NaN, false, true, Infinity, undefined) = NaN + +Math.max() = -Infinity +Math.max(0) = 0 +Math.max(1, 2, 3) = 3 +Math.max(-1.1, -2.2, -3.3) = -1.1 +Math.max(9, NaN, false, true, Infinity, undefined) = NaN + diff --git a/core/tests/swfs/avm2/math/test.fla b/core/tests/swfs/avm2/math/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..c75e11565b07ce8cccc85a4364ce5fef02b4646d GIT binary patch literal 4570 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 literal 0 HcmV?d00001 diff --git a/core/tests/swfs/avm2/math/test.swf b/core/tests/swfs/avm2/math/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..7fe2e9db76f9dbf6eb3f91ffd447dcc9a03b3481 GIT binary patch literal 1859 zcmV-J2fX-0S5ps#4gdgnoTZjqbKAxh$9Hkz5+o(jkxa{uoxn0J*%C-xNV*~`DY}q! zLbDiEFU=x^{x+TF5n6FN-O66IE}jhfmRkX9b*|@m!-^~) zA0OwB3whglBCF+cSynVz({eB(=bl=gev-4?TXSn-pinj3wqp)G)3!w4)(`EGw>mc$ z%AO2{V_D11>mB>h$hYl*e4-C!HLu9N4h*VnIfm}p&Vg7rEt?=pW>{PZb*VC=Gv0YsQN8U6$mHKjhqrS0KsB2oGwyCO{ z^^#I677FE3T`O0MwP2#JrbcR2yFD5hmKUmZeumnG)JU!2m`_aDA8%3J(28YEE0s1> zs#?}Ix61WRWlOCsmugxyQhkfWxK_h4kBm;;u?N9Z80wB|_$#$K7cG^)Ou_nA%r}=w zE2*{3Voj|p@0!>fsgYXemrUr5)JV<#f0pT;65{y5yj-VWyrnzs@eUo1oPKZwb=tDg zH~fEdVVA1GiP33Sy0$aWy)}I}?3-=f7nDzOZqIK2FX;NjM-e+HV_{A*u*HotY7Q2V7~Cho1O|9{giHygw@hS9blM-}u-6p3*yh z)(x)2v&Sg5I~p7s4tHRnIre%7k?5@5m zjI53UrqSU_rF@Cc!GkaIo};%7e20-l_O7@Z-_gBZz9z16KHyq1us_>X6>#~tMCj1O zRTlaQYBuhx3M9oSq#~yVK0de$f$QP6xXL`-o(zor&-V`0$Dl((N{!v%K!;)V88DNZ*PjeDaMh1DooY< zTNU0K-D~#@XQE19Ao{9Z+O|9c_O%Cx6ZK?XiEr8PNdy1l#P)}d=@~)>&$1alLuQ35 zJdZNJXEDa)R|GQzvjlU5jS((RVhKW$gro?bAY_t|DMHc&Un2Mef~N`22rL#-j4;Uv zQ;d*?+z$!9PVh$riv-URoF#ak;5!5_3Q36O2$l&}2`&&^A{hRzOz^J>UM2Vwf;R}> zBDhBIeS)_M{tdx91V1A2KM?MZg!>cWnuPmviV2P+4$+HRY-nNh{)=H)fk83E@o^p{ za10}XM{&fE7{i5!UOa{bl<>Qx-=zY=9EWiV@vumL$IayPZ?kBzk>moxStddz`+bC5 z_J;`no&8sct%=se*AY)H5BrW1&x{*frVY)nz@y%xX zxpd|1yEAF_?2tQ?uAVj0xS9U8^W7o0!2rWRhJ(t#!p*o}c_YpSfFpPjf*g5dCWO|+ z7`~2ZGKBf?z7PebLJ-5dG!sRL4`I!$zm!+UHNUKO1Jha|j4>;-pCSaaV>$L*0dEXr zj*p!y=i9yr5g5$=0FmaU7OS+_N9ab6X@0QI_TtUyb*7hS&aC5JvUzzO^-|5Wbgh-? zUTLHmz#D+G6h8*MO7SM(HHxz#A0r0)7-A%&7UXw6xBBfpyYMND@TE zMuGv%1Ky;l0M1d=0B`x2l8S)YM#}fz1H4TKECbF{tN<=hTmig8aSiY;RaggH^c7Ol zCg2jqDxgGl>wr0$_9AOOlSTC0rY&)hs&i#u_RE{v-oQ3+IY~ x{GFpIt%A}jDy@>zx~H^w_&vfm=+)z3_$SlX!gD41I>}%BIzj#i(vRrJ*Mec6o8ABb literal 0 HcmV?d00001