github.com/minio/console@v1.3.0/api/admin_profiling_test.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2021 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"errors"
    23  	"io"
    24  	"net/http"
    25  	"net/url"
    26  	"testing"
    27  
    28  	"github.com/minio/madmin-go/v3"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  // Implementing fake closingBuffer to mock stopProfiling() (io.ReadCloser, error)
    33  type ClosingBuffer struct {
    34  	*bytes.Buffer
    35  }
    36  
    37  // Implementing a fake Close function for io.ReadCloser
    38  func (cb *ClosingBuffer) Close() error {
    39  	return nil
    40  }
    41  
    42  func TestStartProfiling(t *testing.T) {
    43  	ctx, cancel := context.WithCancel(context.Background())
    44  	defer cancel()
    45  	assert := assert.New(t)
    46  	adminClient := AdminClientMock{}
    47  	mockWSConn := mockConn{}
    48  	function := "startProfiling()"
    49  	testOptions := &profileOptions{
    50  		Types: "cpu",
    51  	}
    52  
    53  	// Test-1 : startProfiling() Get response from MinIO server with one profiling object without errors
    54  	// mock function response from startProfiling()
    55  	minioStartProfiling = func(_ madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
    56  		return []madmin.StartProfilingResult{
    57  			{
    58  				NodeName: "http://127.0.0.1:9000/",
    59  				Success:  true,
    60  				Error:    "",
    61  			},
    62  			{
    63  				NodeName: "http://127.0.0.1:9001/",
    64  				Success:  true,
    65  				Error:    "",
    66  			},
    67  		}, nil
    68  	}
    69  	// mock function response from stopProfiling()
    70  	minioStopProfiling = func() (io.ReadCloser, error) {
    71  		return &ClosingBuffer{bytes.NewBufferString("In memory string eaeae")}, nil
    72  	}
    73  	// mock function response from mockConn.writeMessage()
    74  	connWriteMessageMock = func(_ int, _ []byte) error {
    75  		return nil
    76  	}
    77  	err := startProfiling(ctx, mockWSConn, adminClient, testOptions)
    78  	if err != nil {
    79  		t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
    80  	}
    81  	assert.Equal(err, nil)
    82  
    83  	// Test-2 : startProfiling() Correctly handles errors returned by MinIO
    84  	// mock function response from startProfiling()
    85  	minioStartProfiling = func(_ madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
    86  		return nil, errors.New("error")
    87  	}
    88  	err = startProfiling(ctx, mockWSConn, adminClient, testOptions)
    89  	if assert.Error(err) {
    90  		assert.Equal("error", err.Error())
    91  	}
    92  
    93  	// Test-3: getProfileOptionsFromReq() correctly returns profile options from request
    94  	u, _ := url.Parse("ws://localhost/ws/profile?types=cpu,mem,block,mutex,trace,threads,goroutines")
    95  	req := &http.Request{
    96  		URL: u,
    97  	}
    98  	opts, err := getProfileOptionsFromReq(req)
    99  	if assert.NoError(err) {
   100  		expectedOptions := profileOptions{
   101  			Types: "cpu,mem,block,mutex,trace,threads,goroutines",
   102  		}
   103  		assert.Equal(expectedOptions.Types, opts.Types)
   104  	}
   105  }