blob: f1acaf56a4f2868ffcafb3833876ec40345257cd [file] [log] [blame]
// 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