• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 26323460081

23 May 2026 12:00AM UTC coverage: 89.383% (+0.03%) from 89.349%
26323460081

push

github

web-flow
Merge pull request #5621 from randombit/jack/cli-port-shift

Move the cli test TCP/UDP port range downward

109787 of 122827 relevant lines covered (89.38%)

11032030.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.67
/src/tests/test_x509_dn.cpp
1
/*
2
* (C) 2017 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#if defined(BOTAN_HAS_X509_CERTIFICATES)
10
   #include <botan/ber_dec.h>
11
   #include <botan/pkix_types.h>
12
   #include <sstream>
13
#endif
14

15
namespace Botan_Tests {
16

17
namespace {
18

19
#if defined(BOTAN_HAS_X509_CERTIFICATES)
20
class X509_DN_Comparisons_Tests final : public Text_Based_Test {
×
21
   public:
22
      X509_DN_Comparisons_Tests() : Text_Based_Test("x509_dn.vec", "DN1,DN2") {}
2✔
23

24
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
10✔
25
         const std::vector<uint8_t> dn_bits1 = vars.get_req_bin("DN1");
10✔
26
         const std::vector<uint8_t> dn_bits2 = vars.get_req_bin("DN2");
10✔
27

28
         const bool dn_same = (type == "Equal");
10✔
29

30
         Test::Result result("X509_DN comparisons");
10✔
31
         try {
10✔
32
            Botan::X509_DN dn1;
10✔
33
            Botan::BER_Decoder bd1(dn_bits1);
10✔
34
            dn1.decode_from(bd1);
10✔
35

36
            Botan::X509_DN dn2;
10✔
37
            Botan::BER_Decoder bd2(dn_bits2);
10✔
38
            dn2.decode_from(bd2);
10✔
39

40
            const bool compared_same = (dn1 == dn2);
10✔
41
            result.test_bool_eq("Comparison matches expected", dn_same, compared_same);
10✔
42

43
            const bool lt1 = (dn1 < dn2);
10✔
44
            const bool lt2 = (dn2 < dn1);
10✔
45

46
            if(dn_same) {
10✔
47
               result.test_is_false("same means neither is less than", lt1);
6✔
48
               result.test_is_false("same means neither is less than", lt2);
6✔
49
            } else {
50
               result.test_is_true("different means one is less than", lt1 || lt2);
4✔
51
               result.test_is_false("different means only one is less than", lt1 && lt2);
4✔
52
            }
53
         } catch(Botan::Exception& e) {
30✔
54
            result.test_failure(e.what());
×
55
         }
×
56

57
         return result;
10✔
58
      }
10✔
59
};
60

61
BOTAN_REGISTER_TEST("x509", "x509_dn_cmp", X509_DN_Comparisons_Tests);
62

63
class X509_DN_String_Tests final : public Test {
1✔
64
   public:
65
      std::vector<Test::Result> run() override {
1✔
66
         std::vector<Test::Result> results;
1✔
67
         results.push_back(test_single_ava_round_trip());
2✔
68
         results.push_back(test_multi_ava_rdn_emits_plus());
2✔
69
         results.push_back(test_multi_ava_rdn_round_trip());
2✔
70
         results.push_back(test_parse_multi_ava_rdn());
2✔
71
         results.push_back(test_mixed_single_and_multi_ava_round_trip());
2✔
72
         results.push_back(test_quoted_plus_in_value_not_split());
2✔
73
         return results;
1✔
74
      }
×
75

76
   private:
77
      static Botan::X509_DN parse(std::string_view s) {
6✔
78
         Botan::X509_DN dn;
6✔
79
         std::istringstream iss{std::string(s)};
12✔
80
         iss >> dn;
6✔
81
         return dn;
6✔
82
      }
6✔
83

84
      static std::string format(const Botan::X509_DN& dn) {
5✔
85
         std::ostringstream oss;
5✔
86
         oss << dn;
5✔
87
         return oss.str();
10✔
88
      }
5✔
89

90
      static Test::Result test_single_ava_round_trip() {
1✔
91
         Test::Result result("X509_DN string round-trip (single-AVA RDNs)");
1✔
92
         Botan::X509_DN dn;
1✔
93
         dn.add_attribute("X520.CommonName", "Alice");
1✔
94
         dn.add_attribute("X520.Organization", "Example");
1✔
95

96
         const std::string s = format(dn);
1✔
97
         result.test_str_eq("expected serialization", s, R"(CN="Alice",O="Example")");
1✔
98

99
         const Botan::X509_DN parsed = parse(s);
1✔
100
         result.test_sz_eq("two RDNs", parsed.count(), size_t(2));
1✔
101
         result.test_is_true("parses back to equal DN", parsed == dn);
1✔
102
         return result;
1✔
103
      }
2✔
104

105
      static Test::Result test_multi_ava_rdn_emits_plus() {
1✔
106
         Test::Result result("X509_DN string output uses '+' within RDN");
1✔
107
         Botan::X509_DN dn;
1✔
108
         dn.add_rdn({{Botan::OID::from_string("X520.CommonName"), Botan::ASN1_String("Alice")},
5✔
109
                     {Botan::OID::from_string("X520.Organization"), Botan::ASN1_String("Example")}});
2✔
110

111
         const std::string s = format(dn);
1✔
112
         result.test_str_eq("multi-AVA RDN uses '+' separator", s, R"(CN="Alice"+O="Example")");
1✔
113
         return result;
1✔
114
      }
5✔
115

116
      static Test::Result test_multi_ava_rdn_round_trip() {
1✔
117
         Test::Result result("X509_DN string round-trip (multi-AVA RDN)");
1✔
118
         Botan::X509_DN dn;
1✔
119
         dn.add_rdn({{Botan::OID::from_string("X520.CommonName"), Botan::ASN1_String("Alice")},
5✔
120
                     {Botan::OID::from_string("X520.Organization"), Botan::ASN1_String("Example")}});
2✔
121

122
         const std::string s = format(dn);
1✔
123
         const Botan::X509_DN parsed = parse(s);
1✔
124

125
         result.test_sz_eq("one RDN", parsed.count(), size_t(1));
1✔
126
         result.test_sz_eq("two AVAs in RDN", parsed.rdns().at(0).size(), size_t(2));
1✔
127
         result.test_is_true("parses back to equal DN", parsed == dn);
1✔
128
         result.test_str_eq("re-emits identical string", format(parsed), s);
1✔
129
         return result;
1✔
130
      }
5✔
131

132
      static Test::Result test_parse_multi_ava_rdn() {
1✔
133
         Test::Result result("X509_DN parses '+'-separated AVAs into one RDN");
1✔
134
         const Botan::X509_DN parsed = parse(R"(CN="Alice"+O="Example")");
1✔
135
         result.test_sz_eq("one RDN", parsed.count(), size_t(1));
1✔
136
         result.test_sz_eq("two AVAs in that RDN", parsed.rdns().at(0).size(), size_t(2));
1✔
137

138
         // ',' continues to act as the RDN separator.
139
         const Botan::X509_DN comma = parse(R"(CN="Alice",O="Example")");
1✔
140
         result.test_sz_eq("',' yields two RDNs", comma.count(), size_t(2));
1✔
141
         result.test_sz_eq("each RDN has one AVA", comma.rdns().at(0).size(), size_t(1));
1✔
142
         result.test_is_false("two distinct groupings", parsed == comma);
1✔
143
         return result;
1✔
144
      }
2✔
145

146
      static Test::Result test_mixed_single_and_multi_ava_round_trip() {
1✔
147
         Test::Result result("X509_DN string round-trip (mixed RDNs)");
1✔
148
         Botan::X509_DN dn;
1✔
149
         dn.add_attribute("X520.Country", "US");
1✔
150
         dn.add_rdn({{Botan::OID::from_string("X520.CommonName"), Botan::ASN1_String("Alice")},
5✔
151
                     {Botan::OID::from_string("X520.Organization"), Botan::ASN1_String("Example")}});
2✔
152
         dn.add_attribute("X520.OrganizationalUnit", "Eng");
1✔
153

154
         const std::string s = format(dn);
1✔
155
         result.test_str_eq("mixed RDN format", s, R"(C="US",CN="Alice"+O="Example",OU="Eng")");
1✔
156

157
         const Botan::X509_DN parsed = parse(s);
1✔
158
         result.test_sz_eq("three RDNs", parsed.count(), size_t(3));
1✔
159
         result.test_sz_eq("first is single AVA", parsed.rdns().at(0).size(), size_t(1));
1✔
160
         result.test_sz_eq("second is multi-AVA", parsed.rdns().at(1).size(), size_t(2));
1✔
161
         result.test_sz_eq("third is single AVA", parsed.rdns().at(2).size(), size_t(1));
1✔
162
         result.test_is_true("round-trips equal", parsed == dn);
1✔
163
         return result;
1✔
164
      }
5✔
165

166
      static Test::Result test_quoted_plus_in_value_not_split() {
1✔
167
         Test::Result result("X509_DN parser treats '+' inside quotes as data");
1✔
168
         const Botan::X509_DN parsed = parse(R"(CN="A+B")");
1✔
169
         result.test_sz_eq("one RDN", parsed.count(), size_t(1));
1✔
170
         result.test_sz_eq("one AVA", parsed.rdns().at(0).size(), size_t(1));
1✔
171
         result.test_str_eq("value preserved", parsed.get_first_attribute("CN"), "A+B");
1✔
172
         return result;
1✔
173
      }
1✔
174
};
175

176
BOTAN_REGISTER_TEST("x509", "x509_dn_string", X509_DN_String_Tests);
177
#endif
178

179
}  // namespace
180

181
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc