All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unlaxer.tinyexpression.CalculatorImplTest Maven / Gradle / Ivy

The newest version!
package org.unlaxer.tinyexpression;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.math.BigDecimal;
import java.math.RoundingMode;

import org.junit.Test;
import org.unlaxer.ParserTestBase;
import org.unlaxer.Token;
import org.unlaxer.TokenKind;
import org.unlaxer.TokenPrinter;
import org.unlaxer.listener.OutputLevel;
import org.unlaxer.tinyexpression.CalculationContext.Angle;

import net.arnx.jsonic.JSON;

public abstract class CalculatorImplTest extends ParserTestBase{

	@Test
	public void test() {
		
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		
		assertTrue(calc(context,"0",new BigDecimal("0")));
		assertTrue(calc(context,"1+1",new BigDecimal("2")));
		assertTrue(calc(context,"1+1/5",new BigDecimal("1.20")));
		assertTrue(calc(context,"1+1/5",new BigDecimal("1.20")));
		assertTrue(calc(context,"(1+1)/5",new BigDecimal("0.40")));
		assertTrue(calc(context,"(1e1+1)*5",new BigDecimal("55")));
		assertTrue(calc(context,"(1e1+1)*(5-3)",new BigDecimal("22")));
		assertTrue(calc(context,"10/2/2.5*4.5",new BigDecimal("9.00")));
		assertTrue(calc(context,"10/2+2.5*4.5",new BigDecimal("16.25")));
		assertTrue(calc(context,"-10/2+2.5*4.5",new BigDecimal("6.25")));
		assertTrue(calc(context,"sin(30)",new BigDecimal("0.5")));
		assertTrue(calc(context,"sin(30)*2",new BigDecimal("1")));
		assertTrue(calc(context,"cos(60)",new BigDecimal("0.5")));
		assertTrue(calc(context,"tan(45)",new BigDecimal("1")));
		assertTrue(calc(context,"sqrt(4)",new BigDecimal("2")));
		
		//test recurring decimal
		context = new NormalCalculationContext(10,RoundingMode.HALF_UP,Angle.DEGREE); 

		assertTrue(calc(context,"1/0.11",new BigDecimal("9.0909090909")));
		assertTrue(calc(context,"1/7",new BigDecimal("0.1428571429")));
	}
	
	@Test
	public void testVariable() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("count", 12);
		assertTrue(calc(context,"$count+10",new BigDecimal("22")));
	}
	
	@Test
	public void testTernary() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("isExists", true);
//		assertTrue(calc(context,"true?10:0",new BigDecimal("10")));
//		assertTrue(calc(context,"false?10:0",new BigDecimal("0")));
		assertTrue(calc(context,"if($isExists){10}else{0}",new BigDecimal("10")));
	}

	@Test
	public void testTrueOrFalse() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		assertTrue(calc(context,"if(true){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false){10}else{0}",new BigDecimal("0")));
		
		setLevel(OutputLevel.none);// if level is not none , then got stackOverflow Error!
		assertTrue(calc(context,"if(not(false)){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(not(true)){10}else{0}",new BigDecimal("0")));
	}
	
	@Test
	public void testGreaterOrLessOrEqual() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		assertTrue(calc(context,"if(10==20){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(10==10){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(10!=10){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(10!=20){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(10>=10){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(10>=20){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(10>20){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(10<20){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(10<=20){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(10<=10){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(10>10){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(10>5){30}else{0}",new BigDecimal("30")));
		assertTrue(calc(context,"if(not(10>5)){30}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(not(not(10>5))){30}else{0}",new BigDecimal("30")));
		assertTrue(calc(context,"if(not(not(2*5>5))){6*8}else{0}",new BigDecimal("48")));
		assertTrue(calc(context,"if(not(not(0.7*5>5))){6*8}else{0.3*0.2}",new BigDecimal("0.06")));
		assertTrue(calc(context,"if(not(not(0.7*5>5))){6*8}else{0.3*if(1>0){0.3}else{0.2}}",new BigDecimal("0.09")));
	}
	
	@Test
	public void testAndOrOrOrXor() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		assertTrue(calc(context,"if(true|true){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false|true){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false|false){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(true|true|false){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false|false|true){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false|false|false|true){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false|false|false|false){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(false&true){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(false&false){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(true^true){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(false^true){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if(false^false){10}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(1>0|10<20){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if((1>0|10<20)){10}else{0}",new BigDecimal("10")));
		assertTrue(calc(context,"if((1>0|10<20)&(true)){10}else{0}",new BigDecimal("10")));
		
		context.set("number_accessCountByIPAddressInShortPeriod", 0);
		context.set("number_accessCountByCaulisCookieInShortPeriod", 0);
		context.set("number_accessCountByIPAddressInMiddlePeriod", 0);
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 0);
		
		String formula = "if(($number_accessCountByIPAddressInShortPeriod>=15.0)|($number_accessCountByCaulisCookieInShortPeriod>=10.0)|($number_accessCountByIPAddressInMiddlePeriod>=60.0)|($number_accessCountByCaulisCookieInMiddlePeriod>=30.0)){1}else{0}";
		assertTrue(calc(context,formula,new BigDecimal("0")));
		
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 100);
		assertTrue(calc(context,formula,new BigDecimal("1")));
		
		context.set("number_accessCountByIPAddressInMiddlePeriod", 100);
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 0);
		assertTrue(calc(context,formula,new BigDecimal("1")));

		context.set("number_accessCountByCaulisCookieInShortPeriod", 100);
		context.set("number_accessCountByIPAddressInMiddlePeriod", 0);
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 0);
		assertTrue(calc(context,formula,new BigDecimal("1")));

		context.set("number_accessCountByIPAddressInShortPeriod", 100);
		context.set("number_accessCountByCaulisCookieInShortPeriod", 0);
		context.set("number_accessCountByIPAddressInMiddlePeriod", 0);
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 0);
		assertTrue(calc(context,formula,new BigDecimal("1")));
		
		context.set("number_accessCountByIPAddressInShortPeriod", 0);
		context.set("number_accessCountByCaulisCookieInShortPeriod", 0);
		context.set("number_accessCountByIPAddressInMiddlePeriod", 100);
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 100);
		assertTrue(calc(context,formula,new BigDecimal("1")));
		
	}
	
	@Test
	public void testCalculatorSpeed() {
		String formula = "if(($number_accessCountByIPAddressInShortPeriod>=15.0)|($number_accessCountByCaulisCookieInShortPeriod>=10.0)|($number_accessCountByIPAddressInMiddlePeriod>=60.0)|($number_accessCountByCaulisCookieInMiddlePeriod>=30.0)){1}else{0}";
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		
		context.set("number_accessCountByIPAddressInShortPeriod", 0);
		context.set("number_accessCountByCaulisCookieInShortPeriod", 0);
		context.set("number_accessCountByIPAddressInMiddlePeriod", 100);
		context.set("number_accessCountByCaulisCookieInMiddlePeriod", 100);
		
		long start = System.nanoTime();
		PreConstructedCalculator preConstructedCalculator = preConstructedCalculator(formula);
		for(int i =0 ; i < 10000000; i++) {
			preConstructedCalculator.calculate(context);
		}
		long duration = System.nanoTime() - start;
		System.out.println(formula);
		System.out.format("calculation time:%f(microsec)\n" , ((float)duration)/10000000000f);
	}
	
	public abstract PreConstructedCalculator preConstructedCalculator(String formula);

	@Test
	public void testMultipleVariableCondition() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("float_test_random", 0.2f);
		context.set("boolean_test_random", false);
		assertTrue(calc(context,"if($float_test_random<0.3&($boolean_test_random==false)){1}else{0}",new BigDecimal("1")));
		
		context.set("float_test_random", 0.5f);
		context.set("boolean_test_random", false);
		assertTrue(calc(context,"if(($float_test_random<0.3)&($boolean_test_random==false)){1}else{0}",new BigDecimal("0")));
		
		context.set("float_test_random", 0.5f);
		context.set("boolean_test_random", false);
		assertTrue(calc(context,"if(( $float_test_random < 0.3 ) ^ ( $boolean_test_random ==false)){ 1 }else{ 0 }",new BigDecimal("1")));


	}
	
	@Test
	public void testOr() {
		setLevel(OutputLevel.detail);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		
		String formula ="if(($number_accessPeakCountByIPAddressInLongPeriod>=10.0)|($number_accessPeakCountByCaulisCookieInLongPeriod>=5.0)){1}else{0}";
		context.set("number_accessPeakCountByIPAddressInLongPeriod", 0);
		context.set("number_accessPeakCountByCaulisCookieInLongPeriod", 0);
		assertTrue(calc(context,formula,new BigDecimal("0")));

		context.set("number_accessPeakCountByIPAddressInLongPeriod", 10);
		context.set("number_accessPeakCountByCaulisCookieInLongPeriod", 0);
		assertTrue(calc(context,formula,new BigDecimal("1")));

		context.set("number_accessPeakCountByIPAddressInLongPeriod", 0);
		context.set("number_accessPeakCountByCaulisCookieInLongPeriod", 5);
		assertTrue(calc(context,formula,new BigDecimal("1")));
	}

	
	
	boolean calc(CalculationContext calculationContext , String formula , BigDecimal expected){
		
		Calculator calculator = preConstructedCalculator(formula);
		testAllMatch(calculator.getParser(), formula);
		CalculateResult calculateResult = calculator.calculate(calculationContext , formula);
		calculateResult.errors.raisedException.ifPresent(error->error.printStackTrace());
		BigDecimal x = calculateResult.answer.get();
		System.out.format(" %s = %s \n" , formula , x.toString());
		return 
			expected.compareTo(x) ==0 ||
			// this is work around for rounding error on float calculation
			expected.subtract(x).abs().floatValue() < 0.01;
	}

//	@Test
//	public void testSuggestSinANdSqrt() {
//
//		String formula = "1+1/s";
//		
//		CalculationContext context = new CalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
//		CalculateResult result = calculator.calculate(context, formula);
//		System.out.println(getJson(result.parseContext.suggestsByPosition));
//		
//		int position = formula.indexOf("s");//s is invalid token in '1+1/s'
//		assertEquals(2, result.parseContext.suggestsByPosition.get(position).size());
//
//	}
	
	static String getJson(Object object){
		JSON json = new JSON();
		json.setPrettyPrint(true);
		return json.format(object);
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testUnfinishedFormula() {

		String formula = "1+1/s";
		
		PreConstructedCalculator calculator = preConstructedCalculator(formula);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		CalculateResult result = calculator.calculate(context, formula);
		BigDecimal answer = result.answer.get();
		assertEquals(new BigDecimal("2"), answer);
		assertFalse(result.success);
		assertEquals("1+1", result.parseContext.getConsumed(TokenKind.consumed));
		assertEquals("/s", result.parseContext.getRemain(TokenKind.consumed));
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testNotStartedFormula() {

		String formula = "s/1+1";

		PreConstructedCalculator calculator = preConstructedCalculator(formula);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		CalculateResult result = calculator.calculate(context, formula);
		assertFalse(result.answer.isPresent());
		assertFalse(result.success);
		assertEquals("", result.parseContext.getConsumed(TokenKind.consumed));
		assertEquals(formula, result.parseContext.getRemain(TokenKind.consumed));
		//s 's successor was already inputed , suggests is empty
		// FIXME
//		assertTrue(result.parseContext.suggestsByPosition.isEmpty());
	}
	
	@Test
	public void testTokenPosition() {

		String formula = "(1+1)/3+sin(30)";
		
		PreConstructedCalculator calculator = preConstructedCalculator(formula);
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		CalculateResult result = calculator.calculate(context, formula);
		assertTrue(result.answer.isPresent());
		assertTrue(result.success);
		assertEquals("(1+1)/3+sin(30)", result.parseContext.getConsumed(TokenKind.consumed));
		assertEquals("", result.parseContext.getRemain(TokenKind.consumed));
		assertTrue(result.token.isPresent());
		Token token = result.token.get();
		TokenPrinter.output(token,System.out);
		
	}
	
	@Test
	public void testVariableIsNotPresent() {

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		
		assertTrue(calc(context,"if($isExists){1}else{0}",new BigDecimal("0")));
		context.set("isExists", true);
		assertTrue(calc(context,"if($isExists){1}else{0}",new BigDecimal("1")));
		
		assertTrue(calc(context,"$count",new BigDecimal("0")));
		context.set("count", 5);
		assertTrue(calc(context,"$count",new BigDecimal("5")));
	}
	
	@Test
	public void testVariableIsPresentOperator() {

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		
		assertTrue(calc(context,"if(isPresent($isExists)){5}else{10}",new BigDecimal("10")));
		assertTrue(calc(context,"if(not(isPresent($isExists))){5}else{10}",new BigDecimal("5")));
		context.set("isExists", false);
		assertTrue(calc(context,"if(isPresent($isExists)){5}else{10}",new BigDecimal("5")));
		assertTrue(calc(context,"if(not(isPresent($isExists))){5}else{10}",new BigDecimal("10")));
		
		
		assertTrue(calc(context,"if(isPresent($value)){5}else{10}",new BigDecimal("10")));
		assertTrue(calc(context,"if(not(isPresent($value))){5}else{10}",new BigDecimal("5")));
		context.set("value", 10);
		assertTrue(calc(context,"if(isPresent($value)){5}else{10}",new BigDecimal("5")));
		assertTrue(calc(context,"if(not(isPresent($value))){5}else{10}",new BigDecimal("10")));
		
		assertTrue(calc(context,"if(isPresent($name)){5}else{10}",new BigDecimal("10")));
		assertTrue(calc(context,"if(not(isPresent($name))){5}else{10}",new BigDecimal("5")));
		context.set("name", "opa");
		assertTrue(calc(context,"if(isPresent($name)){5}else{10}",new BigDecimal("5")));
		assertTrue(calc(context,"if(not(isPresent($name))){5}else{10}",new BigDecimal("10")));


		
	}
	
	@Test
	public void testStringVariable() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
//		assertTrue(calc(context,"if($name==''){1}else{0}",new BigDecimal("1")));
		context.set("name", "opa");
		//                                  12345678901234567890123456 
		assertTrue(calc(context,"if($name==\"opa\"){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($name!='opa'){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($name==\"opaopa\"){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($name!='opaopa'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($nameNoSpecified==\"opa\"){1}else{0}",new BigDecimal("0")));
	}
	
	@Test
	public void testStringLiteral() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
//		assertTrue(calc(context,"if($name==''){1}else{0}",new BigDecimal("1")));
		context.set("name", "opa");
		//                                  12345678901234567890123456 
		assertTrue(calc(context,"if(\"opa\"==\"opa\"){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(\"opa\"!=\"opa\"){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(\"opa\"==\"opaopa\"){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(\"opa\"!=\"opaopa\"){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(\"opa\"==$name){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(\"opa\"!=$name){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($name!='opa'){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($name==\"opaopa\"){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($name!='opaopa'){1}else{0}",new BigDecimal("1")));
	}
	
	@Test
	public void testStringConcat() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		assertTrue(calc(context,"if((\"opa\"+'opa'+\"6969\")=='opaopa6969'){1}else{0}",new BigDecimal("1")));
	}
	
	@Test
	public void testStringSlice() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		assertTrue(calc(context,"if('deadbeaf'[1:3]=='ea'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if('gateman'[::-1]=='nametag'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if('1a2b3'[::2]=='123'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if('1a2b3'[1::2]=='ab'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if('gateman'[::-1][0:4]=='name'){1}else{0}",new BigDecimal("1")));
	}

	
	@Test
	public void testStringTrim() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("name", "  opa 133\t");
		
		assertTrue(calc(context,"if(trim($name)=='opa 133'){1}else{0}",new BigDecimal("1")));
	}
	
	@Test
	public void testStringUpperAndLowerCase() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("name", "AlmondChocolate");
		
		assertTrue(calc(context,"if(toUpperCase($name)=='ALMONDCHOCOLATE'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(toUpperCase(\"AlmondChocolate\")=='ALMONDCHOCOLATE'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(toUpperCase(($name))=='ALMONDCHOCOLATE'){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(toUpperCase($name[0:6])=='ALMOND'){1}else{0}",new BigDecimal("1")));

		assertTrue(calc(context,"if(toLowerCase($name)!='almondchocolate'){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(toLowerCase(\"AlmondChocolate\")!='almondchocolate'){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(toLowerCase(($name))!='almondchocolate'){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(toLowerCase(($name)[0:6]+' is delicious')!='almond is delicious'){1}else{0}",new BigDecimal("0")));
	}
	
	@Test
	public void testStringLength() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("name", "AlmondChocolate");
		
		assertTrue(calc(context,"if(len($name)==15){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(len(\"AlmondChocolate\")==15){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(len($name)-5==10){1}else{0}",new BigDecimal("1")));
	}

	@Test
	public void testStringIn() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("country", "jp");
		
		{
			String formula = "if($country.in('jp','ca','us')){1}else{0}";
			
			PreConstructedCalculator calculator = preConstructedCalculator(formula);

			
			Token rootToken = parse(calculator.getParser(),formula).getRootToken();
			TokenPrinter.output(rootToken,System.out);
		}
		
		assertTrue(calc(context,"if($country.in('jp','ca','us')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(false|$country.in('jp','ca','us')){1}else{0}",new BigDecimal("1")));
		
		{
			String formula = "if((isPresent($country)&$country.in('russian-federation','china','taiwan-province-of-china','ukraine','korea-democratic-peoples-republic-of'))|(isPresent($calculated_TorNode)&$calculated_TorNode>0.0)|((isPresent($calculated_BlackIPAddressInThisSite)&$calculated_BlackIPAddressInThisSite>0.0)|(isPresent($calculated_BlackIPAddressInOtherSites)&$calculated_BlackIPAddressInOtherSites>0.0))|(isPresent($calculated_BrowserTypeIsTool)&$calculated_BrowserTypeIsTool>0.0)){1}else{0}";
			
			PreConstructedCalculator calculator = preConstructedCalculator(formula);
			
			Token rootToken = parse(calculator.getParser(),formula).getRootToken();
			TokenPrinter.output(rootToken,System.out);
			assertTrue(calc(context,formula,new BigDecimal("0")));
		}
		
		assertTrue(calc(context,"if($country.in('ca','jp','us')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($country.in('en','ca','us')){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if('cnjpuszn'[0:2].in('en','ca','us')){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if('cnjpuszn'[4:6].in('en','ca','us')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(not('cnjpuszn'[4:6].in('en','ca','us'))){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(not(toUpperCase('cnjpuszn')[4:6].in(toUpperCase('en'),toUpperCase('ca'),toUpperCase('us')))){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if(not(not(toUpperCase('cnjpuszn')[4:6].in(toUpperCase('en'),toUpperCase('ca'),toUpperCase('us'))))){1}else{0}",new BigDecimal("1")));
		
	}
	
	@Test
	public void testStringMethods() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("message", "I even lost my cat.");
		
		assertTrue(calc(context,"if($message.startsWith('I even')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($message.startsWith('i even')){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($message.endsWith('my cat.')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($message.endsWith('my cat')){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($message.contains('lost my ')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($message.contains('lose my ')){1}else{0}",new BigDecimal("0")));
		assertTrue(calc(context,"if($message.contains('lose my '[0:3]+'t')){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if($message.contains('lose my '[0:3]+'e')){1}else{0}",new BigDecimal("0")));
	}

	
	@Test
	public void testMatchCase() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		
		String formula="match { $country == 'en' -> 1 , $country == 'jp' -> 2 , $country == 'cn' -> 3 , \n default -> 0}";
		assertTrue(calc(context,formula ,new BigDecimal("0")));
		
		context.set("country", "en");
		assertTrue(calc(context,formula ,new BigDecimal("1")));
		
		context.set("country", "jp");
		assertTrue(calc(context,formula ,new BigDecimal("2")));

		context.set("country", "cn");
		assertTrue(calc(context,formula ,new BigDecimal("3")));
		
		context.set("country", "ca");
		assertTrue(calc(context,formula ,new BigDecimal("0")));
		
		formula="match { $country == 'en' -> 1*9 , $country == 'jp' -> 2*9 , $country == 'cn' -> 3*9 , \n default -> 30*3}";

		assertTrue(calc(context,formula ,new BigDecimal("90")));
		
		context.set("country", "en");
		assertTrue(calc(context,formula ,new BigDecimal("9")));
		
		context.set("country", "jp");
		assertTrue(calc(context,formula ,new BigDecimal("18")));

		context.set("country", "cn");
		assertTrue(calc(context,formula ,new BigDecimal("27")));
		
		context.set("country", "ca");
		assertTrue(calc(context,formula ,new BigDecimal("90")));
	}
	
	@Test
	public void testMin() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("count", 10);
		
		assertTrue(calc(context,"if(min(0,0)==0){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(min(-1,0)==-1){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(min(-1,-2)==-2){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(min(1,0)==0){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(min($count,5)==5){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(min($count,2*3)==6){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(min($count*0.5,2*3)==5){1}else{0}",new BigDecimal("1")));
	}

	@Test
	public void testMax() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("count", 10);

		assertTrue(calc(context,"if(max(0,0)==0){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(max(-1,0)==0){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(max(-1,-2)==-1){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(max(1,0)==1){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(max($count,5)==10){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(max($count,4*3)==12){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(max($count*2,4*3)==20){1}else{0}",new BigDecimal("1")));
	}
	
	@Test
	public void testRandom() {

		setLevel(OutputLevel.detail);

		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		context.set("count", 10);

		assertTrue(calc(context,"if(random()<=1.0){1}else{0}",new BigDecimal("1")));
		assertTrue(calc(context,"if(random()>=0){1}else{0}",new BigDecimal("1")));
	}
	
	@Test
	public void testFunctions() {
		String[][] functions = new String[][]{
			{"OriginalSpec_AnyBlackList", "if((isPresent($calculated_BlackIPAddressInThisSite)&$calculated_BlackIPAddressInThisSite>0.0)|(isPresent($calculated_BlackCaulisCookieInThisSite)&$calculated_BlackCaulisCookieInThisSite>0.0)){10}else{if((isPresent($calculated_BlackIPAddressInOtherSites)&$calculated_BlackIPAddressInOtherSites>0.0)|(isPresent($calculated_BlackCaulisCookieInOtherSites)&$calculated_BlackCaulisCookieInOtherSites>0.0)){5}else{0}}"},
			{"OriginalSpec_SuspiciousProvider", "if((isPresent($calculated_AccessFromDataCenter)&$calculated_AccessFromDataCenter>0.0)|(isPresent($calculated_TorNode)&$calculated_TorNode>0.0)|(isPresent($calculated_AnonymizingVpn)&$calculated_AnonymizingVpn>0.0)){10}else{0}"},
			{"OriginalSpec_OtherProvider", "0"},
			{"UnknownUsingEmulator", "if((isPresent($calculated_UnknownUsingEmulator)&$calculated_UnknownUsingEmulator>0.0)){10}else{0}"},
			{"Jailbreak", "if((isPresent($calculated_Jailbreak)&$calculated_Jailbreak>0.0)){5}else{0}"},
			{"OriginalSpec_OverseaAccess", "if(isPresent($country)&$country!='japan'){5}else{0}"},
			{"OriginalSpec_NotJapaneseLanguage", "if(isPresent($splanguage)¬($splanguage.in('ja','ja-JP'))){5}else{0}"},
			{"OriginalSpec_MultipleAccess", "if((isPresent($number_accessCountByIPAddressInShortPeriod)&$number_accessCountByIPAddressInShortPeriod>0.0)|(isPresent($number_accessCountByIPAddressInMiddlePeriod)&$number_accessCountByIPAddressInMiddlePeriod>0.0)|(isPresent($number_accessCountByCaulisCookieInShortPeriod)&$number_accessCountByCaulisCookieInShortPeriod>0.0)|(isPresent($number_accessCountByCaulisCookieInMiddlePeriod)&$number_accessCountByCaulisCookieInMiddlePeriod>0.0)|(isPresent($userCountGroupedByCookieOnThisSite)&$userCountGroupedByCookieOnThisSite>0.0)){5}else{0}"},
			{"POST_PROCESS_OriginalSpec_totalScore", "$calculated_OriginalSpec_AnyBlackList+$calculated_OriginalSpec_SuspiciousProvider+$calculated_OriginalSpec_OtherProvider+if(isPresent($calculated_UnknownUsingEmulator)){$calculated_UnknownUsingEmulator}else{0}+if(isPresent($calculated_Jailbreak)){$calculated_Jailbreak}else{0}+$calculated_OriginalSpec_OverseaAccess+$calculated_OriginalSpec_NotJapaneseLanguage+$calculated_OriginalSpec_MultipleAccess"},
			{"POST_PROCESS_OriginalSpec_ChineseLanguageOrNotJapanTimezone", "if((isPresent($priorityLanguage)&$priorityLanguage==\"zh-CN\")|(isPresent($timezone)&$timezone!=\"+9\")){1}else{0}"},
			{"POST_PROCESS_OriginalSpec_RiskyCountry", "if(isPresent($country)&$country.in(\"korea-democratic-peoples-republic-of\",\"iran\",\"iran-islamic-republic-of\",\"cuba\",\"syria\",\"syrian-arab-republic\",\"sudan\")){1}else{0}"},
			{"POST_PROCESS_RELATIVE_SUSPICIOUS", "if($ForcedRelativeSuspiciousValue1){1}else{if($ForcedRelativeSuspiciousValue5){5}else{if(($POST_PROCESS_OriginalSpec_RiskyCountry>0.0)|(isPresent($calculated_TorNode)&$calculated_TorNode>0.0)|(isPresent($calculated_BrowserTypeIsTool)&$calculated_BrowserTypeIsTool>0.0)){5}else{if(($POST_PROCESS_OriginalSpec_ChineseLanguageOrNotJapanTimezone>0.0)){4}else{if($default_RelativeSuspiciousValue==5){4}else{$default_RelativeSuspiciousValue}}}}}"},
			{"POST_PROCESS_OriginalSpec_OverseaAccess", "if(isPresent($country)&$country!=\"japan\"){1}else{0}"},
			{"POST_PROCESS_OriginalSpec_MultiUserAccessToOneAccount", "if(isPresent($cookieCountGroupedByUser)&$cookieCountGroupedByUser>=10.0){1}else{0}"},
			{"POST_PROCESS_OriginalSpec_OneUserAccessToMultiAccount", "if(isPresent($userCountGroupedByCookieOnThisSite)&$userCountGroupedByCookieOnThisSite>=5){1}else{0}"},
			{"POST_PROCESS_OriginalSpec_BlackListOnOtherSites", "if((isPresent($calculated_BlackIPAddressInOtherSites)&$calculated_BlackIPAddressInOtherSites>0.0)|(isPresent($calculated_BlackCaulisCookieInOtherSites)&$calculated_BlackCaulisCookieInOtherSites>0.0)){1}else{0}"},
			{"POST_PROCESS_OriginalSpec_RiskyCountry", "if(isPresent($country)&$country.in(\"korea-democratic-peoples-republic-of\",\"iran\",\"iran-islamic-republic-of\")){1}else{0}"},
			{"POST_PROCESS_RELATIVE_SUSPICIOUS", "if($ForcedRelativeSuspiciousValue1){1}else{if($ForcedRelativeSuspiciousValue5){5}else{if($default_RelativeSuspiciousValue==5){5}else{if($POST_PROCESS_OriginalSpec_RiskyCountry>0.0){5}else{if(($POST_PROCESS_OriginalSpec_OverseaAccess>0.0)|($POST_PROCESS_OriginalSpec_MultiUserAccessToOneAccount>0.0)|($POST_PROCESS_OriginalSpec_OneUserAccessToMultiAccount>0.0)|($POST_PROCESS_OriginalSpec_BlackListOnOtherSites>0.0)|(isPresent($calculated_BrowserTypeIsTool)&$calculated_BrowserTypeIsTool>0.0)){4}else{$default_RelativeSuspiciousValue}}}}}"},
			{"OriginalSpec_ChineseLanguage", "if(isPresent($priorityLanguage)&$priorityLanguage==\"zh-CN\"){50}else{0}"},
			{"OriginalSpec_AnyBlackList", "if((isPresent($calculated_BlackIPAddressInThisSite)&$calculated_BlackIPAddressInThisSite>0.0)|(isPresent($calculated_BlackCaulisCookieInThisSite)&$calculated_BlackCaulisCookieInThisSite>0.0)){10}else{if((isPresent($calculated_BlackIPAddressInOtherSites)&$calculated_BlackIPAddressInOtherSites>0.0)|(isPresent($calculated_BlackCaulisCookieInOtherSites)&$calculated_BlackCaulisCookieInOtherSites>0.0)){5}else{0}}"},
			{"OriginalSpec_SuspiciousProvider", "if((isPresent($calculated_AccessFromDataCenter)&$calculated_AccessFromDataCenter>0.0)|(isPresent($calculated_TorNode)&$calculated_TorNode>0.0)|(isPresent($calculated_AnonymizingVpn)&$calculated_AnonymizingVpn>0.0)){10}else{0}"},
			{"OriginalSpec_OtherProvider", "0"},
			{"UnknownUsingEmulator", "if((isPresent($calculated_UnknownUsingEmulator)&$calculated_UnknownUsingEmulator>0.0)){10}else{0}"},
			{"Jailbreak", "if((isPresent($calculated_Jailbreak)&$calculated_Jailbreak>0.0)){5}else{0}"},
			{"OriginalSpec_OverseaAccess", "if(isPresent($country)&$country!='japan'){5}else{0}"},
			{"OriginalSpec_NotJapaneseLanguage", "if(isPresent($splanguage)¬($splanguage.in('ja','ja-JP'))){5}else{0}"},
			{"OriginalSpec_MultipleAccess", "if((isPresent($number_accessCountByIPAddressInShortPeriod)&$number_accessCountByIPAddressInShortPeriod>0.0)|(isPresent($number_accessCountByIPAddressInMiddlePeriod)&$number_accessCountByIPAddressInMiddlePeriod>0.0)|(isPresent($number_accessCountByCaulisCookieInShortPeriod)&$number_accessCountByCaulisCookieInShortPeriod>0.0)|(isPresent($number_accessCountByCaulisCookieInMiddlePeriod)&$number_accessCountByCaulisCookieInMiddlePeriod>0.0)|(isPresent($userCountGroupedByCookieOnThisSite)&$userCountGroupedByCookieOnThisSite>0.0)){5}else{0}"},
			{"POST_PROCESS_OriginalSpec_totalScore", "$calculated_OriginalSpec_AnyBlackList+$calculated_OriginalSpec_SuspiciousProvider+$calculated_OriginalSpec_OtherProvider+if(isPresent($calculated_UnknownUsingEmulator)){$calculated_UnknownUsingEmulator}else{0}+if(isPresent($calculated_Jailbreak)){$calculated_Jailbreak}else{0}+$calculated_OriginalSpec_OverseaAccess+$calculated_OriginalSpec_NotJapaneseLanguage+$calculated_OriginalSpec_MultipleAccess"},
			{"japanese","if(isPresent($splanguage)¬($splanguage.in('ja','ja-JP','日本語'))){5}else{0}"}			
		};
		
		CalculationContext context = new NormalCalculationContext(2,RoundingMode.HALF_UP,Angle.DEGREE);
		setLevel(OutputLevel.detail);
		for (String[] tuple : functions) {
			String title = tuple[0];
			String function = tuple[1];
			System.out.println(title);
			assertTrue(calc(context,function ,new BigDecimal("0")));
		}
	}
	
	public Class getTestClass(){
		return CalculatorImplTest.class;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy