/**
 * Copyright 2018 Twitter, Inc.
 * Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 */ type autogen_any = any ; import { jsonTemplate } from "sqrl-common" ; import { runSqrl , buildRedisTestInstance } from "./helpers/runSqrl" ; import { Instance , TestLogger } from "sqrl" ; import "jest-extended" ; let instance ; beforeEach ( async ( ) => { instance = await buildRedisTestInstance ( ) ; } ) ; async function getResult ( sqrl ) { return runSqrl ( sqrl , { instance } ) . then ( ( { lastExecution } ) => { return lastExecution . fetchValue ( "Result" ) ; } ) ; } test ( "Basic test works" , async ( ) => { await runSqrl ( `
    LET Ip := "1.2.3.4";
    ASSERT rateLimited(BY Ip MAX 2 EVERY DAY) = false;
    EXECUTE;
    ASSERT rateLimited(BY Ip MAX 2 EVERY DAY) = false;
    EXECUTE;
    ASSERT rateLimited(BY Ip MAX 2 EVERY DAY) = true;
    EXECUTE;

    LET SqrlClock := dateAdd(now(), "P1D");
    ASSERT rateLimited(BY Ip MAX 2 EVERY DAY) = false;
    EXECUTE;
    ` , { instance } ) ; } ) ; test ( "take works with features" , async ( ) => { const run = ( ) => getResult ( jsonTemplate `
LET Value := "1.2.3.4";
LET TakeAmount := 3.5;
LET Result := rateLimit(BY Value MAX 3 EVERY 60 SECOND TAKE TakeAmount);
  ` ) ; expect ( await run ( ) ) . toEqual ( 3 ) ; expect ( await run ( ) ) . toEqual ( 0 ) ; } ) ; test ( "take works with ints" , async ( ) => { const run = ( ) => { return getResult ( jsonTemplate `
LET Value := "1.2.3.4";
LET Result := rateLimit(BY Value MAX 3 EVERY 60 SECOND TAKE 3);
    ` ) ; } ; expect ( await run ( ) ) . toEqual ( 3 ) ; expect ( await run ( ) ) . toEqual ( 0 ) ; } ) ; test ( "works with retries" , ( ) => runSqrl ( `
      LET Ip := '1.2.3.4';
      LET Result := rateLimit(BY Ip MAX 3 EVERY 60 SECOND);
      LET Blocked := rateLimited(BY Ip MAX 3 EVERY 60 SECOND);

      # Expire the 1.2.3.4 rate limit as per usual
      ASSERT Result = 3; EXECUTE;
      ASSERT Result = 2; EXECUTE;
      ASSERT Result = 1; EXECUTE;
      ASSERT Result = 0; EXECUTE;
      ASSERT Result = 0; EXECUTE;

      # Take two off of 1.2.3.5
      LET Ip := '1.2.3.5';
      ASSERT Result = 3; EXECUTE;
      ASSERT Result = 2; EXECUTE;

      # Once we're a retry the rate limit should stop decreasing
      LET SqrlMutate := false;
      ASSERT Result = 1; EXECUTE;
      ASSERT Result = 1; EXECUTE;
      ASSERT Blocked = false;

      # 1.2.3.4 should be rate limited though
      LET Ip := '1.2.3.4';
      ASSERT Result = 0; EXECUTE;
      ASSERT Result = 0; EXECUTE;
      ASSERT Blocked = true;
    ` , { instance } ) ) ; test ( "returns rate limited multi values" , ( ) => runSqrl ( `
  LET TriGrams := entityList("TriGrams", ["julian ate food", "lunch was good"]);
  LET RateLimitedTriGrams := rateLimited(BY TriGrams MAX 1 EVERY 1 DAY);
  LET RateLimitedTriGramsValues := rateLimitedValues(BY TriGrams MAX 1 EVERY 1 DAY);
  ASSERT RateLimitedTriGrams = false;
  ASSERT RateLimitedTriGramsValues = [];

  LET TriGrams := entityList("TriGrams", [
    "julian ate food",
    "julian ate food",
    "lunch was good",
    "dinner be better",
  ]);

  EXECUTE;

  ASSERT RateLimitedTriGrams = true;
  ASSERT RateLimitedTriGramsValues = [
    "julian ate food",
    "julian ate food",
    "lunch was good"
  ];
` , { instance } ) ) ; test ( "works with multiple values" , async ( ) => { const logger = new TestLogger ( ) ; const run = ( ip ? , machine ? ) => { return runSqrl ( `
LET Value1 := ${ JSON . stringify ( ip ) };
LET Value2 := ${ JSON . stringify ( machine ) };
LET Result := rateLimit(BY Value1, Value2 MAX 3 EVERY 60 SECOND);
    ` , { instance , logger } ) . then ( ( { lastExecution } ) => { return lastExecution . fetchValue ( "Result" ) ; } ) ; } ; expect ( await run ( "8.8.8.8" , "M1" ) ) . toEqual ( 3 ) ; expect ( await run ( "8.8.8.8" , "M1" ) ) . toEqual ( 2 ) ; expect ( await run ( "8.8.8.8" , "M2" ) ) . toEqual ( 3 ) ; expect ( await run ( "8.8.8.8" , [ "M1" , "M2" ] ) ) . toEqual ( 1 ) ; expect ( await run ( "8.8.8.8" , "M2" ) ) . toEqual ( 1 ) ; expect ( await run ( "8.8.8.8" , "M2" ) ) . toEqual ( 0 ) ; expect ( await run ( "1.2.3.4" , "M2" ) ) . toEqual ( 3 ) ; expect ( await run ( "1.2.3.4" , [ "M2" ] ) ) . toEqual ( 2 ) ; expect ( await run ( [ "1.2.3.4" ] , "M2" ) ) . toEqual ( 1 ) ; expect ( await run ( "1.2.3.4" , "M2" ) ) . toEqual ( 0 ) ; expect ( await run ( "1.2.3.4" , "M2" ) ) . toEqual ( 0 ) ; expect ( await run ( [ "1.2.3.4" ] , [ "M2" ] ) ) . toEqual ( null ) ; expect ( logger . popLatest ( { level : "error" , } ) . msg ) . toStartWith ( "Error in sqrl function _getKeyList: Error: Exceeded sqrl maximum array count:: 2 of 1" ) ; expect ( logger . countErrors ( ) ) . toEqual ( 0 ) ; } ) ;