| Index: net/http/transport_security_state_unittest.cc | 
| diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc | 
| index 9f092d84a8462f27928f5630af1fd225c51681d9..24d292abc2f06a34996b910a881d1a7f53438c07 100644 | 
| --- a/net/http/transport_security_state_unittest.cc | 
| +++ b/net/http/transport_security_state_unittest.cc | 
| @@ -26,6 +26,8 @@ | 
| #include "net/cert/cert_verifier.h" | 
| #include "net/cert/cert_verify_result.h" | 
| #include "net/cert/ct_policy_status.h" | 
| +#include "net/cert/internal/test_helpers.h" | 
| +#include "net/cert/ocsp_staple.h" | 
| #include "net/cert/test_root_certs.h" | 
| #include "net/cert/x509_cert_types.h" | 
| #include "net/cert/x509_certificate.h" | 
| @@ -78,6 +80,10 @@ const char* const kBadPath[] = { | 
| nullptr, | 
| }; | 
|  | 
| +const char kOCSPPathPrefix[] = "net/data/parse_ocsp_unittest/"; | 
| + | 
| +const base::TimeDelta& kAgeTenYears = base::TimeDelta::FromDays(3650); | 
| + | 
| // A mock ReportSender that just remembers the latest report | 
| // URI and report to be sent. | 
| class MockCertificateReportSender | 
| @@ -1851,4 +1857,204 @@ TEST_F(TransportSecurityStateTest, ExpectCTReporter) { | 
| EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); | 
| } | 
|  | 
| +class MockExpectStapleReportSender : public MockCertificateReportSender { | 
| + public: | 
| +  bool ReportSent() { return latest_report() != ""; } | 
| +}; | 
| + | 
| +class ExpectStapleTest : public TransportSecurityStateTest { | 
| + public: | 
| +  void SetUp() override { | 
| +    TransportSecurityStateTest::SetUp(); | 
| +    security_state_.SetReportSender(&report_sender_); | 
| +    EnableStaticExpectStaple(&security_state_); | 
| +    verify_time_ = base::Time::Now(); | 
| +  } | 
| + | 
| +  struct OCSPTest { | 
| +    std::string response; | 
| +    scoped_refptr<X509Certificate> certificate; | 
| +  }; | 
| + | 
| +  static bool LoadOCSPFromFile(std::string file_name, OCSPTest* ocsp) { | 
| +    std::string ca_data; | 
| +    std::string cert_data; | 
| +    const PemBlockMapping mappings[] = { | 
| +        {"OCSP RESPONSE", &ocsp->response}, | 
| +        {"CA CERTIFICATE", &ca_data}, | 
| +        {"CERTIFICATE", &cert_data}, | 
| +    }; | 
| +    std::string full_path = std::string(kOCSPPathPrefix) + file_name; | 
| +    if (!ReadTestDataFromPemFile(full_path, mappings)) | 
| +      return false; | 
| + | 
| +    // Parse the server certificate | 
| +    CertificateList server_cert_list = | 
| +        X509Certificate::CreateCertificateListFromBytes( | 
| +            cert_data.data(), cert_data.size(), | 
| +            X509Certificate::FORMAT_SINGLE_CERTIFICATE); | 
| +    ocsp->certificate = server_cert_list[0]; | 
| +    return true; | 
| +  } | 
| + | 
| +  static void CheckExpectStapleReport( | 
| +      const std::string& serialized_report, | 
| +      const HostPortPair& host_port, | 
| +      const X509Certificate& served_certificate_chain, | 
| +      const ExpectStapleReport& report) { | 
| +    std::unique_ptr<base::Value> value( | 
| +        base::JSONReader::Read(serialized_report)); | 
| +    ASSERT_TRUE(value); | 
| +    ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); | 
| + | 
| +    base::DictionaryValue* report_dict; | 
| +    ASSERT_TRUE(value->GetAsDictionary(&report_dict)); | 
| +    std::string report_hostname; | 
| +    EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname)); | 
| +    EXPECT_EQ(host_port.host(), report_hostname); | 
| +    int report_port; | 
| +    EXPECT_TRUE(report_dict->GetInteger("port", &report_port)); | 
| +    EXPECT_EQ(host_port.port(), report_port); | 
| + | 
| +    // Check certificate chain. | 
| +    const base::ListValue* report_served_certificate_chain = nullptr; | 
| +    ASSERT_TRUE(report_dict->GetList("served-certificate-chain", | 
| +                                     &report_served_certificate_chain)); | 
| +    std::vector<std::string> pem_encoded_chain; | 
| +    served_certificate_chain.GetPEMEncodedChain(&pem_encoded_chain); | 
| +    ASSERT_EQ(pem_encoded_chain.size(), | 
| +              report_served_certificate_chain->GetSize()); | 
| +    for (size_t i = 0; i < pem_encoded_chain.size(); i++) { | 
| +      std::string cert_pem; | 
| +      ASSERT_TRUE(report_served_certificate_chain->GetString(i, &cert_pem)); | 
| +      EXPECT_EQ(pem_encoded_chain[i], cert_pem); | 
| +    } | 
| + | 
| +    // Check stapled responses. | 
| +    const base::ListValue* report_ocsp_responses = nullptr; | 
| +    ASSERT_TRUE(report_dict->GetList("ocsp-responses", &report_ocsp_responses)); | 
| +    const auto& ocsp_responses = report.stapled_responses(); | 
| +    ASSERT_EQ(ocsp_responses.size(), report_ocsp_responses->GetSize()); | 
| +    for (size_t i = 0; i < ocsp_responses.size(); i++) { | 
| +      const base::DictionaryValue* report_ocsp_response = nullptr; | 
| +      report_ocsp_responses->GetDictionary(i, &report_ocsp_response); | 
| +      bool is_date_valid; | 
| +      ASSERT_TRUE( | 
| +          report_ocsp_response->GetBoolean("is-date-valid", &is_date_valid)); | 
| +      EXPECT_EQ(ocsp_responses[i].is_date_valid, is_date_valid); | 
| +      bool is_correct_certificate; | 
| +      ASSERT_TRUE(report_ocsp_response->GetBoolean("is-correct-certificate", | 
| +                                                   &is_correct_certificate)); | 
| +      EXPECT_EQ(ocsp_responses[i].is_correct_certificate, | 
| +                is_correct_certificate); | 
| +    } | 
| +  } | 
| + | 
| + protected: | 
| +  static bool SerializeExpectStapleReport( | 
| +      const HostPortPair& host_port_pair, | 
| +      const X509Certificate& unverified_certificate, | 
| +      const ExpectStapleReport& report, | 
| +      std::string* serialized_report) { | 
| +    return TransportSecurityState::SerializeExpectStapleReport( | 
| +        host_port_pair, unverified_certificate, report, serialized_report); | 
| +  } | 
| + | 
| +  TransportSecurityState security_state_; | 
| +  MockExpectStapleReportSender report_sender_; | 
| +  base::Time verify_time_; | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, NoReportGoodResponse) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("good_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate, | 
| +                                    *ocsp_test.certificate, verify_time_, | 
| +                                    kAgeTenYears, ocsp_test.response); | 
| +  EXPECT_FALSE(report_sender_.ReportSent()); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, ReportMissingResponse) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("missing_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate, | 
| +                                    *ocsp_test.certificate, verify_time_, | 
| +                                    kAgeTenYears, ocsp_test.response); | 
| +  EXPECT_TRUE(report_sender_.ReportSent()); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, ReportOldResponse) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("good_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  security_state_.CheckExpectStaple( | 
| +      host_port, *ocsp_test.certificate, *ocsp_test.certificate, verify_time_, | 
| +      base::TimeDelta::FromDays(7), ocsp_test.response); | 
| +  EXPECT_TRUE(report_sender_.ReportSent()); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, RevokedResponse) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("revoke_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate, | 
| +                                    *ocsp_test.certificate, verify_time_, | 
| +                                    kAgeTenYears, ocsp_test.response); | 
| +  EXPECT_TRUE(report_sender_.ReportSent()); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, HasExtensions) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("has_extension.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate, | 
| +                                    *ocsp_test.certificate, verify_time_, | 
| +                                    kAgeTenYears, ocsp_test.response); | 
| +  EXPECT_FALSE(report_sender_.ReportSent()); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, MultipleResponse) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("multiple_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate, | 
| +                                    *ocsp_test.certificate, verify_time_, | 
| +                                    kAgeTenYears, ocsp_test.response); | 
| +  EXPECT_FALSE(report_sender_.ReportSent()); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, SerializeEmptyReport) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("missing_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  std::unique_ptr<ExpectStapleReport> report = | 
| +      ExpectStapleReport::FromRawOCSPResponse(ocsp_test.response, verify_time_, | 
| +                                              kAgeTenYears, | 
| +                                              *ocsp_test.certificate); | 
| +  ASSERT_TRUE(report); | 
| +  std::string serialized_report; | 
| +  ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate, | 
| +                                          *report, &serialized_report)); | 
| +  ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport( | 
| +      serialized_report, host_port, *ocsp_test.certificate, *report)); | 
| +}; | 
| + | 
| +TEST_F(ExpectStapleTest, SerializeMultipleResponses) { | 
| +  OCSPTest ocsp_test; | 
| +  ASSERT_TRUE(LoadOCSPFromFile("multiple_response.pem", &ocsp_test)); | 
| +  HostPortPair host_port(kExpectStapleStaticHostname, 443); | 
| +  std::unique_ptr<ExpectStapleReport> report = | 
| +      ExpectStapleReport::FromRawOCSPResponse(ocsp_test.response, verify_time_, | 
| +                                              kAgeTenYears, | 
| +                                              *ocsp_test.certificate); | 
| +  ASSERT_TRUE(report); | 
| +  std::string serialized_report; | 
| +  ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate, | 
| +                                          *report, &serialized_report)); | 
| +  ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport( | 
| +      serialized_report, host_port, *ocsp_test.certificate, *report)); | 
| +}; | 
| + | 
| }  // namespace net | 
|  |