/*
 *------------------------------------------------------------------
 * test.c -- VPP API/Stats tests
 * 
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 *------------------------------------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>


#include <vnet/vnet.h>
#include <vlib/vlib.h>
#include <vlib/unix/unix.h>
#include <vlibapi/api.h>
#include <vppinfra/time.h>
#include <signal.h>
#include "vppapiclient.h"
#include "stat_client.h"

#include <vlibmemory/vlib.api_enum.h>
#include <vlibmemory/vlib.api_types.h>
#include <vlibmemory/memclnt.api_enum.h>
#include <vlibmemory/memclnt.api_types.h>

#include <vpp/api/vpe.api_enum.h>
#include <vpp/api/vpe.api_types.h>

volatile int sigterm_received = 0;
volatile u32 result_ready;
volatile u16 result_msg_id;

/* M_NOALLOC: construct, but don't yet send a message */

#define M_NOALLOC(T,t)                          \
  do {						\
    result_ready = 0;                           \
    clib_memset (mp, 0, sizeof (*mp));		\
    mp->_vl_msg_id = ntohs (VL_API_##T);	\
    mp->client_index = am->my_client_index;	\
  } while(0);



void
wrap_vac_callback (unsigned char *data, int len)
{
  result_ready = 1;
  result_msg_id = ntohs(*((u16 *)data));
}

static void
test_connect ()
{
  static int i;
  int rv = vac_connect("vac_client", NULL, wrap_vac_callback, 32 /* rx queue-length*/);
  if (rv != 0) {
    printf("Connect failed: %d\n", rv);
    exit(rv);
  }
  printf(".");
  vac_disconnect();
  i++;
}

static void
test_messages (void)
{
  api_main_t * am = vlibapi_get_main();
  vl_api_show_version_t message;
  vl_api_show_version_t *mp;
  int async = 1;

  int rv = vac_connect("vac_client", NULL, wrap_vac_callback, 32 /* rx queue-length*/);
  if (rv != 0) {
    printf("Connect failed: %d\n", rv);
    exit(rv);
  }

  double timestamp_start = unix_time_now_nsec() * 1e-6;
 
  /*
   * Test vpe_api_write and vpe_api_read to send and recv message for an
   * API 
   */
  int i;
  long int no_msgs = 10000;
  mp = &message;

  for (i = 0; i < no_msgs; i++) {
    /* Construct the API message */
    M_NOALLOC(SHOW_VERSION, show_version);
    vac_write((char *)mp, sizeof(*mp));
#ifndef __COVERITY__
    /* As given, async is always 1. Shut up Coverity about it */
    if (!async)
      while (result_ready == 0);
#endif
  }
  if (async) {
    vl_api_control_ping_t control;
    vl_api_control_ping_t *mp;
    mp = &control;
    M_NOALLOC(CONTROL_PING, control_ping);
    vac_write((char *)mp, sizeof(*mp));

    while (result_msg_id != VL_API_CONTROL_PING_REPLY);
  }

  double timestamp_end = unix_time_now_nsec() * 1e-6;
  printf("\nTook %.2f msec, %.0f msgs/msec \n", (timestamp_end - timestamp_start),
	 no_msgs/(timestamp_end - timestamp_start));
  printf("Exiting...\n");
  vac_disconnect();
}

static void
test_stats (void)
{
  clib_mem_trace_enable_disable(1);
  clib_mem_trace (1);

  int rv = stat_segment_connect (STAT_SEGMENT_SOCKET_FILE);
  assert(rv == 0);

  u32 *dir;
  int i, k;
  stat_segment_data_t *res;
  u8 **pattern = 0;
  vec_add1(pattern, (u8 *)"/if/names");
  vec_add1(pattern, (u8 *)"/err");

  dir = stat_segment_ls ((u8 **)pattern);

  res = stat_segment_dump (dir);
  for (i = 0; i < vec_len (res); i++) {
    switch (res[i].type) {
    case STAT_DIR_TYPE_NAME_VECTOR:
      if (res[i].name_vector == 0)
	continue;
      for (k = 0; k < vec_len (res[i].name_vector); k++)
	if (res[i].name_vector[k])
	  fformat (stdout, "[%d]: %s %s\n", k, res[i].name_vector[k],
		   res[i].name);
      break;
    default:
      assert(0);
    }
  }
  stat_segment_data_free (res);
  stat_segment_disconnect();

  vec_free(pattern);
  vec_free(dir);

  (void) clib_mem_trace_enable_disable (0);
  u8 *leak_report = format (0, "%U", format_clib_mem_heap, 0,
                            1 /* verbose, i.e. print leaks */ );
  printf("%s", leak_report);
  vec_free (leak_report);
  clib_mem_trace (0);
}

int main (int argc, char ** argv)
{
  clib_mem_init (0, 3ULL << 30);
  test_stats();

  int i;

  for (i = 0; i < 1000; i++) {
    test_connect();
  }
  test_messages();
  exit (0);
}
