diff --git a/go.mod b/go.mod index a4b6e06b31..484e20737c 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,6 @@ require ( github.com/google/uuid v1.3.1 github.com/gorilla/websocket v1.5.0 github.com/hexops/gotextdiff v1.0.3 - github.com/iancoleman/strcase v0.3.0 github.com/mattn/go-colorable v0.1.13 github.com/miekg/dns v1.1.56 github.com/mitchellh/go-wordwrap v1.0.1 diff --git a/go.sum b/go.sum index 7de49cbf99..6db24cc7ed 100644 --- a/go.sum +++ b/go.sum @@ -283,8 +283,6 @@ github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= -github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= diff --git a/internal/netxlite/certifi.go b/internal/netxlite/certifi.go index 3b5c7c0891..e3e533d314 100644 --- a/internal/netxlite/certifi.go +++ b/internal/netxlite/certifi.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// 2023-05-31 11:09:58.566952 +0200 CEST m=+0.556580876 +// 2023-10-04 17:50:10.699722 +0200 CEST m=+0.596753793 // https://curl.haxx.se/ca/cacert.pem package netxlite @@ -10,7 +10,7 @@ const pemcerts string = ` ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Tue May 30 03:12:04 2023 GMT +## Certificate data from Mozilla as of: Tue Aug 22 03:12:04 2023 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -23,7 +23,7 @@ const pemcerts string = ` ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: c47475103fb05bb562bbadff0d1e72346b03236154e1448a6ca191b740f83507 +## SHA256: 0ff137babc6a5561a9cfbe9f29558972e5b528202681b7d3803d03a3e82922bd ## @@ -3231,55 +3231,6 @@ AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -----END CERTIFICATE----- -E-Tugra Global Root CA RSA v3 -============================= ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -E-Tugra Global Root CA ECC v3 -============================= ------BEGIN CERTIFICATE----- -MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV -BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV -BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB -IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP -MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 -Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw -djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2 -w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31 -Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ -zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO -PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W -Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3 ------END CERTIFICATE----- - Security Communication RootCA3 ============================== -----BEGIN CERTIFICATE----- @@ -3371,4 +3322,141 @@ W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== -----END CERTIFICATE----- +Sectigo Public Server Authentication Root E46 +============================================= +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH +QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2 +ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5 +WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0 +aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0 +NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud +DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH +lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U +SAGKcw== +-----END CERTIFICATE----- + +Sectigo Public Server Authentication Root R46 +============================================= +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1 +OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k +1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf +GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP +FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu +ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz +Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A +wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF +plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ +EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW +6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI +IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp +E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4 +exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M +0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI +84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m +pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd +Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b +E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm +J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- + +SSL.com TLS RSA Root CA 2022 +============================ +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG +EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg +Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC +VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u +9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y +7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac +oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M +R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG +D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW +TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk +8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq +g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk +7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu +N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN +j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by +iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU +o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo +ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib +MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi +vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7 +P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0 +9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- + +SSL.com TLS ECC Root CA 2022 +============================ +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v +dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx +GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy +JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1 +5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7 +81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w +7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5 +Zn6g6g== +-----END CERTIFICATE----- + +Atos TrustedRoot Root CA ECC TLS 2021 +===================================== +-----BEGIN CERTIFICATE----- +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB +dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD +VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg +VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT +AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K +DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS +b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX +NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+ +uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY +a3cpetskz2VAv9LcjBHo9H1/IISpQuQo +-----END CERTIFICATE----- + +Atos TrustedRoot Root CA RSA TLS 2021 +===================================== +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD +DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw +CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0 +b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV +BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB +l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG +vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK +ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt +0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK +PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY +sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY +Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+ +rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa +fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G +CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl +Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX +AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G +slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt +afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q +TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj +1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l +PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W +HYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- + ` diff --git a/internal/netxlite/errno.go b/internal/netxlite/errno.go index eb9db4cd98..71ca5777ab 100644 --- a/internal/netxlite/errno.go +++ b/internal/netxlite/errno.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.128923 +0200 CEST m=+0.224674501 +// Generated: 2023-10-04 17:50:11.285004 +0200 CEST m=+0.213615376 package netxlite diff --git a/internal/netxlite/errno_darwin.go b/internal/netxlite/errno_darwin.go index 2351a2140f..6226dd4867 100644 --- a/internal/netxlite/errno_darwin.go +++ b/internal/netxlite/errno_darwin.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:58.904502 +0200 CEST m=+0.000247709 +// Generated: 2023-10-04 17:50:11.071975 +0200 CEST m=+0.000581043 package netxlite diff --git a/internal/netxlite/errno_darwin_test.go b/internal/netxlite/errno_darwin_test.go index e8c6a10783..e38f1dcddf 100644 --- a/internal/netxlite/errno_darwin_test.go +++ b/internal/netxlite/errno_darwin_test.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:58.962606 +0200 CEST m=+0.058353251 +// Generated: 2023-10-04 17:50:11.136114 +0200 CEST m=+0.064721709 package netxlite diff --git a/internal/netxlite/errno_freebsd.go b/internal/netxlite/errno_freebsd.go index f7de074f27..192a4bd5dd 100644 --- a/internal/netxlite/errno_freebsd.go +++ b/internal/netxlite/errno_freebsd.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:58.986123 +0200 CEST m=+0.081871334 +// Generated: 2023-10-04 17:50:11.159 +0200 CEST m=+0.087608168 package netxlite diff --git a/internal/netxlite/errno_freebsd_test.go b/internal/netxlite/errno_freebsd_test.go index e755612567..6038c83630 100644 --- a/internal/netxlite/errno_freebsd_test.go +++ b/internal/netxlite/errno_freebsd_test.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.006625 +0200 CEST m=+0.102373584 +// Generated: 2023-10-04 17:50:11.179697 +0200 CEST m=+0.108305543 package netxlite diff --git a/internal/netxlite/errno_linux.go b/internal/netxlite/errno_linux.go index 2f2da2ca9f..f285773a63 100644 --- a/internal/netxlite/errno_linux.go +++ b/internal/netxlite/errno_linux.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.059949 +0200 CEST m=+0.155698959 +// Generated: 2023-10-04 17:50:11.226097 +0200 CEST m=+0.154706876 package netxlite diff --git a/internal/netxlite/errno_linux_test.go b/internal/netxlite/errno_linux_test.go index 344e6818ef..65668633a2 100644 --- a/internal/netxlite/errno_linux_test.go +++ b/internal/netxlite/errno_linux_test.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.078206 +0200 CEST m=+0.173955501 +// Generated: 2023-10-04 17:50:11.242256 +0200 CEST m=+0.170866459 package netxlite diff --git a/internal/netxlite/errno_openbsd.go b/internal/netxlite/errno_openbsd.go index 4db2a875f2..4214f616a6 100644 --- a/internal/netxlite/errno_openbsd.go +++ b/internal/netxlite/errno_openbsd.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.024286 +0200 CEST m=+0.120034584 +// Generated: 2023-10-04 17:50:11.195049 +0200 CEST m=+0.123657543 package netxlite diff --git a/internal/netxlite/errno_openbsd_test.go b/internal/netxlite/errno_openbsd_test.go index 44516da2bf..7d0295e57a 100644 --- a/internal/netxlite/errno_openbsd_test.go +++ b/internal/netxlite/errno_openbsd_test.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.042781 +0200 CEST m=+0.138530209 +// Generated: 2023-10-04 17:50:11.211149 +0200 CEST m=+0.139758251 package netxlite diff --git a/internal/netxlite/errno_windows.go b/internal/netxlite/errno_windows.go index dbfb2d2140..5aba24ab97 100644 --- a/internal/netxlite/errno_windows.go +++ b/internal/netxlite/errno_windows.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.094846 +0200 CEST m=+0.190596584 +// Generated: 2023-10-04 17:50:11.2566 +0200 CEST m=+0.185210126 package netxlite diff --git a/internal/netxlite/errno_windows_test.go b/internal/netxlite/errno_windows_test.go index e1377a45d8..36cce00a62 100644 --- a/internal/netxlite/errno_windows_test.go +++ b/internal/netxlite/errno_windows_test.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2023-05-31 11:09:59.11131 +0200 CEST m=+0.207060334 +// Generated: 2023-10-04 17:50:11.270225 +0200 CEST m=+0.198835459 package netxlite diff --git a/internal/netxlite/internal/generrno/main.go b/internal/netxlite/internal/generrno/main.go index 94d48ee38d..48915dc14b 100644 --- a/internal/netxlite/internal/generrno/main.go +++ b/internal/netxlite/internal/generrno/main.go @@ -7,7 +7,7 @@ import ( "sort" "time" - "github.com/iancoleman/strcase" + "github.com/ooni/probe-cli/v3/internal/strcasex" "golang.org/x/sys/execabs" ) @@ -69,12 +69,12 @@ func (es *ErrorSpec) AsCanonicalErrnoName() string { // AsFailureVar returns the name of the failure var. func (es *ErrorSpec) AsFailureVar() string { - return "Failure" + strcase.ToCamel(es.failure) + return "Failure" + strcasex.ToCamel(es.failure) } // AsFailureString returns the OONI failure string. func (es *ErrorSpec) AsFailureString() string { - return strcase.ToSnake(es.failure) + return strcasex.ToSnake(es.failure) } // NewSystemError constructs a new ErrorSpec representing a system diff --git a/internal/registry/factory.go b/internal/registry/factory.go index ba599f50ef..9789bb3688 100644 --- a/internal/registry/factory.go +++ b/internal/registry/factory.go @@ -10,8 +10,8 @@ import ( "reflect" "strconv" - "github.com/iancoleman/strcase" "github.com/ooni/probe-cli/v3/internal/model" + "github.com/ooni/probe-cli/v3/internal/strcasex" ) // Factory allows to construct an experiment measurer. @@ -201,7 +201,7 @@ func (b *Factory) NewExperimentMeasurer() model.ExperimentMeasurer { // compatibility with MK, we need to add some exceptions here when // mapping (e.g., DNSCheck => dnscheck). func CanonicalizeExperimentName(name string) string { - switch name = strcase.ToSnake(name); name { + switch name = strcasex.ToSnake(name); name { case "ndt_7": name = "ndt" // since 2020-03-18, we use ndt7 to implement ndt by default case "dns_check": diff --git a/internal/strcasex/acronyms.go b/internal/strcasex/acronyms.go new file mode 100644 index 0000000000..18b0644ffd --- /dev/null +++ b/internal/strcasex/acronyms.go @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT + +package strcasex + +var uppercaseAcronym = map[string]string{ + "ID": "id", +} + +// ConfigureAcronym allows you to add additional words which will be considered acronyms +func ConfigureAcronym(key, val string) { + uppercaseAcronym[key] = val +} diff --git a/internal/strcasex/camel.go b/internal/strcasex/camel.go new file mode 100644 index 0000000000..4c91a236e7 --- /dev/null +++ b/internal/strcasex/camel.go @@ -0,0 +1,80 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcasex + +import ( + "strings" +) + +// Converts a string to CamelCase +func toCamelInitCase(s string, initCase bool) string { + s = strings.TrimSpace(s) + if s == "" { + return s + } + if a, ok := uppercaseAcronym[s]; ok { + s = a + } + + n := strings.Builder{} + n.Grow(len(s)) + capNext := initCase + for i, v := range []byte(s) { + vIsCap := v >= 'A' && v <= 'Z' + vIsLow := v >= 'a' && v <= 'z' + if capNext { + if vIsLow { + v += 'A' + v -= 'a' + } + } else if i == 0 { + if vIsCap { + v += 'a' + v -= 'A' + } + } + if vIsCap || vIsLow { + n.WriteByte(v) + capNext = false + } else if vIsNum := v >= '0' && v <= '9'; vIsNum { + n.WriteByte(v) + capNext = true + } else { + capNext = v == '_' || v == ' ' || v == '-' || v == '.' + } + } + return n.String() +} + +// ToCamel converts a string to CamelCase +func ToCamel(s string) string { + return toCamelInitCase(s, true) +} + +// ToLowerCamel converts a string to lowerCamelCase +func ToLowerCamel(s string) string { + return toCamelInitCase(s, false) +} diff --git a/internal/strcasex/camel_test.go b/internal/strcasex/camel_test.go new file mode 100644 index 0000000000..eb63288b47 --- /dev/null +++ b/internal/strcasex/camel_test.go @@ -0,0 +1,168 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcasex + +import ( + "testing" +) + +func toCamel(tb testing.TB) { + cases := [][]string{ + {"test_case", "TestCase"}, + {"test.case", "TestCase"}, + {"test", "Test"}, + {"TestCase", "TestCase"}, + {" test case ", "TestCase"}, + {"", ""}, + {"many_many_words", "ManyManyWords"}, + {"AnyKind of_string", "AnyKindOfString"}, + {"odd-fix", "OddFix"}, + {"numbers2And55with000", "Numbers2And55With000"}, + {"ID", "Id"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToCamel(in) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToCamel(t *testing.T) { + toCamel(t) +} + +func BenchmarkToCamel(b *testing.B) { + benchmarkCamelTest(b, toCamel) +} + +func toLowerCamel(tb testing.TB) { + cases := [][]string{ + {"foo-bar", "fooBar"}, + {"TestCase", "testCase"}, + {"", ""}, + {"AnyKind of_string", "anyKindOfString"}, + {"AnyKind.of-string", "anyKindOfString"}, + {"ID", "id"}, + {"some string", "someString"}, + {" some string", "someString"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToLowerCamel(in) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToLowerCamel(t *testing.T) { + toLowerCamel(t) +} + +func TestCustomAcronymsToCamel(t *testing.T) { + tests := []struct { + name string + acronymKey string + acronymValue string + expected string + }{ + { + name: "API Custom Acronym", + acronymKey: "API", + acronymValue: "api", + expected: "Api", + }, + { + name: "ABCDACME Custom Acroynm", + acronymKey: "ABCDACME", + acronymValue: "AbcdAcme", + expected: "AbcdAcme", + }, + { + name: "PostgreSQL Custom Acronym", + acronymKey: "PostgreSQL", + acronymValue: "PostgreSQL", + expected: "PostgreSQL", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ConfigureAcronym(test.acronymKey, test.acronymValue) + if result := ToCamel(test.acronymKey); result != test.expected { + t.Errorf("expected custom acronym result %s, got %s", test.expected, result) + } + }) + } +} + +func TestCustomAcronymsToLowerCamel(t *testing.T) { + tests := []struct { + name string + acronymKey string + acronymValue string + expected string + }{ + { + name: "API Custom Acronym", + acronymKey: "API", + acronymValue: "api", + expected: "api", + }, + { + name: "ABCDACME Custom Acroynm", + acronymKey: "ABCDACME", + acronymValue: "AbcdAcme", + expected: "abcdAcme", + }, + { + name: "PostgreSQL Custom Acronym", + acronymKey: "PostgreSQL", + acronymValue: "PostgreSQL", + expected: "postgreSQL", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ConfigureAcronym(test.acronymKey, test.acronymValue) + if result := ToLowerCamel(test.acronymKey); result != test.expected { + t.Errorf("expected custom acronym result %s, got %s", test.expected, result) + } + }) + } +} + +func BenchmarkToLowerCamel(b *testing.B) { + benchmarkCamelTest(b, toLowerCamel) +} + +func benchmarkCamelTest(b *testing.B, fn func(testing.TB)) { + for n := 0; n < b.N; n++ { + fn(b) + } +} diff --git a/internal/strcasex/doc.go b/internal/strcasex/doc.go new file mode 100644 index 0000000000..bf22ecfb36 --- /dev/null +++ b/internal/strcasex/doc.go @@ -0,0 +1,17 @@ +// Package strcasex converts strings to various cases. +// +// This package forks https://github.com/iancoleman/strcase at v0.2.0. +// +// See the conversion table below: +// +// | Function | Result | +// |---------------------------------|--------------------| +// | ToSnake(s) | any_kind_of_string | +// | ToScreamingSnake(s) | ANY_KIND_OF_STRING | +// | ToKebab(s) | any-kind-of-string | +// | ToScreamingKebab(s) | ANY-KIND-OF-STRING | +// | ToDelimited(s, '.') | any.kind.of.string | +// | ToScreamingDelimited(s, '.') | ANY.KIND.OF.STRING | +// | ToCamel(s) | AnyKindOfString | +// | ToLowerCamel(s) | anyKindOfString | +package strcasex diff --git a/internal/strcasex/snake.go b/internal/strcasex/snake.go new file mode 100644 index 0000000000..519a07a4b4 --- /dev/null +++ b/internal/strcasex/snake.go @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcasex + +import ( + "strings" +) + +// ToSnake converts a string to snake_case +func ToSnake(s string) string { + return ToDelimited(s, '_') +} + +func ToSnakeWithIgnore(s string, ignore string) string { + return ToScreamingDelimited(s, '_', ignore, false) +} + +// ToScreamingSnake converts a string to SCREAMING_SNAKE_CASE +func ToScreamingSnake(s string) string { + return ToScreamingDelimited(s, '_', "", true) +} + +// ToKebab converts a string to kebab-case +func ToKebab(s string) string { + return ToDelimited(s, '-') +} + +// ToScreamingKebab converts a string to SCREAMING-KEBAB-CASE +func ToScreamingKebab(s string) string { + return ToScreamingDelimited(s, '-', "", true) +} + +// ToDelimited converts a string to delimited.snake.case +// (in this case `delimiter = '.'`) +func ToDelimited(s string, delimiter uint8) string { + return ToScreamingDelimited(s, delimiter, "", false) +} + +// ToScreamingDelimited converts a string to SCREAMING.DELIMITED.SNAKE.CASE +// (in this case `delimiter = '.'; screaming = true`) +// or delimited.snake.case +// (in this case `delimiter = '.'; screaming = false`) +func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bool) string { + s = strings.TrimSpace(s) + n := strings.Builder{} + n.Grow(len(s) + 2) // nominal 2 bytes of extra space for inserted delimiters + for i, v := range []byte(s) { + vIsCap := v >= 'A' && v <= 'Z' + vIsLow := v >= 'a' && v <= 'z' + if vIsLow && screaming { + v += 'A' + v -= 'a' + } else if vIsCap && !screaming { + v += 'a' + v -= 'A' + } + + // treat acronyms as words, eg for JSONData -> JSON is a whole word + if i+1 < len(s) { + next := s[i+1] + vIsNum := v >= '0' && v <= '9' + nextIsCap := next >= 'A' && next <= 'Z' + nextIsLow := next >= 'a' && next <= 'z' + nextIsNum := next >= '0' && next <= '9' + // add underscore if next letter case type is changed + if (vIsCap && (nextIsLow || nextIsNum)) || (vIsLow && (nextIsCap || nextIsNum)) || (vIsNum && (nextIsCap || nextIsLow)) { + prevIgnore := ignore != "" && i > 0 && strings.ContainsAny(string(s[i-1]), ignore) + if !prevIgnore { + if vIsCap && nextIsLow { + if prevIsCap := i > 0 && s[i-1] >= 'A' && s[i-1] <= 'Z'; prevIsCap { + n.WriteByte(delimiter) + } + } + n.WriteByte(v) + if vIsLow || vIsNum || nextIsNum { + n.WriteByte(delimiter) + } + continue + } + } + } + + if (v == ' ' || v == '_' || v == '-' || v == '.') && !strings.ContainsAny(string(v), ignore) { + // replace space/underscore/hyphen/dot with delimiter + n.WriteByte(delimiter) + } else { + n.WriteByte(v) + } + } + + return n.String() +} diff --git a/internal/strcasex/snake_test.go b/internal/strcasex/snake_test.go new file mode 100644 index 0000000000..22894b9f52 --- /dev/null +++ b/internal/strcasex/snake_test.go @@ -0,0 +1,270 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ian Coleman + * Copyright (c) 2018 Ma_124, + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, Subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or Substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package strcasex + +import ( + "testing" +) + +func toSnake(tb testing.TB) { + cases := [][]string{ + {"testCase", "test_case"}, + {"TestCase", "test_case"}, + {"Test Case", "test_case"}, + {" Test Case", "test_case"}, + {"Test Case ", "test_case"}, + {" Test Case ", "test_case"}, + {"test", "test"}, + {"test_case", "test_case"}, + {"Test", "test"}, + {"", ""}, + {"ManyManyWords", "many_many_words"}, + {"manyManyWords", "many_many_words"}, + {"AnyKind of_string", "any_kind_of_string"}, + {"numbers2and55with000", "numbers_2_and_55_with_000"}, + {"JSONData", "json_data"}, + {"userID", "user_id"}, + {"AAAbbb", "aa_abbb"}, + {"1A2", "1_a_2"}, + {"A1B", "a_1_b"}, + {"A1A2A3", "a_1_a_2_a_3"}, + {"A1 A2 A3", "a_1_a_2_a_3"}, + {"AB1AB2AB3", "ab_1_ab_2_ab_3"}, + {"AB1 AB2 AB3", "ab_1_ab_2_ab_3"}, + {"some string", "some_string"}, + {" some string", "some_string"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToSnake(in) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToSnake(t *testing.T) { toSnake(t) } + +func BenchmarkToSnake(b *testing.B) { + benchmarkSnakeTest(b, toSnake) +} + +func toSnakeWithIgnore(tb testing.TB) { + cases := [][]string{ + {"testCase", "test_case"}, + {"TestCase", "test_case"}, + {"Test Case", "test_case"}, + {" Test Case", "test_case"}, + {"Test Case ", "test_case"}, + {" Test Case ", "test_case"}, + {"test", "test"}, + {"test_case", "test_case"}, + {"Test", "test"}, + {"", ""}, + {"ManyManyWords", "many_many_words"}, + {"manyManyWords", "many_many_words"}, + {"AnyKind of_string", "any_kind_of_string"}, + {"numbers2and55with000", "numbers_2_and_55_with_000"}, + {"JSONData", "json_data"}, + {"AwesomeActivity.UserID", "awesome_activity.user_id", "."}, + {"AwesomeActivity.User.Id", "awesome_activity.user.id", "."}, + {"AwesomeUsername@Awesome.Com", "awesome_username@awesome.com", ".@"}, + {"lets-ignore all.of dots-and-dashes", "lets-ignore_all.of_dots-and-dashes", ".-"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + var ignore string + ignore = "" + if len(i) == 3 { + ignore = i[2] + } + result := ToSnakeWithIgnore(in, ignore) + if result != out { + istr := "" + if len(i) == 3 { + istr = " ignoring '" + i[2] + "'" + } + tb.Errorf("%q (%q != %q%s)", in, result, out, istr) + } + } +} + +func TestToSnakeWithIgnore(t *testing.T) { toSnakeWithIgnore(t) } + +func BenchmarkToSnakeWithIgnore(b *testing.B) { + benchmarkSnakeTest(b, toSnakeWithIgnore) +} + +func toDelimited(tb testing.TB) { + cases := [][]string{ + {"testCase", "test@case"}, + {"TestCase", "test@case"}, + {"Test Case", "test@case"}, + {" Test Case", "test@case"}, + {"Test Case ", "test@case"}, + {" Test Case ", "test@case"}, + {"test", "test"}, + {"test_case", "test@case"}, + {"Test", "test"}, + {"", ""}, + {"ManyManyWords", "many@many@words"}, + {"manyManyWords", "many@many@words"}, + {"AnyKind of_string", "any@kind@of@string"}, + {"numbers2and55with000", "numbers@2@and@55@with@000"}, + {"JSONData", "json@data"}, + {"userID", "user@id"}, + {"AAAbbb", "aa@abbb"}, + {"test-case", "test@case"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToDelimited(in, '@') + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToDelimited(t *testing.T) { toDelimited(t) } + +func BenchmarkToDelimited(b *testing.B) { + benchmarkSnakeTest(b, toDelimited) +} + +func toScreamingSnake(tb testing.TB) { + cases := [][]string{ + {"testCase", "TEST_CASE"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToScreamingSnake(in) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToScreamingSnake(t *testing.T) { toScreamingSnake(t) } + +func BenchmarkToScreamingSnake(b *testing.B) { + benchmarkSnakeTest(b, toScreamingSnake) +} + +func toKebab(tb testing.TB) { + cases := [][]string{ + {"testCase", "test-case"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToKebab(in) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToKebab(t *testing.T) { toKebab(t) } + +func BenchmarkToKebab(b *testing.B) { + benchmarkSnakeTest(b, toKebab) +} + +func toScreamingKebab(tb testing.TB) { + cases := [][]string{ + {"testCase", "TEST-CASE"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToScreamingKebab(in) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToScreamingKebab(t *testing.T) { toScreamingKebab(t) } + +func BenchmarkToScreamingKebab(b *testing.B) { + benchmarkSnakeTest(b, toScreamingKebab) +} + +func toScreamingDelimited(tb testing.TB) { + cases := [][]string{ + {"testCase", "TEST.CASE"}, + } + for _, i := range cases { + in := i[0] + out := i[1] + result := ToScreamingDelimited(in, '.', "", true) + if result != out { + tb.Errorf("%q (%q != %q)", in, result, out) + } + } +} + +func TestToScreamingDelimited(t *testing.T) { toScreamingDelimited(t) } + +func BenchmarkToScreamingDelimited(b *testing.B) { + benchmarkSnakeTest(b, toScreamingDelimited) +} + +func toScreamingDelimitedWithIgnore(tb testing.TB) { + cases := [][]string{ + {"AnyKind of_string", "ANY.KIND OF.STRING", ".", " "}, + } + for _, i := range cases { + in := i[0] + out := i[1] + delimiter := i[2][0] + ignore := i[3][0] + result := ToScreamingDelimited(in, delimiter, string(ignore), true) + if result != out { + istr := "" + if len(i) == 4 { + istr = " ignoring '" + i[3] + "'" + } + tb.Errorf("%q (%q != %q%s)", in, result, out, istr) + } + } +} + +func TestToScreamingDelimitedWithIgnore(t *testing.T) { toScreamingDelimitedWithIgnore(t) } + +func BenchmarkToScreamingDelimitedWithIgnore(b *testing.B) { + benchmarkSnakeTest(b, toScreamingDelimitedWithIgnore) +} + +func benchmarkSnakeTest(b *testing.B, fn func(testing.TB)) { + for n := 0; n < b.N; n++ { + fn(b) + } +}