/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.exprs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_expr_tst {
	private Xop_fxt fxt = new Xop_fxt();
	@Before public void init()				{fxt.Reset();}
	@Test  public void Null()				{fxt.Test_parse_tmpl_str_test("{{#expr:}}"										, "{{test}}"	, "");}
	@Test  public void Num_len1()			{fxt.Test_parse_tmpl_str_test("{{#expr:1}}"										, "{{test}}"	, "1");}
	@Test  public void Num_len3()			{fxt.Test_parse_tmpl_str_test("{{#expr:123}}"									, "{{test}}"	, "123");}
	@Test  public void Num_decimal()		{fxt.Test_parse_tmpl_str_test("{{#expr:1.2}}"									, "{{test}}"	, "1.2");}
	@Test  public void Num_decimal_lead()	{fxt.Test_parse_tmpl_str_test("{{#expr:.12}}"									, "{{test}}"	, "0.12");}
	@Test  public void Num_decimal_lax()	{fxt.Test_parse_tmpl_str_test("{{#expr:1.2.3}}"									, "{{test}}"	, "1.2");}			// PURPOSE: PHP allows 1.2.3 to be 1.2
	@Test  public void Num_neg()			{fxt.Test_parse_tmpl_str_test("{{#expr:-1}}"									, "{{test}}"	, "-1");}
	@Test  public void Num_neg_double()		{fxt.Test_parse_tmpl_str_test("{{#expr:--1}}"									, "{{test}}"	, "1");}
	@Test  public void Ws()					{fxt.Test_parse_tmpl_str_test("{{#expr: 123\t\n }}"								, "{{test}}"	, "123");}
	@Test  public void Plus_op()			{fxt.Test_parse_tmpl_str_test("{{#expr:1 + 2}}"									, "{{test}}"	, "3");}
	@Test  public void Minus_op()			{fxt.Test_parse_tmpl_str_test("{{#expr:3 - 2}}"									, "{{test}}"	, "1");}
	@Test  public void Mult()				{fxt.Test_parse_tmpl_str_test("{{#expr:3 * 2}}"									, "{{test}}"	, "6");}
	@Test  public void Div_sym()			{fxt.Test_parse_tmpl_str_test("{{#expr:6 / 3}}"									, "{{test}}"	, "2");}
	@Test  public void Div_word()			{fxt.Test_parse_tmpl_str_test("{{#expr:6 div 3}}"								, "{{test}}"	, "2");}
	@Test  public void Plus_sign()			{fxt.Test_parse_tmpl_str_test("{{#expr:1 + + 2}}"								, "{{test}}"	, "3");}
	@Test  public void Minus_sign()			{fxt.Test_parse_tmpl_str_test("{{#expr:3 + - 2}}"								, "{{test}}"	, "1");}
	@Test  public void Paren_1()			{fxt.Test_parse_tmpl_str_test("{{#expr:(1 + 2) * 3}}"							, "{{test}}"	, "9");}
	@Test  public void Paren_2()			{fxt.Test_parse_tmpl_str_test("{{#expr:((1 + 2) * 3) * 4}}"						, "{{test}}"	, "36");}
	@Test  public void Pow()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 ^ 4}}"									, "{{test}}"	, "16");}
	@Test  public void Eq_y()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 = 2}}"									, "{{test}}"	, "1");}
	@Test  public void Eq_n()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 = 3}}"									, "{{test}}"	, "0");}
	@Test  public void Neq_1()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 != 3}}"								, "{{test}}"	, "1");}
	@Test  public void Neq_2()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 <> 3}}"								, "{{test}}"	, "1");}
	@Test  public void Gt()					{fxt.Test_parse_tmpl_str_test("{{#expr:3 > 2}}"									, "{{test}}"	, "1");}
	@Test  public void Lt()					{fxt.Test_parse_tmpl_str_test("{{#expr:2 < 3}}"									, "{{test}}"	, "1");}
	@Test  public void Gte()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 >= 2}}"								, "{{test}}"	, "1");}
	@Test  public void Lte()				{fxt.Test_parse_tmpl_str_test("{{#expr:2 <= 2}}"								, "{{test}}"	, "1");}
	@Test  public void Mod()				{fxt.Test_parse_tmpl_str_test("{{#expr:3 mod 2}}"								, "{{test}}"	, "1");}
	@Test  public void And_1()				{fxt.Test_parse_tmpl_str_test("{{#expr:1 and -1}}"								, "{{test}}"	, "1");}
	@Test  public void And_0()				{fxt.Test_parse_tmpl_str_test("{{#expr:1 and  0}}"								, "{{test}}"	, "0");}
	@Test  public void Or_0()				{fxt.Test_parse_tmpl_str_test("{{#expr:1 or  0}}"								, "{{test}}"	, "1");}
	@Test  public void Not_y()				{fxt.Test_parse_tmpl_str_test("{{#expr:not 0}}"									, "{{test}}"	, "1");}
	@Test  public void Not_n()				{fxt.Test_parse_tmpl_str_test("{{#expr:not 1}}"									, "{{test}}"	, "0");}
	@Test  public void Minus_op_neg()		{fxt.Test_parse_tmpl_str_test("{{#expr:2 - 3}}"									, "{{test}}"	, "-1");}
	@Test  public void E_num()				{fxt.Test_parse_tmpl_str_test("{{#expr:e}}"										, "{{test}}"	, "2.71828182845904");}
	@Test  public void Pi_num()				{fxt.Test_parse_tmpl_str_test("{{#expr:pi}}"									, "{{test}}"	, "3.14159265358979");}
	@Test  public void Pi_mult()			{fxt.Test_parse_tmpl_str_test("{{#expr:pi*1}}"									, "{{test}}"	, "3.14159265358979");}
	@Test  public void E_op_pos()			{fxt.Test_parse_tmpl_str_test("{{#expr:1.2 e 2}}"								, "{{test}}"	, "120");}
	@Test  public void E_op_neg()			{fxt.Test_parse_tmpl_str_test("{{#expr:1.2 e -2}}"								, "{{test}}"	, "0.012");}
	@Test  public void Ceil_neg()			{fxt.Test_parse_tmpl_str_test("{{#expr:ceil(-1.2)}}"							, "{{test}}"	, "-1");}
	@Test  public void Trunc_neg()			{fxt.Test_parse_tmpl_str_test("{{#expr:trunc(-1.2)}}"							, "{{test}}"	, "-1");}
	@Test  public void Floor_neg()			{fxt.Test_parse_tmpl_str_test("{{#expr:floor(-1.2)}}"							, "{{test}}"	, "-2");}
	@Test  public void Ceil_pos()			{fxt.Test_parse_tmpl_str_test("{{#expr:ceil(1.2)}}"								, "{{test}}"	, "2");}
	@Test  public void Trunc_pos()			{fxt.Test_parse_tmpl_str_test("{{#expr:trunc(1.2)}}"							, "{{test}}"	, "1");}
	@Test  public void Floor_pos()			{fxt.Test_parse_tmpl_str_test("{{#expr:floor(1.2)}}"							, "{{test}}"	, "1");}
	@Test  public void Abs_pos()			{fxt.Test_parse_tmpl_str_test("{{#expr:abs(1)}}"								, "{{test}}"	, "1");}
	@Test  public void Abs_neg()			{fxt.Test_parse_tmpl_str_test("{{#expr:abs(-1)}}"								, "{{test}}"	, "1");}
	@Test  public void Exp()				{fxt.Test_parse_tmpl_str_test("{{#expr:exp(10)}}"								, "{{test}}"	, "22026.46579480671789");}	// NOTE: MW returns 4807, not 480671789;
	@Test  public void Ln()					{fxt.Test_parse_tmpl_str_test("{{#expr:ln(22026.4657948067)}}"					, "{{test}}"	, "10");}
	@Test  public void Sin()				{fxt.Test_parse_tmpl_str_test("{{#expr:sin(1.5707963267949)}}"					, "{{test}}"	, "1");}
	@Test  public void Cos()				{fxt.Test_parse_tmpl_str_test("{{#expr:cos(0)}}"								, "{{test}}"	, "1");}
	@Test  public void Tan()				{fxt.Test_parse_tmpl_str_test("{{#expr:tan(45)}}"								, "{{test}}"	, "1.61977519054386");}
	@Test  public void Asin()				{fxt.Test_parse_tmpl_str_test("{{#expr:asin(0)}}"								, "{{test}}"	, "0");}
	@Test  public void Acos()				{fxt.Test_parse_tmpl_str_test("{{#expr:acos(0)}}"								, "{{test}}"	, "1.57079632679489");} // NOTE: MW (and C#) returns 49, not 489 
	@Test  public void Atan()				{fxt.Test_parse_tmpl_str_test("{{#expr:atan(0)}}"								, "{{test}}"	, "0");}
	@Test  public void Round()				{fxt.Test_parse_tmpl_str_test("{{#expr:1.5 round 0}}"							, "{{test}}"	, "2");}
	@Test  public void Round_0()			{fxt.Test_parse_tmpl_str_test("{{#expr:0 round 1}}"								, "{{test}}"	, "0");}		// PURPOSE: 0 round 1 should be 0, not 0.0; DATE:2013-11-09
	@Test  public void Round_ex_1()			{fxt.Test_parse_tmpl_str_test("{{#expr:(0.03937007874015)round(3)}}"			, "{{test}}"	, "0.039");}	// PURPOSE: rounding results in excessive decimal places; PAGE:en.w:Milky Way (light year conversions)
	@Test  public void Mod_frac()			{fxt.Test_parse_tmpl_str_test("{{#expr:0.00999999mod10}}"						, "{{test}}"	, "0");}
	@Test  public void Mod_large()			{fxt.Test_parse_tmpl_str_test("{{#expr:39052000900mod100}}"						, "{{test}}"	, "0");}		// PURPOSE: JAVA was failing in converting to int and converted to Int_.MaxValue instead; DATE:2013-01-26
	@Test  public void Fmod()				{fxt.Test_parse_tmpl_str_test("{{#expr:1.25 fmod .5}}"							, "{{test}}"	, "0.25");}
	@Test  public void Sqrt()				{fxt.Test_parse_tmpl_str_test("{{#expr:sqrt 4}}"								, "{{test}}"	, "2");}
	@Test  public void Sqrt_frac()			{fxt.Test_parse_tmpl_str_test("{{#expr:sqrt 2}}"								, "{{test}}"	, "1.41421356237309");}	// NOTE: MW (and C#) returns 31, not 309 
	@Test  public void Esc_xml_entRef()		{fxt.Test_parse_tmpl_str_test("{{#expr:&minus;1 &lt; 5}}"						, "{{test}}"	, "1");}
	@Test  public void Ex_1()				{fxt.Test_parse_tmpl_str_test("{{#expr:1e2round0}}"								, "{{test}}"	, "100");}		// PURPOSE: used in Convert
	@Test  public void Floating()			{fxt.Test_parse_tmpl_str_test("{{#expr:27.321582}}"								, "{{test}}"	, "27.321582");}
	@Test  public void Floating_2()			{fxt.Test_parse_tmpl_str_test("{{#expr:0.1*41}}"								, "{{test}}"	, "4.1");}		// PURPOSE: division results in expanded floating-point; PAGE:en.w:Wikipedia
	@Test  public void Floating_3()			{fxt.Test_parse_tmpl_str_test("{{#expr:111/10^(-1)}}"							, "{{test}}"	, "1110");}		// PURPOSE: division by pow; PAGE:en.w:Wikipedia:Featured articles
	@Test  public void Floating_4()			{fxt.Test_parse_tmpl_str_test("{{#expr:abs(-73.9023)}}"							, "{{test}}"	, "73.9023");}	// PURPOSE: Abs;
	@Test  public void Unicode_8722()		{fxt.Test_parse_tmpl_str_test("{{#expr:2−1}}"									, "{{test}}"	, "1");}		// PURPOSE: handle alternate minus; PAGE:en.w:Australian krill
	@Test  public void Exp_large_neg()		{fxt.Test_parse_tmpl_str_test("{{#expr:418400000000000000000000E-23}}"			, "{{test}}"	, "4.184");}	// PURPOSE: handle large neg; EX: w:Chicxulub_crater; {{convert|100|TtonTNT|J|lk=on}}
	@Test  public void Exp_large_neg2()		{fxt.Test_parse_tmpl_str_test("{{#expr:210000000000000000E-17}}"				, "{{test}}"	, "2.1");}		// PURPOSE: handle large neg2; EX: w:Chicxulub_crater; {{convert|50|MtonTNT|J|lk=on}}
	@Test  public void Fix_transclusion()	{fxt.Test_parse_tmpl_str_test("{{#expr:{{#if:||1}}/.2}}"						, "{{test}}"	, "5");}		// PURPOSE: /. was invoking transclusion; DATE:2013-04-26
	@Test  public void Exc_unrecognised_word()					{fxt.Test_parse_tmpl_str_test("{{#expr:abc}}"				, "{{test}}"	, "<strong class=\"error\">Expression error: Unrecognised word \"abc\"</strong>");}
	@Test  public void Exc_division_by_zero()					{fxt.Test_parse_tmpl_str_test("{{#expr:1/0}}"				, "{{test}}"	, "<strong class=\"error\">Division by zero</strong>");}
	@Test  public void Exc_division_by_zero_mod()				{fxt.Test_parse_tmpl_str_test("{{#expr:1 mod 0}}"			, "{{test}}"	, "<strong class=\"error\">Division by zero</strong>");}
	@Test  public void Exc_unexpected_number()					{fxt.Test_parse_tmpl_str_test("{{#expr:0 1}}"				, "{{test}}"	, "<strong class=\"error\">Expression error: Unexpected number</strong>");}
	@Test  public void Exc_unexpected_closing_bracket()			{fxt.Test_parse_tmpl_str_test("{{#expr:5 + 1)}}"			, "{{test}}"	, "<strong class=\"error\">Expression error: Unexpected closing bracket</strong>");}
	@Test  public void Exc_unclosed_bracket()					{fxt.Test_parse_tmpl_str_test("{{#expr:(5 + 1}}"			, "{{test}}"	, "<strong class=\"error\">Expression error: Unclosed bracket</strong>");}
	@Test  public void Exc_unexpected_operator_paren_end()		{fxt.Test_parse_tmpl_str_test("{{#expr:5 ( 1}}"				, "{{test}}"	, "<strong class=\"error\">Expression error: Unexpected ( operator</strong>");}
	@Test  public void Exc_unexpected_number_pi()				{fxt.Test_parse_tmpl_str_test("{{#expr:5 pi}}"				, "{{test}}"	, "<strong class=\"error\">Expression error: Unexpected number</strong>");}
	@Test  public void Exc_missing_operand()					{fxt.Test_parse_tmpl_str_test("{{#expr:5 *}}"				, "{{test}}"	, "<strong class=\"error\">Expression error: Missing operand for *</strong>");}
	@Test  public void Exc_invalid_argument_asin()				{fxt.Test_parse_tmpl_str_test("{{#expr:asin(2)}}"			, "{{test}}"	, "<strong class=\"error\">Invalid argument for asin: < -1 or > 1</strong>");}
	@Test  public void Exc_invalid_argument_acos()				{fxt.Test_parse_tmpl_str_test("{{#expr:acos(2)}}"			, "{{test}}"	, "<strong class=\"error\">Invalid argument for acos: < -1 or > 1</strong>");}
	@Test  public void Exc_invalid_argument_ln()				{fxt.Test_parse_tmpl_str_test("{{#expr:ln(-1)}}"			, "{{test}}"	, "<strong class=\"error\">Invalid argument for ln: <= 0</strong>");}
	@Test  public void Exc_pow_nan()							{fxt.Test_parse_tmpl_str_test("{{#expr:(-2)^1.2}}"			, "{{test}}"	, "NaN");}	// PURPOSE: handle nan; EX: w:Help:Calculation
	@Test  public void Exc_unrecognized_word_ornot()			{fxt.Test_parse_tmpl_str_test("{{#expr:0ornot0}}"			, "{{test}}"	, "<strong class=\"error\">Expression error: Unrecognised word \"ornot\"</strong>");}	// PURPOSE: handle nan; EX: w:Help:Calculation
	@Test  public void Exc_unrecognized_word_notnot()			{fxt.Test_parse_tmpl_str_test("{{#expr:notnot0}}"			, "{{test}}"	, "<strong class=\"error\">Expression error: Unrecognised word \"notnot\"</strong>");}	// PURPOSE: handle nan; EX: w:Help:Calculation
	@Test  public void Exc_unrecognized_word_sinln()			{fxt.Test_parse_tmpl_str_test("{{#expr:sinln1.1}}"			, "{{test}}"	, "<strong class=\"error\">Expression error: Unrecognised word \"sinln\"</strong>");}	// PURPOSE: handle nan; EX: w:Help:Calculation
}
