Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: fix faucet test #4543

Merged
merged 2 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@

// 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
Loading