From 4014037e505876ed8c4df229ace3a65092e64ca8 Mon Sep 17 00:00:00 2001 From: Murilo Ijanc Date: Mon, 27 Jul 2026 20:39:38 -0300 Subject: Expose the faixa a missing CEP would have belonged to 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 attaches that municipality to the 404, and a caller left with nothing but "does not exist" cannot tell a typo in a real city from a CEP that was never plausible. It goes in CEPIS-STATUS, not CEPIS-ADDRESS. The call has still failed and the address is still empty; putting a localidade where the address lives would let a caller that forgets to test the status read Areal as the answer to a CEP that does not exist. Parsing is best effort throughout. faixa is omitted rather than sent as null for a band no municipality owns, so its absence is the normal case and there is a flag instead of a marker value; a block that is missing, is not an object, or is short of localidade, uf, cep_ini, cep_fim and ceps is dropped and the not-found comes back clean. Failing a 404 the caller already understands over a decoration on it would be a poor trade. cep_ini and cep_fim are the CEPs that exist, not the bounds the Correios publish, and the span between them is mostly empty -- hence ceps beside them, so the pair is not read as a list. --- tests/cepis-tests.cob | 109 +++++++++++++++++++++++++++++++++++++++++++++++++- tests/server.py | 42 +++++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/cepis-tests.cob b/tests/cepis-tests.cob index 4bc1a11..6978a2d 100644 --- a/tests/cepis-tests.cob +++ b/tests/cepis-tests.cob @@ -67,7 +67,7 @@ MAIN-START. MOVE 2 TO RETURN-CODE STOP RUN END-IF - DISPLAY "cepis 0.1.0 test suite against " FUNCTION TRIM (WS-BASE) + DISPLAY "cepis 0.2.0 test suite against " FUNCTION TRIM (WS-BASE) DISPLAY " " PERFORM T-NORMALIZE-ACCEPTS @@ -79,6 +79,11 @@ MAIN-START. PERFORM T-UNKNOWN-FIELDS PERFORM T-LONG-VALUE-FLAGGED PERFORM T-NOT-FOUND + PERFORM T-NOT-FOUND-FAIXA + PERFORM T-NOT-FOUND-FAIXA-OMITTED + PERFORM T-NOT-FOUND-FAIXA-MALFORMED + PERFORM T-NOT-FOUND-FAIXA-NOT-OBJECT + PERFORM T-FAIXA-CLEARED-ON-SUCCESS PERFORM T-NOT-FOUND-NOT-RETRIED PERFORM T-INVALID-NEVER-LEAVES PERFORM T-API-400 @@ -308,6 +313,106 @@ T-NOT-FOUND. MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL PERFORM CHECK. +*> 25845000 is the DNE's own published start for Areal/RJ and does not +*> exist -- the classic guess. The faixa says which municipality the +*> guess landed in; cep_ini is 25845001, one past what was asked for. +T-NOT-FOUND-FAIXA. + PERFORM FRESH-CONFIG + MOVE "25845-000" TO CEPIS-CEP-INPUT + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-NOT-FOUND AND CEPIS-FAIXA-KNOWN + AND CEPIS-FAIXA-LOCALIDADE = "Areal" + AND CEPIS-FAIXA-UF = "RJ" + AND CEPIS-FAIXA-ESTADO = "Rio de Janeiro" + AND CEPIS-FAIXA-REGIAO = "Sudeste" + AND CEPIS-FAIXA-IBGE = "3300225" + AND CEPIS-FAIXA-CEP-INI = "25845001" + AND CEPIS-FAIXA-CEP-FIM = "25849899" + AND CEPIS-FAIXA-CEPS = 118 + AND ADDR-LOCALIDADE = SPACES AND ADDR-CEP = SPACES + MOVE "Y" TO WS-OK + END-IF + MOVE "a 404 names the municipality, and stays a 404" TO WS-LABEL + MOVE CEPIS-FAIXA-LOCALIDADE TO WS-DETAIL + PERFORM CHECK. + +*> 25849900 is one past Areal's last CEP, in a band no municipality +*> owns, so the API sends no faixa -- it never sends null. Runs after +*> the test above on purpose: the faixa that one left behind must not +*> survive into this lookup. +T-NOT-FOUND-FAIXA-OMITTED. + PERFORM FRESH-CONFIG + MOVE "25849900" TO CEPIS-CEP-INPUT + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-NOT-FOUND AND CEPIS-FAIXA-ABSENT + AND CEPIS-FAIXA-LOCALIDADE = SPACES + AND CEPIS-FAIXA-CEPS = 0 + MOVE "Y" TO WS-OK + END-IF + MOVE "a band no municipality owns has no faixa at all" TO WS-LABEL + MOVE CEPIS-FAIXA-LOCALIDADE TO WS-DETAIL + PERFORM CHECK. + +T-NOT-FOUND-FAIXA-MALFORMED. + PERFORM FRESH-CONFIG + MOVE "25845002" TO CEPIS-CEP-INPUT + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + MOVE 0 TO WS-TALLY + INSPECT CEPIS-STATUS-MESSAGE + TALLYING WS-TALLY FOR ALL "does not exist in the DNE database" + MOVE "N" TO WS-OK + IF CEPIS-NOT-FOUND AND CEPIS-FAIXA-ABSENT AND WS-TALLY = 1 + AND CEPIS-FAIXA-LOCALIDADE = SPACES + MOVE "Y" TO WS-OK + END-IF + MOVE "a malformed faixa is dropped, the 404 is clean" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-NOT-FOUND-FAIXA-NOT-OBJECT. + PERFORM FRESH-CONFIG + MOVE "25845003" TO CEPIS-CEP-INPUT + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-NOT-FOUND AND CEPIS-FAIXA-ABSENT + MOVE "Y" TO WS-OK + END-IF + MOVE "a faixa that is not an object is dropped" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-FAIXA-CLEARED-ON-SUCCESS. + PERFORM FRESH-CONFIG + MOVE "25845000" TO CEPIS-CEP-INPUT + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-FAIXA-KNOWN + MOVE "01001-000" TO CEPIS-CEP-INPUT + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + IF CEPIS-OK AND CEPIS-FAIXA-ABSENT + AND ADDR-LOCALIDADE = "São Paulo" + MOVE "Y" TO WS-OK + END-IF + END-IF + MOVE "a later success clears the faixa of an earlier 404" + TO WS-LABEL + MOVE CEPIS-FAIXA-LOCALIDADE TO WS-DETAIL + PERFORM CHECK. + T-NOT-FOUND-NOT-RETRIED. MOVE "/99999999" TO WS-COUNT-PATH PERFORM COUNT-FOR @@ -746,7 +851,7 @@ T-TRAILING-SLASH. T-DEFAULT-USER-AGENT. CALL "CEPIS-DEFAULT-CONFIG" USING CEPIS-CONFIG MOVE 0 TO WS-TALLY - INSPECT CFG-USER-AGENT TALLYING WS-TALLY FOR ALL "cepis-cobol/0.1.0" + INSPECT CFG-USER-AGENT TALLYING WS-TALLY FOR ALL "cepis-cobol/0.2.0" MOVE "N" TO WS-OK IF WS-TALLY = 1 AND CFG-BASE-URL = "https://cep.is" AND CFG-MAX-ATTEMPTS = 3 AND CFG-BACKOFF-BASE-MS = 500 diff --git a/tests/server.py b/tests/server.py index 46185a0..57fa120 100644 --- a/tests/server.py +++ b/tests/server.py @@ -76,6 +76,22 @@ SYNTHETIC = [ DROPPED_CEP = "00000099" +# The municipality a missing CEP would have belonged to, attached to the +# 404 for /25845000 below. The numbers are Areal/RJ's real ones: cep_ini is +# 25845001, one past the 25845000 the DNE publishes as the start of the +# range and that the route refuses, and the 118 CEPs are scattered over the +# ~4900 numbers up to cep_fim rather than filling them. +AREAL = { + "localidade": "Areal", + "uf": "RJ", + "estado": "Rio de Janeiro", + "regiao": "Sudeste", + "ibge": "3300225", + "cep_ini": "25845001", + "cep_fim": "25849899", + "ceps": 118, +} + LONG_STREET = "Avenida " + ("Muito Comprida " * 20) COUNTS = {} @@ -166,6 +182,32 @@ def route(path, query, hits): return 404, json_body( {"erro": "cep_nao_encontrado", "mensagem": "gone"} ), {} + if path == "/25845000": + return 404, json_body( + { + "erro": "cep_nao_encontrado", + "mensagem": "CEP não existe na base do DNE", + "faixa": AREAL, + } + ), {} + if path == "/25849900": + return 404, json_body( + { + "erro": "cep_nao_encontrado", + "mensagem": "CEP não existe na base do DNE", + } + ), {} + if path == "/25845002": + broken = dict(AREAL) + broken["cep_fim"] = "nope" + broken["ceps"] = "many" + return 404, json_body( + {"erro": "cep_nao_encontrado", "faixa": broken} + ), {} + if path == "/25845003": + return 404, json_body( + {"erro": "cep_nao_encontrado", "faixa": "Areal"} + ), {} if path == "/00000000": return 400, json_body( {"erro": "cep_invalido", "mensagem": "rejected by the API"} -- cgit v1.3