diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-26 12:49:48 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-26 12:49:48 -0300 |
| commit | f979d07d23098b96e758b3feb555cd06d85d9b2d (patch) | |
| tree | 47298197a17a3d6c438a1f4cc7cb61afd390cf05 /tests/cepis-tests.cob | |
| download | cobol-f979d07d23098b96e758b3feb555cd06d85d9b2d.tar.gz | |
Initial importv0.1.0
Diffstat (limited to 'tests/cepis-tests.cob')
| -rw-r--r-- | tests/cepis-tests.cob | 761 |
1 files changed, 761 insertions, 0 deletions
diff --git a/tests/cepis-tests.cob b/tests/cepis-tests.cob new file mode 100644 index 0000000..4bc1a11 --- /dev/null +++ b/tests/cepis-tests.cob @@ -0,0 +1,761 @@ +IDENTIFICATION DIVISION. +PROGRAM-ID. CEPIS-TESTS. + +*> --------------------------------------------------------------------- +*> The suite. Run it through tests/server.py, which binds a loopback +*> port, exports CEPIS_TEST_URL and runs this program: +*> +*> python3 tests/server.py ./build/cepis-tests +*> +*> Every test goes through the real transport against that server, so +*> what is exercised is the code that runs in production -- request +*> construction, header handling and error-body reading included. It +*> doubles as the test that CFG-BASE-URL works: without it none of this +*> would reach anything. +*> +*> The process exits non-zero if any check fails. +*> --------------------------------------------------------------------- + +DATA DIVISION. +WORKING-STORAGE SECTION. +COPY "cepis.cpy". +COPY "cepis-http.cpy". + +01 WS-BASE PIC X(200). +01 WS-CHECKS PIC 9(4) VALUE 0. +01 WS-FAILURES PIC 9(4) VALUE 0. +01 WS-LABEL PIC X(56). +01 WS-DETAIL PIC X(200). +01 WS-OK PIC X. +01 WS-TALLY PIC 9(4). +01 WS-I PIC 9(4). +01 WS-COUNT PIC 9(9). +01 WS-COUNT-BEFORE PIC 9(9). +01 WS-COUNT-PATH PIC X(40). +01 WS-NUM8 PIC 9(8). +01 WS-T0 PIC S9(18) COMP-5. +01 WS-T1 PIC S9(18) COMP-5. +01 WS-ELAPSED PIC S9(18). +01 WS-SAVED-ATTEMPTS PIC 9(4). +01 WS-SAVED-RETRY PIC S9(9). + +01 WS-GOOD-TABLE. + 05 FILLER PIC X(20) VALUE "01001000". + 05 FILLER PIC X(20) VALUE "01001-000". + 05 FILLER PIC X(20) VALUE " 01001-000 ". + 05 FILLER PIC X(20) VALUE "01001.000". +01 WS-GOODS REDEFINES WS-GOOD-TABLE. + 05 WS-GOOD OCCURS 4 TIMES PIC X(20). + +01 WS-BAD-TABLE. + 05 FILLER PIC X(20) VALUE SPACES. + 05 FILLER PIC X(20) VALUE "123". + 05 FILLER PIC X(20) VALUE "0100100a". + 05 FILLER PIC X(20) VALUE "010010000". + 05 FILLER PIC X(20) VALUE "abcdefgh". +01 WS-BADS REDEFINES WS-BAD-TABLE. + 05 WS-BAD OCCURS 5 TIMES PIC X(20). + +PROCEDURE DIVISION. + +MAIN-START. + MOVE SPACES TO WS-BASE + ACCEPT WS-BASE FROM ENVIRONMENT "CEPIS_TEST_URL" + IF WS-BASE = SPACES + DISPLAY "CEPIS_TEST_URL is not set -- run through " + "tests/server.py" + MOVE 2 TO RETURN-CODE + STOP RUN + END-IF + DISPLAY "cepis 0.1.0 test suite against " FUNCTION TRIM (WS-BASE) + DISPLAY " " + + PERFORM T-NORMALIZE-ACCEPTS + PERFORM T-NORMALIZE-REJECTS + PERFORM T-LOOKUP-SUCCESS + PERFORM T-GEO-PRECISE + PERFORM T-GEO-CITY-WIDE + PERFORM T-GEO-MALFORMED + PERFORM T-UNKNOWN-FIELDS + PERFORM T-LONG-VALUE-FLAGGED + PERFORM T-NOT-FOUND + PERFORM T-NOT-FOUND-NOT-RETRIED + PERFORM T-INVALID-NEVER-LEAVES + PERFORM T-API-400 + PERFORM T-NOT-JSON + PERFORM T-RETRY-THEN-SUCCESS + PERFORM T-RETRY-EXHAUSTED + PERFORM T-ONE-ATTEMPT-NO-RETRY + PERFORM T-RATE-LIMITED + PERFORM T-RETRY-AFTER-CAPPED + PERFORM T-RETRY-AFTER-HTTP-DATE + PERFORM T-NETWORK-ERROR + PERFORM T-TOTAL-TIMEOUT + PERFORM T-BATCH-ORDER + PERFORM T-BATCH-QUOTING + PERFORM T-BATCH-MALFORMED-ENTRY + PERFORM T-BATCH-EMPTY + PERFORM T-BATCH-TRUNCATED + PERFORM T-BATCH-CHUNKING + PERFORM T-BATCH-OVER-CAPACITY + PERFORM T-HEALTH + PERFORM T-HEALTH-DEGRADED + PERFORM T-TRAILING-SLASH + PERFORM T-DEFAULT-USER-AGENT + + DISPLAY " " + DISPLAY WS-CHECKS " checks, " WS-FAILURES " failed" + IF WS-FAILURES > 0 + MOVE 1 TO RETURN-CODE + ELSE + MOVE 0 TO RETURN-CODE + END-IF + STOP RUN. + +*> =================================================================== +*> Fixtures +*> =================================================================== +FRESH-CONFIG. + CALL "CEPIS-DEFAULT-CONFIG" USING CEPIS-CONFIG + MOVE WS-BASE TO CFG-BASE-URL + MOVE 5000 TO CFG-TIMEOUT-MS + MOVE 3 TO CFG-MAX-ATTEMPTS + MOVE 1 TO CFG-BACKOFF-BASE-MS + MOVE 10 TO CFG-BACKOFF-MAX-MS + MOVE 0 TO CFG-TOTAL-TIMEOUT-MS. + +CHECK. + ADD 1 TO WS-CHECKS + IF WS-OK = "Y" + DISPLAY "ok " WS-LABEL + ELSE + ADD 1 TO WS-FAILURES + DISPLAY "FAIL " WS-LABEL " -- " FUNCTION TRIM (WS-DETAIL) + END-IF + MOVE SPACES TO WS-DETAIL + MOVE "N" TO WS-OK. + +*> The fake server counts requests per path; that is how a 404 not being +*> retried, or 501 CEPs becoming two requests, is proved rather than +*> assumed. +COUNT-FOR. + PERFORM FRESH-CONFIG + MOVE 1 TO CFG-MAX-ATTEMPTS + MOVE SPACES TO HTTPQ-PATH + STRING "/count?path=" FUNCTION TRIM (WS-COUNT-PATH) + DELIMITED BY SIZE INTO HTTPQ-PATH + END-STRING + COMPUTE HTTPQ-PATH-LEN = + 12 + FUNCTION LENGTH (FUNCTION TRIM (WS-COUNT-PATH)) + MOVE "N" TO HTTPQ-ALLOW-503 + MOVE 0 TO WS-COUNT + CALL "CEPIS-REQUEST" USING CEPIS-CONFIG CEPIS-HTTP-REQUEST + CEPIS-HTTP-RESPONSE CEPIS-STATUS + END-CALL + IF CEPIS-OK AND HTTP-BODY-LEN > 0 + COMPUTE WS-COUNT = + FUNCTION NUMVAL (HTTP-BODY (1:HTTP-BODY-LEN)) + END-IF. + +*> =================================================================== +*> Local validation +*> =================================================================== +T-NORMALIZE-ACCEPTS. + PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 4 + MOVE WS-GOOD (WS-I) TO CEPIS-CEP-INPUT + CALL "CEPIS-NORMALIZE-CEP" + USING CEPIS-CEP-INPUT CEPIS-CEP CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK AND CEPIS-CEP = "01001000" + MOVE "Y" TO WS-OK + END-IF + MOVE SPACES TO WS-LABEL + STRING "normalize accepts " WS-GOOD (WS-I) + DELIMITED BY SIZE INTO WS-LABEL + END-STRING + MOVE CEPIS-CEP TO WS-DETAIL + PERFORM CHECK + END-PERFORM. + +T-NORMALIZE-REJECTS. + PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 5 + MOVE WS-BAD (WS-I) TO CEPIS-CEP-INPUT + CALL "CEPIS-NORMALIZE-CEP" + USING CEPIS-CEP-INPUT CEPIS-CEP CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-INVALID-CEP AND CEPIS-CEP = SPACES + MOVE "Y" TO WS-OK + END-IF + MOVE SPACES TO WS-LABEL + STRING "normalize rejects '" WS-BAD (WS-I) "'" + DELIMITED BY SIZE INTO WS-LABEL + END-STRING + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK + END-PERFORM. + +*> =================================================================== +*> Single lookup +*> =================================================================== +T-LOOKUP-SUCCESS. + PERFORM FRESH-CONFIG + MOVE "01001-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-OK + AND ADDR-LOCALIDADE = "São Paulo" + AND ADDR-UF = "SP" + AND ADDR-LOGRADOURO = "Praça da Sé" + AND ADDR-IBGE = "3550308" + AND ADDR-CEP-MASKED = "01001-000" + AND ADDR-GEO-ABSENT + AND ADDR-NOT-TRUNCATED + MOVE "Y" TO WS-OK + END-IF + MOVE "lookup returns the address, masked cep, no geo" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-GEO-PRECISE. + PERFORM FRESH-CONFIG + MOVE "01310100" 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-OK AND ADDR-GEO-KNOWN AND ADDR-GEO-PRECISE + AND ADDR-GEO-RAIO-M = 120 + AND ADDR-GEO-LAT < -23.5 AND ADDR-GEO-LAT > -23.6 + AND ADDR-GEO-LON < -46.6 AND ADDR-GEO-LON > -46.7 + MOVE "Y" TO WS-OK + END-IF + MOVE "geo present is read and reports precisao logradouro" + TO WS-LABEL + PERFORM CHECK. + +T-GEO-CITY-WIDE. + PERFORM FRESH-CONFIG + MOVE "01001001" 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-OK AND ADDR-GEO-KNOWN AND ADDR-GEO-CITY-WIDE + AND NOT ADDR-GEO-PRECISE AND ADDR-GEO-RAIO-M = 22000 + MOVE "Y" TO WS-OK + END-IF + MOVE "a municipality centroid is not precise" TO WS-LABEL + PERFORM CHECK. + +T-GEO-MALFORMED. + PERFORM FRESH-CONFIG + MOVE "01001002" 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-OK AND ADDR-GEO-ABSENT + AND ADDR-LOCALIDADE = "São Paulo" + MOVE "Y" TO WS-OK + END-IF + MOVE "a malformed geo does not lose the address" TO WS-LABEL + PERFORM CHECK. + +T-UNKNOWN-FIELDS. + PERFORM FRESH-CONFIG + MOVE "01001003" 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-OK AND ADDR-LOCALIDADE = "São Paulo" + AND ADDR-GEO-ABSENT + MOVE "Y" TO WS-OK + END-IF + MOVE "fields the client does not know are ignored" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-LONG-VALUE-FLAGGED. + PERFORM FRESH-CONFIG + MOVE "01001010" 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-OK AND ADDR-WAS-TRUNCATED + MOVE "Y" TO WS-OK + END-IF + MOVE "a value past the field width sets ADDR-TRUNCATED" + TO WS-LABEL + PERFORM CHECK. + +T-NOT-FOUND. + PERFORM FRESH-CONFIG + MOVE "99999999" 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 ADDR-LOCALIDADE = SPACES + MOVE "Y" TO WS-OK + END-IF + MOVE "a missing CEP is CEPIS-NOT-FOUND" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-NOT-FOUND-NOT-RETRIED. + MOVE "/99999999" TO WS-COUNT-PATH + PERFORM COUNT-FOR + MOVE "N" TO WS-OK + IF WS-COUNT = 1 + MOVE "Y" TO WS-OK + END-IF + MOVE "404 is definitive and is not retried" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "requests: " WS-COUNT + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-INVALID-NEVER-LEAVES. + PERFORM FRESH-CONFIG + MOVE "123" 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-INVALID-CEP + MOVE "Y" TO WS-OK + END-IF + MOVE "/123" TO WS-COUNT-PATH + PERFORM COUNT-FOR + IF WS-COUNT NOT = 0 + MOVE "N" TO WS-OK + END-IF + MOVE "a malformed CEP never leaves the machine" TO WS-LABEL + PERFORM CHECK. + +T-API-400. + PERFORM FRESH-CONFIG + MOVE "00000000" 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 "rejected by the API" + MOVE "N" TO WS-OK + IF CEPIS-INVALID-CEP AND WS-TALLY = 1 + MOVE "Y" TO WS-OK + END-IF + MOVE "an API 400 carries the API's own message" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-NOT-JSON. + PERFORM FRESH-CONFIG + MOVE "01001004" 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-INVALID-RESPONSE + MOVE "Y" TO WS-OK + END-IF + MOVE "a body that is not JSON is CEPIS-INVALID-RESPONSE" + TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +*> =================================================================== +*> Retrying +*> =================================================================== +T-RETRY-THEN-SUCCESS. + PERFORM FRESH-CONFIG + MOVE "01001005" 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-OK AND ADDR-LOCALIDADE = "São Paulo" + MOVE "Y" TO WS-OK + END-IF + MOVE "/01001005" TO WS-COUNT-PATH + PERFORM COUNT-FOR + IF WS-COUNT NOT = 2 + MOVE "N" TO WS-OK + END-IF + MOVE "500 is retried and the second attempt succeeds" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "requests: " WS-COUNT + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-RETRY-EXHAUSTED. + PERFORM FRESH-CONFIG + MOVE "01001006" 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-SERVER-ERROR AND CEPIS-STATUS-HTTP = 503 + AND CEPIS-STATUS-ATTEMPTS = 3 + MOVE "Y" TO WS-OK + END-IF + MOVE "/01001006" TO WS-COUNT-PATH + PERFORM COUNT-FOR + IF WS-COUNT NOT = 3 + MOVE "N" TO WS-OK + END-IF + MOVE "three attempts, then CEPIS-SERVER-ERROR" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "requests: " WS-COUNT + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-ONE-ATTEMPT-NO-RETRY. + PERFORM FRESH-CONFIG + MOVE 1 TO CFG-MAX-ATTEMPTS + MOVE "01001012" 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-SERVER-ERROR + MOVE "Y" TO WS-OK + END-IF + MOVE "/01001012" TO WS-COUNT-PATH + PERFORM COUNT-FOR + IF WS-COUNT NOT = 1 + MOVE "N" TO WS-OK + END-IF + MOVE "CFG-MAX-ATTEMPTS of 1 disables retrying" TO WS-LABEL + PERFORM CHECK. + +T-RATE-LIMITED. + PERFORM FRESH-CONFIG + MOVE "01001007" 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-RATE-LIMITED AND CEPIS-STATUS-RETRY-AFTER-MS = 7000 + MOVE "Y" TO WS-OK + END-IF + MOVE "429 exposes Retry-After in seconds" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "retry-after ms: " CEPIS-STATUS-RETRY-AFTER-MS + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-RETRY-AFTER-CAPPED. + PERFORM FRESH-CONFIG + MOVE "01001008" TO CEPIS-CEP-INPUT + CALL "cepis_monotonic_ms" USING WS-T0 + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + CALL "cepis_monotonic_ms" USING WS-T1 + COMPUTE WS-ELAPSED = WS-T1 - WS-T0 + MOVE "N" TO WS-OK + IF CEPIS-RATE-LIMITED AND WS-ELAPSED < 3000 + MOVE "Y" TO WS-OK + END-IF + MOVE "an absurd Retry-After is capped at the backoff maximum" + TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "elapsed ms: " WS-ELAPSED + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-RETRY-AFTER-HTTP-DATE. + PERFORM FRESH-CONFIG + MOVE "01001009" 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-RATE-LIMITED + AND CEPIS-STATUS-RETRY-AFTER-MS >= 1000 + AND CEPIS-STATUS-RETRY-AFTER-MS <= 8000 + MOVE "Y" TO WS-OK + END-IF + MOVE "Retry-After is also read as an HTTP date" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "retry-after ms: " CEPIS-STATUS-RETRY-AFTER-MS + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-NETWORK-ERROR. + PERFORM FRESH-CONFIG + MOVE "http://127.0.0.1:1" TO CFG-BASE-URL + MOVE 2 TO CFG-MAX-ATTEMPTS + MOVE 1000 TO CFG-TIMEOUT-MS + MOVE "01001000" 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-NETWORK-ERROR AND CEPIS-STATUS-ATTEMPTS = 2 + MOVE "Y" TO WS-OK + END-IF + MOVE "a refused connection is CEPIS-NETWORK-ERROR" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-TOTAL-TIMEOUT. + PERFORM FRESH-CONFIG + MOVE 50 TO CFG-MAX-ATTEMPTS + MOVE 50 TO CFG-BACKOFF-BASE-MS + MOVE 50 TO CFG-BACKOFF-MAX-MS + MOVE 300 TO CFG-TOTAL-TIMEOUT-MS + MOVE "01001011" TO CEPIS-CEP-INPUT + CALL "cepis_monotonic_ms" USING WS-T0 + CALL "CEPIS-LOOKUP" USING CEPIS-CONFIG CEPIS-CEP-INPUT + CEPIS-ADDRESS CEPIS-STATUS + END-CALL + CALL "cepis_monotonic_ms" USING WS-T1 + COMPUTE WS-ELAPSED = WS-T1 - WS-T0 + MOVE CEPIS-STATUS-ATTEMPTS TO WS-SAVED-ATTEMPTS + MOVE "N" TO WS-OK + IF CEPIS-SERVER-ERROR AND WS-ELAPSED < 3000 + AND WS-SAVED-ATTEMPTS < 50 + MOVE "Y" TO WS-OK + END-IF + MOVE "CFG-TOTAL-TIMEOUT-MS bounds the whole call" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "elapsed ms: " WS-ELAPSED + " attempts: " WS-SAVED-ATTEMPTS + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +*> =================================================================== +*> Batch +*> =================================================================== +T-BATCH-ORDER. + PERFORM FRESH-CONFIG + MOVE 3 TO BATCH-COUNT + MOVE "01001000" TO BATCH-REQUESTED (1) + MOVE "99999999" TO BATCH-REQUESTED (2) + MOVE "20040020" TO BATCH-REQUESTED (3) + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK + AND BATCH-ENTRY-FOUND (1) + AND BAT-LOCALIDADE (1) = "São Paulo" + AND BATCH-ENTRY-MISSING (2) + AND BATCH-ENTRY-FOUND (3) + AND BAT-UF (3) = "RJ" + AND BAT-GEO-ABSENT (1) + MOVE "Y" TO WS-OK + END-IF + MOVE "a missing CEP keeps its slot and nothing shifts" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-BATCH-QUOTING. + PERFORM FRESH-CONFIG + MOVE 1 TO BATCH-COUNT + MOVE "01001111" TO BATCH-REQUESTED (1) + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK AND BATCH-ENTRY-FOUND (1) + AND BAT-LOGRADOURO (1) = "Rua Um, Dois" + AND BAT-COMPLEMENTO (1) = 'aspas "aqui"' + MOVE "Y" TO WS-OK + END-IF + MOVE "quoted CSV fields with commas and quotes are parsed" + TO WS-LABEL + MOVE BAT-LOGRADOURO (1) TO WS-DETAIL + PERFORM CHECK. + +T-BATCH-MALFORMED-ENTRY. + PERFORM FRESH-CONFIG + MOVE 3 TO BATCH-COUNT + MOVE "01001000" TO BATCH-REQUESTED (1) + MOVE "nonsense" TO BATCH-REQUESTED (2) + MOVE "20040020" TO BATCH-REQUESTED (3) + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK + AND BATCH-ENTRY-FOUND (1) + AND BATCH-ENTRY-MISSING (2) + AND BATCH-ENTRY-FOUND (3) + AND BAT-UF (3) = "RJ" + MOVE "Y" TO WS-OK + END-IF + MOVE "a malformed CEP is missing, not an error" TO WS-LABEL + PERFORM CHECK. + +T-BATCH-EMPTY. + MOVE "/csv" TO WS-COUNT-PATH + PERFORM COUNT-FOR + MOVE WS-COUNT TO WS-COUNT-BEFORE + PERFORM FRESH-CONFIG + MOVE 0 TO BATCH-COUNT + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK + MOVE "Y" TO WS-OK + END-IF + MOVE "/csv" TO WS-COUNT-PATH + PERFORM COUNT-FOR + IF WS-COUNT NOT = WS-COUNT-BEFORE + MOVE "N" TO WS-OK + END-IF + MOVE "an empty batch makes no request" TO WS-LABEL + PERFORM CHECK. + +T-BATCH-TRUNCATED. + PERFORM FRESH-CONFIG + MOVE 2 TO BATCH-COUNT + MOVE "01001000" TO BATCH-REQUESTED (1) + MOVE "00000099" TO BATCH-REQUESTED (2) + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK AND BATCH-ENTRY-FOUND (1) + AND BATCH-ENTRY-MISSING (2) + MOVE "Y" TO WS-OK + END-IF + MOVE "a short response pads rather than shifts" TO WS-LABEL + PERFORM CHECK. + +T-BATCH-CHUNKING. + MOVE "/csv" TO WS-COUNT-PATH + PERFORM COUNT-FOR + MOVE WS-COUNT TO WS-COUNT-BEFORE + PERFORM FRESH-CONFIG + MOVE 501 TO BATCH-COUNT + PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 501 + COMPUTE WS-NUM8 = 70000000 + WS-I + MOVE WS-NUM8 TO BATCH-REQUESTED (WS-I) + END-PERFORM + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK AND BATCH-ENTRY-FOUND (1) + AND BATCH-ENTRY-FOUND (500) + AND BATCH-ENTRY-FOUND (501) + AND BAT-LOCALIDADE (501) = "Cidade Sintetica" + MOVE "Y" TO WS-OK + END-IF + MOVE "/csv" TO WS-COUNT-PATH + PERFORM COUNT-FOR + COMPUTE WS-COUNT = WS-COUNT - WS-COUNT-BEFORE + IF WS-COUNT NOT = 2 + MOVE "N" TO WS-OK + END-IF + MOVE "501 CEPs become two requests, not one 400" TO WS-LABEL + MOVE SPACES TO WS-DETAIL + STRING "requests: " WS-COUNT " status: " CEPIS-STATUS-MESSAGE + DELIMITED BY SIZE INTO WS-DETAIL + END-STRING + PERFORM CHECK. + +T-BATCH-OVER-CAPACITY. + PERFORM FRESH-CONFIG + MOVE 1001 TO BATCH-COUNT + CALL "CEPIS-LOOKUP-MANY" USING CEPIS-CONFIG CEPIS-BATCH + CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-INVALID-CEP + MOVE "Y" TO WS-OK + END-IF + MOVE 0 TO BATCH-COUNT + MOVE "a BATCH-COUNT past the table is refused, not truncated" + TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +*> =================================================================== +*> Health and configuration +*> =================================================================== +T-HEALTH. + PERFORM FRESH-CONFIG + CALL "CEPIS-HEALTH" USING CEPIS-CONFIG CEPIS-HEALTH CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK AND HEALTH-OK AND HEALTH-DNE = "26071" + AND HEALTH-CEPS = 1596168 AND HEALTH-GEO = 894489 + AND HEALTH-BASE-GERADA-EM = "2026-07-24T03:48:28Z" + MOVE "Y" TO WS-OK + END-IF + MOVE "health reports the live database" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +T-HEALTH-DEGRADED. + PERFORM FRESH-CONFIG + MOVE SPACES TO CFG-BASE-URL + STRING FUNCTION TRIM (WS-BASE) "/degraded" + DELIMITED BY SIZE INTO CFG-BASE-URL + END-STRING + CALL "CEPIS-HEALTH" USING CEPIS-CONFIG CEPIS-HEALTH CEPIS-STATUS + END-CALL + MOVE "N" TO WS-OK + IF CEPIS-OK AND NOT HEALTH-OK + AND HEALTH-STATUS = "degradado" + AND CEPIS-STATUS-ATTEMPTS = 1 + MOVE "Y" TO WS-OK + END-IF + MOVE "a degraded API is diagnosed, not retried" TO WS-LABEL + MOVE HEALTH-STATUS TO WS-DETAIL + PERFORM CHECK. + +T-TRAILING-SLASH. + PERFORM FRESH-CONFIG + MOVE SPACES TO CFG-BASE-URL + STRING FUNCTION TRIM (WS-BASE) "/" + DELIMITED BY SIZE INTO CFG-BASE-URL + END-STRING + MOVE "01001000" 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-OK AND ADDR-UF = "SP" + MOVE "Y" TO WS-OK + END-IF + MOVE "a trailing slash on the base URL is dropped" TO WS-LABEL + MOVE CEPIS-STATUS-MESSAGE TO WS-DETAIL + PERFORM CHECK. + +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" + 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 + AND CFG-BACKOFF-MAX-MS = 8000 + MOVE "Y" TO WS-OK + END-IF + MOVE "the defaults identify the library and its version" + TO WS-LABEL + MOVE CFG-USER-AGENT TO WS-DETAIL + PERFORM CHECK. + +END PROGRAM CEPIS-TESTS. |