github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/admin/client_test.go (about)

     1  //go:build !windows
     2  // +build !windows
     3  
     4  package admin_test
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"time"
    10  
    11  	. "github.com/onsi/ginkgo/v2"
    12  	. "github.com/onsi/gomega"
    13  
    14  	"github.com/pyroscope-io/pyroscope/pkg/admin"
    15  )
    16  
    17  var _ = Describe("client", func() {
    18  	fastTimeout := time.Millisecond * 100
    19  	var (
    20  		cleanup    func()
    21  		socketAddr string
    22  		server     *admin.UdsHTTPServer
    23  		handler    *http.ServeMux
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		c, dir := genRandomDir()
    28  		socketAddr = dir + "/pyroscope.sock"
    29  		handler = http.NewServeMux()
    30  
    31  		cleanup = c
    32  	})
    33  
    34  	JustBeforeEach(func() {
    35  		s, err := admin.NewUdsHTTPServer(socketAddr, createHttpClientWithFastTimeout(socketAddr))
    36  		Expect(err).ToNot(HaveOccurred())
    37  		server = s
    38  		go server.Start(handler)
    39  		waitUntilServerIsReady(socketAddr)
    40  	})
    41  
    42  	AfterEach(func() {
    43  		server.Stop()
    44  		cleanup()
    45  	})
    46  
    47  	// this test isn't super useful since this is already tested in the actual http client
    48  	// but I wanted to test instantiaton error
    49  	// without requiring dependency injection
    50  	Context("when socket address is empty", func() {
    51  		It("fails", func() {
    52  			_, err := admin.NewClient("", fastTimeout)
    53  			Expect(err).To(MatchError(admin.ErrHTTPClientCreation))
    54  		})
    55  	})
    56  
    57  	Describe("GetAppNames", func() {
    58  		Context("when server returns just fine", func() {
    59  			BeforeEach(func() {
    60  				handler = http.NewServeMux()
    61  				handler.HandleFunc("/v1/apps", func(w http.ResponseWriter, r *http.Request) {
    62  					w.WriteHeader(200)
    63  					_, _ = fmt.Fprintf(w, `[{ "name": "name1"}, {"name": "name2" }]`)
    64  				})
    65  			})
    66  
    67  			It("works", func() {
    68  				client, err := admin.NewClient(socketAddr, fastTimeout)
    69  				Expect(err).ToNot(HaveOccurred())
    70  
    71  				_, err = client.GetAppsNames()
    72  				Expect(err).ToNot(HaveOccurred())
    73  			})
    74  		})
    75  
    76  		Context("when server responds with 500 error", func() {
    77  			BeforeEach(func() {
    78  				handler = http.NewServeMux()
    79  				handler.HandleFunc("/v1/apps", func(w http.ResponseWriter, r *http.Request) {
    80  					w.WriteHeader(500)
    81  				})
    82  			})
    83  
    84  			It("fails", func() {
    85  				client, err := admin.NewClient(socketAddr, fastTimeout)
    86  
    87  				_, err = client.GetAppsNames()
    88  				Expect(err).To(MatchError(admin.ErrStatusCodeNotOK))
    89  			})
    90  		})
    91  
    92  		Context("when server returns invalid json", func() {
    93  			BeforeEach(func() {
    94  				handler = http.NewServeMux()
    95  				handler.HandleFunc("/v1/apps", func(w http.ResponseWriter, r *http.Request) {
    96  					w.WriteHeader(200)
    97  
    98  					_, _ = fmt.Fprintf(w, "broken_json")
    99  					_, _ = fmt.Fprintln(w)
   100  				})
   101  			})
   102  
   103  			It("fails", func() {
   104  				client, err := admin.NewClient(socketAddr, fastTimeout)
   105  				Expect(err).ToNot(HaveOccurred())
   106  
   107  				_, err = client.GetAppsNames()
   108  				Expect(err).To(MatchError(admin.ErrDecodingResponse))
   109  			})
   110  		})
   111  
   112  		Context("when can't talk to server", func() {
   113  			It("fails", func() {
   114  				Expect(true).To(Equal(true))
   115  				client, err := admin.NewClient("foobar.sock", fastTimeout)
   116  				Expect(err).ToNot(HaveOccurred())
   117  
   118  				_, err = client.GetAppsNames()
   119  				Expect(err).To(MatchError(admin.ErrMakingRequest))
   120  			})
   121  		})
   122  	})
   123  
   124  	Describe("DeleteApp", func() {
   125  		Context("when server returns just fine", func() {
   126  			BeforeEach(func() {
   127  				handler = http.NewServeMux()
   128  				handler.HandleFunc("/v1/apps", func(w http.ResponseWriter, r *http.Request) {
   129  					w.WriteHeader(200)
   130  				})
   131  			})
   132  
   133  			It("works", func() {
   134  				client, err := admin.NewClient(socketAddr, fastTimeout)
   135  				Expect(err).ToNot(HaveOccurred())
   136  
   137  				err = client.DeleteApp("appname")
   138  				Expect(err).ToNot(HaveOccurred())
   139  			})
   140  		})
   141  
   142  		Context("when can't talk to server", func() {
   143  			It("fails", func() {
   144  				Expect(true).To(Equal(true))
   145  				client, err := admin.NewClient("foobar.sock", fastTimeout)
   146  				Expect(err).ToNot(HaveOccurred())
   147  
   148  				err = client.DeleteApp("appname")
   149  				Expect(err).To(MatchError(admin.ErrMakingRequest))
   150  			})
   151  		})
   152  
   153  		Context("when server responds with error", func() {
   154  			BeforeEach(func() {
   155  				handler = http.NewServeMux()
   156  				handler.HandleFunc("/v1/apps", func(w http.ResponseWriter, r *http.Request) {
   157  					w.WriteHeader(500)
   158  				})
   159  			})
   160  
   161  			It("fails", func() {
   162  				client, err := admin.NewClient(socketAddr, fastTimeout)
   163  				Expect(err).ToNot(HaveOccurred())
   164  
   165  				err = client.DeleteApp("appname")
   166  				Expect(err).To(MatchError(admin.ErrStatusCodeNotOK))
   167  			})
   168  		})
   169  	})
   170  
   171  })