| // Copyright 2018 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "cronet_c.h" | 
 |  | 
 | #include "base/check.h" | 
 | #include "base/files/file_util.h" | 
 | #include "base/files/scoped_temp_dir.h" | 
 | #include "base/run_loop.h" | 
 | #include "components/cronet/native/test/test_util.h" | 
 | #include "net/cert/mock_cert_verifier.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | namespace { | 
 |  | 
 | const char* kUserAgent = "EngineTest/1"; | 
 |  | 
 | class EngineTest : public ::testing::Test { | 
 |  public: | 
 |   EngineTest(const EngineTest&) = delete; | 
 |   EngineTest& operator=(const EngineTest&) = delete; | 
 |  | 
 |  protected: | 
 |   EngineTest() = default; | 
 |   ~EngineTest() override {} | 
 | }; | 
 |  | 
 | TEST_F(EngineTest, StartCronetEngine) { | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_EngineParams_user_agent_set(engine_params, kUserAgent); | 
 |   EXPECT_EQ(Cronet_RESULT_SUCCESS, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   Cronet_Engine_Destroy(engine); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 | } | 
 |  | 
 | TEST_F(EngineTest, CronetEngineDefaultUserAgent) { | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   // Version and DefaultUserAgent don't require engine start. | 
 |   std::string version = Cronet_Engine_GetVersionString(engine); | 
 |   std::string default_agent = Cronet_Engine_GetDefaultUserAgent(engine); | 
 |   EXPECT_NE(default_agent.find(version), std::string::npos); | 
 |   Cronet_Engine_Destroy(engine); | 
 | } | 
 |  | 
 | TEST_F(EngineTest, InitDifferentEngines) { | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_EnginePtr first_engine = Cronet_Engine_Create(); | 
 |   Cronet_Engine_StartWithParams(first_engine, engine_params); | 
 |   Cronet_EnginePtr second_engine = Cronet_Engine_Create(); | 
 |   Cronet_Engine_StartWithParams(second_engine, engine_params); | 
 |   Cronet_EnginePtr third_engine = Cronet_Engine_Create(); | 
 |   Cronet_Engine_StartWithParams(third_engine, engine_params); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 |   Cronet_Engine_Destroy(first_engine); | 
 |   Cronet_Engine_Destroy(second_engine); | 
 |   Cronet_Engine_Destroy(third_engine); | 
 | } | 
 |  | 
 | TEST_F(EngineTest, StartResults) { | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   // Disable runtime CHECK of the result, so it could be verified. | 
 |   Cronet_EngineParams_enable_check_result_set(engine_params, false); | 
 |   Cronet_EngineParams_http_cache_mode_set( | 
 |       engine_params, Cronet_EngineParams_HTTP_CACHE_MODE_DISK); | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_ARGUMENT_STORAGE_PATH_MUST_EXIST, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   Cronet_EngineParams_storage_path_set(engine_params, "InvalidPath"); | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_ARGUMENT_STORAGE_PATH_MUST_EXIST, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   base::ScopedTempDir temp_dir; | 
 |   EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); | 
 |   base::FilePath temp_path = base::MakeAbsoluteFilePath(temp_dir.GetPath()); | 
 |   Cronet_EngineParams_storage_path_set(engine_params, | 
 |                                        temp_path.AsUTF8Unsafe().c_str()); | 
 |   // Now the engine should start successfully. | 
 |   EXPECT_EQ(Cronet_RESULT_SUCCESS, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   // The second start should fail. | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_STATE_ENGINE_ALREADY_STARTED, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   // The second engine should fail because storage path is already used. | 
 |   Cronet_EnginePtr second_engine = Cronet_Engine_Create(); | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_STATE_STORAGE_PATH_IN_USE, | 
 |             Cronet_Engine_StartWithParams(second_engine, engine_params)); | 
 |   // Shutdown first engine to free storage path. | 
 |   EXPECT_EQ(Cronet_RESULT_SUCCESS, Cronet_Engine_Shutdown(engine)); | 
 |   // Now the second engine should start. | 
 |   EXPECT_EQ(Cronet_RESULT_SUCCESS, | 
 |             Cronet_Engine_StartWithParams(second_engine, engine_params)); | 
 |   Cronet_Engine_Destroy(second_engine); | 
 |   Cronet_Engine_Destroy(engine); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 | } | 
 |  | 
 | TEST_F(EngineTest, InvalidPkpParams) { | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   // Disable runtime CHECK of the result, so it could be verified. | 
 |   Cronet_EngineParams_enable_check_result_set(engine_params, false); | 
 |   // Try adding invalid public key pins. | 
 |   Cronet_PublicKeyPinsPtr public_key_pins = Cronet_PublicKeyPins_Create(); | 
 |   Cronet_EngineParams_public_key_pins_add(engine_params, public_key_pins); | 
 |   EXPECT_EQ(Cronet_RESULT_NULL_POINTER_HOSTNAME, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   Cronet_EngineParams_public_key_pins_clear(engine_params); | 
 |   // Detect long host name. | 
 |   Cronet_PublicKeyPins_host_set(public_key_pins, std::string(256, 'a').c_str()); | 
 |   Cronet_EngineParams_public_key_pins_add(engine_params, public_key_pins); | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_ARGUMENT_INVALID_HOSTNAME, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   Cronet_EngineParams_public_key_pins_clear(engine_params); | 
 |   // Detect invalid host name. | 
 |   Cronet_PublicKeyPins_host_set(public_key_pins, "invalid:host/name"); | 
 |   Cronet_EngineParams_public_key_pins_add(engine_params, public_key_pins); | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_ARGUMENT_INVALID_HOSTNAME, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   Cronet_EngineParams_public_key_pins_clear(engine_params); | 
 |   // Set valid host name. | 
 |   Cronet_PublicKeyPins_host_set(public_key_pins, "valid.host.name"); | 
 |   Cronet_EngineParams_public_key_pins_add(engine_params, public_key_pins); | 
 |   // Detect missing pins. | 
 |   EXPECT_EQ(Cronet_RESULT_NULL_POINTER_SHA256_PINS, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   // Detect invalid pin. | 
 |   Cronet_EngineParams_public_key_pins_clear(engine_params); | 
 |   Cronet_PublicKeyPins_pins_sha256_add(public_key_pins, "invalid_sha256"); | 
 |   Cronet_EngineParams_public_key_pins_add(engine_params, public_key_pins); | 
 |   EXPECT_EQ(Cronet_RESULT_ILLEGAL_ARGUMENT_INVALID_PIN, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   // THe engine cannot start with these params, and have to be destroyed. | 
 |   Cronet_Engine_Destroy(engine); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 |   Cronet_PublicKeyPins_Destroy(public_key_pins); | 
 | } | 
 |  | 
 | TEST_F(EngineTest, ValidPkpParams) { | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   // Disable runtime CHECK of the result, so it could be verified. | 
 |   Cronet_EngineParams_enable_check_result_set(engine_params, false); | 
 |   // Add valid public key pins. | 
 |   Cronet_PublicKeyPinsPtr public_key_pins = Cronet_PublicKeyPins_Create(); | 
 |   Cronet_PublicKeyPins_host_set(public_key_pins, "valid.host.name"); | 
 |   Cronet_PublicKeyPins_pins_sha256_add( | 
 |       public_key_pins, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); | 
 |   Cronet_EngineParams_public_key_pins_add(engine_params, public_key_pins); | 
 |   // The engine should start successfully. | 
 |   EXPECT_EQ(Cronet_RESULT_SUCCESS, | 
 |             Cronet_Engine_StartWithParams(engine, engine_params)); | 
 |   Cronet_Engine_Destroy(engine); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 |   Cronet_PublicKeyPins_Destroy(public_key_pins); | 
 | } | 
 |  | 
 | // Verify that Cronet_Engine_SetMockCertVerifierForTesting() doesn't crash or | 
 | // leak anything. | 
 | TEST_F(EngineTest, SetMockCertVerifierForTesting) { | 
 |   auto cert_verifier(std::make_unique<net::MockCertVerifier>()); | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   Cronet_Engine_SetMockCertVerifierForTesting(engine, cert_verifier.release()); | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_Engine_StartWithParams(engine, engine_params); | 
 |   Cronet_Engine_Destroy(engine); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 | } | 
 |  | 
 | TEST_F(EngineTest, StartNetLogToFile) { | 
 |   base::ScopedTempDir temp_dir; | 
 |   EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); | 
 |   base::FilePath temp_path = base::MakeAbsoluteFilePath(temp_dir.GetPath()); | 
 |   base::FilePath net_log_file = | 
 |       temp_path.Append(FILE_PATH_LITERAL("netlog.json")); | 
 |  | 
 |   Cronet_EnginePtr engine = Cronet_Engine_Create(); | 
 |   Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); | 
 |   Cronet_EngineParams_experimental_options_set( | 
 |       engine_params, | 
 |       "{ \"QUIC\" : {\"max_server_configs_stored_in_properties\" : 8} }"); | 
 |   // Test that net log cannot start/stop before engine start. | 
 |   EXPECT_FALSE(Cronet_Engine_StartNetLogToFile( | 
 |       engine, net_log_file.AsUTF8Unsafe().c_str(), true)); | 
 |   Cronet_Engine_StopNetLog(engine); | 
 |  | 
 |   // Start the engine. | 
 |   Cronet_Engine_StartWithParams(engine, engine_params); | 
 |   Cronet_EngineParams_Destroy(engine_params); | 
 |  | 
 |   // Test that normal start/stop net log works. | 
 |   EXPECT_TRUE(Cronet_Engine_StartNetLogToFile( | 
 |       engine, net_log_file.AsUTF8Unsafe().c_str(), true)); | 
 |   Cronet_Engine_StopNetLog(engine); | 
 |  | 
 |   // Test that double start/stop net log works. | 
 |   EXPECT_TRUE(Cronet_Engine_StartNetLogToFile( | 
 |       engine, net_log_file.AsUTF8Unsafe().c_str(), true)); | 
 |   // Test that second start fails. | 
 |   EXPECT_FALSE(Cronet_Engine_StartNetLogToFile( | 
 |       engine, net_log_file.AsUTF8Unsafe().c_str(), true)); | 
 |   // Test that multiple stops work. | 
 |   Cronet_Engine_StopNetLog(engine); | 
 |   Cronet_Engine_StopNetLog(engine); | 
 |   Cronet_Engine_StopNetLog(engine); | 
 |  | 
 |   // Test that net log contains effective experimental options. | 
 |   std::string net_log; | 
 |   EXPECT_TRUE(base::ReadFileToString(net_log_file, &net_log)); | 
 |   EXPECT_TRUE( | 
 |       net_log.find( | 
 |           "{\"QUIC\":{\"max_server_configs_stored_in_properties\":8}") != | 
 |       std::string::npos); | 
 |  | 
 |   // Test that bad file name fails. | 
 |   EXPECT_FALSE(Cronet_Engine_StartNetLogToFile(engine, "bad/file/name", true)); | 
 |  | 
 |   Cronet_Engine_Shutdown(engine); | 
 |   // Test that net log cannot start/stop after engine shutdown. | 
 |   EXPECT_FALSE(Cronet_Engine_StartNetLogToFile( | 
 |       engine, net_log_file.AsUTF8Unsafe().c_str(), true)); | 
 |   Cronet_Engine_StopNetLog(engine); | 
 |   Cronet_Engine_Destroy(engine); | 
 | } | 
 |  | 
 | }  // namespace |