深入理解Android gtest 测试框架

首先#include <gtest/gtest.h>,当然工程的头文件路径要设置正确

1.简单测试TEST

 Cpp代码  收藏代码

  1. #include <gtest/gtest.h>  
  2.  int Factorial( int n )  
  3.  {  
  4.   if(n==2) return 100; //故意出个错,嘻嘻  
  5.   return n<=0? 1 : n*Factorial(n - 1);  
  6.  }  
  7.  //用TEST做简单测试  
  8.  TEST(TestFactorial, ZeroInput) //第一个参数是测试用例名,第二个参数是测试名:随后的测试结果将以"测试用例名.测试名"的形式给出  
  9.  {  
  10.   EXPECT_EQ(1, Factorial(0));  //EXPECT_EQ稍候再说,现在只要知道它是测试两个数据是否相等的就行了。  
  11.  }  
  12.   
  13.  TEST(TestFactorial, OtherInput)  
  14.  {  
  15.   EXPECT_EQ(1, Factorial(1));  
  16.   EXPECT_EQ(2, Factorial(2));  
  17.   EXPECT_EQ(6, Factorial(3));  
  18.   EXPECT_EQ(40320, Factorial(8));  
  19.  }   
  20.   
  21.  int main(int argc, char* argv[])  
  22.  {  
  23.   testing::InitGoogleTest(&argc,argv); //用来处理Test相关的命令行开关,如果不关注也可不加  
  24.   RUN_ALL_TESTS();  //看函数名就知道干啥了  
  25.       std::cin.get();   //只是让它暂停而已,不然一闪就没了  
  26.       return 0;  
  27.  }  
 

 

2.多个测试场景需要相同数据配置的情况,用TEST_F

Cpp代码   收藏代码
  1.  //用TEST_F做同配置的系列测试  
  2.  typedef std::basic_string<TCHAR> tstring;  
  3.  struct FooTest : testing::Test {  
  4.   //这里定义要测试的东东  
  5.   tstring strExe;  
  6.   //可以利用构造、析构来初始化一些参数  
  7.   FooTest() {}  
  8.   virtual ~FooTest() {}  
  9.   
  10.  //如果构造、析构还不能满足你,还有下面两个虚拟函数  
  11.  virtual void SetUp() {  
  12.   // 在构造后调用  
  13.   strExe.resize(MAX_PATH);  
  14.   GetModuleFileName(NULL, &strExe[0], MAX_PATH);  
  15.  }  
  16.   
  17.  virtual void TearDown() { }   // 在析构前调用  
  18. };  
  19.   
  20. tstring getfilename(const tstring &full)  //偶写的从完整路径里取出文件名的函数(路径分隔符假定为'\\')  
  21. {  
  22.  return full.substr(full.rfind(_T('\\')));  
  23. }  
  24.   
  25. tstring getpath(const tstring &full)   //偶写的从完整路径里取出路径名的函数(Windows路径)  
  26. {  
  27.  return full.substr(0, full.rfind(_T('\\')));  
  28. }  
  29.   
  30. TEST_F(FooTest, Test_GFN) //测试getfilename函数  
  31. {  
  32.  EXPECT_STREQ(_T("Projectexe"), getfilename(strExe).c_str());  
  33. }  
  34.   
  35. TEST_F(FooTest, Test_GP) //测试getpath函数  
  36. {  
  37.  EXPECT_STREQ(_T("D:\\Code\\libs\\google\\gtest-1\\BCC_SPC\\bcc\\ex"), getpath(strExe).c_str());  
  38. }  
  39.   
  40. int main(int argc, TCHAR* argv[])  //主函数还是一样地  
  41. {  
  42.  testing::InitGoogleTest(&argc,argv);  
  43.  RUN_ALL_TESTS();  
  44.      std::cin.get();  
  45.      return 0;  
  46. }  
 

 

快速入门:
Google提供了两种断言形式,一种以ASSERT_开头,另一种以EXPECT_开头,它们的区别是ASSERT_*一旦失败立马退出,而EXPECT_还能继续下去。

断言列表:

真假条件测试:

 

致命断言非致命断言验证条件
ASSERT_TRUE(condition );EXPECT_TRUE(condition );condition 为真
ASSERT_FALSE(condition );EXPECT_FALSE(condition );condition 为假

数据对比测试:

 

致命断言非致命断言验证条件
ASSERT_EQ(期望值 , 实际值 );EXPECT_EQ(期望值 , 实际值 );期望值 == 实际值
ASSERT_NE(val1 , val2 );EXPECT_NE(val1 , val2 );val1 != val2
ASSERT_LT(val1 , val2 );EXPECT_LT(val1 , val2 );val1 < val2
ASSERT_LE(val1 , val2 );EXPECT_LE(val1 , val2 );val1 <= val2
ASSERT_GT(val1 , val2 );EXPECT_GT(val1 , val2 );val1 > val2
ASSERT_GE(val1 , val2 );EXPECT_GE(val1 , val2 );val1 >= val2

字符串(针对C形式的字符串,即char*或wchar_t*)对比测试:

 

致命断言非致命断言验证条件
ASSERT_STREQ(expected_str , actual_str );EXPECT_STREQ(expected_str , actual_str );两个C字符串有相同的内容
ASSERT_STRNE(str1 , str2 );EXPECT_STRNE(str1 , str2 );两个C字符串有不同的内容
ASSERT_STRCASEEQ(expected_str , actual_str );EXPECT_STRCASEEQ(expected_str , actual_str );两个C字符串有相同的内容,忽略大小写
ASSERT_STRCASENE(str1 , str2 );EXPECT_STRCASENE(str1 , str2 );两个C字符串有不同的内容,忽略大小写

 

TEST宏:

TEST宏的作用是创建一个简单测试,它定义了一个测试函数,在这个函数里可以使用任何C++代码并使用上面提供的断言来进行检查。

TEST的第一个 参数是测试用例名,第二个 参数是测试用例中某项测试的名称。一个测试用例可以包含任意数量的独立测试。这两个参数组成了一个测试的全称。

就前面的例子来说:

我们要测试这个函数:int Factorial(int n); // 返回n的阶乘

我们的测试用例是:测试输入0的情况,测试输入其它数据的情况,于是就有了:

  1. TEST(TestFactorial, ZeroInput)  //第一个参数是测试用例名,第二个参数是测试名:随后的测试结果将以"测试用例名.测试名"的形式给出
  2. {
  3.  EXPECT_EQ(1, Factorial(0));   //EXPECT_EQ稍候再说,现在只要知道它是测试两个数据是否相等的就行了。
  4. }

  5. TEST(TestFactorial, OtherInput)
  6. {
  7.  EXPECT_EQ(1, Factorial(1));
  8.  EXPECT_EQ(2, Factorial(2));
  9.  EXPECT_EQ(6, Factorial(3));
  10.  EXPECT_EQ(40320, Factorial(8));
  11. }

 

Google Test根据测试用例来分组收集测试结果,因此,逻辑相关的测试应该在同一测试用例中;换句话说,它们的TEST()的第一个参数应该是一样的。在上面的 例子中,我们有两个测试,ZeroInput和OtherInput,它们都属于同一个测试用例TestFactorial。

 

TEST_F宏:

TEST_F宏用于在多个测试中使用同样的数据配置,所以它又叫:测试夹具(Test Fixtures)

如果我们的多个测试要使用相同的数据(如前例中,我们的Test_GFN和Test_GP都使用程序自身的完整文件名来测试),就可以采用一个测试夹具。

要创建测试固件,只需:

  1. 创建一个类继承自testing::Test。将其中的成员声明为protected:或是public:,因为我们想要从子类中存取夹具成员。
  2. 在该类中声明测试中所要使用到的数据。
  3. 如果需要,编写一个默认构造函数或者SetUp()函数来为每个测试准备对象。
  4. 如果需要,编写一个析构函数或者TearDown()函数来释放你在SetUp()函数中申请的资源。
  5. 如果需要,定义你的测试所需要共享的子程序。

当我们要使用固件时,使用TEST_F()替换掉TEST(),它允许我们存取测试固件中的对象和子程序:

TEST_F(test_case_name, test_name) {
... test body ...
}

与TEST()一样,第一个参数是测试用例的名称,但对TEST_F()来说,这个名称必须与测试夹具类的名称一样。

对于TEST_F()中定义的每个 测试,Google Test将会:

  1. 创建一个全新的测试夹具
  2. 通过SetUp()初始化它,
  3. 运行测试
  4. 调用TearDown()来进行清理工作
  5. 删除测试夹具。

注意,同一测试用例中,不同的测试拥有不同的测试夹具。Google Test不会对多个测试重用一个测试夹具,测试对测试夹具的改动并不会影响到其他测试。

 

调用测试

TEST()和TEST_F()向Google Test隐式注册它们的测试。因此,与很多其他的C++测试框架不同,你不需要为了运行你定义的测试而将它们全部再列出来一次。

在定义好测试后,你可以通过RUN_ALL_TESTS()来运行它们,如果所有测试成功,该函数返回0,否则会返回1.注意RUN_ALL_TESTS()会运行你链接到的所有测试——它们可以来自不同的测试用例,甚至是来自不同的文件。

当被调用时,RUN_ALL_TESTS()宏会:

  1. 保存所有的Google Test标志。
  2. 为一个测试创建测试夹具对象。
  3. 调用SetUp()初始化它。
  4. 在固件对象上运行测试。
  5. 调用TearDown()清理夹具。
  6. 删除固件。
  7. 恢复所有Google Test标志的状态。
  8. 重复上诉步骤,直到所有测试完成。

此外,如果第二步时,测试夹具的构造函数产生一个致命错误,继续执行3至5部显然没有必要,所以它们会被跳过。与之相似,如果第3部产生致命错误,第4部也会被跳过。

重要:你不能忽略掉RUN_ALL_TESTS()的返回值,否则gcc会报一个编译错误。这样设计的理由是自动化测试服务会根据测试退出返回码来 决定一个测试是否通过,而不是根据其stdout/stderr输出;因此你的main()函数必须返回RUN_ALL_TESTS()的值。

而且,你应该只调用RUN_ALL_TESTS()一次。多次调用该函数会与Google Test的一些高阶特性(如线程安全死亡测试thread-safe death tests)冲突,因而是不被支持的。

 

编写 main() 函数

你可以从下面这个模板开始:

  1. #include "this/package/foo.h"
  2. #include <gtest/gtest.h>
  3. namespace  {
  4. // 测试Foo类的测试固件
  5. class  FooTest :  public  testing::Test {
  6. protected :
  7.    // You can remove any or all of the following functions if its body
  8.    // is empty.
  9.   FooTest() {
  10.      // You can do set-up work for each test here.
  11.   }
  12.    virtual  ~FooTest() {
  13.      // You can do clean-up work that doesn't throw exceptions here.
  14.   }
  15.    // If the constructor and destructor are not enough for setting up
  16.    // and cleaning up each test, you can define the following methods:
  17.    virtual   void  SetUp() {
  18.      // Code here will be called immediately after the constructor (right
  19.      // before each test).
  20.   }
  21.    virtual   void  TearDown() {
  22.      // Code here will be called immediately after each test (right
  23.      // before the destructor).
  24.   }
  25.    // Objects declared here can be used by all tests in the test case for Foo.
  26. };
  27. // Tests that the Foo::Bar() method does Abc.
  28. TEST_F(FooTest, MethodBarDoesAbc) {
  29.    const  string input_filepath =  "this/package/testdata/myinputfile.dat" ;
  30.    const  string output_filepath =  "this/package/testdata/myoutputfile.dat" ;
  31.   Foo f;
  32.   EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
  33. }
  34. // Tests that Foo does Xyz.
  35. TEST_F(FooTest, DoesXyz) {
  36.    // Exercises the Xyz feature of Foo.
  37. }
  38. }   // namespace
  39. int  main( int  argc,  char  **argv) {
  40.   testing::InitGoogleTest(&argc, argv);
  41.    return  RUN_ALL_TESTS();
  42. }

 

testing::InitGoogleTest() 函数负责解析命令行传入的Google Test标志,并删除所有它可以处理的标志。这使得用户可以通过各种不同的标志控制一个测试程序的行为。关于这一点我们会在GTestAdvanced中 讲到。你必须在调用RUN_ALL_TESTS()之前调用该函数,否则就无法正确地初始化标示。

在Windows上InitGoogleTest()可以支持宽字符串,所以它也可以被用在以UNICODE模式编译的程序中。 


socket net test:

/system/extras/tests/iptables/qtaguid/socketTag.cpp

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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 requied 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.
 *
 */

/*
 * This socket tagging test is to ensure that the
 * netfilter/xt_qtaguid kernel module somewhat behaves as expected
 * with respect to tagging sockets.
 */
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <gtest/gtest.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
#define LOG_TAG "socketTagTest"
#include <utils/Log.h>
#include <testUtil.h>

namespace android {

class SockInfo {
public:
    SockInfo() : fd(-1), addr(NULL) {};
    int setup(uint64_t tag);
    bool checkTag(uint64_t tag, uid_t uid);
    int fd;
    void *addr;
};


int openCtrl() {
    int ctrl;
    ctrl = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
    if (!ctrl) {
       testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
    }
    return ctrl;
}

int doCtrlCommand(const char *fmt, ...) {
    char *buff;
    int ctrl;
    int res;
    va_list argp;

    va_start(argp, fmt);
    ctrl = openCtrl();
    vasprintf(&buff, fmt, argp);
    errno = 0;
    res = write(ctrl, buff, strlen(buff));
    testPrintI("cmd: '%s' res=%d %d/%s", buff, res, errno, strerror(errno));
    close(ctrl);
    free(buff);
    va_end(argp);
    return res;
}


int writeModuleParam(const char *param, const char *data) {
    int param_fd;
    int res;
    std::string filename("/sys/module/xt_qtaguid/parameters/");

    filename += param;
    param_fd = open(filename.c_str(), O_WRONLY);
    if (param_fd < 0) {
        testPrintE("qtaguid param open failed: %s", strerror(errno));
        return -1;
    }
    res = write(param_fd, data, strlen(data));
    if (res < 0) {
        testPrintE("qtaguid param write failed: %s", strerror(errno));
    }
    close(param_fd);
    return res;
}

/*----------------------------------------------------------------*/
int SockInfo::setup(uint64_t tag) {
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        testPrintE("socket creation failed: %s", strerror(errno));
        return -1;
    }
    if (doCtrlCommand("t %d %llu", fd, tag) < 0) {
        testPrintE("socket setup: failed to tag");
        close(fd);
        return -1;
    }
    if (!checkTag(tag, getuid())) {
        testPrintE("socket setup: Unexpected results: tag not found");
        close(fd);
        return -1;
    }
    if (doCtrlCommand("u %d", fd) < 0) {
        testPrintE("socket setup: Unexpected results");
        close(fd);
        return -1;
    }
    return 0;
}

/* checkTag() also tries to lookup the socket address in the kernel and
 * return it when *addr  == NULL.
 * This allows for better look ups when another process is also setting the same
 * tag + uid. But it is not fool proof.
 * Without the kernel reporting more info on who setup the socket tag, it is
 * not easily verifiable from user-space.
 * Returns: true if tag found.
 */
bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
    int ctrl_fd;
    ctrl_fd = openCtrl();
    char ctrl_data[1024];
    ssize_t read_size;
    char *buff;
    char *pos;
    int res;
    char *match_template;
    uint64_t k_tag;
    uint32_t k_uid;
    uint64_t full_tag;
    long dummy_count;
    pid_t dummy_pid;

    read_size = read(ctrl_fd, ctrl_data, sizeof(ctrl_data));
    if (read_size < 0) {
       testPrintE("Unable to read active tags from ctrl %d/%s",
                  errno, strerror(errno));
    }
    ctrl_data[read_size] = '\0';
    testPrintI("<ctrl_raw_data>\n%s</ctrl_raw_data>", ctrl_data);

    if (addr) {
        assert(sizeof(void*) == sizeof(long int));  // Why does %p use 0x? grrr. %lx.
        asprintf(&match_template, "sock=%lx %s", addr, "tag=0x%llx (uid=%u)");
    }
    else {
        /* Allocate for symmetry */
        asprintf(&match_template, "%s", " tag=0x%llx (uid=%u)");
    }

    full_tag = acct_tag | uid;

    asprintf(&buff, match_template, full_tag | uid, uid);
    testPrintI("looking for '%s'", buff);
    pos = strstr(ctrl_data, buff);

    if (pos && !addr) {
        assert(sizeof(void*) == sizeof(long int));  // Why does %p use 0x? grrr. %lx.
        res = sscanf(pos - strlen("sock=1234abcd"),
                     "sock=%lx tag=0x%llx (uid=%lu) pid=%u f_count=%lu",
                     &addr, &k_tag, &k_uid, &dummy_pid, &dummy_count );
        if (!(res == 5 && k_tag == full_tag && k_uid == uid)) {
            testPrintE("Unable to read sock addr res=%d", res);
           addr = 0;
        }
        else {
            testPrintI("Got sock_addr %lx", addr);
        }
    }
    free(buff);
    free(match_template);
    close(ctrl_fd);
    return pos != NULL;
}


class SocketTaggingTest : public ::testing::Test {
protected:
    virtual void SetUp() {
        ctrl_fd = -1;
        dev_fd = -1;
        my_uid = getuid();
        my_pid = getpid();
        srand48(my_pid * my_uid);
        // Adjust fake UIDs and tags so that multiple instances can run in parallel.
        fake_uid = testRand();
        fake_uid2 = testRand();
        valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
        valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
        valid_tag2 &= 0xffffff00ffffffffllu;  // Leave some room to make counts visible.
        testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
                   " tag1=0x%llx/%llu tag2=0x%llx/%llu",
                   my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
                   valid_tag1, valid_tag1, valid_tag2, valid_tag2);
        max_uint_tag = 0xffffffff00000000llu;
        max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);

        testPrintI("kernel has qtaguid");
        ctrl_fd = openCtrl();
        ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
        close(ctrl_fd);
        dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
        EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";

        // We want to clean up any previous faulty test runs.
        testPrintI("delete command does not fail");
        EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
        EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
        EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";

        testPrintI("setup sock0 and addr via tag");
        ASSERT_FALSE(sock0.setup(valid_tag1))  << "socket0 setup failed";
        testPrintI("setup sock1 and addr via tag");
        ASSERT_FALSE(sock1.setup(valid_tag1))  << "socket1 setup failed";
    }

   virtual void TearDown() {
       if (dev_fd >= 0) {
           close(dev_fd);
       }
       if (ctrl_fd >= 0) {
           close(ctrl_fd);
       }
   }

   SockInfo sock0;
   SockInfo sock1;
   int ctrl_fd;
   int dev_fd;
   uid_t fake_uid;
   uid_t fake_uid2;
   uid_t my_uid;
   pid_t my_pid;
   uint64_t valid_tag1;
   uint64_t valid_tag2;
   uint64_t max_uint_tag;
   static const uint64_t invalid_tag1 = 0x0000000100000001llu;
   static const int max_tags = 5;
};

TEST_F(SocketTaggingTest, TagData) {
    max_uint_tag = 0xffffffff00000000llu;
    char *max_tags_str;

    testPrintI("setup tag limit");
    asprintf(&max_tags_str, "%d", max_tags);
    ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";

    testPrintI("tag quota reach limit");
    for (int cnt = 0; cnt < max_tags; cnt++ ) {
        uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
        EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, tag , fake_uid2), 0)
            << "Tagging within limit failed";
        EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<<  "Unexpected results: tag not found";
    }

    testPrintI("tag quota go over limit");
    uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
    EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
                               fake_uid2)) << "Unexpected results: tag not found";

    testPrintI("valid untag");
    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
        << "Untagged tag should not be there";

    testPrintI("tag after untag should not free up max tags");
    uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
    EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag2 , fake_uid2), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
        << "Tag should not be there";

    testPrintI("delete one tag");
    uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
    EXPECT_GE(doCtrlCommand("d %llu %u", new_tag3, fake_uid2), 0);

    testPrintI("2 tags after 1 delete pass/fail");
    uint64_t new_tag4;
    new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag4 , fake_uid2), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
        << "Tag not found";
    new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
    EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag4 , fake_uid2), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
        << "Tag should not be there";

    /* TODO(jpa): test tagging two different sockets with same tags and
     * check refcounts  the tag_node should be +2
     */
}

TEST_F(SocketTaggingTest, InsufficientArgsFails) {
    // Insufficient args. Expected failure
    EXPECT_LE(doCtrlCommand("t"), 0) << "Insufficient args, should fail.";
}

TEST_F(SocketTaggingTest, BadCommandFails) {
    // Bad command. Expected failure";
    EXPECT_LE(doCtrlCommand("?"), 0) << "Bad command, should fail";
}

TEST_F(SocketTaggingTest, NoTagNoUid) {
    // no tag, no uid
    EXPECT_GE(doCtrlCommand("t %d", sock0.fd), 0);
    ASSERT_TRUE(sock0.checkTag(0, my_uid))  << "Tag not found";
}

TEST_F(SocketTaggingTest, InvalidTagFail) {
    // Invalid tag. Expected failure
    EXPECT_LE(doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1), 0);
    ASSERT_FALSE(sock0.checkTag(invalid_tag1, my_uid)) << "Tag should not be there";
}

TEST_F(SocketTaggingTest, ValidTagWithNoUid) {
    // Valid tag with no uid
    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, valid_tag1), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
}

TEST_F(SocketTaggingTest, ValidUntag) {
    // Valid untag
    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, valid_tag1), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
}

TEST_F(SocketTaggingTest, ValidFirsttag) {
    // Valid 1st tag
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
}

TEST_F(SocketTaggingTest, ValidReTag) {
    // Valid re-tag
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
}

TEST_F(SocketTaggingTest, ValidReTagWithAcctTagChange) {
    // Valid re-tag with acct_tag change
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
}

TEST_F(SocketTaggingTest, ReTagWithUidChange) {
    // Re-tag with uid change
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid), 0);
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2), 0);
}

TEST_F(SocketTaggingTest, Valid64BitAcctTag) {
    // Valid 64bit acct tag
    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag), 0);
    EXPECT_TRUE(sock0.checkTag(max_uint_tag, my_uid)) << "Tag not found.";
}

TEST_F(SocketTaggingTest, TagAnotherSocket) {
    testPrintI("Tag two sockets");
    EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag), 0);
    EXPECT_GE(doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2), 0);
    EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
    testPrintI("Untag socket0 of them only.");
    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
    EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
    EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
    testPrintI("Now untag socket1 as well.");
    EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
    EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
}

TEST_F(SocketTaggingTest, TagInvalidSocketFail) {
    // Invalid tag. Expected failure
    close(sock0.fd);
    EXPECT_LE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should not be there";
}

TEST_F(SocketTaggingTest, UntagInvalidSocketFail) {
    // Invalid untag. Expected failure";
    close(sock1.fd);
    EXPECT_LE(doCtrlCommand("u %d", sock1.fd), 0);
}


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

    return RUN_ALL_TESTS();
}
}  // namespace android



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用gtest测试框架实现快速排序的示例代码: ```c++ #include <gtest/gtest.h> void quickSort(int arr[], int left, int right) { int i = left, j = right; int tmp; int pivot = arr[(left + right) / 2]; // partition while (i <= j) { while (arr[i] < pivot) i++; while (arr[j] > pivot) j--; if (i <= j) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; i++; j--; } }; // recursion if (left < j) quickSort(arr, left, j); if (i < right) quickSort(arr, i, right); } TEST(QuickSortTest, PositiveNos) { int arr[] = { 5, 2, 3, 1, 4 }; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); ASSERT_EQ(arr[0], 1); ASSERT_EQ(arr[1], 2); ASSERT_EQ(arr[2], 3); ASSERT_EQ(arr[3], 4); ASSERT_EQ(arr[4], 5); } TEST(QuickSortTest, NegativeNos) { int arr[] = { -5, -2, -3, -1, -4 }; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); ASSERT_EQ(arr[0], -5); ASSERT_EQ(arr[1], -4); ASSERT_EQ(arr[2], -3); ASSERT_EQ(arr[3], -2); ASSERT_EQ(arr[4], -1); } TEST(QuickSortTest, MixedNos) { int arr[] = { -5, 2, -3, 1, 0 }; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); ASSERT_EQ(arr[0], -5); ASSERT_EQ(arr[1], -3); ASSERT_EQ(arr[2], 0); ASSERT_EQ(arr[3], 1); ASSERT_EQ(arr[4], 2); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ``` 在这个示例代码中,我们使用了gtest测试框架测试快速排序函数quickSort。我们定义了三个测试用例,分别测试了正数、负数和混合数的情况。在每个测试用例中,我们使用ASSERT_EQ宏来断言排序后数组的每个元素是否与预期值相等。如果不相等,则测试失败。 注意,这里的示例代码仅供参考,实际实现中可能需要根据具体情况进行相应修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值