summaryrefslogtreecommitdiffstats
path: root/test/run.lua
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:33:25 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:33:25 -0300
commit58dbe934a90c1eda8e76cd218a413f01a4d9b11d (patch)
treedeaee88adad3791c8f010db7f7161a95318ed67e /test/run.lua
parent7fd555fcaf4304cb0dff3e8f5661565c3618299e (diff)
downloadlua-58dbe934a90c1eda8e76cd218a413f01a4d9b11d.tar.gz
Carry the municipality of a missing CEP on not_foundHEADv0.2.0main
A CEP that fails is rarely a random number: it is someone who knows the city and guessed the digits, and the classic guess is the -000 that 957 municipalities never received. The API now answers that 404 with an optional faixa block naming where the CEP would have been, so a caller can turn "CEP does not exist" into something the user can act on. It hangs off the error, never off an address: the lookup still failed. Parsing gives up quietly at every step — no block, a block that is not an object, one without a municipality to name — because a broken piece of context must not turn a clean not-found into a parse failure. cep_ini and cep_fim are the CEPs that exist, not the range the Correios publish, and the interval between them is sparse; ceps is what keeps the pair from being read as a list of valid CEPs.
Diffstat (limited to 'test/run.lua')
-rw-r--r--test/run.lua94
1 files changed, 93 insertions, 1 deletions
diff --git a/test/run.lua b/test/run.lua
index 6220615..3b646c7 100644
--- a/test/run.lua
+++ b/test/run.lua
@@ -38,6 +38,28 @@ local SE_ADDRESS = {
siafi = "7107",
}
+-- The 404 body of a CEP that does not exist, optionally carrying the `faixa`
+-- block. `nil` is encoded as the field being absent, which is what the API
+-- does — it omits the block, it never sends null.
+local AREAL_FAIXA = {
+ localidade = "Areal",
+ uf = "RJ",
+ estado = "Rio de Janeiro",
+ regiao = "Sudeste",
+ ibge = "3300225",
+ cep_ini = "25845001",
+ cep_fim = "25849899",
+ ceps = 118,
+}
+
+local function not_found_json(faixa)
+ return json.encode({
+ erro = "cep_nao_encontrado",
+ mensagem = "CEP não existe na base do DNE",
+ faixa = faixa,
+ })
+end
+
local CSV_HEADER =
"cep,logradouro,complemento,unidade,bairro,localidade,uf,estado,regiao,ibge,gia,ddd,siafi"
@@ -176,6 +198,76 @@ test("404 is not retried", function()
equal(server:count("/99999999"), 1)
end)
+test("a missing CEP names the municipality it would have been in", function()
+ -- 25845000 is the DNE's own start for Areal and does not exist: the classic
+ -- guess, the -000 that 957 municipalities never received.
+ server:program({ ["/25845000"] = once(404, not_found_json(AREAL_FAIXA)) })
+ local address, err = client():lookup("25845000")
+
+ local failure = harness.error_kind(address, err, cepis.NOT_FOUND)
+ equal(failure.cep, "25845000")
+ equal(failure:is_retriable(), false)
+
+ local faixa = failure.faixa
+ ok(faixa, "the faixa was not read")
+ equal(getmetatable(faixa), cepis.Faixa)
+ equal(faixa.localidade, "Areal")
+ equal(faixa.uf, "RJ")
+ equal(faixa.estado, "Rio de Janeiro")
+ equal(faixa.regiao, "Sudeste")
+ equal(faixa.ibge, "3300225")
+ equal(faixa:label(), "Areal/RJ")
+
+ -- The bounds are the CEPs that exist, not the ones the Correios publish:
+ -- the published range starts at the 25845000 that just failed.
+ equal(faixa.cep_ini, "25845001")
+ equal(faixa.cep_fim, "25849899")
+
+ -- And the range is sparse — 118 CEPs over some 4,900 numbers. `ceps` is
+ -- what keeps the pair from being read as a list of valid CEPs.
+ equal(faixa.ceps, 118)
+ ok(faixa.ceps < tonumber(faixa.cep_fim) - tonumber(faixa.cep_ini))
+
+ ok(failure.message:find("Areal/RJ", 1, true), failure.message)
+end)
+
+test("a not_found is not turned into an address by its faixa", function()
+ server:program({ ["/25845000"] = once(404, not_found_json(AREAL_FAIXA)) })
+ local address, err = client():lookup("25845000")
+ harness.error_kind(address, err, cepis.NOT_FOUND)
+ harness.is_nil(address, "a 404 with a faixa returned something")
+ equal(server:count("/25845000"), 1, "a 404 with a faixa was retried")
+end)
+
+test("a 404 without a faixa is a not_found all the same", function()
+ server:program({ ["/99999999"] = once(404, not_found_json(nil)) })
+ local address, err = client():lookup("99999999")
+ local failure = harness.error_kind(address, err, cepis.NOT_FOUND)
+ harness.is_nil(failure.faixa)
+ equal(failure.message, "CEP 99999999 does not exist in the DNE database")
+end)
+
+test("an unusable faixa yields nil, never a parse failure", function()
+ local bodies = {
+ ['{"erro":"cep_nao_encontrado","faixa":null}'] = "null",
+ ['{"erro":"cep_nao_encontrado","faixa":{}}'] = "empty object",
+ ['{"erro":"cep_nao_encontrado","faixa":"Areal"}'] = "a string",
+ ['{"erro":"cep_nao_encontrado","faixa":[1,2]}'] = "an array",
+ ['{"erro":"cep_nao_encontrado","faixa":{"uf":"RJ"}}'] = "no localidade",
+ ['{"erro":"cep_nao_encontrado","faixa":{"localidade":""}}'] = "empty localidade",
+ ["<html>captive portal</html>"] = "not JSON at all",
+ [""] = "an empty body",
+ }
+
+ for body, what in pairs(bodies) do
+ server:program({ ["/99999999"] = once(404, body) })
+ local address, err = client():lookup("99999999")
+ local failure = harness.error_kind(address, err, cepis.NOT_FOUND)
+ harness.is_nil(failure.faixa, "expected no faixa for " .. what)
+ equal(failure.cep, "99999999", what)
+ end
+end)
+
test("an invalid CEP never leaves the machine", function()
server:program({})
local address, err = client():lookup("123")
@@ -480,7 +572,7 @@ test("the defaults are the documented ones", function()
equal(c.backoff_max, 8.0)
harness.is_nil(c.total_timeout)
equal(cepis.MAX_BATCH, 500)
- equal(cepis._VERSION, "0.1.0")
+ equal(cepis._VERSION, "0.2.0")
end)
test("the CSV reader handles quotes, escapes and CRLF", function()