Added an explicit yield (OP_SLEEP) to QUIC testing for cooperative threading.
[openssl.git] / test / recipes / tconversion.pl
1 #! /usr/bin/env perl
2 # Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9
10 use strict;
11 use warnings;
12
13 use File::Compare qw/compare_text/;
14 use File::Copy;
15 use OpenSSL::Test qw/:DEFAULT/;
16 use Time::Piece;
17 use POSIX qw(strftime);
18
19 my %conversionforms = (
20     # Default conversion forms.  Other series may be added with
21     # specific test types as key.
22     "*"         => [ "d", "p" ],
23     "msb"       => [ "d", "p", "msblob" ],
24     "pvk"       => [ "d", "p", "pvk" ],
25     );
26 sub tconversion {
27     my %opts = @_;
28
29     die "Missing option -type" unless $opts{-type};
30     die "Missing option -in" unless $opts{-in};
31     my $testtype = $opts{-type};
32     my $t = $opts{-in};
33     my $prefix = $opts{-prefix} // $testtype;
34     my @conversionforms =
35         defined($conversionforms{$testtype}) ?
36         @{$conversionforms{$testtype}} :
37         @{$conversionforms{"*"}};
38     my @openssl_args;
39     if (defined $opts{-args}) {
40         @openssl_args = @{$opts{-args}} if ref $opts{-args} eq 'ARRAY';
41         @openssl_args = ($opts{-args}) if ref $opts{-args} eq '';
42     }
43     @openssl_args = ($testtype) unless @openssl_args;
44
45     my $n = scalar @conversionforms;
46     my $totaltests =
47         1                       # for initializing
48         + $n                    # initial conversions from p to all forms (A)
49         + $n*$n                 # conversion from result of A to all forms (B)
50         + 1                     # comparing original test file to p form of A
51         + $n*($n-1);            # comparing first conversion to each form in A with B
52     $totaltests-- if ($testtype eq "p7d"); # no comparison of original test file
53     $totaltests -= $n if ($testtype eq "pvk"); # no comparisons of the pvk form
54     plan tests => $totaltests;
55
56     my @cmd = ("openssl", @openssl_args);
57
58     my $init;
59     if (scalar @openssl_args > 0 && $openssl_args[0] eq "pkey") {
60         $init = ok(run(app([@cmd, "-in", $t, "-out", "$prefix-fff.p"])),
61                    'initializing');
62     } else {
63         $init = ok(copy($t, "$prefix-fff.p"), 'initializing');
64     }
65     if (!$init) {
66         diag("Trying to copy $t to $prefix-fff.p : $!");
67     }
68
69   SKIP: {
70       skip "Not initialized, skipping...", 22 unless $init;
71
72       foreach my $to (@conversionforms) {
73           ok(run(app([@cmd,
74                       "-in", "$prefix-fff.p",
75                       "-inform", "p",
76                       "-out", "$prefix-f.$to",
77                       "-outform", $to])),
78              "p -> $to");
79       }
80
81       foreach my $to (@conversionforms) {
82           foreach my $from (@conversionforms) {
83               ok(run(app([@cmd,
84                           "-in", "$prefix-f.$from",
85                           "-inform", $from,
86                           "-out", "$prefix-ff.$from$to",
87                           "-outform", $to])),
88                  "$from -> $to");
89           }
90       }
91
92       if ($testtype ne "p7d") {
93           is(cmp_text("$prefix-fff.p", "$prefix-f.p"), 0,
94              'comparing orig to p');
95       }
96
97       foreach my $to (@conversionforms) {
98           next if $to eq "d" or $to eq "pvk";
99           foreach my $from (@conversionforms) {
100               is(cmp_text("$prefix-f.$to", "$prefix-ff.$from$to"), 0,
101                  "comparing $to to $from$to");
102           }
103       }
104     }
105 }
106
107 sub cmp_text {
108     return compare_text(@_, sub {
109         $_[0] =~ s/\R//g;
110         $_[1] =~ s/\R//g;
111         return $_[0] ne $_[1];
112     });
113 }
114
115 sub file_contains {
116     $_ = shift @_;
117     my $pattern = shift @_;
118     open(DATA, $_) or return 0;
119     $_= join('', <DATA>);
120     close(DATA);
121     s/\s+/ /g; # take multiple whitespace (including newline) as single space
122     return m/$pattern/ ? 1 : 0;
123 }
124
125 sub cert_contains {
126     my $cert = shift @_;
127     my $pattern = shift @_;
128     my $expected = shift @_;
129     my $name = shift @_;
130     my $out = "cert_contains.out";
131     run(app(["openssl", "x509", "-noout", "-text", "-in", $cert, "-out", $out]));
132     is(file_contains($out, $pattern), $expected, ($name ? "$name: " : "").
133        "$cert should ".($expected ? "" : "not ")."contain: \"$pattern\"");
134     # not unlinking $out
135 }
136
137 sub has_version {
138     my $cert = shift @_;
139     my $expect = shift @_;
140     cert_contains($cert, "Version: $expect", 1);
141 }
142
143 sub has_SKID {
144     my $cert = shift @_;
145     my $expect = shift @_;
146     cert_contains($cert, "Subject Key Identifier", $expect);
147 }
148
149 sub has_AKID {
150     my $cert = shift @_;
151     my $expect = shift @_;
152     cert_contains($cert, "Authority Key Identifier", $expect);
153 }
154
155 sub uniq (@) {
156     my %seen = ();
157     grep { not $seen{$_}++ } @_;
158 }
159
160 sub file_n_different_lines {
161     my $filename = shift @_;
162     open(DATA, $filename) or return 0;
163     chomp(my @lines = <DATA>);
164     close(DATA);
165     return scalar(uniq @lines);
166 }
167
168 sub cert_ext_has_n_different_lines {
169     my $cert = shift @_;
170     my $expected = shift @_;
171     my $exts = shift @_;
172     my $name = shift @_;
173     my $out = "cert_n_different_exts.out";
174     run(app(["openssl", "x509", "-noout", "-ext", $exts,
175              "-in", $cert, "-out", $out]));
176     is(file_n_different_lines($out), $expected, ($name ? "$name: " : "").
177        "$cert '$exts' output should contain $expected different lines");
178     # not unlinking $out
179 }
180
181 # extracts string value of certificate field from a -text formatted-output
182 sub get_field {
183     my ($f, $field) = @_;
184     my $string = "";
185     open my $fh, $f or die;
186     while (my $line = <$fh>) {
187         if ($line =~ /$field:\s+(.*)/) {
188             $string = $1;
189         }
190     }
191     close $fh;
192     return $string;
193 }
194
195 sub get_issuer {
196     return get_field(@_, "Issuer");
197 }
198
199 sub get_not_before {
200     return get_field(@_, "Not Before");
201 }
202
203 # Date as yyyy-mm-dd
204 sub get_not_before_date {
205     return Time::Piece->strptime(
206         get_not_before(@_),
207         "%b %d %T %Y %Z")->date;
208 }
209
210 sub get_not_after {
211     return get_field(@_, "Not After ");
212 }
213
214 # Date as yyyy-mm-dd
215 sub get_not_after_date {
216     return Time::Piece->strptime(
217         get_not_after(@_),
218         "%b %d %T %Y %Z")->date;
219 }
220
221 1;