[omnibox] Add tests for ExtractJsonData

MERGED2026components/omniboxunit-test
2026. 9. 7.jeonggyeom 프로필 이미지jeonggyeom

SearchSuggestionParser::ExtractJsonData()의 주요 분기를 검증하는 단위 테스트를 추가했습니다.

문제 설명

  • issue url: https://crbug.com/41382281
  • 대상 함수: components/omnibox/browser/search_suggestion_parser.ccSearchSuggestionParser::ExtractJsonData()
  • 테스트 파일: components/omnibox/browser/search_suggestion_parser_unittest.cc

ExtractJsonData()는 suggest 서버에서 받은 응답 body를 JSON 문자열로 넘기기 전에 응답 헤더의 charset을 확인합니다.

JSON은 원칙적으로 UTF-8이지만 일부 suggest provider가 다른 인코딩을 사용할 수 있기 때문에, Content-Type에 charset이 지정되어 있으면 CodepageToUTF16()UTF16ToUTF8()을 이용해 UTF-8로 변환합니다.

if (response_headers) {
  std::string charset;
  if (response_headers->GetCharset(&charset)) {
    std::u16string data_16;

    // TODO(jungshik): Switch to CodePageToUTF8 after it's added.
    if (base::CodepageToUTF16(
            json_data, charset.c_str(),
            base::OnStringConversionError::FAIL, &data_16)) {
      json_data = base::UTF16ToUTF8(data_16);
    }
  }
}

함수 안에는 여러 조건 분기가 있었지만 ExtractJsonData() 자체를 대상으로 이 동작을 직접 확인하는 단위 테스트가 없었습니다.

테스트 분기

  1. source == nullptr
  2. response_body == std::nullopt
  3. response header는 있지만 charset이 없음
  4. charset이 있고 인코딩 변환에 성공
  5. charset이 있지만 잘못된 데이터라 변환에 실패

해결 내용

search_suggestion_parser_unittest.ccExtractJsonData()의 주요 동작을 검증하는 테스트를 추가했습니다.

응답 body가 없는 경우에는 빈 문자열이 반환되는지 확인합니다.

TEST(SearchSuggestionParserTest, ExtractJsonDataWithoutResponseBody) {
  std::optional<std::string> response_body;

  std::string result = SearchSuggestionParser::ExtractJsonData(
      /*source=*/nullptr, response_body);

  ASSERT_TRUE(result.empty());
}

source가 없는 경우에는 별도의 charset 처리 없이 원래 body가 그대로 반환되는지 확인했습니다.

TEST(SearchSuggestionParserTest, ExtractJsonDataWithoutSource) {
  std::string response_body = R"(["one"])";

  std::string result = SearchSuggestionParser::ExtractJsonData(
      /*source=*/nullptr, response_body);

  ASSERT_EQ(response_body, result);
}

charset 관련 테스트에서는 실제 SimpleURLLoader의 응답 헤더를 구성해야 했기 때문에, Content-Type을 지정한 loader를 만드는 작은 테스트 helper도 추가했습니다.

std::unique_ptr<network::SimpleURLLoader> CreateLoaderWithContentType(
    network::TestURLLoaderFactory* url_loader_factory,
    std::string_view content_type) {
  const GURL url("https://example.com/");

  auto response_head = network::CreateURLResponseHead(net::HTTP_OK);
  response_head->headers->SetHeader("Content-Type", content_type);

  url_loader_factory->AddResponse(url, std::move(response_head), /*content=*/"",
                                  network::URLLoaderCompletionStatus(net::OK));

  auto resource_request = std::make_unique<network::ResourceRequest>();
  resource_request->url = url;

  auto loader = network::SimpleURLLoader::Create(std::move(resource_request),
                                                 TRAFFIC_ANNOTATION_FOR_TESTS);

  base::test::TestFuture<std::optional<std::string>> future;
  loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(url_loader_factory,
                                                          future.GetCallback());
  static_cast<void>(future.Get());

  return loader;
}

이를 이용해 application/json처럼 charset이 없는 응답은 body가 그대로 유지되는지 확인했습니다.

charset=euc-kr인 응답에 EUC-KR로 인코딩된 "안녕하세요"를 넣어 UTF-8로 정상 변환되는 경우를 테스트했습니다.

// "안녕하세요" encoded as EUC-KR.
std::string response_body =
    "[\""
    "\xBE\xC8\xB3\xE7\xC7\xCF\xBC\xBC\xBF\xE4"
    "\"]";

반대로 "\xFE\x22"처럼 EUC-KR로 올바르게 해석할 수 없는 데이터를 전달해 CodepageToUTF16() 변환이 실패하면 원본 데이터가 그대로 반환되는 동작도 검증했습니다.

테스트 방법

이번 변경 자체가 기존 동작에 대한 unit test 추가이므로 다음 동작을 각각 검증했습니다.

  • response body가 없으면 빈 문자열 반환
  • source가 없으면 원본 body 반환
  • response header에 charset이 없으면 원본 body 반환
  • EUC-KR 데이터의 charset 변환 성공 시 UTF-8 문자열 반환
  • 잘못된 EUC-KR 데이터의 charset 변환 실패 시 원본 body 유지

배운 점

  • 테스트를 추가하기 전에 함수의 조건문을 먼저 분기로 나눠 보는 것이 도움이 됐습니다. source, response_body, header, charset, conversion 결과를 따로 정리하니 빠뜨린 경로를 확인하기 쉬었습니다.

참고 자료