Skip to content

Commit

Permalink
test: fix faucet test (#4543)
Browse files Browse the repository at this point in the history
* test: fix faucet test

* cl
  • Loading branch information
julienrbrt authored Feb 26, 2025
1 parent a3c4c51 commit c60540e
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 27 deletions.
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
- [#4091](https://github.com/ignite/cli/pull/4091) Fix race conditions in the plugin logic
- [#4128](https://github.com/ignite/cli/pull/4128) Check for duplicate proto fields in config
- [#4402](https://github.com/ignite/cli/pull/4402) Fix gentx parser into the cosmosutil package
- [#4540](https://github.com/ignite/cli/pull/4540) Skip logs / gibberish when parsing commands outputs
- [#4540](https://github.com/ignite/cli/pull/4540), [#4543](https://github.com/ignite/cli/pull/4543) Skip logs / gibberish when parsing commands outputs

## [`v28.8.0`](https://github.com/ignite/cli/releases/tag/v28.8.0)

Expand Down
114 changes: 90 additions & 24 deletions ignite/pkg/chaincmd/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,47 +143,113 @@ type buffer struct {

// JSONEnsuredBytes ensures that encoding format for returned bytes is always
// JSON even if the written data is originally encoded in YAML.
// This method is purposely verbose to trim gibberish output.
func (b *buffer) JSONEnsuredBytes() ([]byte, error) {
bz := b.Bytes()
content := strings.TrimSpace(string(bz))

// check for valid json
// Early detection - check first non-whitespace character
if len(content) > 0 {
firstChar := content[0]

// Quick check for JSON format (starts with { or [)
if firstChar == '{' || firstChar == '[' {
// Attempt to validate and extract clean JSON
return cleanAndValidateJSON(bz)
}

// Quick check for YAML format (common indicators)
if firstChar == '-' || strings.HasPrefix(content, "---") ||
strings.Contains(content, ":\n") || strings.Contains(content, ": ") {
// Likely YAML, convert to JSON directly
var out any
if err := yaml.Unmarshal(bz, &out); err == nil {
return yaml.YAMLToJSON(bz)
}
}
}

// If format wasn't immediately obvious, try the more thorough approach
return fallbackFormatDetection(bz)
}

// cleanAndValidateJSON attempts to extract valid JSON from potentially messy output

Check failure on line 176 in ignite/pkg/chaincmd/runner/runner.go

View workflow job for this annotation

GitHub Actions / Lint Go code

Comment should end in a period (godot)
func cleanAndValidateJSON(bz []byte) ([]byte, error) {
// Find the first JSON opening character
startIndex := strings.IndexAny(string(bz), "{[")
if startIndex >= 0 {
// check if we need to find the matching closing bracket
opening := bz[startIndex]
var closing byte
if opening == '{' {
closing = '}'
} else {
closing = ']'
if startIndex < 0 {
return bz, nil // No JSON structure found
}

// Determine matching closing character
opening := bz[startIndex]
var closing byte
if opening == '{' {
closing = '}'
} else {
closing = ']'
}

endIndex := findMatchingCloseBracket(bz[startIndex:], opening, closing)
if endIndex < 0 {
// no proper closing found, try last instance
endIndex = bytes.LastIndexByte(bz, closing)
if endIndex <= startIndex {
return bz[startIndex:], nil // Return from start to end if no closing found
}
} else {
endIndex += startIndex
}

// look for the last matching closing bracket
endIndex := bytes.LastIndexByte(bz, closing)
if endIndex > startIndex {
// extract what appears to be valid JSON
bz = bz[startIndex : endIndex+1]
// validate JSON
jsonData := bz[startIndex : endIndex+1]
var jsonTest any
if err := json.Unmarshal(jsonData, &jsonTest); err == nil {
return jsonData, nil
}

// if validation failed, return from start to end
return bz[startIndex:], nil
}

// verify it's actually valid JSON
var jsonTest any
if err := json.Unmarshal(bz, &jsonTest); err == nil {
return bz, nil
// findMatchingCloseBracket finds the index of the matching closing bracket
// accounting for nested structures

Check failure on line 216 in ignite/pkg/chaincmd/runner/runner.go

View workflow job for this annotation

GitHub Actions / Lint Go code

Comment should end in a period (godot)
func findMatchingCloseBracket(data []byte, openChar, closeChar byte) int {
depth := 0
for i, b := range data {
if b == openChar {
depth++
} else if b == closeChar {
depth--
if depth == 0 {
return i // Found matching closing bracket
}
}
}
return -1 // No matching bracket found
}

// fallbackFormatDetection tries different approaches to detect and convert format

Check failure on line 232 in ignite/pkg/chaincmd/runner/runner.go

View workflow job for this annotation

GitHub Actions / Lint Go code

Comment should end in a period (godot)
func fallbackFormatDetection(bz []byte) ([]byte, error) {
// first try to find and extract JSON
startIndex := strings.IndexAny(string(bz), "{[")
if startIndex >= 0 {
result, err := cleanAndValidateJSON(bz)
if err == nil {
return result, nil
}

// if extraction failed but we found a start, return from there
return bz[startIndex:], nil
}

// fallback to yaml parsing
var out any
if err := yaml.Unmarshal(bz, &out); err == nil {
return yaml.YAMLToJSON(bz)
}

// if neither JSON nor YAML parsing succeeded, return the original bytes
// starting from the first opening brace if found, or the entire buffer
if startIndex >= 0 {
return bz[startIndex:], nil
}

// nothing worked, return original
return bz, nil
}

Expand Down
11 changes: 9 additions & 2 deletions ignite/pkg/cosmosfaucet/client_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"

"github.com/ignite/cli/v29/ignite/pkg/errors"
)

// ErrTransferRequest is an error that occurs when a transfer request fails.
type ErrTransferRequest struct {
Body string
StatusCode int
}

Expand Down Expand Up @@ -48,11 +50,16 @@ func (c HTTPClient) Transfer(ctx context.Context, req TransferRequest) (Transfer
defer hres.Body.Close()

if hres.StatusCode != http.StatusOK {
return TransferResponse{}, ErrTransferRequest{hres.StatusCode}
bodyBytes, _ := io.ReadAll(hres.Body)
return TransferResponse{}, ErrTransferRequest{Body: string(bodyBytes), StatusCode: hres.StatusCode}
}

var res TransferResponse
return res, json.NewDecoder(hres.Body).Decode(&res)
if err = json.NewDecoder(hres.Body).Decode(&res); err != nil {
return TransferResponse{}, err
}

return res, nil
}

// FaucetInfo fetch the faucet info for clients to determine if this is a real faucet and
Expand Down

0 comments on commit c60540e

Please sign in to comment.