summaryrefslogtreecommitdiffstats
path: root/tests/test_cepis.cpp
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:33:51 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:33:51 -0300
commit2fb251996798798af38903fe535b8d147084a50a (patch)
tree9bcbb6ead9c7c4c1910495186707dc0f8859169d /tests/test_cepis.cpp
parentb71faa6e95a0736f1ff171e006b171467b65db90 (diff)
downloadcpp-2fb251996798798af38903fe535b8d147084a50a.tar.gz
Expose the municipality behind a not-found CEPHEADv0.2.0main
A CEP that fails a lookup is rarely random: it is usually someone who knows the city and guessed the number, and the classic guess is the -000 that 957 municipalities never received. The API now names, on the 404 itself, the municipality that CEP would have belonged to, so a caller can say "not found — did you mean somewhere in Areal/RJ?" instead of just "not found". CepNotFound carries it as an optional Faixa. It stays an error: the block is context, not an address, and the range it describes is sparse, which is why it reports a count alongside the first and last CEP that actually exist there rather than the bounds the Correios publish. Parsing it is best-effort on purpose — a missing, empty or malformed block leaves the optional empty, since a 404 is already the answer and reading the hint attached to it must never cost the diagnosis.
Diffstat (limited to 'tests/test_cepis.cpp')
-rw-r--r--tests/test_cepis.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/tests/test_cepis.cpp b/tests/test_cepis.cpp
index 6b8b9bf..96b6826 100644
--- a/tests/test_cepis.cpp
+++ b/tests/test_cepis.cpp
@@ -145,6 +145,94 @@ CEPIS_TEST(not_found_throws_cep_not_found) {
CHECK_THROWS(fixture.client.lookup("99999999"), cepis::CepNotFound);
}
+CEPIS_TEST(not_found_names_the_municipality_when_the_api_does) {
+ Fixture fixture;
+ fixture.server.respond(
+ "/25845000",
+ Reply{404,
+ R"({"erro":"cep_nao_encontrado","mensagem":"CEP não existe na base do DNE",)"
+ R"("faixa":{"localidade":"Areal","uf":"RJ","estado":"Rio de Janeiro",)"
+ R"("regiao":"Sudeste","ibge":"3300225","cep_ini":"25845001",)"
+ R"("cep_fim":"25849899","ceps":118}})",
+ {}});
+
+ bool threw = false;
+ try {
+ (void)fixture.client.lookup("25845-000");
+ } catch (const cepis::CepNotFound& error) {
+ threw = true;
+ CHECK(error.faixa().has_value());
+ CHECK_EQ(error.faixa()->localidade, std::string("Areal"));
+ CHECK_EQ(error.faixa()->uf, std::string("RJ"));
+ CHECK_EQ(error.faixa()->estado, std::string("Rio de Janeiro"));
+ CHECK_EQ(error.faixa()->regiao, std::string("Sudeste"));
+ CHECK_EQ(error.faixa()->ibge, std::string("3300225"));
+ // The bounds are the CEPs that exist, not the ones the Correios publish:
+ // the DNE's own start for Areal is 25845000 — the CEP that just failed.
+ CHECK_EQ(error.faixa()->cep_ini, std::string("25845001"));
+ CHECK_EQ(error.faixa()->cep_fim, std::string("25849899"));
+ // And the range is sparse: 118 CEPs across ~4,900 numbers.
+ CHECK_EQ(error.faixa()->ceps, std::int64_t{118});
+ CHECK(std::string(error.what()).find("Areal/RJ") != std::string::npos);
+ }
+ CHECK(threw);
+}
+
+CEPIS_TEST(not_found_without_a_faixa_is_still_a_plain_not_found) {
+ Fixture fixture;
+ fixture.server.respond(
+ "/99999999",
+ Reply{
+ 404, R"({"erro":"cep_nao_encontrado","mensagem":"CEP não existe na base do DNE"})", {}});
+
+ bool threw = false;
+ try {
+ (void)fixture.client.lookup("99999999");
+ } catch (const cepis::CepNotFound& error) {
+ threw = true;
+ // The API omits the block for a band no municipality owns. It never sends
+ // null, and an absent block is not an error.
+ CHECK(!error.faixa().has_value());
+ CHECK(std::string(error.what()).find("99999999") != std::string::npos);
+ }
+ CHECK(threw);
+}
+
+CEPIS_TEST(malformed_faixa_does_not_become_a_parse_failure) {
+ for (const std::string body : {
+ R"({"erro":"cep_nao_encontrado","faixa":{}})",
+ R"({"erro":"cep_nao_encontrado","faixa":null})",
+ R"({"erro":"cep_nao_encontrado","faixa":"Areal"})",
+ R"({"erro":"cep_nao_encontrado","faixa":{"localidade":"","uf":"RJ"}})",
+ R"({"erro":"cep_nao_encontrado","faixa":{"uf":"RJ","ceps":118}})",
+ "<html>gateway</html>",
+ }) {
+ Fixture broken;
+ broken.server.respond("/99999999", Reply{404, body, {}});
+
+ bool threw = false;
+ try {
+ (void)broken.client.lookup("99999999");
+ } catch (const cepis::CepNotFound& error) {
+ threw = true;
+ CHECK(!error.faixa().has_value());
+ }
+ CHECK(threw);
+ }
+}
+
+CEPIS_TEST(a_faixa_never_turns_a_not_found_into_an_address) {
+ Fixture fixture;
+ fixture.server.respond(
+ "/25845000", Reply{404,
+ R"({"erro":"cep_nao_encontrado","faixa":{"localidade":"Areal",)"
+ R"("uf":"RJ","cep_ini":"25845001","cep_fim":"25849899","ceps":118}})",
+ {}});
+
+ CHECK_THROWS(fixture.client.lookup("25845000"), cepis::CepNotFound);
+ CHECK_EQ(fixture.server.count("/25845000"), 1);
+}
+
CEPIS_TEST(not_found_is_not_retried) {
Fixture fixture;
fixture.server.respond("/99999999", Reply{404, R"({"erro":"cep_nao_encontrado"})", {}});