| // Copyright 2017-2020 The Verible Authors. | |
| // | |
| // 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 required 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. | |
| #include "common/strings/obfuscator.h" | |
| #include "gmock/gmock.h" | |
| #include "gtest/gtest.h" | |
| #include "common/util/bijective_map.h" | |
| #include "common/util/logging.h" | |
| namespace verible { | |
| namespace { | |
| static char Rot13(char c) { | |
| if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M')) | |
| return c + 13; | |
| else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z')) | |
| return c - 13; | |
| else | |
| return c; | |
| } | |
| // Non-random generator, just for the sake of testing. | |
| static std::string RotateGenerator(absl::string_view input) { | |
| std::string s(input); | |
| for (auto& ch : s) ch = Rot13(ch); | |
| return s; | |
| } | |
| TEST(ObfuscatorTest, Construction) { | |
| Obfuscator ob(RotateGenerator); | |
| EXPECT_TRUE(ob.GetTranslator().empty()); | |
| } | |
| TEST(ObfuscatorTest, Transform) { | |
| Obfuscator ob(RotateGenerator); | |
| const auto& tran = ob.GetTranslator(); | |
| // repeat same string | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("cat"); | |
| EXPECT_EQ(str, "png"); | |
| EXPECT_EQ(tran.size(), 1); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), "png"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("png")), "cat"); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("Dog"); | |
| EXPECT_EQ(str, "Qbt"); | |
| EXPECT_EQ(tran.size(), 2); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), "png"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("png")), "cat"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("Dog")), "Qbt"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("Qbt")), "Dog"); | |
| } | |
| } | |
| TEST(ObfuscatorTest, Encode) { | |
| Obfuscator ob(RotateGenerator); | |
| ob.encode("cat", "sheep"); | |
| const auto& tran = ob.GetTranslator(); | |
| EXPECT_EQ(tran.size(), 1); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), "sheep"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("sheep")), "cat"); | |
| // repeat same string | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("cat"); | |
| EXPECT_EQ(str, "sheep"); | |
| EXPECT_EQ(tran.size(), 1); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), "sheep"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("sheep")), "cat"); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("dog"); | |
| EXPECT_EQ(str, "qbt"); | |
| EXPECT_EQ(tran.size(), 2); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), "sheep"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("sheep")), "cat"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("dog")), "qbt"); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse("qbt")), "dog"); | |
| } | |
| } | |
| TEST(ObfuscatorTest, DecodeMode) { | |
| Obfuscator ob(RotateGenerator); | |
| EXPECT_FALSE(ob.is_decoding()); | |
| ob.set_decode_mode(true); | |
| EXPECT_TRUE(ob.is_decoding()); | |
| ob.set_decode_mode(false); | |
| EXPECT_FALSE(ob.is_decoding()); | |
| } | |
| TEST(ObfuscatorTest, DecodeModeDoesNotAddEntries) { | |
| Obfuscator ob(RotateGenerator); | |
| ob.set_decode_mode(true); | |
| EXPECT_TRUE(ob.is_decoding()); | |
| EXPECT_TRUE(ob.GetTranslator().empty()); | |
| EXPECT_EQ(ob("dog"), "dog"); // unrecognized id, unchanged | |
| EXPECT_TRUE(ob.GetTranslator().empty()); | |
| // can still manually add entries | |
| EXPECT_TRUE(ob.encode("shark", "snake")); | |
| EXPECT_EQ(ob.GetTranslator().size(), 1); | |
| EXPECT_EQ(ob("snake"), "shark"); // decoded | |
| EXPECT_EQ(ob.GetTranslator().size(), 1); | |
| EXPECT_EQ(ob("cow"), "cow"); | |
| EXPECT_EQ(ob.GetTranslator().size(), 1); | |
| } | |
| TEST(ObfuscatorTest, SaveMap) { | |
| Obfuscator ob(RotateGenerator); | |
| EXPECT_EQ(ob.save(), ""); | |
| EXPECT_EQ(ob("cat"), "png"); | |
| EXPECT_EQ(ob.save(), "cat png\n"); | |
| EXPECT_EQ(ob("zzz"), "mmm"); | |
| EXPECT_EQ(ob.save(), "cat png\nzzz mmm\n"); | |
| } | |
| TEST(ObfuscatorTest, LoadMap) { | |
| { | |
| Obfuscator ob(RotateGenerator); | |
| const auto status = ob.load(""); | |
| EXPECT_TRUE(status.ok()) << status.message(); | |
| } | |
| { | |
| Obfuscator ob(RotateGenerator); | |
| const auto status = ob.load("cat dog"); | |
| EXPECT_TRUE(status.ok()) << status.message(); | |
| EXPECT_EQ(ob("cat"), "dog"); | |
| } | |
| { | |
| Obfuscator ob(RotateGenerator); | |
| const auto status = ob.load("cat dog\n"); | |
| EXPECT_TRUE(status.ok()) << status.message(); | |
| EXPECT_EQ(ob("cat"), "dog"); | |
| } | |
| { | |
| Obfuscator ob(RotateGenerator); | |
| const auto status = ob.load("cat\n"); // malformed line | |
| EXPECT_FALSE(status.ok()); | |
| EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument); | |
| } | |
| } | |
| TEST(IdentifierObfuscatorTest, Transform) { | |
| IdentifierObfuscator ob; | |
| const auto& tran = ob.GetTranslator(); | |
| // repeat same string | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("cat"); // str is random | |
| EXPECT_EQ(tran.size(), 1); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), str); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse(std::string(str))), "cat"); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("dog"); // str is random | |
| EXPECT_EQ(tran.size(), 2); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("dog")), str); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse(std::string(str))), "dog"); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("cat"); // str is random | |
| EXPECT_EQ(tran.size(), 2); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), str); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse(std::string(str))), "cat"); | |
| } | |
| } | |
| TEST(IdentifierObfuscatorTest, EncodeInvalid) { | |
| IdentifierObfuscator ob; | |
| EXPECT_DEATH(ob.encode("cat", "sheep"), ""); // mismatch length | |
| } | |
| TEST(IdentifierObfuscatorTest, EncodeValidTransform) { | |
| IdentifierObfuscator ob; | |
| ob.encode("cat", "cow"); | |
| const auto& tran = ob.GetTranslator(); | |
| // repeat same string | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("cat"); | |
| EXPECT_EQ(str, "cow"); | |
| EXPECT_EQ(tran.size(), 1); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), str); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse(std::string(str))), "cat"); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("Dog"); // str is random | |
| EXPECT_EQ(tran.size(), 2); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("Dog")), str); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse(std::string(str))), "Dog"); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| const auto str = ob("cat"); | |
| EXPECT_EQ(str, "cow"); | |
| EXPECT_EQ(tran.size(), 2); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_forward("cat")), str); | |
| EXPECT_EQ(*ABSL_DIE_IF_NULL(tran.find_reverse(std::string(str))), "cat"); | |
| } | |
| } | |
| } // namespace | |
| } // namespace verible |