Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-31 02:19:34

0001 #include "catch.hpp"
0002 
0003 #include <iostream>
0004 #include <list>
0005 #include <string>
0006 #include <vector>
0007 
0008 #include "FWCore/Utilities/interface/compactStringSerializer.h"
0009 #include "FWCore/Utilities/interface/Exception.h"
0010 
0011 namespace cs = edm::compactString;
0012 
0013 TEST_CASE("Test edm::compactString serializer", "[edm::compactString]") {
0014   using namespace std::string_literals;
0015   SECTION("Empty inputs") {
0016     SECTION("Serialization") {
0017       SECTION("Empty string") {
0018         auto result = cs::serialize(""s);
0019         CHECK(result.size() == 1);  // one delimiter
0020         result = cs::serialize("");
0021         CHECK(result.size() == 1);  // one delimiter
0022       }
0023 
0024       SECTION("Two empty strings") {
0025         auto result = cs::serialize(""s, ""s);
0026         CHECK(result.size() == 2);
0027         result = cs::serialize(""s, "");
0028         CHECK(result.size() == 2);
0029         result = cs::serialize("", ""s);
0030         CHECK(result.size() == 2);
0031         result = cs::serialize("", "");
0032         CHECK(result.size() == 2);
0033       }
0034 
0035       SECTION("Empty vector of strings and empty string") {
0036         auto result = cs::serialize(std::vector<std::string>());
0037         CHECK(result.size() == 1);
0038         result = cs::serialize(""s, std::vector<std::string>());
0039         CHECK(result.size() == 2);
0040         result = cs::serialize(std::vector<std::string>(), "");
0041         CHECK(result.size() == 2);
0042         result = cs::serialize(std::vector<std::string>(), std::vector<std::string>());
0043         CHECK(result.size() == 2);
0044       }
0045 
0046       SECTION("Empty list and vector of strings and empty string") {
0047         auto result = cs::serialize(std::list<std::string>());
0048         CHECK(result.size() == 1);
0049         result = cs::serialize(""s, std::list<std::string>());
0050         CHECK(result.size() == 2);
0051         result = cs::serialize(std::list<std::string>(), "");
0052         CHECK(result.size() == 2);
0053         result = cs::serialize(std::list<std::string>(), std::list<std::string>());
0054         CHECK(result.size() == 2);
0055         result = cs::serialize(std::vector<std::string>(), std::list<std::string>());
0056         CHECK(result.size() == 2);
0057         result = cs::serialize(std::list<std::string>(), std::vector<std::string>());
0058         CHECK(result.size() == 2);
0059       }
0060 
0061       SECTION("Vectors of empty strings") {
0062         auto result = cs::serialize(std::vector<std::string>{""});
0063         CHECK(result.size() == 2);
0064         result = cs::serialize(std::vector<std::string>{"", ""});
0065         CHECK(result.size() == 3);
0066         result = cs::serialize(std::vector<std::string>{""}, std::vector<std::string>{});
0067         CHECK(result.size() == 3);
0068         result = cs::serialize(std::vector<std::string>{"", ""}, std::vector<std::string>{});
0069         CHECK(result.size() == 4);
0070         result = cs::serialize(std::vector<std::string>{""}, std::vector<std::string>{""});
0071         CHECK(result.size() == 4);
0072         result = cs::serialize(std::vector<std::string>{"", ""}, std::vector<std::string>{""});
0073         CHECK(result.size() == 5);
0074         result = cs::serialize(std::vector<std::string>{""}, std::vector<std::string>{"", ""});
0075         CHECK(result.size() == 5);
0076         result = cs::serialize(std::vector<std::string>{"", ""}, std::vector<std::string>{"", ""});
0077         CHECK(result.size() == 6);
0078       }
0079     }
0080 
0081     SECTION("Serialization and deserialization") {
0082       SECTION("Empty string") {
0083         std::string res;
0084         auto ret = cs::deserialize(cs::serialize(""), res);
0085         CHECK(ret == 1);
0086         CHECK(res.empty());
0087       }
0088 
0089       SECTION("Two empty strings") {
0090         std::string res1, res2;
0091         auto ret = cs::deserialize(cs::serialize("", ""), res1, res2);
0092         CHECK(ret == 2);
0093         CHECK(res1.empty());
0094         CHECK(res2.empty());
0095       }
0096 
0097       SECTION("Empty vector") {
0098         std::vector<std::string> res;
0099         auto ret = cs::deserialize(cs::serialize(std::vector<std::string>()), std::back_inserter(res));
0100         CHECK(ret == 1);
0101         CHECK(res.empty());
0102       }
0103 
0104       SECTION("Two empty vectors") {
0105         std::vector<std::string> res1, res2;
0106         auto ret = cs::deserialize(cs::serialize(std::vector<std::string>(), std::vector<std::string>()),
0107                                    std::back_inserter(res1),
0108                                    std::back_inserter(res2));
0109         CHECK(ret == 2);
0110         CHECK(res1.empty());
0111         CHECK(res2.empty());
0112       }
0113 
0114       SECTION("Mixture") {
0115         std::string res1;
0116         std::vector<std::string> res2;
0117         std::list<std::string> res3;
0118         auto ret = cs::deserialize(cs::serialize("", std::vector<std::string>(), std::list<std::string>()),
0119                                    res1,
0120                                    std::back_inserter(res2),
0121                                    std::back_inserter(res3));
0122         CHECK(ret == 3);
0123         CHECK(res1.empty());
0124         CHECK(res2.empty());
0125         CHECK(res3.empty());
0126 
0127         ret = cs::deserialize(cs::serialize(std::vector<std::string>(), "", std::list<std::string>()),
0128                               std::back_inserter(res3),
0129                               res1,
0130                               std::back_inserter(res2));
0131         CHECK(ret == 3);
0132         CHECK(res1.empty());
0133         CHECK(res2.empty());
0134         CHECK(res3.empty());
0135       }
0136     }
0137   }
0138 
0139   SECTION("Inputs with values") {
0140     SECTION("Strings") {
0141       std::string res1, res2;
0142       auto serial = cs::serialize("foo");
0143       REQUIRE(serial == "foo"s + cs::detail::kContainerDelimiter);
0144       auto ret = cs::deserialize(serial, res1);
0145       CHECK(ret == 3 + 1);
0146       CHECK(res1 == "foo");
0147 
0148       serial = cs::serialize("foo", "bar");
0149       REQUIRE(serial == "foo"s + cs::detail::kContainerDelimiter + "bar"s + cs::detail::kContainerDelimiter);
0150       ret = cs::deserialize(serial, res1, res2);
0151       CHECK(ret == 3 + 1 + 3 + 1);
0152       CHECK(res1 == "foo");
0153       CHECK(res2 == "bar");
0154     }
0155 
0156     SECTION("Vector of strings") {
0157       std::vector<std::string> res;
0158       auto serial = cs::serialize(std::vector<std::string>{"foo"});
0159       REQUIRE(serial == "foo"s + cs::detail::kElementDelimiter + cs::detail::kContainerDelimiter);
0160       auto ret = cs::deserialize(serial, std::back_inserter(res));
0161       CHECK(ret == 3 + 2);
0162       REQUIRE(res.size() == 1);
0163       REQUIRE(res[0] == "foo");
0164       res.clear();
0165 
0166       serial = cs::serialize(std::vector<std::string>{"foo", "bar"});
0167       REQUIRE(serial == "foo"s + cs::detail::kElementDelimiter + "bar"s + cs::detail::kElementDelimiter +
0168                             cs::detail::kContainerDelimiter);
0169       ret = cs::deserialize(serial, std::back_inserter(res));
0170       CHECK(ret == 3 + 1 + 3 + 2);
0171       REQUIRE(res.size() == 2);
0172       CHECK(res[0] == "foo");
0173       CHECK(res[1] == "bar");
0174       res.clear();
0175 
0176       serial = cs::serialize(std::vector<std::string>{"foo", "bar", "xyzzy"});
0177       ret = cs::deserialize(serial, std::back_inserter(res));
0178       CHECK(ret == serial.size());
0179       REQUIRE(res.size() == 3);
0180       CHECK(res[0] == "foo");
0181       CHECK(res[1] == "bar");
0182       CHECK(res[2] == "xyzzy");
0183       res.clear();
0184 
0185       SECTION("Deserialize to list") {
0186         std::list<std::string> res2;
0187         ret = cs::deserialize(serial, std::front_inserter(res2));
0188         CHECK(ret == serial.size());
0189         REQUIRE(res2.size() == 3);
0190         auto it = res2.begin();
0191         CHECK(*it == "xyzzy");
0192         ++it;
0193         CHECK(*it == "bar");
0194         ++it;
0195         CHECK(*it == "foo");
0196       }
0197     }
0198 
0199     SECTION("Vectors of strings") {
0200       std::vector<std::string> res1, res2;
0201       ;
0202       auto serial =
0203           cs::serialize(std::vector<std::string>{"foo", "bar", "xyzzy"}, std::vector<std::string>{"fred", "wilma"});
0204       auto ret = cs::deserialize(serial, std::back_inserter(res1), std::back_inserter(res2));
0205       CHECK(ret == serial.size());
0206       REQUIRE(res1.size() == 3);
0207       CHECK(res1[0] == "foo");
0208       CHECK(res1[1] == "bar");
0209       CHECK(res1[2] == "xyzzy");
0210       REQUIRE(res2.size() == 2);
0211       CHECK(res2[0] == "fred");
0212       CHECK(res2[1] == "wilma");
0213     }
0214 
0215     SECTION("Mixture") {
0216       auto serial = cs::serialize(
0217           "foobar", std::vector<std::string>{"fred", "wilma"}, "xyzzy", std::list<std::string>{"one", "two", "th ree"});
0218       std::string res1, res3;
0219       std::vector<std::string> res2, res4;
0220       auto ret = cs::deserialize(serial, res1, std::back_inserter(res2), res3, std::back_inserter(res4));
0221       CHECK(ret == serial.size());
0222       CHECK(res1 == "foobar");
0223       REQUIRE(res2.size() == 2);
0224       CHECK(res2[0] == "fred");
0225       CHECK(res2[1] == "wilma");
0226       CHECK(res3 == "xyzzy");
0227       REQUIRE(res4.size() == 3);
0228       CHECK(res4[0] == "one");
0229       CHECK(res4[1] == "two");
0230       CHECK(res4[2] == "th ree");
0231     }
0232   }
0233   SECTION("Deserialize only part of the serialized content") {
0234     SECTION("String") {
0235       std::string res;
0236       auto serial = cs::serialize("foo", "bar");
0237       auto ret = cs::deserialize(serial, res);
0238       CHECK(ret != 0);
0239       CHECK(ret != serial.size());
0240       CHECK(res == "foo");
0241       res.clear();
0242 
0243       serial = cs::serialize("bar", std::vector<std::string>{"foo"});
0244       ret = cs::deserialize(serial, res);
0245       CHECK(ret != 0);
0246       CHECK(ret != serial.size());
0247       CHECK(res == "bar");
0248     }
0249 
0250     SECTION("Vector of strings") {
0251       std::vector<std::string> res;
0252       auto serial = cs::serialize(std::vector<std::string>{"foo", "bar"}, std::vector<std::string>{"fred", "wilma"});
0253       auto ret = cs::deserialize(serial, std::back_inserter(res));
0254       CHECK(ret != 0);
0255       CHECK(ret != serial.size());
0256       REQUIRE(res.size() == 2);
0257       CHECK(res[0] == "foo");
0258       CHECK(res[1] == "bar");
0259       res.clear();
0260 
0261       serial = cs::serialize(std::vector<std::string>{"wilma", "fred"}, "fintstones");
0262       ret = cs::deserialize(serial, std::back_inserter(res));
0263       CHECK(ret != 0);
0264       CHECK(ret != serial.size());
0265       REQUIRE(res.size() == 2);
0266       CHECK(res[0] == "wilma");
0267       CHECK(res[1] == "fred");
0268     }
0269   }
0270 
0271   SECTION("Serialization error cases") {
0272     CHECK_THROWS_AS(cs::serialize(""s + cs::detail::kElementDelimiter), cms::Exception);
0273     CHECK_THROWS_AS(cs::serialize("foo"s + cs::detail::kElementDelimiter), cms::Exception);
0274     CHECK_THROWS_AS(cs::serialize(cs::detail::kElementDelimiter + "bar"s), cms::Exception);
0275     CHECK_THROWS_AS(cs::serialize("foo"s + cs::detail::kElementDelimiter + "bar"s), cms::Exception);
0276     CHECK_THROWS_AS(cs::serialize(""s + cs::detail::kContainerDelimiter), cms::Exception);
0277     CHECK_THROWS_AS(cs::serialize("foo"s + cs::detail::kContainerDelimiter), cms::Exception);
0278     CHECK_THROWS_AS(cs::serialize(cs::detail::kContainerDelimiter + "bar"s), cms::Exception);
0279     CHECK_THROWS_AS(cs::serialize("foo"s + cs::detail::kContainerDelimiter + "bar"s), cms::Exception);
0280 
0281     std::string str = "foo"s + cs::detail::kContainerDelimiter;
0282     std::vector<std::string> vstr{str};
0283     CHECK_THROWS_AS(cs::serialize(str, std::vector<std::string>{"foo"}), cms::Exception);
0284     CHECK_THROWS_AS(cs::serialize(std::vector<std::string>{"foo"}, str), cms::Exception);
0285     CHECK_THROWS_AS(cs::serialize(vstr, "foo"), cms::Exception);
0286     CHECK_THROWS_AS(cs::serialize("foo", vstr), cms::Exception);
0287   }
0288 
0289   SECTION("Deserialization error cases") {
0290     SECTION("Invalid input") {
0291       SECTION("Deserializing to string") {
0292         std::string res;
0293         CHECK(cs::deserialize("", res) == 0);
0294         CHECK(cs::deserialize(" ", res) == 0);
0295         CHECK(cs::deserialize("foo", res) == 0);
0296         CHECK(cs::deserialize("foo"s + cs::detail::kElementDelimiter + "bar"s, res) == 0);
0297         CHECK(cs::deserialize("foo"s + cs::detail::kElementDelimiter + "bar"s + cs::detail::kContainerDelimiter, res) ==
0298               0);
0299       }
0300 
0301       SECTION("Deserializing to container") {
0302         std::vector<std::string> res;
0303         CHECK(cs::deserialize("", std::back_inserter(res)) == 0);
0304         CHECK(cs::deserialize(" ", std::back_inserter(res)) == 0);
0305         CHECK(cs::deserialize("foo", std::back_inserter(res)) == 0);
0306         CHECK(cs::deserialize("foo"s + cs::detail::kElementDelimiter + "bar"s, std::back_inserter(res)) == 0);
0307         CHECK(cs::deserialize("foo"s + cs::detail::kContainerDelimiter, std::back_inserter(res)) == 0);
0308       }
0309     }
0310 
0311     SECTION("Schema mismatch") {
0312       // Note: empty container and empty string have the same
0313       // presentation, but this behavior is not tested here as one
0314       // should not rely on it
0315 
0316       SECTION("Deserializing container as string") {
0317         std::string res;
0318         auto ret = cs::deserialize(cs::serialize(std::vector<std::string>{""}), res);
0319         CHECK(ret == 0);
0320         ret = cs::deserialize(cs::serialize(std::vector<std::string>{"foo"}), res);
0321         CHECK(ret == 0);
0322         ret = cs::deserialize(cs::serialize(std::vector<std::string>{"foo", "bar"}), res);
0323         CHECK(ret == 0);
0324       }
0325 
0326       SECTION("Deserializing string as container") {
0327         std::vector<std::string> res;
0328         auto ret = cs::deserialize(cs::serialize("foo"), std::back_inserter(res));
0329         CHECK(ret == 0);
0330         ret = cs::deserialize(cs::serialize("foo", "bar"), std::back_inserter(res));
0331         CHECK(ret == 0);
0332       }
0333     }
0334 
0335     SECTION("Deserializing too much") {
0336       SECTION("Strings") {
0337         std::string res1, res2;
0338         auto ret = cs::deserialize(cs::serialize("foo"), res1, res2);
0339         CHECK(ret == 0);
0340         CHECK(res2.empty());
0341       }
0342 
0343       SECTION("Vector of strings") {
0344         std::vector<std::string> res1, res2;
0345         auto ret = cs::deserialize(
0346             cs::serialize(std::vector<std::string>{"foo", "bar"}), std::back_inserter(res1), std::back_inserter(res2));
0347         CHECK(ret == 0);
0348         CHECK(res2.empty());
0349       }
0350 
0351       SECTION("Mixture") {
0352         std::string ress;
0353         std::vector<std::string> resv;
0354         auto ret = cs::deserialize(cs::serialize("foo"), ress, std::back_inserter(resv));
0355         CHECK(ret == 0);
0356         CHECK(resv.empty());
0357         ress.clear();
0358 
0359         ret = cs::deserialize(cs::serialize(std::vector<std::string>{"foo"}), std::back_inserter(resv), ress);
0360         CHECK(ret == 0);
0361         CHECK(ress.empty());
0362       }
0363     }
0364   }
0365 }