普通文本  |  201行  |  4.75 KB

// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>
#include <gtest/gtest.h>

extern "C" {
#include "cras_tm.h"
#include "cras_types.h"
}

namespace {

class TimerTestSuite : public testing::Test{
  protected:
    virtual void SetUp() {
      tm_ = cras_tm_init();
      ASSERT_TRUE(tm_);
    }

    virtual void TearDown() {
      cras_tm_deinit(tm_);
    }

  struct cras_tm *tm_;
};

static struct timespec time_now;
static unsigned int test_cb_called;
static unsigned int test_cb2_called;

void test_cb(struct cras_timer *t, void *data) {
  test_cb_called++;
}

void test_cb2(struct cras_timer *t, void *data) {
  test_cb2_called++;
}

TEST_F(TimerTestSuite, InitNoTimers) {
  struct timespec ts;
  int timers_active;

  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  EXPECT_FALSE(timers_active);
}

TEST_F(TimerTestSuite, AddTimer) {
  struct cras_timer *t;

  t = cras_tm_create_timer(tm_, 10, test_cb, this);
  EXPECT_TRUE(t);
}

TEST_F(TimerTestSuite, AddLongTimer) {
  struct timespec ts;
  struct cras_timer *t;
  int timers_active;

  time_now.tv_sec = 0;
  time_now.tv_nsec = 0;
  t = cras_tm_create_timer(tm_, 10000, test_cb, this);
  EXPECT_TRUE(t);

  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);
  EXPECT_EQ(10, ts.tv_sec);
  EXPECT_EQ(0, ts.tv_nsec);

  // All timers already fired.
  time_now.tv_sec = 12;
  time_now.tv_nsec = 0;
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);
  EXPECT_EQ(0, ts.tv_sec);
  EXPECT_EQ(0, ts.tv_nsec);

  cras_tm_cancel_timer(tm_, t);
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  EXPECT_FALSE(timers_active);
}

TEST_F(TimerTestSuite, AddRemoveTimer) {
  struct timespec ts;
  struct cras_timer *t;
  int timers_active;

  time_now.tv_sec = 0;
  time_now.tv_nsec = 0;
  t = cras_tm_create_timer(tm_, 10, test_cb, this);
  EXPECT_TRUE(t);

  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);
  EXPECT_EQ(0, ts.tv_sec);
  EXPECT_EQ(10 * 1000000, ts.tv_nsec);

  // All timers already fired.
  time_now.tv_sec = 1;
  time_now.tv_nsec = 0;
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);
  EXPECT_EQ(0, ts.tv_sec);
  EXPECT_EQ(0, ts.tv_nsec);

  cras_tm_cancel_timer(tm_, t);
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  EXPECT_FALSE(timers_active);
}

TEST_F(TimerTestSuite, AddTwoTimers) {
  struct timespec ts;
  struct cras_timer *t1, *t2;
  int timers_active;
  static const unsigned int t1_to = 10;
  static const unsigned int t2_offset = 5;
  static const unsigned int t2_to = 7;

  time_now.tv_sec = 0;
  time_now.tv_nsec = 0;
  t1 = cras_tm_create_timer(tm_, t1_to, test_cb, this);
  ASSERT_TRUE(t1);

  time_now.tv_sec = 0;
  time_now.tv_nsec = t2_offset;
  t2 = cras_tm_create_timer(tm_, t2_to, test_cb2, this);
  ASSERT_TRUE(t2);

  /* Check That the right calls are made at the right times. */
  test_cb_called = 0;
  test_cb2_called = 0;
  time_now.tv_sec = 0;
  time_now.tv_nsec = t2_to * 1000000 + t2_offset;
  cras_tm_call_callbacks(tm_);
  EXPECT_EQ(0, test_cb_called);
  EXPECT_EQ(1, test_cb2_called);
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);

  time_now.tv_sec = 0;
  time_now.tv_nsec = t2_offset;
  t2 = cras_tm_create_timer(tm_, t2_to, test_cb2, this);
  ASSERT_TRUE(t2);

  test_cb_called = 0;
  test_cb2_called = 0;
  time_now.tv_sec = 0;
  time_now.tv_nsec = t1_to * 1000000;
  cras_tm_call_callbacks(tm_);
  EXPECT_EQ(1, test_cb_called);
  EXPECT_EQ(1, test_cb2_called);
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  EXPECT_FALSE(timers_active);

  time_now.tv_sec = 0;
  time_now.tv_nsec = 0;
  t1 = cras_tm_create_timer(tm_, t1_to, test_cb, this);
  ASSERT_TRUE(t1);

  time_now.tv_sec = 0;
  time_now.tv_nsec = t2_offset;
  t2 = cras_tm_create_timer(tm_, t2_to, test_cb2, this);
  ASSERT_TRUE(t2);

  /* Timeout values returned are correct. */
  time_now.tv_sec = 0;
  time_now.tv_nsec = 50;
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);
  EXPECT_EQ(0, ts.tv_sec);
  EXPECT_EQ(t2_to * 1000000 + t2_offset - time_now.tv_nsec, ts.tv_nsec);

  cras_tm_cancel_timer(tm_, t2);

  time_now.tv_sec = 0;
  time_now.tv_nsec = 60;
  timers_active = cras_tm_get_next_timeout(tm_, &ts);
  ASSERT_TRUE(timers_active);
  EXPECT_EQ(0, ts.tv_sec);
  EXPECT_EQ(t1_to * 1000000 - time_now.tv_nsec, ts.tv_nsec);
  cras_tm_cancel_timer(tm_, t1);
}

/* Stubs */
extern "C" {

int clock_gettime(clockid_t clk_id, struct timespec *tp) {
  *tp = time_now;
  return 0;
}

}  // extern "C"

}  //  namespace

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}