--Test program for MoA.
--If the output process receives events from the MySQL process in wrong order
--then this test program chash with a runtime error.
--Compile with -d for more detailed information about runtime errors.

-- The database have 3 tables:
--    an empty one (t0)
--    a table with one row (t1)
--    a table with 3 rows (t3)
-- This is for testing query, query.row, query.all and remaining.rows
-- If successfull the program with deadlock with one procces alive, the
-- mergechar PROC

#INCLUDE "moa.module"
#INCLUDE "course.module"

PROC mergechar([2]CHAN OF BYTE in?,CHAN OF BYTE out!)
  BYTE b:
  WHILE TRUE
    ALT i = 0 FOR 2
      in[i] ? b
        out ! b
:
                      
PROC the.test(CHAN MYSQL.CONTROL control ,CHAN MYSQL.RESULT in, CHAN BYTE out)
  SEQ
    --CONNECTION
    in ? CASE 
      connected
        SEQ
          out.string("connected*n",0,out)


    -- QUERY AND TESTING next.row
    control ! query ; "select ** from t0"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    -- NEXT ROW FOR 0 ROWS
    SEQ i=0 FOR 1
      control ! next.row
    in ? CASE
      end.of.data
        out.string("next for empty set ok*n",0,out) 

    --NEXT ROW FOR 1 ROWS
    control ! query ; "select ** from t1"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    MOBILE []MOBILE []BYTE row:
    SEQ i=0 FOR 1
      SEQ
        control ! next.row
        in ? CASE
          data.row ;row
            out.string("fetched out *n",0,out)
    control ! next.row
    in ? CASE
      end.of.data
        out.string("next for 1 row set ok*n",0,out) 
    --NEXT ROW FOR 3 ROWS
    control ! query ; "select ** from t3"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    MOBILE []MOBILE []BYTE row:
    SEQ i=0 FOR 3
      SEQ
        control ! next.row
        in ? CASE
          data.row ;row
            out.string("fetched row *n",0,out)
    control ! next.row
    in ? CASE
      end.of.data
        out.string("next for 3 row set ok*n",0,out) 
    -- QUERY.ROW FOR 0
    control ! query.row ; "select ** from t0"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)

    in ? CASE
      end.of.data
        out.string("query.row for 0 rows ok*n",0,out)
    -- QUERY.ROW FOR 1
    control ! query.row ; "select ** from t1"
    in ? CASE
      INT rows:
      data.ready;rows
        out.string("data ready*n",0,out) 
    SEQ i=0 FOR 1
      in ? CASE
        MOBILE []MOBILE []BYTE row:
        data.row ; row 
          out.string("fetched row from t1 *n",0,out)
    control ! next.row
    in ? CASE
      end.of.data
        out.string("query.row for 1 rows ok",0,out)
    -- QUERY.ROW FOR 3
    control ! query.row ; "select ** from t3"
    in ? CASE
      INT rows:
      data.ready;rows
        out.string("data ready*n",0,out) 
    SEQ i=0 FOR 3
      SEQ
        in ? CASE
          MOBILE []MOBILE []BYTE row:
          data.row ; row 
            out.string("fetched row *n",0,out)
        control ! next.row
    in ? CASE
      end.of.data
        out.string("query.row for 3 rows ok*n",0,out)
    --REMAINING FOR 0 ROWS
    control ! query ; "select ** from t0"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    control ! remaining.rows
    in ? CASE
      end.of.data
        out.string("remaining.rows for 0 ok*n",0,out)
    -- REMAINING FOR 1
    control ! query ; "select ** from t1"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    control ! remaining.rows
    SEQ i=0 FOR 1
      SEQ
        in ? CASE
          MOBILE []MOBILE []BYTE row:
          data.row ; row 
            out.string("fetched row *n",0,out)
    in ? CASE
      end.of.data
        out.string("remaining.rows for 1 ok*n",0,out)
    -- REMAINING FOR 3
    control ! query ; "select ** from t3"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    control ! remaining.rows
    SEQ i=0 FOR 3
      SEQ
        in ? CASE
          MOBILE []MOBILE []BYTE row:
          data.row ; row 
            out.string("fetched row *n",0,out)
    in ? CASE
      end.of.data
        out.string("remaining.rows for 3 ok*n",0,out)
    --TEST all.rows
    control ! query.all ; "select ** from t0"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    SEQ i=0 FOR 0
      SEQ
        in ? CASE
          MOBILE []MOBILE []BYTE row:
          data.row ; row 
            out.string("fetched row *n",0,out)
    in ? CASE
      end.of.data
        out.string("all.rows for 0 ok*n",0,out)

    --TEST all.rows
    control ! query.all ; "select ** from t1"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    SEQ i=0 FOR 1
      SEQ
        in ? CASE
          MOBILE []MOBILE []BYTE row:
          data.row ; row 
            out.string("fetched row *n",0,out)
    in ? CASE
      end.of.data
        out.string("all.rows for 1 ok*n",0,out)

    --TEST all.rows
    control ! query.all ; "select ** from t3"
    INT rows:
    in ? CASE
      data.ready;rows
        out.string("data ready*n",0,out)
    SEQ i=0 FOR 3
      SEQ
        in ? CASE
          MOBILE []MOBILE []BYTE row:
          data.row ; row 
            out.string("fetched row *n",0,out)
    in ? CASE
      end.of.data
        out.string("all.rows for 3 ok*n",0,out)
    
    --AFFECTED ROWS
    control ! query; "update t3 set s=3"
    in ? CASE
      INT rows:
      data.ready; rows
        SEQ
          out.string("data ready rows : ",0,out)
          out.int(rows,0,out)
          out.string("*n",0,out)
    control ! affected.rows
    in ? CASE
      INT arows:
      data.affected.rows ; arows
        SEQ
          out.string("data affected rows : ",0,out)
          out.int(arows,0,out)
          out.string("*n",0,out)
      
    -- QUIT
    control ! quit
    in ? CASE
      quit
        SEQ
          out.string("quit*n",0,out)
:

PROC main(CHAN BYTE kyb,scr,err)
  [2]CHAN OF BYTE merge:
  CHAN MYSQL.CONTROL control1:
  CHAN MYSQL.RESULT result1:
  CHAN MYSQL.CONTROL control2:
  CHAN MYSQL.RESULT result2:
  BOOL init.error:
  SEQ
    MySQL.init(init.error)
    PAR
      the.test(control1,result1,merge[0])
      MySQL(control1,result1,"bach-1","root","latte","test",0,"")
      the.test(control2,result2,merge[1])
      MySQL(control2,result2,"bach-1","root","latte","test",0,"")
      mergechar(merge,scr)
    MySQL.end()
:
