TEST_F(TestTimerTask, test_timer_fetch)
{
  ObMergerRpcStub stub;
  ThreadSpecificBuffer buffer;
  ObPacketFactory factory;
  tbnet::Transport transport;
  tbnet::DefaultPacketStreamer streamer; 
  streamer.setPacketFactory(&factory);
  transport.start();
  ObClientManager client_manager;
  EXPECT_TRUE(OB_SUCCESS == client_manager.initialize(&transport, &streamer));
  EXPECT_TRUE(OB_SUCCESS == stub.init(&buffer, &client_manager));

  int64_t timeout = 1000000;
  ObServer root_server;
  root_server.set_ipv4_addr(addr, MockRootServer::ROOT_SERVER_PORT);

  ObServer merge_server;
  ObMergerRpcProxy proxy(1, timeout, root_server, merge_server);

  EXPECT_TRUE(OB_SUCCESS != proxy.init(NULL, NULL, NULL));
  EXPECT_TRUE(OB_SUCCESS != proxy.init(&stub, NULL, NULL));

  ObMergerSchemaManager * schema = new ObMergerSchemaManager;
  EXPECT_TRUE(NULL != schema);
  ObSchemaManagerV2 temp(200);
  EXPECT_TRUE(OB_SUCCESS == schema->init(false, temp));

  ObTabletLocationCache * location = new ObMergerTabletLocationCache;
  EXPECT_TRUE(NULL != location);
  EXPECT_TRUE(OB_SUCCESS == proxy.init(&stub, schema, location));

  // not start root server
  ObMergerSchemaTask task;
  task.init(&proxy, schema);
  ObTimer timer;
  EXPECT_TRUE(OB_SUCCESS == timer.init());
  task.set_version(1024, 1025);
  EXPECT_TRUE(OB_SUCCESS == timer.schedule(task, 2000 * 1000, false));
  EXPECT_TRUE(200 == schema->get_latest_version());

  // start root server
  MockRootServer server;
  MockServerRunner test_root_server(server);
  tbsys::CThread root_server_thread;
  root_server_thread.start(&test_root_server, NULL); 
  sleep(5);

  // wait timer task processed 
  EXPECT_TRUE(1025 == schema->get_latest_version());
  timer.destroy();

  transport.stop();
  server.stop();
  sleep(5);
}
TEST_F(TestSchemaProxy, test_get)
{
  ObMergerRpcStub stub;
  ThreadSpecificBuffer buffer;
  ObPacketFactory factory;
  tbnet::Transport transport;
  tbnet::DefaultPacketStreamer streamer; 
  streamer.setPacketFactory(&factory);
  transport.start();
  ObClientManager client_manager;

  EXPECT_TRUE(OB_SUCCESS == client_manager.initialize(&transport, &streamer));
  EXPECT_TRUE(OB_SUCCESS == stub.init(&buffer, &client_manager));

  ObServer root_server;
  root_server.set_ipv4_addr(addr, MockRootServer::ROOT_SERVER_PORT);
  ObMergerRootRpcProxy root_proxy(0, timeout, root_server);

  // not init
  const ObSchemaManagerV2 * schema = NULL;
  ObMergerSchemaManager * manager = new ObMergerSchemaManager;
  EXPECT_TRUE(NULL != manager);
  int64_t timestamp = ObMergerSchemaProxy::LOCAL_NEWEST;
  ObMergerSchemaProxy proxy(&root_proxy, manager);
  EXPECT_TRUE(OB_SUCCESS == proxy.get_schema(timestamp, &schema));
  EXPECT_TRUE(schema == NULL);
  
  timestamp = 1001;
  EXPECT_TRUE(OB_SUCCESS != proxy.get_schema(timestamp, &schema));

  timestamp = ObMergerSchemaProxy::LOCAL_NEWEST;
  EXPECT_TRUE(OB_SUCCESS == root_proxy.init(&stub));
  EXPECT_TRUE(OB_SUCCESS == proxy.get_schema(timestamp, &schema));
  EXPECT_TRUE(schema == NULL);

  // init schema manger
  ObSchemaManagerV2 sample(1022);
  EXPECT_TRUE(OB_SUCCESS == manager->init(sample));

  EXPECT_TRUE(OB_SUCCESS == proxy.get_schema(timestamp, &schema));
  EXPECT_TRUE(NULL != schema);
  EXPECT_TRUE(schema->get_version() == 1022);
  EXPECT_TRUE(OB_SUCCESS == proxy.release_schema(schema));
  
  // server not start
  timestamp = 1024;
  EXPECT_TRUE(OB_SUCCESS != proxy.get_schema(timestamp, &schema));
  
  // start root server
  MockRootServer server;
  MockServerRunner test_root_server(server);
  tbsys::CThread root_server_thread;
  root_server_thread.start(&test_root_server, NULL); 
  sleep(2);
  
  // not exist but server exist
  timestamp = 1024;
  EXPECT_TRUE(OB_SUCCESS == proxy.get_schema(timestamp, &schema));
  EXPECT_TRUE(NULL != schema);
  EXPECT_TRUE(schema->get_version() == 1025);
  EXPECT_TRUE(OB_SUCCESS == proxy.release_schema(schema));

  // get server newest for init
  timestamp = 100;
  // add schema failed
  EXPECT_TRUE(OB_SUCCESS != proxy.get_schema(timestamp, &schema));
  
  // local version
  timestamp = ObMergerSchemaProxy::LOCAL_NEWEST;
  EXPECT_TRUE(OB_SUCCESS == proxy.get_schema(timestamp, &schema));
  EXPECT_TRUE(NULL != schema);
  EXPECT_TRUE(schema->get_version() == 1025);
  EXPECT_TRUE(OB_SUCCESS == proxy.release_schema(schema));
  
  if (manager)
  {
    delete manager;
    manager = NULL;
  }

  transport.stop();
  server.stop();
  sleep(5);
}
// multi-thread schema test
TEST_F(TestSchemaProxy, test_multi_schema)
{
  ObMergerRpcStub stub;
  ThreadSpecificBuffer buffer;
  ObPacketFactory factory;
  tbnet::Transport transport;
  tbnet::DefaultPacketStreamer streamer; 
  streamer.setPacketFactory(&factory);
  transport.start();
  ObClientManager client_manager;

  EXPECT_TRUE(OB_SUCCESS == client_manager.initialize(&transport, &streamer));
  EXPECT_TRUE(OB_SUCCESS == stub.init(&buffer, &client_manager));

  ObServer root_server;
  root_server.set_ipv4_addr(addr, MockRootServer::ROOT_SERVER_PORT);

  ObServer update_server;
  update_server.set_ipv4_addr(addr, MockUpdateServer::UPDATE_SERVER_PORT);
  
  ObServer merge_server;
  merge_server.set_ipv4_addr(addr, 10256);
  ObMergerRootRpcProxy root_proxy(0, timeout, root_server);
  EXPECT_TRUE(OB_SUCCESS == root_proxy.init(&stub));

  ObMergerSchemaManager * manager = new ObMergerSchemaManager;
  EXPECT_TRUE(NULL != manager);
  ObSchemaManagerV2 sample(1022);
  EXPECT_TRUE(OB_SUCCESS == manager->init(sample));
  
  ObMergerSchemaProxy proxy(&root_proxy, manager);
  // start root server
  MockRootServer server;
  MockServerRunner test_root_server(server);
  tbsys::CThread root_server_thread;
  root_server_thread.start(&test_root_server, NULL); 
  sleep(2);
  
  const int MAX_THREAD_COUNT = 15;
  pthread_t threads[MAX_THREAD_COUNT];
  for (int i = 0; i < MAX_THREAD_COUNT; ++i)
  {
    int ret = pthread_create(&threads[i], NULL, fetch_schema, &proxy);
    if (ret != OB_SUCCESS)
    {
      break;
    }
  }

  for (int i = 0; i < MAX_THREAD_COUNT; ++i)
  {
    pthread_join(threads[i], NULL);
  }
  
  if (NULL != manager)
  {
    delete manager;
    manager = NULL;
  }
  transport.stop();
  server.stop();
  sleep(5);
}
TEST_F(TestMergerVersionProxy, test_version)
{
  ObMergerRpcStub stub;
  ThreadSpecificBuffer buffer;
  ObPacketFactory factory;
  tbnet::Transport transport;
  tbnet::DefaultPacketStreamer streamer; 
  streamer.setPacketFactory(&factory);
  transport.start();
  ObClientManager client_manager;
  EXPECT_TRUE(OB_SUCCESS == client_manager.initialize(&transport, &streamer));
  EXPECT_TRUE(OB_SUCCESS == stub.init(&buffer, &client_manager));

  int64_t timeout = 1000000;
  ObServer root_server;
  root_server.set_ipv4_addr(addr, MockRootServer::ROOT_SERVER_PORT);

  ObServer merge_server;
  ObMergerRpcProxy proxy(1, timeout, root_server, merge_server);
  ObServer update_server;
  update_server.set_ipv4_addr(addr, MockUpdateServer::UPDATE_SERVER_PORT);

  proxy.set_master_ups(update_server);
  EXPECT_TRUE(OB_SUCCESS != proxy.init(NULL, NULL, NULL));
  EXPECT_TRUE(OB_SUCCESS != proxy.init(&stub, NULL, NULL));

  ObMergerSchemaManager * schema = new ObMergerSchemaManager;
  EXPECT_TRUE(NULL != schema);
  ObSchemaManagerV2 temp(200);
  EXPECT_TRUE(OB_SUCCESS == schema->init(false, temp));

  ObTabletLocationCache * location = new ObMergerTabletLocationCache;
  EXPECT_TRUE(NULL != location);
  EXPECT_TRUE(OB_SUCCESS == proxy.init(&stub, schema, location));

  int64_t version_timeout = 1000 * 1000 * 2L;
  ObMergerVersionProxy version_proxy(version_timeout);
  int64_t version = 0;

  // not init
  EXPECT_TRUE(OB_SUCCESS != version_proxy.get_version(version));
  EXPECT_TRUE(OB_SUCCESS != version_proxy.init(NULL));
  EXPECT_TRUE(OB_SUCCESS == version_proxy.init(&proxy));
  // not run server
  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(version));
  EXPECT_TRUE(-1 == version);

  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(version));
  EXPECT_TRUE(-1 == version);

  // start mock server
  MockUpdateServer server;
  MockServerRunner test_update_server(server);
  tbsys::CThread update_server_thread;
  update_server_thread.start(&test_update_server, NULL); 

  sleep(2);

  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(version));
  EXPECT_TRUE(-1 != version);

  int64_t new_version = 0;
  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version == version);

  usleep(static_cast<useconds_t>(version_timeout * 2));
  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version != version);

  version = new_version;
  new_version = 0;
  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version == version);

  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version == version);

  // cache timeout
  usleep(static_cast<useconds_t>(version_timeout * 2));
  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version != version);
  server.stop();
  version = new_version;
  new_version = 0;
  // server stoped
  usleep(static_cast<useconds_t>(version_timeout * 2));
  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version == version);

  EXPECT_TRUE(OB_SUCCESS == version_proxy.get_version(new_version));
  EXPECT_TRUE(new_version == version);

  transport.stop();
}
TEST_F(TestTimerTask, test_fetch_schema)
{
  /*
  const char * test = "test";
  printf("ret[%d]\n", memcmp(NULL, test, 0));
  printf("ret[%d]\n", memcmp(test, NULL, 0));
  */

  ObMergerRpcStub stub;
  ThreadSpecificBuffer buffer;
  ObPacketFactory factory;
  tbnet::Transport transport;
  tbnet::DefaultPacketStreamer streamer; 
  streamer.setPacketFactory(&factory);
  transport.start();
  ObClientManager client_manager;
  EXPECT_TRUE(OB_SUCCESS == client_manager.initialize(&transport, &streamer));
  EXPECT_TRUE(OB_SUCCESS == stub.init(&buffer, &client_manager));

  int64_t timeout = 100000;
  ObServer root_server;
  root_server.set_ipv4_addr(addr, MockRootServer::ROOT_SERVER_PORT);

  ObServer merge_server;
  ObMergerRpcProxy proxy(1, timeout, root_server, merge_server);

  EXPECT_TRUE(OB_SUCCESS != proxy.init(NULL, NULL, NULL));
  EXPECT_TRUE(OB_SUCCESS != proxy.init(&stub, NULL, NULL));

  ObMergerSchemaManager * schema = new ObMergerSchemaManager;
  EXPECT_TRUE(NULL != schema);
  ObSchemaManagerV2 temp(200);
  EXPECT_TRUE(OB_SUCCESS == schema->init(false, temp));

  ObTabletLocationCache * location = new ObMergerTabletLocationCache;
  EXPECT_TRUE(NULL != location);
  EXPECT_TRUE(OB_SUCCESS == proxy.init(&stub, schema, location));

  // not start root server
  ObMergerSchemaTask task;
  task.init(&proxy, schema);
  task.runTimerTask();
  EXPECT_TRUE(200 == schema->get_latest_version());

  // stat failed
  ObMergerSchemaTask task1;
  task1.init(NULL, NULL);
  task1.runTimerTask();
  EXPECT_TRUE(200 == schema->get_latest_version());

  // start root server
  MockRootServer server;
  MockServerRunner test_root_server(server);
  tbsys::CThread root_server_thread;
  root_server_thread.start(&test_root_server, NULL); 
  sleep(2);

  task.set_version(1024, 1025);
  task.runTimerTask();
  // root server returned
  EXPECT_TRUE(1025 == schema->get_latest_version());

  transport.stop();
  server.stop();
  sleep(5);
}