Skip to content
Open
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
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
- [#4864](https://github.com/ignite/cli/pull/4864) Mismatch for message names.
- [#4735](https://github.com/ignite/cli/issues/4735) Cleanup `xgenny` runner to avoid duplicated generators.

## Features

- [#4869](https://github.com/ignite/cli/pull/4869) Improve the httpstatuschecker by injecting clients.

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

## Changes
Expand Down
9 changes: 9 additions & 0 deletions ignite/pkg/httpstatuschecker/httpstatuschecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ func Method(name string) Option {
}
}

// Client configures http client.
func Client(client *http.Client) Option {
return func(cr *checker) {
if client != nil {
cr.c = client
}
}
}

// Check checks if given http addr is alive by applying options.
func Check(ctx context.Context, addr string, options ...Option) (isAvailable bool, err error) {
cr := &checker{
Expand Down
34 changes: 27 additions & 7 deletions ignite/pkg/httpstatuschecker/httpstatuschecker_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
package httpstatuschecker

import (
"bytes"
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/require"
)

type roundTripperFunc func(*http.Request) (*http.Response, error)

func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req)
}

func newTestClient(fn roundTripperFunc) *http.Client {
return &http.Client{Transport: fn}
}

func TestCheckStatus(t *testing.T) {
cases := []struct {
name string
Expand All @@ -21,20 +33,28 @@ func TestCheckStatus(t *testing.T) {
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(tt.returnedStatus)
}))
defer ts.Close()
client := newTestClient(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: tt.returnedStatus,
Body: io.NopCloser(bytes.NewReader(nil)),
Header: make(http.Header),
ContentLength: 0,
Request: req,
}, nil
})

isAvailable, err := Check(context.Background(), ts.URL)
isAvailable, err := Check(context.Background(), "http://example.com", Client(client))
require.NoError(t, err)
require.Equal(t, tt.isAvaiable, isAvailable)
})
}
}

func TestCheckServerUnreachable(t *testing.T) {
isAvailable, err := Check(context.Background(), "http://localhost:63257")
client := newTestClient(func(*http.Request) (*http.Response, error) {
return nil, errors.New("dial tcp: connection refused")
})
isAvailable, err := Check(context.Background(), "http://example.com", Client(client))
require.NoError(t, err)
require.False(t, isAvailable)
}
15 changes: 14 additions & 1 deletion ignite/pkg/jsonfile/jsonfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ func FromPath(path string) (*JSONFile, error) {
// tarballFileName is extracted from it and is returned instead of the URL
// content.
func FromURL(ctx context.Context, url, destPath, tarballFileName string) (*JSONFile, error) {
return fromURL(ctx, url, destPath, tarballFileName, http.DefaultClient)
}

// FromURLWithClient fetches the file using the provided HTTP client.
// If client is nil, http.DefaultClient is used.
func FromURLWithClient(ctx context.Context, url, destPath, tarballFileName string, client *http.Client) (*JSONFile, error) {
if client == nil {
client = http.DefaultClient
}
return fromURL(ctx, url, destPath, tarballFileName, client)
}

func fromURL(ctx context.Context, url, destPath, tarballFileName string, client *http.Client) (*JSONFile, error) {
// TODO create a cache system to avoid download genesis with the same hash again

// Download the file from URL
Expand All @@ -95,7 +108,7 @@ func FromURL(ctx context.Context, url, destPath, tarballFileName string) (*JSONF
return nil, err
}

resp, err := http.DefaultClient.Do(req)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
Expand Down
45 changes: 36 additions & 9 deletions ignite/pkg/jsonfile/jsonfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"reflect"
"testing"
Expand All @@ -19,6 +19,26 @@ import (
"github.com/ignite/cli/v29/ignite/pkg/tarball"
)

type roundTripperFunc func(*http.Request) (*http.Response, error)

func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req)
}

func newTestClient(statusCode int, body []byte) *http.Client {
return &http.Client{
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: statusCode,
Body: io.NopCloser(bytes.NewReader(body)),
Header: make(http.Header),
ContentLength: int64(len(body)),
Request: req,
}, nil
}),
}
}

func TestJSONFile_Field(t *testing.T) {
type (
invalidStruct struct {
Expand Down Expand Up @@ -356,17 +376,24 @@ func TestFromURL(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
url := tt.args.url
if url == "" {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
file, err := os.ReadFile(tt.args.filepath)
require.NoError(t, err)
_, err = w.Write(file)
require.NoError(t, err)
}))
url = ts.URL
url = "https://example.com/testdata"
}

var body []byte
if tt.args.filepath != "" {
var err error
body, err = os.ReadFile(tt.args.filepath)
require.NoError(t, err)
}

statusCode := http.StatusOK
if tt.err == ErrInvalidURL {
statusCode = http.StatusNotFound
}
client := newTestClient(statusCode, body)

filepath := fmt.Sprintf("%s/jsonfile.json", t.TempDir())
got, err := FromURL(context.TODO(), url, filepath, tt.args.tarballFileName)
got, err := FromURLWithClient(context.TODO(), url, filepath, tt.args.tarballFileName, client)
if tt.err != nil {
require.Error(t, err)
require.ErrorIs(t, err, tt.err)
Expand Down