普通文本  |  236行  |  6.26 KB

// Copyright (c) 2013 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 <gtest/gtest.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include "cras_alert.h"

namespace {

void callback1(void *arg, void *data);
void callback2(void *arg, void *data);
void prepare(struct cras_alert *alert);

struct cb_data_struct {
  int data;
};

static int cb1_called = 0;
static cb_data_struct cb1_data;
static int cb2_called = 0;
static int cb2_set_pending = 0;
static int prepare_called = 0;

void ResetStub() {
  cb1_called = 0;
  cb2_called = 0;
  cb2_set_pending = 0;
  prepare_called = 0;
  cb1_data.data = 0;
}

class Alert: public testing::Test {
  protected:
    virtual void SetUp() {
      cb1_data.data = 0;
    }

    virtual void TearDown() {
    }
};

TEST_F(Alert, OneCallback) {
  struct cras_alert *alert = cras_alert_create(NULL, 0);
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  cras_alert_pending(alert);
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, cb1_called);
  cras_alert_destroy(alert);
}

TEST_F(Alert, OneCallbackPost2Call1) {
  struct cras_alert *alert = cras_alert_create(NULL, 0);
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  // Alert twice, callback should only be called once.
  cras_alert_pending(alert);
  cras_alert_pending(alert);
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, cb1_called);
  cras_alert_destroy(alert);
}

TEST_F(Alert, OneCallbackWithData) {
  struct cras_alert *alert = cras_alert_create(NULL, 0);
  struct cb_data_struct data = {1};
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  cras_alert_pending_data(alert, (void *)&data, sizeof(struct cb_data_struct));
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, cb1_called);
  EXPECT_EQ(1, cb1_data.data);
  cras_alert_destroy(alert);
}

TEST_F(Alert, OneCallbackTwoDataCalledOnce) {
  struct cras_alert *alert = cras_alert_create(NULL, 0);
  struct cb_data_struct data = {1};
  struct cb_data_struct data2 = {2};
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  // Callback called with last data only.
  cras_alert_pending_data(
      alert, (void *)&data, sizeof(struct cb_data_struct));
  cras_alert_pending_data(
      alert, (void *)&data2, sizeof(struct cb_data_struct));
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, cb1_called);
  EXPECT_EQ(2, cb1_data.data);
  cras_alert_destroy(alert);
}

TEST_F(Alert, OneCallbackTwoDataKeepAll) {
  struct cras_alert *alert = cras_alert_create(
                                 NULL, CRAS_ALERT_FLAG_KEEP_ALL_DATA);
  struct cb_data_struct data = {1};
  struct cb_data_struct data2 = {2};
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  // Callbacks with data should each be called.
  cras_alert_pending_data(alert, (void *)&data, sizeof(cb_data_struct));
  cras_alert_pending_data(alert, (void *)&data2, sizeof(cb_data_struct));
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(2, cb1_called);
  EXPECT_EQ(2, cb1_data.data);
  cras_alert_destroy(alert);
}

TEST_F(Alert, TwoCallbacks) {
  struct cras_alert *alert = cras_alert_create(NULL, 0);
  cras_alert_add_callback(alert, &callback1, NULL);
  cras_alert_add_callback(alert, &callback2, NULL);
  ResetStub();
  cras_alert_pending(alert);
  EXPECT_EQ(0, cb1_called);
  EXPECT_EQ(0, cb2_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, cb1_called);
  EXPECT_EQ(1, cb2_called);
  cras_alert_destroy(alert);
}

TEST_F(Alert, NoPending) {
  struct cras_alert *alert = cras_alert_create(NULL, 0);
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(0, cb1_called);
  cras_alert_destroy(alert);
}

TEST_F(Alert, PendingInCallback) {
  struct cras_alert *alert1 = cras_alert_create(NULL, 0);
  struct cras_alert *alert2 = cras_alert_create(NULL, 0);
  cras_alert_add_callback(alert1, &callback1, NULL);
  cras_alert_add_callback(alert2, &callback2, alert1);
  ResetStub();
  cras_alert_pending(alert2);
  EXPECT_EQ(0, cb1_called);
  EXPECT_EQ(0, cb2_called);
  cb2_set_pending = 1;
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, cb1_called);
  EXPECT_EQ(1, cb2_called);
  cras_alert_destroy(alert1);
  cras_alert_destroy(alert2);
}

TEST_F(Alert, Prepare) {
  struct cras_alert *alert = cras_alert_create(prepare, 0);
  cras_alert_add_callback(alert, &callback1, NULL);
  ResetStub();
  cras_alert_pending(alert);
  EXPECT_EQ(0, cb1_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, prepare_called);
  EXPECT_EQ(1, cb1_called);
  cras_alert_destroy(alert);
}

TEST_F(Alert, TwoAlerts) {
  struct cras_alert *alert1 = cras_alert_create(prepare, 0);
  struct cras_alert *alert2 = cras_alert_create(prepare, 0);
  cras_alert_add_callback(alert1, &callback1, NULL);
  cras_alert_add_callback(alert2, &callback2, NULL);

  ResetStub();
  cras_alert_pending(alert1);
  EXPECT_EQ(0, cb1_called);
  EXPECT_EQ(0, cb2_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, prepare_called);
  EXPECT_EQ(1, cb1_called);
  EXPECT_EQ(0, cb2_called);

  ResetStub();
  cras_alert_pending(alert2);
  EXPECT_EQ(0, cb1_called);
  EXPECT_EQ(0, cb2_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(1, prepare_called);
  EXPECT_EQ(0, cb1_called);
  EXPECT_EQ(1, cb2_called);

  ResetStub();
  cras_alert_pending(alert1);
  cras_alert_pending(alert2);
  EXPECT_EQ(0, cb1_called);
  EXPECT_EQ(0, cb2_called);
  cras_alert_process_all_pending_alerts();
  EXPECT_EQ(2, prepare_called);
  EXPECT_EQ(1, cb1_called);
  EXPECT_EQ(1, cb2_called);

  cras_alert_destroy_all();
}

void callback1(void *arg, void *data)
{
  cb1_called++;
  if(data)
    cb1_data.data = ((struct cb_data_struct *)data)->data;
}

void callback2(void *arg, void *data)
{
  cb2_called++;
  if (cb2_set_pending) {
    cb2_set_pending = 0;
    cras_alert_pending((struct cras_alert *)arg);
  }
}

void prepare(struct cras_alert *alert)
{
  prepare_called++;
  return;
}

}

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