当前位置: 首页 > news >正文

手撕基于AMQP协议的简易消息队列-8(单元测试的编写)

在MQTest中编写模块的单元测试

在MQTest中编写makefile文件来编译客户端模块
all:Test_FileHelper Test_Exchange Test_Queue Test_Binding Test_Message Test_VirtualHost Test_Route Test_Consumer Test_Channel Test_Connection Test_VirtualHost:Test_VirtualHost.cpp ../MQCommon/message.pb.ccg++ -g -o $@ $^ -std=c++11 -lgtest -lprotobuf -lsqlite3 -pthreadTest_Binding:Test_Binding.cppg++ -g -o $@ $^ -std=c++11 -lgtest -lprotobuf -lsqlite3 -pthreadTest_Queue:Test_Queue.cppg++ -g -o $@ $^ -std=c++11 -lgtest -lprotobuf -lsqlite3 -pthreadTest_FileHelper:Test_FileHelper.cppg++ -o $@ $^ -std=c++11Test_Exchange:Test_Exchange.cppg++ -g -std=c++11 $^ -o $@ -lgtest -lprotobuf -lsqlite3Test_Message:Test_Message.cpp ../MQCommon/message.pb.ccg++ -g -std=c++11 $^ -o $@ -lgtest -lprotobuf -lsqlite3Test_Route:Test_Route.cpp ../MQCommon/message.pb.ccg++ -g -std=c++11 $^ -o $@ -lgtest -lprotobuf -lsqlite3Test_Consumer:Test_Consumer.cpp ../MQCommon/message.pb.ccg++ -g -std=c++11 $^ -o $@ -lgtest -lprotobuf -lsqlite3Test_Channel:Test_Channel.cpp ../MQCommon/message.pb.cc ../MQCommon/request.pb.ccg++ -g -std=c++11 $^ -o $@ -lgtest -lprotobuf -lsqlite3 -I../ThirdLib/lib/includeTest_Connection:Test_Connection.cpp ../MQCommon/message.pb.cc ../MQCommon/request.pb.ccg++ -g -std=c++11 $^ -o $@ -lgtest -lprotobuf -lsqlite3 -I../ThirdLib/lib/include.PHONY:
clean:rm -rf Test_FileHelper Test_Exchange Test_Queue Test_Binding Test_Message Test_VirtualHost Test_Route Test_Consumer Test_Channel Test_Connection
在MQTest中编写Test_Exchange.cpp文件来编译交换机模块单元测试
#include "../MQServer/Exchange.hpp"
#include <gtest/gtest.h>
#include<unordered_map>
MQ::ExchangeManager::ptr emp;class ExchangeTest : public testing::Environment
{
public:virtual void SetUp() override{emp = std::make_shared<MQ::ExchangeManager>("./data/meta.db");}virtual void TearDown() override{emp->clear();std::cout << "最后的清理!!\n";}
};TEST(exchange_test, insert_test)
{std::unordered_map<std::string, std::string> tmp =  {{"k1","v1"},{"k2","v2"}};std::unordered_map<std::string, std::string> map;map.insert(tmp.begin(),tmp.end());for(auto& a : map){std::cout<<a.first<<' '<<a.second<<std::endl;}emp->declareExchange("exchange1", MQ::ExchangeType::DIRECT, true, false, map);emp->declareExchange("exchange2", MQ::ExchangeType::DIRECT, true, false, map);emp->declareExchange("exchange3", MQ::ExchangeType::DIRECT, true, false, map);emp->declareExchange("exchange4", MQ::ExchangeType::DIRECT, true, false, map);ASSERT_EQ(emp->size(), 4);
}TEST(exchange_test, select_test)
{ASSERT_EQ(emp->exists("exchange1"), false);ASSERT_EQ(emp->exists("exchange2"), true);ASSERT_EQ(emp->exists("exchange3"), true);ASSERT_EQ(emp->exists("exchange4"), true);MQ::Exchange::ptr exp = emp->selectExchange("exchange1");ASSERT_NE(exp.get(), nullptr);ASSERT_EQ(exp->_name, "exchange1");ASSERT_EQ(exp->_durable, true);ASSERT_EQ(exp->_auto_delete, false);ASSERT_EQ(exp->_type, MQ::ExchangeType::DIRECT);ASSERT_EQ(exp->getArgs(), std::string("k1=v1&k2=v2&"));
}TEST(exchange_test, remove_test)
{emp->deleteExchange("exchange2");MQ::Exchange::ptr exp = emp->selectExchange("exchange2");ASSERT_EQ(exp.get(), nullptr);ASSERT_EQ(emp->exists("exchange2"), false);
}int main(int argc, char *argv[])
{testing::InitGoogleTest(&argc, argv);testing::AddGlobalTestEnvironment(new ExchangeTest);RUN_ALL_TESTS();return 0;
}
在MQTest中编写Test_Binding.cpp文件来编译绑定模块单元测试
#include "../MQServer/Binding.hpp"
#include <gtest/gtest.h>MQ::BindingManager::ptr bmp;class QueueTest : public testing::Environment {public:virtual void SetUp() override {bmp = std::make_shared<MQ::BindingManager>("./data/meta.db");}virtual void TearDown() override {// bmp->clear();}
};// TEST(queue_test, insert_test) {
//     bmp->bind("exchange1", "queue1", "news.music.#", true);
//     bmp->bind("exchange1", "queue2", "news.sport.#", true);
//     bmp->bind("exchange1", "queue3", "news.gossip.#", true);
//     bmp->bind("exchange2", "queue1", "news.music.pop", true);
//     bmp->bind("exchange2", "queue2", "news.sport.football", true);
//     bmp->bind("exchange2", "queue3", "news.gossip.#", true);
//     ASSERT_EQ(bmp->size(), 6);
// }TEST(queue_test, recovery_test) {ASSERT_EQ(bmp->exist("exchange1", "queue1"), false);ASSERT_EQ(bmp->exist("exchange1", "queue2"), false);ASSERT_EQ(bmp->exist("exchange1", "queue3"), false);ASSERT_EQ(bmp->exist("exchange2", "queue1"), true);ASSERT_EQ(bmp->exist("exchange2", "queue2"), false);ASSERT_EQ(bmp->exist("exchange2", "queue3"), true);
}TEST(queue_test, select_test) {ASSERT_EQ(bmp->exist("exchange1", "queue1"), false);ASSERT_EQ(bmp->exist("exchange1", "queue2"), false);ASSERT_EQ(bmp->exist("exchange1", "queue3"), false);ASSERT_EQ(bmp->exist("exchange2", "queue1"), true);ASSERT_EQ(bmp->exist("exchange2", "queue2"), false);ASSERT_EQ(bmp->exist("exchange2", "queue3"), true);MQ::Binding::ptr bp = bmp->getBinding("exchange2", "queue1");ASSERT_NE(bp.get(), nullptr);ASSERT_EQ(bp->name_exchange, std::string("exchange2"));ASSERT_EQ(bp->name_queue, std::string("queue1"));ASSERT_EQ(bp->binding_key, std::string("news.music.pop"));
}TEST(queue_test, select_exchange_test) {MQ::QueueBindingMap mqbm = bmp->getExchangeBindings("exchange2");ASSERT_EQ(mqbm.size(), 2);ASSERT_NE(mqbm.find("queue1"), mqbm.end());ASSERT_EQ(mqbm.find("queue2"), mqbm.end());ASSERT_NE(mqbm.find("queue3"), mqbm.end());
}// // e2-q3// TEST(queue_test, remove_exchange_test) {
//     bmp->unbindByExchange("exchange1");
//     ASSERT_EQ(bmp->exist("exchange1", "queue1"), false);
//     ASSERT_EQ(bmp->exist("exchange1", "queue2"), false);
//     ASSERT_EQ(bmp->exist("exchange1", "queue3"), false);
// }// TEST(queue_test, remove_single_test) {
//     ASSERT_EQ(bmp->exist("exchange2", "queue2"), true);
//     bmp->unbind("exchange2", "queue2");
//     ASSERT_EQ(bmp->exist("exchange2", "queue2"), false);
//     ASSERT_EQ(bmp->exist("exchange2", "queue3"), true);
// }int main(int argc,char *argv[])
{testing::InitGoogleTest(&argc, argv);testing::AddGlobalTestEnvironment(new QueueTest);RUN_ALL_TESTS();return 0;
}
在MQTest中编写Test_Channel.cpp文件来编译信道模块单元测试
#include "../MQServer/Channel.hpp"int main()
{MQ::ChannelManager::ptr cmp = std::make_shared<MQ::ChannelManager>();cmp->openChannel("c1", std::make_shared<MQ::VirtualHost>("host1", "./data/host1/message/", "./data/host1/host1.db"),std::make_shared<MQ::ConsumerManager>(),MQ::ProtobufCodecPtr(),muduo::net::TcpConnectionPtr(),MQ::ThreadPool::ptr());return 0;
}
在MQTest中编写Test_Connection.cpp文件来编译链接模块单元测试
#include "../MQServer/Connection.hpp"int main()
{MQ::ConnectionManager::ptr cmp = std::make_shared<MQ::ConnectionManager>();cmp->newConnection(std::make_shared<MQ::VirtualHost>("host1", "./data/host1/message/", "./data/host1/host1.db"),std::make_shared<MQ::ConsumerManager>(),MQ::ProtobufCodecPtr(),muduo::net::TcpConnectionPtr(),MQ::ThreadPool::ptr());return 0;
}
在MQTest中编写Test_Consumer.cpp文件来编译消费者模块单元测试
#include "../MQServer/Consumer.hpp"
#include <gtest/gtest.h>MQ::ConsumerManager::ptr cmp;class ConsumerTest : public testing::Environment {public:virtual void SetUp() override {cmp = std::make_shared<MQ::ConsumerManager>();cmp->initQueueConsumer("queue1");}virtual void TearDown() override {cmp->clear();}
};void cb(const std::string &tag, const MQ::BasicProperties *bp, const std::string &body) 
{std::cout << tag << " 消费了消息:" << body << std::endl;
}TEST(consumer_test, insert_test) {cmp->createConsumer("consumer1", "queue1", false, cb);cmp->createConsumer("consumer2", "queue1", false, cb);cmp->createConsumer("consumer3", "queue1", false, cb);ASSERT_EQ(cmp->isExist("consumer1", "queue1"), true);ASSERT_EQ(cmp->isExist("consumer2", "queue1"), true);ASSERT_EQ(cmp->isExist("consumer3", "queue1"), true);
}
TEST(consumer_test, remove_test) {cmp->removeConsumer("consumer1", "queue1");ASSERT_EQ(cmp->isExist("consumer1", "queue1"), false);ASSERT_EQ(cmp->isExist("consumer2", "queue1"), true);ASSERT_EQ(cmp->isExist("consumer3", "queue1"), true);
}TEST(consumer_test, choose_test) {MQ::Consumer::ptr cp = cmp->chooseConsumer("queue1");ASSERT_NE(cp.get(), nullptr);ASSERT_EQ(cp->_consumer_tag, "consumer2");cp = cmp->chooseConsumer("queue1");ASSERT_NE(cp.get(), nullptr);ASSERT_EQ(cp->_consumer_tag, "consumer3");cp = cmp->chooseConsumer("queue1");ASSERT_NE(cp.get(), nullptr);ASSERT_EQ(cp->_consumer_tag, "consumer2");
}int main(int argc,char *argv[])
{testing::InitGoogleTest(&argc, argv);testing::AddGlobalTestEnvironment(new ConsumerTest);RUN_ALL_TESTS();return 0;
}
在MQTest中编写Test_FileHelper.cpp文件来文件操作类单元测试
#include "../MQCommon/Helper.hpp"int main()
{FileHelper helper("../MQCommon/Helper.hpp");DLOG("是否存在:%d", helper.exists());DLOG("文件大小:%ld", helper.size());FileHelper tmp_helper("./aaa/bbb/ccc/tmp.hpp");if (tmp_helper.exists() == false){std::string path = FileHelper::parentDirectory("./aaa/bbb/ccc/tmp.hpp");DLOG("path:%s",path.c_str());if (FileHelper(path).exists() == false){FileHelper::createDirectory(path);}FileHelper::createFile("./aaa/bbb/ccc/tmp.hpp");}std::string body;helper.read(body);DLOG("读测试,读出的内容:%s",body.c_str());tmp_helper.write(body);FileHelper tmp_helper1("./aaa/bbb/ccc/tmp.hpp");char str[16] = {0};tmp_helper.read(str, 8, 11);DLOG("[%s]", str);tmp_helper.write("12345678901", 8, 11);tmp_helper.rename("./aaa/bbb/ccc/test.hpp");FileHelper::removeFile("./aaa/bbb/ccc/test.hpp");FileHelper::removeDirectory("./aaa");return 0;
}
在MQTest中编写Test_Message.cpp文件来编译消息模块单元测试
#include "../MQServer/Message.hpp"
#include <gtest/gtest.h>MQ::MessageManager::ptr mmp;class MessageTest : public testing::Environment {public:virtual void SetUp() override {mmp = std::make_shared<MQ::MessageManager>("./data/message/");mmp->initQueueMessage("queue1");}virtual void TearDown() override {// mmp->clear();}
};//新增消息测试:新增消息,然后观察可获取消息数量,以及持久化消息数量
// TEST(message_test, insert_test) 
// {
//   MQ::BasicProperties properties;
//     properties.set_id(UUIDHelper::uuid());
//     properties.set_delivery_mode(MQ::DeliveryMode::DURABLE);
//     properties.set_routing_key("news.music.pop");
//     mmp->insert("queue1", &properties, "Hello World-1", true);
//     mmp->insert("queue1", nullptr, "Hello World-2", true);
//     mmp->insert("queue1", nullptr, "Hello World-3", true);
//     mmp->insert("queue1", nullptr, "Hello World-4", true);
//     mmp->insert("queue1", nullptr, "Hello World-5", false);
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 5);
//     ASSERT_EQ(mmp->getTotalCount("queue1"), 4);
//     ASSERT_EQ(mmp->getDurableCount("queue1"), 4);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 0);
// }//获取消息测试:获取一条消息,然后在不进行确认的情况下,查看可获取消息数量,待确认消息数量,以及测试消息获取的顺序
// TEST(message_test, select_test) {
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 5);
//     MQ::MessagePtr msg1 = mmp->front("queue1");
//     ASSERT_NE(msg1.get(), nullptr);
//     ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 4);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 1);//     MQ::MessagePtr msg2 = mmp->front("queue1");
//     ASSERT_NE(msg2.get(), nullptr);
//     ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 3);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 2);//     MQ::MessagePtr msg3 = mmp->front("queue1");
//     ASSERT_NE(msg3.get(), nullptr);
//     ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 2);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 3);//     MQ::MessagePtr msg4 = mmp->front("queue1");
//     ASSERT_NE(msg4.get(), nullptr);
//     ASSERT_EQ(msg4->payload().body(), std::string("Hello World-4"));
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 1);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 4);//     MQ::MessagePtr msg5 = mmp->front("queue1");
//     ASSERT_NE(msg5.get(), nullptr);
//     ASSERT_EQ(msg5->payload().body(), std::string("Hello World-5"));
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 0);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 5);
// }
//删除消息测试:确认一条消息,查看持久化消息数量,待确认消息数量
// TEST(message_test, delete_test) {
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 5);
//     MQ::MessagePtr msg1 = mmp->front("queue1");
//     ASSERT_NE(msg1.get(), nullptr);
//     ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));
//     ASSERT_EQ(mmp->getAbleCount("queue1"), 4);
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 1);//     mmp->ack("queue1", msg1->payload().properties().id());
//     ASSERT_EQ(mmp->getWaitAckCount("queue1"), 0);
//     ASSERT_EQ(mmp->getDurableCount("queue1"), 3);
//     ASSERT_EQ(mmp->getTotalCount("queue1"), 4);
// }
// 销毁测试
// TEST(message_test, clear) {
//     mmp->destroyQueueMessage("queue1");
// }//恢复历史数据测试MQ::MessageManager::ptr mmp1;
class MessageTest2 : public testing::Environment {public:virtual void SetUp() override {mmp1 = std::make_shared<MQ::MessageManager>("./data/message/");}virtual void TearDown() override {//mmp->clear();}
};
TEST(message_test2, recovery_test) {mmp1->initQueueMessage("queue1");ASSERT_EQ(mmp1->getAbleCount("queue1"), 4);MQ::MessagePtr msg1 = mmp1->front("queue1");ASSERT_NE(msg1.get(), nullptr);ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));ASSERT_EQ(mmp1->getAbleCount("queue1"), 3);ASSERT_EQ(mmp1->getWaitAckCount("queue1"), 1);MQ::MessagePtr msg2 = mmp1->front("queue1");ASSERT_NE(msg2.get(), nullptr);ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));ASSERT_EQ(mmp1->getAbleCount("queue1"), 2);ASSERT_EQ(mmp1->getWaitAckCount("queue1"), 2);MQ::MessagePtr msg3 = mmp1->front("queue1");ASSERT_NE(msg3.get(), nullptr);ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));ASSERT_EQ(mmp1->getAbleCount("queue1"), 1);ASSERT_EQ(mmp1->getWaitAckCount("queue1"), 3);MQ::MessagePtr msg4 = mmp1->front("queue1");ASSERT_NE(msg4.get(), nullptr);ASSERT_EQ(msg4->payload().body(), std::string("Hello World-4"));ASSERT_EQ(mmp1->getAbleCount("queue1"), 0);ASSERT_EQ(mmp1->getWaitAckCount("queue1"), 4);
}int main(int argc,char *argv[])
{testing::InitGoogleTest(&argc, argv);//testing::AddGlobalTestEnvironment(new MessageTest);testing::AddGlobalTestEnvironment(new MessageTest2);RUN_ALL_TESTS();return 0;
}
在MQTest中编写Test_Queue.cpp文件来编译队列模块单元测试
#include "../MQServer/Queue.hpp"
#include <gtest/gtest.h>MQ::QueueManager::ptr mqmp;class QueueTest : public testing::Environment {public:virtual void SetUp() override {mqmp = std::make_shared<MQ::QueueManager>("./data/meta.db");DLOG("创建数据库文件");}virtual void TearDown() override {// mqmp->clear();}
};// TEST(queue_test, insert_test) {
//     std::unordered_map<std::string, std::string> map = {{"k1", "v1"}};
//     mqmp->declareQueue("queue1", true, false, false, map);
//     mqmp->declareQueue("queue2", true, false, false, map);
//     mqmp->declareQueue("queue3", true, false, false, map);
//     mqmp->declareQueue("queue4", true, false, false, map);
//     ASSERT_EQ(mqmp->size(), 4);
// }TEST(queue_test, select_test) {ASSERT_EQ(mqmp->exist("queue1"), true);ASSERT_EQ(mqmp->exist("queue2"), true);ASSERT_EQ(mqmp->exist("queue3"), false);ASSERT_EQ(mqmp->exist("queue4"), true);MQ::Queue::ptr mqp = mqmp->selectQueue("queue1");ASSERT_NE(mqp.get(), nullptr);ASSERT_EQ(mqp->_name, "queue1");ASSERT_EQ(mqp->_durable, true);ASSERT_EQ(mqp->_exclusive, false);ASSERT_EQ(mqp->_auto_delete, false);ASSERT_EQ(mqp->getArgs(), std::string("k1=v1&"));
}TEST(queue_test, remove_test) {mqmp->deleteQueue("queue3");ASSERT_EQ(mqmp->exist("queue3"), false);
}int main(int argc,char *argv[])
{testing::InitGoogleTest(&argc, argv);testing::AddGlobalTestEnvironment(new QueueTest);RUN_ALL_TESTS();return 0;
}
在MQTest中编写Test_Route.cpp文件来编译路由模块单元测试
#include "../MQServer/Route.hpp"
#include <gtest/gtest.h>class QueueTest : public testing::Environment {public:virtual void SetUp() override {}virtual void TearDown() override {//bmp->clear();}
};TEST(route_test, legal_routing_key) {std::string rkey1 = "news.music.pop";std::string rkey2 = "news..music.pop";std::string rkey3 = "news.,music.pop";std::string rkey4 = "news.music_123.pop";ASSERT_EQ(MQ::RouteManager::isValidRoutingKey(rkey1), true);ASSERT_EQ(MQ::RouteManager::isValidRoutingKey(rkey2), false);ASSERT_EQ(MQ::RouteManager::isValidRoutingKey(rkey3), false);ASSERT_EQ(MQ::RouteManager::isValidRoutingKey(rkey4), true);
}
TEST(route_test, legal_binding_key) {std::string bkey1 = "news.music.pop";std::string bkey2 = "news.#.music.pop";std::string bkey3 = "news.#.*.music.pop";//std::string bkey4 = "news.*.#.music.pop";//std::string bkey5 = "news.#.#.music.pop";//std::string bkey6 = "news.*.*.music.pop";std::string bkey7 = "news.,music_123.pop";//ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey1), true);ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey2), true);ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey3), false);ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey4), false);ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey5), false);ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey6), true);ASSERT_EQ(MQ::RouteManager::isValidBindingKey(bkey7), false);
}
TEST(route_test, route) {
// aaa                  aaa                     true
// aaa.bbb              aaa.bbb                 true
// aaa.bbb              aaa.bbb.ccc             false
// aaa.bbb              aaa.ccc                 false
// aaa.#.bbb            aaa.bbb.ccc             false
// aaa.bbb.#            aaa.ccc.bbb             false
// #.bbb.ccc            aaa.bbb.ccc.ddd         false
// aaa.bbb.ccc          aaa.bbb.ccc             true
// aaa.*                aaa.bbb                 true
// aaa.*.bbb            aaa.bbb.ccc             false
// *.aaa.bbb            aaa.bbb                 false
// #                    aaa.bbb.ccc             true
// aaa.#                aaa.bbb                 true
// aaa.#                aaa.bbb.ccc             true
// aaa.#.ccc            aaa.ccc                 true
// aaa.#.ccc            aaa.bbb.ccc             true
// aaa.#.ccc            aaa.aaa.bbb.ccc         true
// #.ccc                ccc                     true
// #.ccc                aaa.bbb.ccc             true
// aaa.#.ccc.ccc        aaa.bbb.ccc.ccc.ccc     true
// aaa.#.bbb.*.bbb      aaa.ddd.ccc.bbb.eee.bbb truestd::vector<std::string> bkeys = {"aaa","aaa.bbb","aaa.bbb", "aaa.bbb","aaa.#.bbb","aaa.bbb.#","#.bbb.ccc","aaa.bbb.ccc","aaa.*","aaa.*.bbb","*.aaa.bbb", "#",   "aaa.#", "aaa.#",  "aaa.#.ccc","aaa.#.ccc","aaa.#.ccc","#.ccc","#.ccc","aaa.#.ccc.ccc","aaa.#.bbb.*.bbb"};std::vector<std::string> rkeys = {"aaa","aaa.bbb",    "aaa.bbb.ccc",        "aaa.ccc",        "aaa.bbb.ccc",        "aaa.ccc.bbb",        "aaa.bbb.ccc.ddd",    "aaa.bbb.ccc",       "aaa.bbb",         "aaa.bbb.ccc",      "aaa.bbb",         "aaa.bbb.ccc",       "aaa.bbb",        "aaa.bbb.ccc",     "aaa.ccc",        "aaa.bbb.ccc",       "aaa.aaa.bbb.ccc",  "ccc",         "aaa.bbb.ccc",    "aaa.bbb.ccc.ccc.ccc","aaa.ddd.ccc.bbb.eee.bbb"};std::vector<bool> result = {true,true,false,false,false,false,false,true,true,false,false,true,true,true,true,true,true,true,true,true,true};for (int i = 0; i < bkeys.size(); i++) {ASSERT_EQ(MQ::RouteManager::route(MQ::ExchangeType::TOPIC, rkeys[i], bkeys[i]), result[i]);}
}int main(int argc,char *argv[])
{testing::InitGoogleTest(&argc, argv);testing::AddGlobalTestEnvironment(new QueueTest);RUN_ALL_TESTS();return 0;
}
在MQTest中编写Test_VirtualHost.cpp文件来编译虚拟机模块单元测试
#include <gtest/gtest.h>
#include "../MQServer/VirtualHost.hpp"class HostTest : public testing::Test {public:void SetUp() override {std::unordered_map<std::string, std::string> empty_map = std::unordered_map<std::string, std::string>();_host = std::make_shared<MQ::VirtualHost>("host1", "./data/host1/message/", "./data/host1/host1.db");_host->declareExchange("exchange1", MQ::ExchangeType::DIRECT, true, false, empty_map);_host->declareExchange("exchange2", MQ::ExchangeType::DIRECT, true, false, empty_map);_host->declareExchange("exchange3", MQ::ExchangeType::DIRECT, true, false, empty_map);_host->declareQueue("queue1", true, false, false, empty_map);_host->declareQueue("queue2", true, false, false, empty_map);_host->declareQueue("queue3", true, false, false, empty_map);_host->bind("exchange1", "queue1", "news.music.#");_host->bind("exchange1", "queue2", "news.music.#");_host->bind("exchange1", "queue3", "news.music.#");_host->bind("exchange2", "queue1", "news.music.#");_host->bind("exchange2", "queue2", "news.music.#");_host->bind("exchange2", "queue3", "news.music.#");_host->bind("exchange3", "queue1", "news.music.#");_host->bind("exchange3", "queue2", "news.music.#");_host->bind("exchange3", "queue3", "news.music.#");_host->basicPublish("queue1", nullptr, "Hello World-1");_host->basicPublish("queue1", nullptr, "Hello World-2");_host->basicPublish("queue1", nullptr, "Hello World-3");_host->basicPublish("queue2", nullptr, "Hello World-1");_host->basicPublish("queue2", nullptr, "Hello World-2");_host->basicPublish("queue2", nullptr, "Hello World-3");_host->basicPublish("queue3", nullptr, "Hello World-1");_host->basicPublish("queue3", nullptr, "Hello World-2");_host->basicPublish("queue3", nullptr, "Hello World-3");}void TearDown() override {_host->clear();}public:MQ::VirtualHost::ptr _host;
};TEST_F(HostTest, init_test) {ASSERT_EQ(_host->existExchange("exchange1"), true);ASSERT_EQ(_host->existExchange("exchange2"), true);ASSERT_EQ(_host->existExchange("exchange3"), true);ASSERT_EQ(_host->existQueue("queue1"), true);ASSERT_EQ(_host->existQueue("queue2"), true);ASSERT_EQ(_host->existQueue("queue3"), true);ASSERT_EQ(_host->existBinding("exchange1", "queue1"), true);ASSERT_EQ(_host->existBinding("exchange1", "queue2"), true);ASSERT_EQ(_host->existBinding("exchange1", "queue3"), true);ASSERT_EQ(_host->existBinding("exchange2", "queue1"), true);ASSERT_EQ(_host->existBinding("exchange2", "queue2"), true);ASSERT_EQ(_host->existBinding("exchange2", "queue3"), true);ASSERT_EQ(_host->existBinding("exchange3", "queue1"), true);ASSERT_EQ(_host->existBinding("exchange3", "queue2"), true);ASSERT_EQ(_host->existBinding("exchange3", "queue3"), true);MQ::MessagePtr msg1 = _host->basicConsume("queue1");ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));MQ::MessagePtr msg2 = _host->basicConsume("queue1");ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));MQ::MessagePtr msg3 = _host->basicConsume("queue1");ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));MQ::MessagePtr msg4 = _host->basicConsume("queue1");ASSERT_EQ(msg4.get(), nullptr);
}TEST_F(HostTest, remove_exchange) {_host->deleteExchange("exchange1");ASSERT_EQ(_host->existBinding("exchange1", "queue1"), false);ASSERT_EQ(_host->existBinding("exchange1", "queue2"), false);ASSERT_EQ(_host->existBinding("exchange1", "queue3"), false);
}TEST_F(HostTest, remove_queue) {_host->deleteQueue("queue1");ASSERT_EQ(_host->existBinding("exchange1", "queue1"), false);ASSERT_EQ(_host->existBinding("exchange2", "queue1"), false);ASSERT_EQ(_host->existBinding("exchange3", "queue1"), false);MQ::MessagePtr msg1 = _host->basicConsume("queue1");ASSERT_EQ(msg1.get(), nullptr);
}TEST_F(HostTest, ack_message) {MQ::MessagePtr msg1 = _host->basicConsume("queue1");ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));_host->basicAck(std::string("queue1"), msg1->payload().properties().id());MQ::MessagePtr msg2 = _host->basicConsume("queue1");ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));_host->basicAck(std::string("queue1"), msg2->payload().properties().id());MQ::MessagePtr msg3 = _host->basicConsume("queue1");ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));_host->basicAck(std::string("queue1"), msg3->payload().properties().id());}int main(int argc, char *argv[])
{testing::InitGoogleTest(&argc, argv);RUN_ALL_TESTS();return 0;
}

相关文章:

手撕基于AMQP协议的简易消息队列-8(单元测试的编写)

在MQTest中编写模块的单元测试 在MQTest中编写makefile文件来编译客户端模块 all:Test_FileHelper Test_Exchange Test_Queue Test_Binding Test_Message Test_VirtualHost Test_Route Test_Consumer Test_Channel Test_Connection Test_VirtualHost:Test_VirtualHost.cpp ..…...

硬件选型:工控机的选择要素

在机器视觉应用中&#xff0c;工控机作为核心计算设备&#xff0c;承担着图像处理、数据分析和设备控制等多重任务。由于机器视觉常常在工业自动化、质量检测和精密控制中发挥重要作用&#xff0c;工控机的选型直接影响系统的性能和可靠性。 1. 应用场景与需求 机器视觉系统广…...

【芯片设计- RTL 数字逻辑设计入门 4.1 -- verilog 组合逻辑和时序逻辑延时比较】

文章目录 Overview时间线简单示意Overview 我们来详细分析下面这段 RTL Code , sbcs_sbbusy 为什么会比 sbcs_sbbusy_nx 慢一拍(晚一个时钟周期变化)。 assign sbcs_sbbusy_nx = set_sbcs_sbbusy;always @(posedge clk or negedge dmi_resetn) beginif (!dmi_resetn) begi…...

关于ubuntu下交叉编译arrch64下的gtsam报错问题,boost中boost_regex.so中连接libicui18n.so.55报错的问题

交叉编译gtsam时遇到的报错信息如下&#xff1a;gtsam需要连接boost&#xff0c; 解决办法&#xff1a; 1.重新编译boost可解决。 2.自己搞定生成一个libicui18n.so.55。 由于我们的boost是公用的&#xff0c;因此1不太可能&#xff08;我试过重新编译完boost,在编译gtsam完…...

IoT平台和AIoT平台的区别

1. 什么是AIoT平台&#xff1f; AIoT&#xff08;人工智能物联网&#xff0c;Artificial Intelligence of Things&#xff09;平台 是 人工智能&#xff08;AI&#xff09; 与 物联网&#xff08;IoT&#xff09; 深度融合的技术框架&#xff0c;通过将AI算法嵌入物联网终端或…...

iOS 模块化开发流程

iOS模块化开发是一种将大型项目拆分为独立、可复用模块的开发模式&#xff0c;能够提升代码可维护性、团队协作效率和动态交付能力。以下是iOS模块化开发的核心流程与关键要点&#xff1a; 一、模块化设计阶段 业务解耦与模块划分 横向分层&#xff1a;基础层&#xff08;网络、…...

云原生安全治理体系建设全解:挑战、框架与落地路径

📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:云原生环境下,安全治理正在被重构 在传统IT架构中,安全防护多依赖边界设备(如防火墙、WAF、堡垒机)进行集中式防护。然而,在云原生环境下,这种“边界式”安全模型正面临颠覆。 应用微服务化…...

如何在Vue-Cli中使用Element-UI和Echarts和swiper插件(低版本)

1st.Element-UI 1.1 安装 在终端输入 npm install element-ui 1.2 导入 在全局main.js中全局导入Element-UI&#xff1a; // 导入element-ui组件库 import ElementUI from element-ui; // 导入element-ui组件库的样式 import element-ui/lib/theme-chalk/index.css; // 注…...

[特殊字符]【实战教程】用大模型LLM查询Neo4j图数据库(附完整代码)

&#x1f31f; 核心要点速览 ✅ 基于LangChain框架实现LLM查询Neo4j ✅ 使用Qwen2.5模型(实测Llama3.1查不出内容) ✅ 包含完整数据准备代码实现效果演示 ✅ GitHub/Gitee源码已同步(文末获取) &#x1f6e0;️ 环境准备 1️⃣ 安装Neo4j图数据库 # Windows安装指南参考&…...

Qt获取CPU使用率及内存占用大小

Qt 获取 CPU 使用率及内存占用大小 文章目录 Qt 获取 CPU 使用率及内存占用大小一、简介二、关键函数2.1 获取当前运行程序pid2.2 通过pid获取运行时间2.3 通过pid获取内存大小 三、具体实现五、写在最后 ​ 一、简介 近期在使用软件的过程中发现一个有意思的东西。如下所示&a…...

算法解密:除自身以外数组的乘积问题详解

算法解密:除自身以外数组的乘积问题详解 一、引言 在算法的奇妙旅程中,我们时常会遇到一些看似简单却蕴含深刻智慧的问题,“除自身以外数组的乘积”就是其中之一。这个问题不仅考验我们对数组操作的熟练程度,还要求我们在特定的限制条件下(不能使用除法且时间复杂度为O(n…...

基于Kubernetes的Apache Pulsar云原生架构解析与集群部署指南(上)

#作者&#xff1a;闫乾苓 文章目录 概念和架构概述主要特点消息传递核心概念Pulsar 的消息模型Pulsar 的消息存储与分发Pulsar 的高级特性架构BrokerBookKeeperZooKeeper 概念和架构 概述 Pulsar 是一个多租户、高性能的服务器到服务器消息传递解决方案。Pulsar 最初由雅虎开…...

信创生态核心技术栈:数据库与中间件

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…...

CMU-15445(3)——PROJECT#1-BufferPoolManager-Task#1

PROJECT#1-BufferPoolManager 在完成了前面基础的PROJECT#0后&#xff0c;从本节开始才正式进入了CMU-15445的学习&#xff0c;最终目的是构建一个面向磁盘的数据库管理系统。 PROJECT#1 的主要任务是实现数据库管理系统的缓冲池管理器&#xff0c;缓冲池负责在主存缓冲区与持…...

《数据结构初阶》【链式二叉树】

《数据结构初阶》【链式二叉树】 前言&#xff1a;---------------树---------------什么是树&#xff1f;&#x1f4cc;爱心❤小贴士&#xff1a;树与非树&#xff1f;树的基本术语有哪些&#xff1f;关于节点的一些定义&#xff1a;关于树的一些定义&#xff1a;关于森林的定…...

Oracle免费认证来袭

1、Oracle Cloud Infrastructure 2025 Foundations Associate” &#x1f517; 考证地址&#xff1a;https://mylearn.oracle.com/ou/exam-unproctored/oracle-cloud-infrastructure-2025-foundations-associate-1z0-1085-25/148056/241954 2、Oracle Cloud Infrastructure 2…...

Vim 编辑器常用快捷键速查表

Vim 编辑器常用快捷键速查表 Vim 快捷键大全 **1. 基础操作****2. 光标移动****3. 编辑文本****4. 查找替换****5. 分屏操作****6. 可视化模式** **附&#xff1a;Vim 模式切换流程图** 1. 基础操作 快捷键功能说明i进入插入模式&#xff08;光标前&#xff09;a进入插入模式&…...

从父类到子类:C++ 继承的奇妙旅程(1)

前言&#xff1a; 在前文&#xff0c;小编讲述了C模板的进阶内容&#xff0c;下面我们就要结束C初阶的旅行&#xff0c;开始进入C进阶容的旅c程&#xff0c;今天旅程的第一站就是C三大特性之一——继承的旅程&#xff0c;各位扶好扶手&#xff0c;开始我们今天的C继承的奇妙旅程…...

HTML9:页面结构分析

页面结构分析 元素名描述header标题头部区域的内容&#xff08;用于页面或页面中的一块区域&#xff09;footer标记脚部区域的内容&#xff08;用于整个页面或页面的一块区域&#xff09;sectionWeb页面的一块独立区域article独立的文章内容aside相关的内容或应用&#xff08;…...

LabVIEW超声波液位计检定

在工业生产、运输和存储等环节&#xff0c;液位计的应用十分广泛&#xff0c;其中超声波液位计作为非接触式液位测量设备备受青睐。然而&#xff0c;传统立式水槽式液位计检定装置存在受建筑高度影响、量程范围受限、流程耗时长等问题&#xff0c;无法满足大量程超声波液位计的…...

maven 安装 本地 jar

命令&#xff1a; mvn install:install-file -DgroupIdnet.pingfang.application -DartifactIdjna -Dversion5.1.0 -Dpackagingjar -DfileD:\maven\repository1\jna\5.1.0\jna-5.1.0.jarmvn&#xff1a;这是Maven的执行命令。 install:install-file&#xff1a;这是Maven插件目…...

leetcode 141. Linked List Cycle

题目描述&#xff1a; 代码&#xff1a; 用哈希表也可以解决&#xff0c;但真正考察的是用快慢指针法。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Soluti…...

【Python】通过`Editable Install`模式详解,解决Python开发总是import出错的问题

摘要 田辛老师在很久以前&#xff0c;写过一篇关于Python的模块、包之间的内部关系的博客&#xff0c;叫做【Python】__init__.py 文件详解。 虽然我觉得这篇文章已经足够了&#xff0c; 但是还是有很多朋友碰到开发的过程中import包报错的问题。 今天&#xff0c; 田辛老师想…...

C 语言网络编程问题:E1696 无法打开 源 文件 “sys/socket.h“

#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>在 C 语言网络编程中&#xff0c;上述代码报如下错误 E1696 无法打开 源 文件 "sys/socket.h"E1696 无法打开 源 文件 "netinet/in.h" E1696 无法打开 源 文件…...

操作指南*

任务1: 环境搭建 1.1 创建Spring Boot项目 操作步骤&#xff1a; 使用IDEA创建项目&#xff1a; 打开IDEA → File → New → Project选择 Spring Initializr → 设置项目信息&#xff08;Group、Artifact、Java版本&#xff09;选择依赖&#xff1a;Spring Web、MySQL Drive…...

VRM Add-on for Blender 学习笔记

VRM Add-on for Blender 使用教程-CSDN博客 VRM Add-on for Blender 是 Blender 的一个官方插件&#xff0c;主要用于 导入和导出 VRM 格式的 3D 模型。VRM&#xff08;Virtual Reality Model&#xff09;是一种开放标准的 3D 人形角色模型格式&#xff0c;起源于日本&#xf…...

C++ 完美转发

C 完美转发逐步详解 1. 问题背景与核心目标 在 C 模板编程中&#xff0c;若直接将参数传递给其他函数&#xff0c;参数的 值类别&#xff08;左值/右值&#xff09;和 类型信息&#xff08;如 const&#xff09;可能会丢失。例如&#xff1a; template<typename T> voi…...

学习记录:DAY23

项目开发与学习记录&#xff1a;字段注入优化 前言 我总有一种什么大的要来了的危机感。还是尽快把项目做起来吧&#xff0c;现在全在弄底层的框架。这是一个两天的blog&#xff0c;前一天bug没修好&#xff0c;气到连blog都没写。 日程 5月7日 晚上7点&#xff1a;本来想玩…...

Linux 信号(下篇)

Linux 信号-CSDN博客&#xff08;上篇&#xff09; 前言&#xff1a;在我上一篇博客写到了信号产生的三种条件分别是键盘组合键、kill命令、系统调用接口&#xff1b; 接下来我要把信号产生剩余的两个条件介绍完毕并理解信号的保存&#xff0c;和信号从产生到保存到处理整个过…...

hadoop中的序列化和反序列化(1)

1. 什么是序列化和反序列化 序列化&#xff08;Serialization&#xff09; 是将对象的状态信息转换为可以存储或传输的格式的过程。序列化后的对象可以保存到文件中&#xff0c;或者通过网络传输。 反序列化&#xff08;Deserialization&#xff09; 是序列化的逆过程&#x…...

linux查java进程CPU高的原因

问题&#xff1a;linux查java进程CPU高的原因 解决&#xff1a;用jdk带的工具分析 被查的java最好也使用jdk启动 systemctl启动的注意要去掉PrivateTmptrue /opt/jdk1.8.0_441/bin/jps -l top -Hp 8156 printf "%x" 8533 /opt/jdk1.8.0_441/bin/jstack 8156 |…...

鸿蒙开发——3.ArkTS声明式开发:构建第一个ArkTS应用

鸿蒙开发——3.ArkTS声明式开发:构建第一个ArkTS应用 一、创建ArkTS工程二、ArkTS工程目录结构&#xff08;Stage模型&#xff09;三、构建第一个页面四、构建第二个页面五、实现页面之间的跳转六、模拟器运行 一、创建ArkTS工程 1、若首次打开DevEco Studio&#xff0c;请点击…...

vue3+ts的watch全解!

vue3中的watch只能监听以下四种数据&#xff1a; 1.ref定义的数据 2.reactive定义的数据 3.函数返回一个值&#xff08;getter函数&#xff09; 4.一个包含上述内容的数组 通常我们在使用watch的时候&#xff0c;通常会遇到以下几种情况&#xff1a; 情况一&#xff1a; …...

yarn的概述

1.Yarn的定义 2.Yarn的三大组件 3.Yarn的调度策略 1. YARN的定义 YARN&#xff08;Yet Another Resource Negotiator&#xff09; 是Hadoop生态系统中的一个资源管理框架&#xff0c;用于管理和调度集群中的计算资源。它允许多个应用程序在同一个集群上高效地运行&#xff0c;…...

C++初阶-string类4

目录 1.String operations 1.1string::c_str 1.2string::data 1.3string::copy 1.4string::find 1.5string::rfind 1.6string::find_first_of 1.7string::find_last_of 1.8string::find_first_not_of和string::find_last_not_of find_first_not_of 功能 典型用途 f…...

HarmonyOS NEXT深度解析:自研框架ArkUI-X的技术革命与跨平台实践

HarmonyOS NEXT&#xff5e;深度解析&#xff1a;自研框架ArkUI-X的技术革命与跨平台实践 引言&#xff1a;ArkUI-X的诞生背景与战略意义 在HarmonyOS NEXT全面摒弃AOSP代码的历史性转折点上&#xff0c;华为推出的ArkUI-X框架标志着国产操作系统研发进入深水区。根据华为202…...

CUDA:out of memory的解决方法(实测有效)

一、问题概述 1.问题分析 CUDA out of memory问题通常发生在深度学习训练过程中&#xff0c;当GPU的显存不足以容纳模型、输入数据以及中间计算结果时就会触发。这个问题可能由几个因素引起&#xff1a; 模型和数据规模&#xff1a;深度学习模型尤其是大型模…...

canal mysqltomysql增加同步的库操作

例如增加库 online 1、停止canal.adapter 服务。 ./bin/stop.sh2、备份数据库online&#xff0c;导入目标mysql 备份 mysqldump -h 127.0.0.1 -P 3307 --single-transaction -uroot -p -B online > online.sql导入 mysql -h 127.0.0.1 -P 3308 -uroot -p < onl…...

【AI】模型与权重的基本概念

在 ModelScope 平台上&#xff0c;「模型」和「权重」的定义与工程实践紧密结合&#xff0c;理解它们的区别需要从实际的文件结构和加载逻辑入手。以下是一个典型 ModelScope 模型仓库的组成及其概念解析&#xff1a; 1. ModelScope 模型仓库的典型结构 以 deepseek-ai/deepse…...

k8s 中 deployment 管理的多个 pod 构成集群吗

在 Kubernetes (k8s) 中&#xff0c;通过 Deployment 创建的多个 Pod 本身并不构成一个“集群”&#xff0c;而是属于同一个 工作负载&#xff08;Workload&#xff09; 的多个副本实例。它们的角色是 无状态服务副本&#xff0c;而非独立的集群节点。以下是详细解释&#xff1…...

「动态规划」线性DP:股票问题合集 / LeetCode 121|122|123|188 (C++)

目录 概述 Question1 思路 算法过程 Code 复杂度 Question2 思路 解题过程 Code 复杂度 Question3 思路 解题过程 Code 复杂度 Question4 思路 解题过程 Code 复杂度 总结 概述 我们已经了解过了线性DP&#xff1a; 「动态规划」线性DP&#xff1a;最长…...

【Python os模块完全指南】从基础到高效文件操作

目录 &#x1f31f; 前言&#x1f9e9; 技术背景与价值&#x1f6a7; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f4da; 一、技术原理剖析&#x1f3a8; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f511; 关键技术模块说明⚖️ 技术选型…...

Ubuntu 安装 Keepalived、LVS

Keepalived Keepalived 是什么&#xff08;高可用&#xff09; Keepalived 是一个用于实现 高可用 性&#xff08;High Availability, HA&#xff09;的服务&#xff0c;是一款基于 VRRP 协议的高可用软件&#xff0c;常用于主备切换和虚拟IP漂移&#xff0c;在服务故障时自动…...

记录一个rabbitmq因为linux主机名服务无法启动的问题

https://g.co/gemini/share/fb5a55644f6f 过程因为主机名为数字导致之间无法进行网络访问&#xff0c;导致无法开启。修改主机名解决这一问题&#xff0c;debian在系统安装时会指定一个用户名&#xff0c;一般为IP地址的第一块&#xff0c;数字导致了无法访问。 #使用命令查看…...

打造个人知识库,wsl+ollama部署deepseek与vscode集成

目前大模型应用如火如荼,各大LLM如Deepseek也都提供了在线的助手服务,结合mcp-server还可以进一步拓展到本地的工具能力。 但对于一些和本地业务和数据强相关的资料,在线的大模型训练数据集一般并不能涵盖,特别还有一些敏感或对安全要求很高的数据,使用在线大模型并不现实…...

Spring 项目无法连接 MySQL:Nacos 配置误区排查与解决

在开发过程中&#xff0c;我们使用 Nacos 来管理 Spring Boot 项目的配置&#xff0c;其中包括数据库连接配置。然而&#xff0c;在实际操作中&#xff0c;由于一些概念的混淆&#xff0c;我们遇到了一些连接问题。本文将分享我的故障排查过程&#xff0c;帮助大家避免类似的错…...

P值、置信度与置信区间的关系:统计推断的三大支柱

目录 引言一、P值是什么&#xff1f;——假设检验的“证据强度”1.1 定义1.2 判断标准&#xff1a;显著性水平 α \alpha α&#xff08;阿尔法&#xff09;1.3 示例说明 二、置信区间与置信度&#xff1a;参数估计的“不确定性范围”2.1 置信区间的定义2.2 置信度的含义 三、显…...

探索智能仓颉:Cangjie Magic开发体验

探索智能仓颉:Cangjie Magic 的开发体验与技术革新 在大型语言模型(LLM)驱动的智能体开发领域,2025年3月开源的 Cangjie Magic 以其独特的原生仓颉语言基因和三大核心技术突破,为开发者提供了一种全新的开发范式。本文将从技术架构、实际应用、开发体验及未来潜力等角度,…...

$在R语言中的作用

在 R 语言中&#xff0c;$ 是一个非常重要的操作符&#xff0c;主要用于访问对象的成员或组件。它的用途非常广泛&#xff0c;不仅限于数据框&#xff08;data frame&#xff09;&#xff0c;还可以用于列表&#xff08;list&#xff09;、环境&#xff08;environment&#xf…...

【Pandas】pandas DataFrame rolling

Pandas2.2 DataFrame Function application, GroupBy & window 方法描述DataFrame.apply(func[, axis, raw, …])用于沿 DataFrame 的轴&#xff08;行或列&#xff09;应用一个函数DataFrame.map(func[, na_action])用于对 DataFrame 的每个元素应用一个函数DataFrame.a…...