BandwidthControllerTest.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * Copyright 2016 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. * BandwidthControllerTest.cpp - unit tests for BandwidthController.cpp
  17. */
  18. #include <string>
  19. #include <vector>
  20. #include <inttypes.h>
  21. #include <fcntl.h>
  22. #include <unistd.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <gtest/gtest.h>
  26. #include <android-base/strings.h>
  27. #include <android-base/stringprintf.h>
  28. #include <netdutils/MockSyscalls.h>
  29. #include "BandwidthController.h"
  30. #include "Fwmark.h"
  31. #include "IptablesBaseTest.h"
  32. #include "bpf/BpfUtils.h"
  33. #include "netdbpf/bpf_shared.h"
  34. #include "tun_interface.h"
  35. using ::testing::_;
  36. using ::testing::ByMove;
  37. using ::testing::Invoke;
  38. using ::testing::Return;
  39. using ::testing::StrictMock;
  40. using android::base::Join;
  41. using android::base::StringPrintf;
  42. using android::net::TunInterface;
  43. using android::netdutils::UniqueFile;
  44. using android::netdutils::status::ok;
  45. const std::string ACCOUNT_RULES_WITHOUT_BPF =
  46. "*filter\n"
  47. "-A bw_INPUT -j bw_global_alert\n"
  48. "-A bw_INPUT -p esp -j RETURN\n"
  49. "-A bw_INPUT -m mark --mark 0x100000/0x100000 -j RETURN\n"
  50. "-A bw_INPUT -m owner --socket-exists\n"
  51. "-A bw_INPUT -j MARK --or-mark 0x100000\n"
  52. "-A bw_OUTPUT -j bw_global_alert\n"
  53. "-A bw_OUTPUT -o ipsec+ -j RETURN\n"
  54. "-A bw_OUTPUT -m policy --pol ipsec --dir out -j RETURN\n"
  55. "-A bw_OUTPUT -m owner --socket-exists\n"
  56. "-A bw_costly_shared --jump bw_penalty_box\n"
  57. "\n"
  58. "-A bw_penalty_box --jump bw_happy_box\n"
  59. "-A bw_happy_box --jump bw_data_saver\n"
  60. "-A bw_data_saver -j RETURN\n"
  61. "-I bw_happy_box -m owner --uid-owner 0-9999 --jump RETURN\n"
  62. "COMMIT\n"
  63. "*raw\n"
  64. "-A bw_raw_PREROUTING -i ipsec+ -j RETURN\n"
  65. "-A bw_raw_PREROUTING -m policy --pol ipsec --dir in -j RETURN\n"
  66. "-A bw_raw_PREROUTING -m owner --socket-exists\n"
  67. "COMMIT\n"
  68. "*mangle\n"
  69. "-A bw_mangle_POSTROUTING -o ipsec+ -j RETURN\n"
  70. "-A bw_mangle_POSTROUTING -m policy --pol ipsec --dir out -j RETURN\n"
  71. "-A bw_mangle_POSTROUTING -m owner --socket-exists\n"
  72. "-A bw_mangle_POSTROUTING -j MARK --set-mark 0x0/0x100000\n"
  73. "\n"
  74. "COMMIT\n";
  75. const std::string ACCOUNT_RULES_WITH_BPF =
  76. "*filter\n"
  77. "-A bw_INPUT -j bw_global_alert\n"
  78. "-A bw_INPUT -p esp -j RETURN\n"
  79. "-A bw_INPUT -m mark --mark 0x100000/0x100000 -j RETURN\n"
  80. "\n"
  81. "-A bw_INPUT -j MARK --or-mark 0x100000\n"
  82. "-A bw_OUTPUT -j bw_global_alert\n"
  83. "-A bw_OUTPUT -o ipsec+ -j RETURN\n"
  84. "-A bw_OUTPUT -m policy --pol ipsec --dir out -j RETURN\n"
  85. "\n"
  86. "-A bw_costly_shared --jump bw_penalty_box\n" +
  87. StringPrintf("-I bw_penalty_box -m bpf --object-pinned %s -j REJECT\n",
  88. XT_BPF_BLACKLIST_PROG_PATH) +
  89. "-A bw_penalty_box --jump bw_happy_box\n"
  90. "-A bw_happy_box --jump bw_data_saver\n"
  91. "-A bw_data_saver -j RETURN\n" +
  92. StringPrintf("-I bw_happy_box -m bpf --object-pinned %s -j RETURN\n",
  93. XT_BPF_WHITELIST_PROG_PATH) +
  94. "COMMIT\n"
  95. "*raw\n"
  96. "-A bw_raw_PREROUTING -i ipsec+ -j RETURN\n"
  97. "-A bw_raw_PREROUTING -m policy --pol ipsec --dir in -j RETURN\n" +
  98. StringPrintf("-A bw_raw_PREROUTING -m bpf --object-pinned %s\n", XT_BPF_INGRESS_PROG_PATH) +
  99. "COMMIT\n"
  100. "*mangle\n"
  101. "-A bw_mangle_POSTROUTING -o ipsec+ -j RETURN\n"
  102. "-A bw_mangle_POSTROUTING -m policy --pol ipsec --dir out -j RETURN\n"
  103. "\n"
  104. "-A bw_mangle_POSTROUTING -j MARK --set-mark 0x0/0x100000\n" +
  105. StringPrintf("-A bw_mangle_POSTROUTING -m bpf --object-pinned %s\n",
  106. XT_BPF_EGRESS_PROG_PATH) +
  107. "COMMIT\n";
  108. class BandwidthControllerTest : public IptablesBaseTest {
  109. protected:
  110. BandwidthControllerTest() {
  111. BandwidthController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
  112. }
  113. BandwidthController mBw;
  114. TunInterface mTun;
  115. void SetUp() {
  116. ASSERT_EQ(0, mTun.init());
  117. }
  118. void TearDown() {
  119. mTun.destroy();
  120. }
  121. void expectSetupCommands(const std::string& expectedClean,
  122. const std::string& expectedAccounting) {
  123. std::string expectedList =
  124. "*filter\n"
  125. "-S\n"
  126. "COMMIT\n";
  127. std::string expectedFlush =
  128. "*filter\n"
  129. ":bw_INPUT -\n"
  130. ":bw_OUTPUT -\n"
  131. ":bw_FORWARD -\n"
  132. ":bw_happy_box -\n"
  133. ":bw_penalty_box -\n"
  134. ":bw_data_saver -\n"
  135. ":bw_costly_shared -\n"
  136. ":bw_global_alert -\n"
  137. "COMMIT\n"
  138. "*raw\n"
  139. ":bw_raw_PREROUTING -\n"
  140. "COMMIT\n"
  141. "*mangle\n"
  142. ":bw_mangle_POSTROUTING -\n"
  143. "COMMIT\n";
  144. ExpectedIptablesCommands expected = {{ V4, expectedList }};
  145. if (expectedClean.size()) {
  146. expected.push_back({ V4V6, expectedClean });
  147. }
  148. expected.push_back({ V4V6, expectedFlush });
  149. if (expectedAccounting.size()) {
  150. expected.push_back({ V4V6, expectedAccounting });
  151. }
  152. expectIptablesRestoreCommands(expected);
  153. }
  154. using IptOp = BandwidthController::IptOp;
  155. int runIptablesAlertCmd(IptOp a, const char* b, int64_t c) {
  156. return mBw.runIptablesAlertCmd(a, b, c);
  157. }
  158. int setCostlyAlert(const std::string& a, int64_t b, int64_t* c) {
  159. return mBw.setCostlyAlert(a, b, c);
  160. }
  161. int removeCostlyAlert(const std::string& a, int64_t* b) { return mBw.removeCostlyAlert(a, b); }
  162. void expectUpdateQuota(uint64_t quota) {
  163. uintptr_t dummy;
  164. FILE* dummyFile = reinterpret_cast<FILE*>(&dummy);
  165. EXPECT_CALL(mSyscalls, fopen(_, _)).WillOnce(Return(ByMove(UniqueFile(dummyFile))));
  166. EXPECT_CALL(mSyscalls, vfprintf(dummyFile, _, _))
  167. .WillOnce(Invoke([quota](FILE*, const std::string&, va_list ap) {
  168. EXPECT_EQ(quota, va_arg(ap, uint64_t));
  169. return 0;
  170. }));
  171. EXPECT_CALL(mSyscalls, fclose(dummyFile)).WillOnce(Return(ok));
  172. }
  173. void checkBandwithControl(bool useBpf) {
  174. // Pretend no bw_costly_shared_<iface> rules already exist...
  175. addIptablesRestoreOutput(
  176. "-P OUTPUT ACCEPT\n"
  177. "-N bw_costly_shared\n"
  178. "-N unrelated\n");
  179. // ... so none are flushed or deleted.
  180. std::string expectedClean = "";
  181. std::string expectedAccounting =
  182. useBpf ? ACCOUNT_RULES_WITH_BPF : ACCOUNT_RULES_WITHOUT_BPF;
  183. mBw.setBpfEnabled(useBpf);
  184. mBw.enableBandwidthControl();
  185. expectSetupCommands(expectedClean, expectedAccounting);
  186. }
  187. StrictMock<android::netdutils::ScopedMockSyscalls> mSyscalls;
  188. };
  189. TEST_F(BandwidthControllerTest, TestSetupIptablesHooks) {
  190. // Pretend some bw_costly_shared_<iface> rules already exist...
  191. addIptablesRestoreOutput(
  192. "-P OUTPUT ACCEPT\n"
  193. "-N bw_costly_rmnet_data0\n"
  194. "-N bw_costly_shared\n"
  195. "-N unrelated\n"
  196. "-N bw_costly_rmnet_data7\n");
  197. // ... and expect that they be flushed and deleted.
  198. std::string expectedCleanCmds =
  199. "*filter\n"
  200. ":bw_costly_rmnet_data0 -\n"
  201. "-X bw_costly_rmnet_data0\n"
  202. ":bw_costly_rmnet_data7 -\n"
  203. "-X bw_costly_rmnet_data7\n"
  204. "COMMIT\n";
  205. mBw.setupIptablesHooks();
  206. expectSetupCommands(expectedCleanCmds, "");
  207. }
  208. TEST_F(BandwidthControllerTest, TestCheckUidBillingMask) {
  209. uint32_t uidBillingMask = Fwmark::getUidBillingMask();
  210. // If mask is non-zero, and mask & mask-1 is equal to 0, then the mask is a power of two.
  211. bool isPowerOfTwo = uidBillingMask && (uidBillingMask & (uidBillingMask - 1)) == 0;
  212. // Must be exactly a power of two
  213. EXPECT_TRUE(isPowerOfTwo);
  214. }
  215. TEST_F(BandwidthControllerTest, TestEnableBandwidthControlWithBpf) {
  216. checkBandwithControl(true);
  217. }
  218. TEST_F(BandwidthControllerTest, TestEnableBandwidthControlWithoutBpf) {
  219. checkBandwithControl(false);
  220. }
  221. TEST_F(BandwidthControllerTest, TestDisableBandwidthControl) {
  222. // Pretend some bw_costly_shared_<iface> rules already exist...
  223. addIptablesRestoreOutput(
  224. "-P OUTPUT ACCEPT\n"
  225. "-N bw_costly_rmnet_data0\n"
  226. "-N bw_costly_shared\n"
  227. "-N unrelated\n"
  228. "-N bw_costly_rmnet_data7\n");
  229. // ... and expect that they be flushed.
  230. std::string expectedCleanCmds =
  231. "*filter\n"
  232. ":bw_costly_rmnet_data0 -\n"
  233. ":bw_costly_rmnet_data7 -\n"
  234. "COMMIT\n";
  235. mBw.disableBandwidthControl();
  236. expectSetupCommands(expectedCleanCmds, "");
  237. }
  238. TEST_F(BandwidthControllerTest, TestEnableDataSaver) {
  239. mBw.enableDataSaver(true);
  240. std::string expected4 =
  241. "*filter\n"
  242. ":bw_data_saver -\n"
  243. "-A bw_data_saver --jump REJECT\n"
  244. "COMMIT\n";
  245. std::string expected6 =
  246. "*filter\n"
  247. ":bw_data_saver -\n"
  248. "-A bw_data_saver -p icmpv6 --icmpv6-type packet-too-big -j RETURN\n"
  249. "-A bw_data_saver -p icmpv6 --icmpv6-type router-solicitation -j RETURN\n"
  250. "-A bw_data_saver -p icmpv6 --icmpv6-type router-advertisement -j RETURN\n"
  251. "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN\n"
  252. "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN\n"
  253. "-A bw_data_saver -p icmpv6 --icmpv6-type redirect -j RETURN\n"
  254. "-A bw_data_saver --jump REJECT\n"
  255. "COMMIT\n";
  256. expectIptablesRestoreCommands({
  257. {V4, expected4},
  258. {V6, expected6},
  259. });
  260. mBw.enableDataSaver(false);
  261. std::string expected = {
  262. "*filter\n"
  263. ":bw_data_saver -\n"
  264. "-A bw_data_saver --jump RETURN\n"
  265. "COMMIT\n"
  266. };
  267. expectIptablesRestoreCommands({
  268. {V4, expected},
  269. {V6, expected},
  270. });
  271. }
  272. const std::vector<std::string> makeInterfaceQuotaCommands(const std::string& iface, int ruleIndex,
  273. int64_t quota) {
  274. const std::string chain = "bw_costly_" + iface;
  275. const char* c_chain = chain.c_str();
  276. const char* c_iface = iface.c_str();
  277. std::vector<std::string> cmds = {
  278. "*filter",
  279. StringPrintf(":%s -", c_chain),
  280. StringPrintf("-A %s -j bw_penalty_box", c_chain),
  281. StringPrintf("-I bw_INPUT %d -i %s --jump %s", ruleIndex, c_iface, c_chain),
  282. StringPrintf("-I bw_OUTPUT %d -o %s --jump %s", ruleIndex, c_iface, c_chain),
  283. StringPrintf("-A bw_FORWARD -i %s --jump %s", c_iface, c_chain),
  284. StringPrintf("-A bw_FORWARD -o %s --jump %s", c_iface, c_chain),
  285. StringPrintf("-A %s -m quota2 ! --quota %" PRIu64 " --name %s --jump REJECT", c_chain,
  286. quota, c_iface),
  287. "COMMIT\n",
  288. };
  289. return {Join(cmds, "\n")};
  290. }
  291. const std::vector<std::string> removeInterfaceQuotaCommands(const std::string& iface) {
  292. const std::string chain = "bw_costly_" + iface;
  293. const char* c_chain = chain.c_str();
  294. const char* c_iface = iface.c_str();
  295. std::vector<std::string> cmds = {
  296. "*filter",
  297. StringPrintf("-D bw_INPUT -i %s --jump %s", c_iface, c_chain),
  298. StringPrintf("-D bw_OUTPUT -o %s --jump %s", c_iface, c_chain),
  299. StringPrintf("-D bw_FORWARD -i %s --jump %s", c_iface, c_chain),
  300. StringPrintf("-D bw_FORWARD -o %s --jump %s", c_iface, c_chain),
  301. StringPrintf("-F %s", c_chain),
  302. StringPrintf("-X %s", c_chain),
  303. "COMMIT\n",
  304. };
  305. return {Join(cmds, "\n")};
  306. }
  307. TEST_F(BandwidthControllerTest, TestSetInterfaceQuota) {
  308. constexpr uint64_t kOldQuota = 123456;
  309. const std::string iface = mTun.name();
  310. std::vector<std::string> expected = makeInterfaceQuotaCommands(iface, 1, kOldQuota);
  311. EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kOldQuota));
  312. expectIptablesRestoreCommands(expected);
  313. constexpr uint64_t kNewQuota = kOldQuota + 1;
  314. expected = {};
  315. expectUpdateQuota(kNewQuota);
  316. EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kNewQuota));
  317. expectIptablesRestoreCommands(expected);
  318. expected = removeInterfaceQuotaCommands(iface);
  319. EXPECT_EQ(0, mBw.removeInterfaceQuota(iface));
  320. expectIptablesRestoreCommands(expected);
  321. }
  322. const std::vector<std::string> makeInterfaceSharedQuotaCommands(const std::string& iface,
  323. int ruleIndex, int64_t quota,
  324. bool insertQuota) {
  325. const std::string chain = "bw_costly_shared";
  326. const char* c_chain = chain.c_str();
  327. const char* c_iface = iface.c_str();
  328. std::vector<std::string> cmds = {
  329. "*filter",
  330. StringPrintf("-I bw_INPUT %d -i %s --jump %s", ruleIndex, c_iface, c_chain),
  331. StringPrintf("-I bw_OUTPUT %d -o %s --jump %s", ruleIndex, c_iface, c_chain),
  332. StringPrintf("-A bw_FORWARD -i %s --jump %s", c_iface, c_chain),
  333. StringPrintf("-A bw_FORWARD -o %s --jump %s", c_iface, c_chain),
  334. };
  335. if (insertQuota) {
  336. cmds.push_back(StringPrintf(
  337. "-I %s -m quota2 ! --quota %" PRIu64 " --name shared --jump REJECT", c_chain, quota));
  338. }
  339. cmds.push_back("COMMIT\n");
  340. return {Join(cmds, "\n")};
  341. }
  342. const std::vector<std::string> removeInterfaceSharedQuotaCommands(const std::string& iface,
  343. int64_t quota, bool deleteQuota) {
  344. const std::string chain = "bw_costly_shared";
  345. const char* c_chain = chain.c_str();
  346. const char* c_iface = iface.c_str();
  347. std::vector<std::string> cmds = {
  348. "*filter",
  349. StringPrintf("-D bw_INPUT -i %s --jump %s", c_iface, c_chain),
  350. StringPrintf("-D bw_OUTPUT -o %s --jump %s", c_iface, c_chain),
  351. StringPrintf("-D bw_FORWARD -i %s --jump %s", c_iface, c_chain),
  352. StringPrintf("-D bw_FORWARD -o %s --jump %s", c_iface, c_chain),
  353. };
  354. if (deleteQuota) {
  355. cmds.push_back(StringPrintf(
  356. "-D %s -m quota2 ! --quota %" PRIu64 " --name shared --jump REJECT", c_chain, quota));
  357. }
  358. cmds.push_back("COMMIT\n");
  359. return {Join(cmds, "\n")};
  360. }
  361. TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaDuplicate) {
  362. constexpr uint64_t kQuota = 123456;
  363. const std::string iface = mTun.name();
  364. std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, 123456, true);
  365. EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
  366. expectIptablesRestoreCommands(expected);
  367. expected = {};
  368. EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
  369. expectIptablesRestoreCommands(expected);
  370. expected = removeInterfaceSharedQuotaCommands(iface, kQuota, true);
  371. EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
  372. expectIptablesRestoreCommands(expected);
  373. }
  374. TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaUpdate) {
  375. constexpr uint64_t kOldQuota = 123456;
  376. const std::string iface = mTun.name();
  377. std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, kOldQuota, true);
  378. EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kOldQuota));
  379. expectIptablesRestoreCommands(expected);
  380. constexpr uint64_t kNewQuota = kOldQuota + 1;
  381. expected = {};
  382. expectUpdateQuota(kNewQuota);
  383. EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kNewQuota));
  384. expectIptablesRestoreCommands(expected);
  385. expected = removeInterfaceSharedQuotaCommands(iface, kNewQuota, true);
  386. EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
  387. expectIptablesRestoreCommands(expected);
  388. }
  389. TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaTwoInterfaces) {
  390. constexpr uint64_t kQuota = 123456;
  391. const std::vector<std::string> ifaces{
  392. {"a" + mTun.name()},
  393. {"b" + mTun.name()},
  394. };
  395. for (const auto& iface : ifaces) {
  396. // Quota rule is only added when the total number of
  397. // interfaces transitions from 0 -> 1.
  398. bool first = (iface == ifaces[0]);
  399. auto expected = makeInterfaceSharedQuotaCommands(iface, 1, kQuota, first);
  400. EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
  401. expectIptablesRestoreCommands(expected);
  402. }
  403. for (const auto& iface : ifaces) {
  404. // Quota rule is only removed when the total number of
  405. // interfaces transitions from 1 -> 0.
  406. bool last = (iface == ifaces[1]);
  407. auto expected = removeInterfaceSharedQuotaCommands(iface, kQuota, last);
  408. EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
  409. expectIptablesRestoreCommands(expected);
  410. }
  411. }
  412. TEST_F(BandwidthControllerTest, IptablesAlertCmd) {
  413. std::vector<std::string> expected = {
  414. "*filter\n"
  415. "-I bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
  416. "COMMIT\n"};
  417. EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
  418. expectIptablesRestoreCommands(expected);
  419. expected = {
  420. "*filter\n"
  421. "-D bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
  422. "COMMIT\n"};
  423. EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
  424. expectIptablesRestoreCommands(expected);
  425. }
  426. TEST_F(BandwidthControllerTest, CostlyAlert) {
  427. const int64_t kQuota = 123456;
  428. int64_t alertBytes = 0;
  429. std::vector<std::string> expected = {
  430. "*filter\n"
  431. "-A bw_costly_shared -m quota2 ! --quota 123456 --name sharedAlert\n"
  432. "COMMIT\n"
  433. };
  434. EXPECT_EQ(0, setCostlyAlert("shared", kQuota, &alertBytes));
  435. EXPECT_EQ(kQuota, alertBytes);
  436. expectIptablesRestoreCommands(expected);
  437. expected = {};
  438. expectUpdateQuota(kQuota);
  439. EXPECT_EQ(0, setCostlyAlert("shared", kQuota + 1, &alertBytes));
  440. EXPECT_EQ(kQuota + 1, alertBytes);
  441. expectIptablesRestoreCommands(expected);
  442. expected = {
  443. "*filter\n"
  444. "-D bw_costly_shared -m quota2 ! --quota 123457 --name sharedAlert\n"
  445. "COMMIT\n"
  446. };
  447. EXPECT_EQ(0, removeCostlyAlert("shared", &alertBytes));
  448. EXPECT_EQ(0, alertBytes);
  449. expectIptablesRestoreCommands(expected);
  450. }
  451. TEST_F(BandwidthControllerTest, ManipulateSpecialApps) {
  452. std::vector<const char *> appUids = { "1000", "1001", "10012" };
  453. std::vector<std::string> expected = {
  454. "*filter\n"
  455. "-I bw_happy_box -m owner --uid-owner 1000 --jump RETURN\n"
  456. "-I bw_happy_box -m owner --uid-owner 1001 --jump RETURN\n"
  457. "-I bw_happy_box -m owner --uid-owner 10012 --jump RETURN\n"
  458. "COMMIT\n"
  459. };
  460. EXPECT_EQ(0, mBw.addNiceApps(appUids.size(), const_cast<char**>(&appUids[0])));
  461. expectIptablesRestoreCommands(expected);
  462. expected = {
  463. "*filter\n"
  464. "-D bw_penalty_box -m owner --uid-owner 1000 --jump REJECT\n"
  465. "-D bw_penalty_box -m owner --uid-owner 1001 --jump REJECT\n"
  466. "-D bw_penalty_box -m owner --uid-owner 10012 --jump REJECT\n"
  467. "COMMIT\n"
  468. };
  469. EXPECT_EQ(0, mBw.removeNaughtyApps(appUids.size(), const_cast<char**>(&appUids[0])));
  470. expectIptablesRestoreCommands(expected);
  471. }