TEST(DedupBlocksTest, useSwitch) { g_redex = new RedexContext(); const char* dexfile = std::getenv("dexfile"); EXPECT_NE(nullptr, dexfile); std::vector<DexStore> stores; DexMetadata dm; dm.set_id("classes"); DexStore root_store(dm); root_store.add_classes(load_classes_from_dex(dexfile)); DexClasses& classes = root_store.get_dexen().back(); stores.emplace_back(std::move(root_store)); TRACE(RME, 1, "Code before:\n"); for (const auto& cls : classes) { TRACE(RME, 1, "Class %s\n", SHOW(cls)); for (const auto& m : cls->get_vmethods()) { TRACE(RME, 1, "\nmethod %s:\n", SHOW(m)); IRCode* code = m->get_code(); code->build_cfg(true); EXPECT_EQ(2, count_sgets(code->cfg())); code->clear_cfg(); } } auto copy_prop = new CopyPropagationPass(); copy_prop->m_config.static_finals = true; copy_prop->m_config.wide_registers = true; std::vector<Pass*> passes = { copy_prop }; PassManager manager(passes); manager.set_testing_mode(); Json::Value conf_obj = Json::nullValue; Scope external_classes; ConfigFiles dummy_cfg(conf_obj); manager.run_passes(stores, external_classes, dummy_cfg); TRACE(RME, 1, "Code after:\n"); for (const auto& cls : classes) { for (const auto& m : cls->get_vmethods()) { TRACE(RME, 1, "\nmethod %s:\n", SHOW(m)); IRCode* code = m->get_code(); code->build_cfg(true); if (strcmp(m->get_name()->c_str(), "remove") == 0) { EXPECT_EQ(1, count_sgets(code->cfg())); } else { EXPECT_EQ(2, count_sgets(code->cfg())); } code->clear_cfg(); } } }
TEST_F(PostVerify, ConstantPropagation) { TRACE(CONSTP, 1, "------------- post ---------------\n"); auto cls = find_class_named(classes, "Lredex/ConstantPropagationTest;"); ASSERT_NE(cls, nullptr); for (auto& meth : cls->get_vmethods()) { if(meth->get_name()->str().find("if") == std::string::npos) { continue; } IRCode* code = new IRCode(meth); EXPECT_NE(code, nullptr); code->build_cfg(/* editable */ true); if (meth->get_name()->str().find("plus_one") != std::string::npos) { TRACE(CONSTP, 1, "%s\n", SHOW(meth)); TRACE(CONSTP, 1, "%s\n", SHOW(code)); } EXPECT_EQ(0, count_ifs(code->cfg())); if (meth->get_name()->str().find("plus_one") != std::string::npos) { EXPECT_EQ(0, count_ops(code->cfg(), OPCODE_ADD_INT_LIT8)); } if (meth->get_name()->str().find("overflow") != std::string::npos) { // make sure we don't fold overflow at compile time EXPECT_EQ(1, count_ops(code->cfg(), OPCODE_ADD_INT_LIT8)); } code->clear_cfg(); } }
TEST(ResultPropagationTest, useSwitch) { g_redex = new RedexContext(); const char* dexfile = std::getenv("dexfile"); EXPECT_NE(nullptr, dexfile); std::vector<DexStore> stores; DexMetadata dm; dm.set_id("classes"); DexStore root_store(dm); root_store.add_classes(load_classes_from_dex(dexfile)); DexClasses& classes = root_store.get_dexen().back(); stores.emplace_back(std::move(root_store)); std::vector<Pass*> passes = { new ResultPropagationPass(), }; PassManager manager(passes); manager.set_testing_mode(); Json::Value conf_obj = Json::nullValue; ConfigFiles dummy_cfg(conf_obj); manager.run_passes(stores, dummy_cfg); int num_test_classes = 0; const char* test_class_prefix = "Lcom/facebook/redextest/ResultPropagation$"; const char* test_method_prefix = "returns_"; for (const auto& cls : classes) { if (strncmp(cls->get_name()->c_str(), test_class_prefix, strlen(test_class_prefix)) == 0) { TRACE(RP, 1, "test class %s\n", cls->get_name()->c_str()); num_test_classes++; int num_tests_in_class = 0; for (const auto& m : cls->get_vmethods()) { const auto method_name = m->get_name()->c_str(); TRACE(RP, 1, " test method %s\n", method_name); EXPECT_EQ(strncmp(method_name, test_method_prefix, strlen(test_method_prefix)), 0); const auto suffix = method_name + strlen(test_method_prefix); boost::optional<ParamIndex> expected; if (strcmp(suffix, "none") != 0) { expected = atoi(suffix); } IRCode* code = m->get_code(); code->build_cfg(/* editable */ true); auto actual = find_return_param_index(code->cfg()); code->clear_cfg(); if (expected) { EXPECT_TRUE(actual); EXPECT_EQ(*actual, *expected); } else { EXPECT_FALSE(actual); } num_tests_in_class++; } EXPECT_EQ(num_tests_in_class, 1); } } EXPECT_EQ(num_test_classes, 6); }