// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/boca/babelorca/tachyon_client_impl.h"
#include <algorithm>
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/types/expected.h"
#include "chromeos/ash/components/boca/babelorca/proto/testing_message.pb.h"
#include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h"
#include "chromeos/ash/components/boca/babelorca/response_callback_wrapper.h"
#include "chromeos/ash/components/boca/babelorca/response_callback_wrapper_impl.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace ash::babelorca {
namespace {
using ExpectedTestingMessage =
base::expected<TestingMessage,
ResponseCallbackWrapper::TachyonRequestError>;
using RequestDataPtr = std::unique_ptr<RequestDataWrapper>;
constexpr char kOAuthToken[] = "oauth-token";
constexpr char kUrl[] = "https://test.com";
const net::NetworkTrafficAnnotationTag kTrafficAnnotationTag =
net::DefineNetworkTrafficAnnotation("babelorca-testid",
R"(semantics { sender "client test"})");
class TachyonClientImplTest : public testing::Test {
protected:
RequestDataPtr request_data() {
auto response_cb =
std::make_unique<ResponseCallbackWrapperImpl<TestingMessage>>(
result_future_.GetCallback());
auto request_data = std::make_unique<RequestDataWrapper>(
kTrafficAnnotationTag, kUrl, /*max_retries_param=*/1,
std::move(response_cb));
request_data->content_data = "request-body";
return request_data;
}
base::test::TestFuture<RequestDataPtr>* auth_failure_future() {
return &auth_failure_future_;
}
base::test::TestFuture<ExpectedTestingMessage>* result_future() {
return &result_future_;
}
private:
base::test::TestFuture<RequestDataPtr> auth_failure_future_;
base::test::TestFuture<ExpectedTestingMessage> result_future_;
base::test::TaskEnvironment task_env_;
};
TEST_F(TachyonClientImplTest, SuccessfulRequest) {
network::TestURLLoaderFactory url_loader_factory;
TestingMessage response;
response.set_int_field(9999);
url_loader_factory.AddResponse(kUrl, response.SerializeAsString());
TachyonClientImpl client(url_loader_factory.GetSafeWeakWrapper());
client.StartRequest(request_data(), kOAuthToken,
auth_failure_future()->GetCallback());
auto result = result_future()->Get();
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result.value().int_field(), 9999);
EXPECT_FALSE(auth_failure_future()->IsReady());
}
TEST_F(TachyonClientImplTest, NetworkFailure) {
network::TestURLLoaderFactory url_loader_factory;
url_loader_factory.AddResponse(
GURL(kUrl), network::mojom::URLResponseHead::New(), "",
network::URLLoaderCompletionStatus(net::Error::ERR_NETWORK_CHANGED));
TachyonClientImpl client(url_loader_factory.GetSafeWeakWrapper());
client.StartRequest(request_data(), kOAuthToken,
auth_failure_future()->GetCallback());
auto result = result_future()->Get();
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error(),
ResponseCallbackWrapper::TachyonRequestError::kNetworkError);
EXPECT_FALSE(auth_failure_future()->IsReady());
}
TEST_F(TachyonClientImplTest, HttpError) {
network::TestURLLoaderFactory url_loader_factory;
url_loader_factory.AddResponse(kUrl, "error",
net::HttpStatusCode::HTTP_PRECONDITION_FAILED);
TachyonClientImpl client(url_loader_factory.GetSafeWeakWrapper());
client.StartRequest(request_data(), kOAuthToken,
auth_failure_future()->GetCallback());
auto result = result_future()->Get();
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error(),
ResponseCallbackWrapper::TachyonRequestError::kHttpError);
EXPECT_FALSE(auth_failure_future()->IsReady());
}
TEST_F(TachyonClientImplTest, AuthError) {
network::TestURLLoaderFactory url_loader_factory;
url_loader_factory.AddResponse(kUrl, "error",
net::HttpStatusCode::HTTP_UNAUTHORIZED);
TachyonClientImpl client(url_loader_factory.GetSafeWeakWrapper());
RequestDataPtr data = request_data();
auto* request_data_ptr = data.get();
client.StartRequest(std::move(data), kOAuthToken,
auth_failure_future()->GetCallback());
RequestDataPtr auth_request_data = auth_failure_future()->Take();
EXPECT_EQ(auth_request_data->annotation_tag,
request_data_ptr->annotation_tag);
EXPECT_EQ(auth_request_data->url, request_data_ptr->url);
EXPECT_EQ(auth_request_data->max_retries, request_data_ptr->max_retries);
EXPECT_EQ(auth_request_data->response_cb, request_data_ptr->response_cb);
EXPECT_FALSE(result_future()->IsReady());
}
} // namespace
} // namespace ash::babelorca