! Test HTTPGET command with invoke, timeouts, one-shot mode,
! and ability to process HTTP GET request via messages sent to it.
!
! @author  Neon Ngo
!
startmacro L:port[0]
  ! port 0 to listen on any free port
  switch INTERACTIVE interAct   GET DEF=TRUE
  switch BASELINE    baseline   GET DEF=FALSE
  switch DEBUG       debug      GET DEF=FALSE
  switch ALTTESTENV  alttestenv GET DEF=FALSE SDEF=TRUE

  set mname      "mymacro"
  set sendParams "a=test&requestNumber=1"

  ! variables for test case #4, sending multiple HTTP request via thread pool (Bug 1993)
  set requestCount  0
  set responseCount 0
  set NUM_REQUESTS  10
  set delayTime     250
  set timeout       NUM_REQUESTS*delayTime*2


  pipe on
    httpserv/id=httpserv/msgid=main/mname="^mname" port=^port

    ! NXM-3865 TODO: This test will fail because java.net.InetAddress.isSiteLocalAddress() is returning false
    !                and thus allowing the httpserv host to default to unknown
    if alttestenv and reg.httpserv.host eqs "unknown" then
      warn "************************************************************************\n        &
            ^{reg.main.name}: Skipping because in alternate test environment and\n                       &
                              Java method java.net.InetAddress.isSiteLocalAddress()\n                       &
                              returns false when it should return true.\n                       &
                              Please see JIRA issue NXM-3865 for more details.\n      &
            ************************************************************************"
      pipe stop
    endif

    set url "http://^{reg.httpserv.host}:^{reg.httpserv.port}"
    set macrourl "^{url}/^{mname}"

    ! NTN: setting ThreadPoolSize to be half the number of requests for test case #4
    httpget/id=hg timeout=3000 ThreadPoolSize=NUM_REQUESTS/2

    ! test case #1 - send HTTP GET request via a message to HTTPGET command
    message send id=hg name=HTTP_REQUEST &
      data={URL="^{macrourl}?^{sendParams}",LABEL=RESPONSE1,MSGNAME="HTTP_RESPONSE1"}

  pipe off

endmacro

procedure processMessage m:msg
  !say "^{reg.main}: Got message name=^msg.name info=^msg.info data=^msg.data"

  if msg.name eqs "EXIT" then
    say "^{reg.main}: got EXIT message"
    pipe stop

  elseif ^msg.fid eqs HTTPSERV AND msg.name eqs "HTTPGET"  then
    ! http server part to handle HTTP requests from HTTPSERV
    set socket msg.data.socket
    set params msg.data.parameters

    if params.delayTime rexists AND params.delayTime gt 0 then
      pause ^{params.delayTime}/1000    ! convert milliseconds to seconds
    endif

    invoke,,socket.openSocket()
    invoke,,socket.writeln("Got request with ^{params}")
    invoke,,socket.closeSocket()

  elseif msg.name eqs "HTTP_RESPONSE1" then
    ! verify test case #1
    assert/text="^reg.main.name: Got HTTP RESPOSNE from request sent via message" "requestNumber" SUBS msg.data
    assert/text="^reg.main.name: HTTP RESPOSNE saved to label" "requestNumber" SUBS RESPONSE1
    ! test case for BUG 2342 for getResponseCode() (success)
    invoke code hg.getResponseCode()
    assert/text="^reg.main.name: HTTP RESPONSE CODE: ^code (OK)" code eq 200

    ! start rest of cases
    ! test case #2 (test invoke and timeout for a request)
    ! this should cause request to timeout (since it blocks the macro's
    ! processMessage so that httpserv cannot forward the request to this macro
    info "The following will fail to get the Page with a SocketTimeout. (warning printout disabled)"
    invoke ,, hg.setShowWarn(false) ! disable warning printouts
    invoke x hg.getPage("^{macrourl}?a=hi")
    invoke ,, hg.setShowWarn(true)  ! enable warning printouts
    assert/text="^reg.main.name: Timeout on HTTP GET request" x EQS NULL
    ! test case for BUG 2342 for getResponseCode() (failure)
    invoke code hg.getResponseCode()
    assert/text="^reg.main.name: HTTP RESPONSE CODE: ^code (none for timeout)" code eq -1

    ! test case for BUG 2342 for setTimeoutDebug / isTimeoutDebug
    invoke origTimeoutDbg hg.isTimeoutDebug()
    assert/text="^reg.main.name: httpgetdata.isTimeoutDebug() : ^origTimeoutDbg" origTimeoutDbg rexists
    invoke ,, hg.setTimeoutDebug(true)
    invoke val hg.isTimeoutDebug()
    assert/text="^reg.main.name: httpgetdata.setTimeoutDebug(true)" val isTrue
    invoke ,, hg.setTimeoutDebug(false)
    invoke val hg.isTimeoutDebug()
    assert/text="^reg.main.name: httpgetdata.setTimeoutDebug(false)" val isFalse
    invoke ,, hg.setTimeoutDebug(origTimeoutDbg)

    ! test case #3 (check open & read timeout)
    info "The following will fail to get the Page with another SocketTimeout."

    message send id=hg name=HTTP_REQUEST &
      data={URL="^{macrourl}?delayTime=2000",OPENTIMEOUT=1000,READTIMEOUT=1000,MSGNAME="HTTP_RESPONSE2",USERDATA="joey"}

  elseif msg.name eqs "HTTP_RESPONSE2" then
    assert/text="^reg.main.name: Got HTTP RESPONSE 2 with no data b/c of timeout" ^{msg.data} NREXISTS
    ! test case for BUG 2342 for getResponseCode() (failure)
    invoke code hg.getResponseCode()
    assert/text="^reg.main.name: HTTP RESPONSE CODE: ^code (none for timeout)" code eq -1

    ! since 3.1.1: test case for entries added to QUALS field for BUG 2557
    assert/text="^reg.main.name: QUALS field exists"  msg.quals             NISNULL
    assert/text="^reg.main.name: QUALS - URL"         msg.quals.url         eqs "^{macrourl}?delayTime=2000"
    assert/text="^reg.main.name: QUALS - OpenTimeout" msg.quals.OPENTIMEOUT eq 1000
    assert/text="^reg.main.name: QUALS - ReadTimeout" msg.quals.READTIMEOUT eq 1000
    assert/text="^reg.main.name: QUALS - UserData"    msg.quals.userdata    eqs "joey"
    ! end of test cae for BUG 2557

    ! test one-shot mode (this will not block since we are getting the / (root) page)
    httpget timeout=3000 label=response2 url="^{url}"
    assert/text="^reg.main.name: One-shot mode" response2 REXISTS

    ! test case BUG 2270 (should convert input DATA (String) to a Table
    res S:tblAsString {URL="^{macrourl}?bug_id=2270",MSGNAME="HTTP_RESPONSE3"}
    message send id=hg name=HTTP_REQUEST data=tblAsString

  elseif msg.name eqs "HTTP_RESPONSE3" then
    assert/text="^reg.main.name: Got HTTP RESPONSE 3 from request with a String form of a Table" msg.data REXISTS AND "2270" SUBS msg.data
    invoke code hg.getResponseCode()
    assert/text="^reg.main.name: HTTP RESPONSE CODE: ^code (OK)" code eq 200

    ! send message to start test case #4
    message send id=main name=TEST_THREADPOOL

  elseif msg.name eqs "TEST_THREADPOOL" then
    ! test case #4 - sending multiple (10) HTTP GET request concurrently via a message to HTTPGET command
    ! NTN: set a delayTime of 250ms so that this do loop can finish before a response is sent back
    info "^reg.main.name: Testing Thread Pool with ^NUM_REQUESTS concurrent requests."
    do i 1 NUM_REQUESTS
      calc requestCount requestCount 1 +
      set sendParams "delayTime=^delayTime&num=^requestCount"
      if debug then say "DEBUG: sending thread pool request ^i params=^sendParams"
      message send id=hg name=HTTP_REQUEST &
        data={URL="^{macrourl}?^{sendParams}",READTIMEOUT=^timeout,MSGNAME="HTTP_RESPONSE4"}
    enddo
    assert/text="^reg.main.name: multiple HTTP GET request submitted concurrently (no response yet)" responseCount eq 0
    assert/text="^reg.main.name: multiple HTTP GET request submitted concurrently (count)"           requestCount  eq NUM_REQUESTS

    ! start timer to check that all request got sent/received and to end test macro
    set this.timer(0) NUM_REQUESTS/2

  elseif msg.name eqs "HTTP_RESPONSE4" then
    ! increase response count for test case #4
    calc responseCount responseCount 1 +

  elseif msg.name eqs "TIMER" then
    ! verify that all HTTP submission requests got received for test case #4
    assert/text="^reg.main.name: received all concurrently submitted HTTP GET requests" responseCount eq NUM_REQUESTS

    ! end of test cases
    pipe stop
  endif
return
