#include "kernel/types.h"
#include "user/user.h"

#define WORK 20000000000L
#define MAXTIME 500

int *
test(int checkPause, int checkFork)
{
  int id = fork();
  int *result = malloc(2 * sizeof(int));

  // Fork 10 direct child processes, id is 0 for all child processes and
  // non zero for the parent process
  for (int i = 0; i < 10 && id && (id = fork()); i++)
    ;

  int baseTime = uptime();
  int status;

  // Let the children do work
  if (!id) {
    int forkCount = 0;

    for (long long i = 0;; i++) {
      if (i % (WORK / 509) == 0) {
        pause(17);
      }
      if (i % (WORK / 105) == 0) {
        fork();
        forkCount++;
      }
      if (i % (WORK / 704) == 0 && uptime() > baseTime + MAXTIME)
        break;
    }

    for (int i = 0; i < forkCount; i++)
      wait(&status);

    exit(0);
  } else {
    int errorCount = 0;

    while (1) {
      if (ps((int)(errorCount < 5))) {
        result[0]++;
        errorCount++;
      }

      pause(7);
      result[1]++;

      if (uptime() > baseTime + MAXTIME)
        break;
    }
  }

  return result;
}

int
main()
{
  printf("=================================\n");
  printf("-----RUNNING TESTCASE-POLICY-----\n");
  printf("=================================\n");

  int status;
  int *result = test(1, 1);

  for (int i = 0; i < 10; i++)
    wait(&status);

  if (result[0]) {
    printf("===========================\n");
    printf("------TESTCASE FAILED------\n");
    printf("Unfair checks : %d/%d\n", result[0], result[1]);
    printf("===========================\n");
  } else {
    printf("===========================\n");
    printf("------TESTCASE PASSED------\n");
    printf("Unfair checks : %d/%d\n", result[0], result[1]);
    printf("===========================\n");
  }
}
