github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/registry/regserver/handlers/profile_test.go (about)

     1  package handlers
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"strings"
    11  	"testing"
    12  
    13  	crypto "github.com/libp2p/go-libp2p-core/crypto"
    14  	"github.com/qri-io/qri/auth/key"
    15  	"github.com/qri-io/qri/registry"
    16  )
    17  
    18  // base64-encoded Test Private Key, decoded in init
    19  var (
    20  	// peerId: QmZePf5LeXow3RW5U1AgEiNbW46YnRGhZ7HPvm1UmPFPwt
    21  	testPk1  = `CAASpgkwggSiAgEAAoIBAQC/7Q7fILQ8hc9g07a4HAiDKE4FahzL2eO8OlB1K99Ad4L1zc2dCg+gDVuGwdbOC29IngMA7O3UXijycckOSChgFyW3PafXoBF8Zg9MRBDIBo0lXRhW4TrVytm4Etzp4pQMyTeRYyWR8e2hGXeHArXM1R/A/SjzZUbjJYHhgvEE4OZy7WpcYcW6K3qqBGOU5GDMPuCcJWac2NgXzw6JeNsZuTimfVCJHupqG/dLPMnBOypR22dO7yJIaQ3d0PFLxiDG84X9YupF914RzJlopfdcuipI+6gFAgBw3vi6gbECEzcohjKf/4nqBOEvCDD6SXfl5F/MxoHurbGBYB2CJp+FAgMBAAECggEAaVOxe6Y5A5XzrxHBDtzjlwcBels3nm/fWScvjH4dMQXlavwcwPgKhy2NczDhr4X69oEw6Msd4hQiqJrlWd8juUg6vIsrl1wS/JAOCS65fuyJfV3Pw64rWbTPMwO3FOvxj+rFghZFQgjg/i45uHA2UUkM+h504M5Nzs6Arr/rgV7uPGR5e5OBw3lfiS9ZaA7QZiOq7sMy1L0qD49YO1ojqWu3b7UaMaBQx1Dty7b5IVOSYG+Y3U/dLjhTj4Hg1VtCHWRm3nMOE9cVpMJRhRzKhkq6gnZmni8obz2BBDF02X34oQLcHC/Wn8F3E8RiBjZDI66g+iZeCCUXvYz0vxWAQQKBgQDEJu6flyHPvyBPAC4EOxZAw0zh6SF/r8VgjbKO3n/8d+kZJeVmYnbsLodIEEyXQnr35o2CLqhCvR2kstsRSfRz79nMIt6aPWuwYkXNHQGE8rnCxxyJmxV4S63GczLk7SIn4KmqPlCI08AU0TXJS3zwh7O6e6kBljjPt1mnMgvr3QKBgQD6fAkdI0FRZSXwzygx4uSg47Co6X6ESZ9FDf6ph63lvSK5/eue/ugX6p/olMYq5CHXbLpgM4EJYdRfrH6pwqtBwUJhlh1xI6C48nonnw+oh8YPlFCDLxNG4tq6JVo071qH6CFXCIank3ThZeW5a3ZSe5pBZ8h4bUZ9H8pJL4C7yQKBgFb8SN/+/qCJSoOeOcnohhLMSSD56MAeK7KIxAF1jF5isr1TP+rqiYBtldKQX9bIRY3/8QslM7r88NNj+aAuIrjzSausXvkZedMrkXbHgS/7EAPflrkzTA8fyH10AsLgoj/68mKr5bz34nuY13hgAJUOKNbvFeC9RI5g6eIqYH0FAoGAVqFTXZp12rrK1nAvDKHWRLa6wJCQyxvTU8S1UNi2EgDJ492oAgNTLgJdb8kUiH0CH0lhZCgr9py5IKW94OSM6l72oF2UrS6PRafHC7D9b2IV5Al9lwFO/3MyBrMocapeeyaTcVBnkclz4Qim3OwHrhtFjF1ifhP9DwVRpuIg+dECgYANwlHxLe//tr6BM31PUUrOxP5Y/cj+ydxqM/z6papZFkK6Mvi/vMQQNQkh95GH9zqyC5Z/yLxur4ry1eNYty/9FnuZRAkEmlUSZ/DobhU0Pmj8Hep6JsTuMutref6vCk2n02jc9qYmJuD7iXkdXDSawbEG6f5C4MUkJ38z1t1OjA==`
    22  	privKey1 crypto.PrivKey
    23  
    24  	testPk2  = `CAASqAkwggSkAgEAAoIBAQDdqbl7nT6hQnTDD+nMkrSLzyoqnx2l+kfF2GN7hZDQGMbh5VgvXyEUifnczUbEIGT/llyOdQmDIvsiGBCMU1T+P1MuhzxSKgblrLtp7yAf6jUgQU6GsbJ5r+MvstG6ds7QqPgKidJL302V0+FMJP6nmpupowDxYQe5GqGJuGwNYBqGTrxqM4FsWNquNPmuE0vCDLqYs2vm6ur2k5RIyTXhnFbpHyO31qsgU5d1dR/Wda0KlyQrS0k3Cmj1foRFGuKJKDJVJ1FTryLAWv9VDSCooQKpWUQ3cUuUSuw9OmTnuvC2xx0IaDAjlh8l+4FRbA+nySVsk82B30MlGYc6jSyDAgMBAAECggEAEhvNhWXBOhddxpnENew+R7Wy8ixxlZ+uwWD+L5cnz3hWtxmvbJ9O6oijGwDCKT+kQKUeBp1VG5t9/LkOkQg1x1eRChoOOYApdBX6cZsResn9cRckvShDNmHCI6FuNNeD6dQD/4hm37/sbLMUks3q5/JfiSpB53ZP1TVxwPiKC0WJriS+dHC6kuiilA0uA+lgOD/w2voqeiFQrjcDu71b3DUulamwq3zt4h2I5pnaOKw7N22k2T9rADS7WbBHVIdd7bxgLkc6EEyho7PT4HqOH15QVS9B4Y4xIYVk0Osqq+uDqSTNEn8SBtL9RE3sO7ygQoKgLL3uvRSXGwP4ISNcYQKBgQD5sBrICL+7+JyAxieirR8kHUS2pfn6/rMrx8lu/fHs6yjOpeHojlKdaCcWLkYn5iahCwayNMFiu/0S9mA3FhNI+nANHbGH/I8RET3EJVPPvdfPhP9YpAXiQYLO5OaSdoKrEyqURDUI3ve+xy/2+JSX4R9q8ovH8c2m7L6gjzlMGQKBgQDjRECMkOxoOxC4i/j3tGI30qz+vYFtpDwz34cEKyKo/tEdmG6PWvm1NlY/GJNvi8fVBxPsIoP1m6ys/842ALYygwm4pV3c3xO8XdrJ8k8jfy6UzbsHXXsoTx9ofqz34IYJ71Pw8MGdwgkwr1qTizKB28E4c22CaAg6yudTcU4Q+wKBgQChh/preq1/z8B/1rIBnfpNhNnVR99HL8t+AUwhkAwY97F4rvxNVPXBe4X95YXhfhVzjgyQ8WxCkdeRku5/9LoZNluTQKh/jzaHFh5dbMCh3vFlAWeoUsSzsSoM6yz3h8/VGRssvEuLJ6QjOf2fywVmlG+c4rjna1leKj7Q5Jdu0QKBgF+5W8bZM/ojBsP0kQUkgUop/pu9jkp0JrdiqyfiU1MDIWlpzweqtgrRvDoPS+pr4dukg4uubg6BZ5XmmSC95AAamXmgjYx+mX15urHc0eCNrT0X+nL7uOgdi4kj8g7mDw8YMy8E+UhNdjl/YpNKyhdQTG5OkA2ha/X3iL/otY0JAoGBAM2E6orKtOiJuLHA+kZfp5BdSNpx5QYGtG+hnPuHspxmFHR8Kj5LgQgJwUsZ6aXtcxPpYOEERAjehJ66CIREHfsy2l1BPdtMPlHIPnnYWSrwtQg0T38VSzhIrFBenOcwg27EGiwPZGccw3JrgyWKRJ7zB5DILlC9306Hz4JNwtGH`
    25  	privKey2 crypto.PrivKey
    26  )
    27  
    28  func init() {
    29  	var err error
    30  	privKey1, err = key.DecodeB64PrivKey(testPk1)
    31  	if err != nil {
    32  		panic(err)
    33  	}
    34  	privKey2, err = key.DecodeB64PrivKey(testPk2)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  }
    39  
    40  func TestProfile(t *testing.T) {
    41  	s := httptest.NewServer(NewRoutes(registry.Registry{Profiles: registry.NewMemProfiles()}))
    42  
    43  	p1, err := registry.ProfileFromPrivateKey(&registry.Profile{Username: "b5"}, privKey1)
    44  	if err != nil {
    45  		t.Errorf("error generating profile: %s", err.Error())
    46  		return
    47  	}
    48  
    49  	p2, err := registry.ProfileFromPrivateKey(&registry.Profile{Username: "b5"}, privKey2)
    50  	if err != nil {
    51  		t.Errorf("error generating profile: %s", err.Error())
    52  		return
    53  	}
    54  
    55  	p1Rename, err := registry.ProfileFromPrivateKey(&registry.Profile{Username: "b6"}, privKey1)
    56  	if err != nil {
    57  		t.Errorf("error generating profile: %s", err.Error())
    58  		return
    59  	}
    60  
    61  	type env struct {
    62  		Data *registry.Profile
    63  		Meta struct {
    64  			Code int
    65  		}
    66  	}
    67  
    68  	b5 := &registry.Profile{
    69  		ProfileID: "QmZePf5LeXow3RW5U1AgEiNbW46YnRGhZ7HPvm1UmPFPwt",
    70  		Username:  "b5",
    71  		PublicKey: "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/7Q7fILQ8hc9g07a4HAiDKE4FahzL2eO8OlB1K99Ad4L1zc2dCg+gDVuGwdbOC29IngMA7O3UXijycckOSChgFyW3PafXoBF8Zg9MRBDIBo0lXRhW4TrVytm4Etzp4pQMyTeRYyWR8e2hGXeHArXM1R/A/SjzZUbjJYHhgvEE4OZy7WpcYcW6K3qqBGOU5GDMPuCcJWac2NgXzw6JeNsZuTimfVCJHupqG/dLPMnBOypR22dO7yJIaQ3d0PFLxiDG84X9YupF914RzJlopfdcuipI+6gFAgBw3vi6gbECEzcohjKf/4nqBOEvCDD6SXfl5F/MxoHurbGBYB2CJp+FAgMBAAE=",
    72  	}
    73  
    74  	b6 := &registry.Profile{
    75  		ProfileID: "QmZePf5LeXow3RW5U1AgEiNbW46YnRGhZ7HPvm1UmPFPwt",
    76  		Username:  "b6",
    77  		PublicKey: "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/7Q7fILQ8hc9g07a4HAiDKE4FahzL2eO8OlB1K99Ad4L1zc2dCg+gDVuGwdbOC29IngMA7O3UXijycckOSChgFyW3PafXoBF8Zg9MRBDIBo0lXRhW4TrVytm4Etzp4pQMyTeRYyWR8e2hGXeHArXM1R/A/SjzZUbjJYHhgvEE4OZy7WpcYcW6K3qqBGOU5GDMPuCcJWac2NgXzw6JeNsZuTimfVCJHupqG/dLPMnBOypR22dO7yJIaQ3d0PFLxiDG84X9YupF914RzJlopfdcuipI+6gFAgBw3vi6gbECEzcohjKf/4nqBOEvCDD6SXfl5F/MxoHurbGBYB2CJp+FAgMBAAE=",
    78  	}
    79  
    80  	cases := []struct {
    81  		method      string
    82  		contentType string
    83  		profile     *registry.Profile
    84  		resStatus   int
    85  		res         *env
    86  	}{
    87  		{"OPTIONS", "", nil, http.StatusBadRequest, nil},
    88  		{"OPTIONS", "application/json", nil, http.StatusBadRequest, nil},
    89  		{"OPTIONS", "application/json", &registry.Profile{Username: "foo"}, http.StatusNotFound, nil},
    90  		{"POST", "", nil, http.StatusBadRequest, nil},
    91  		{"POST", "application/json", nil, http.StatusBadRequest, nil},
    92  		{"POST", "application/json", &registry.Profile{Username: p1.Username}, http.StatusBadRequest, nil},
    93  		{"POST", "application/json", &registry.Profile{Username: p1.Username, ProfileID: p1.ProfileID}, http.StatusBadRequest, nil},
    94  		{"POST", "application/json", &registry.Profile{Username: p1.Username, ProfileID: p1.ProfileID, Signature: p1.Signature}, http.StatusBadRequest, nil},
    95  		{"POST", "application/json", p1, http.StatusOK, nil},
    96  		{"GET", "application/json", &registry.Profile{Username: b5.Username}, http.StatusOK, &env{Data: b5}},
    97  		{"GET", "application/json", &registry.Profile{Username: "b5"}, http.StatusOK, nil},
    98  		{"GET", "application/json", &registry.Profile{Username: "b6"}, http.StatusNotFound, nil},
    99  		{"GET", "application/json", &registry.Profile{ProfileID: b5.ProfileID}, http.StatusOK, nil},
   100  		{"GET", "application/json", &registry.Profile{ProfileID: "fooooo"}, http.StatusNotFound, nil},
   101  		{"POST", "application/json", p1, http.StatusOK, nil},
   102  		{"POST", "application/json", p2, http.StatusBadRequest, nil},
   103  		{"POST", "application/json", p1Rename, http.StatusOK, nil},
   104  		{"GET", "application/json", &registry.Profile{Username: b6.Username}, http.StatusOK, &env{Data: b6}},
   105  		{"DELETE", "", p1Rename, http.StatusBadRequest, nil},
   106  		{"DELETE", "application/json", nil, http.StatusBadRequest, nil},
   107  		{"DELETE", "application/json", &registry.Profile{Username: p1.Username, ProfileID: p1.ProfileID, Signature: p1.Signature}, http.StatusBadRequest, nil},
   108  		{"DELETE", "application/json", p1Rename, http.StatusOK, nil},
   109  	}
   110  
   111  	for i, c := range cases {
   112  		req, err := http.NewRequest(c.method, fmt.Sprintf("%s/registry/profile", s.URL), nil)
   113  		if err != nil {
   114  			t.Errorf("case %d error creating request: %s", i, err.Error())
   115  			continue
   116  		}
   117  
   118  		if c.contentType != "" {
   119  			req.Header.Set("Content-Type", c.contentType)
   120  		}
   121  		if c.profile != nil {
   122  			data, err := json.Marshal(c.profile)
   123  			if err != nil {
   124  				t.Errorf("error marshaling json body: %s", err.Error())
   125  				return
   126  			}
   127  			req.Body = ioutil.NopCloser(bytes.NewReader([]byte(data)))
   128  		}
   129  
   130  		res, err := http.DefaultClient.Do(req)
   131  		if res.StatusCode != c.resStatus {
   132  			t.Errorf("case %d res status mismatch. expected: %d, got: %d", i, c.resStatus, res.StatusCode)
   133  			continue
   134  		}
   135  
   136  		if c.res != nil {
   137  			e := &env{}
   138  			if err := json.NewDecoder(res.Body).Decode(e); err != nil {
   139  				t.Errorf("case %d error reading response body: %s", i, err.Error())
   140  				continue
   141  			}
   142  
   143  			// if len(e.Data) != len(c.res.Data) {
   144  			// 	t.Errorf("case %d reponse body mismatch. expected %d, got: %d", i, len(e.Data), len(c.res.Data))
   145  			// 	continue
   146  			// }
   147  			if e.Data.Username != c.res.Data.Username {
   148  				t.Errorf("case %d reponse username mismatch. expected %s, got: %s", i, e.Data.Username, c.res.Data.Username)
   149  			}
   150  
   151  			// TODO - check each response for profile matches
   152  		}
   153  	}
   154  }
   155  
   156  func TestProfiles(t *testing.T) {
   157  	s := httptest.NewServer(NewRoutes(registry.Registry{Profiles: registry.NewMemProfiles()}))
   158  
   159  	p1, err := registry.ProfileFromPrivateKey(&registry.Profile{Username: "b5"}, privKey1)
   160  	if err != nil {
   161  		t.Errorf("error generating profile: %s", err.Error())
   162  		return
   163  	}
   164  
   165  	p1Rename, err := registry.ProfileFromPrivateKey(&registry.Profile{Username: "b6"}, privKey1)
   166  	if err != nil {
   167  		t.Errorf("error generating profile: %s", err.Error())
   168  		return
   169  	}
   170  
   171  	type env struct {
   172  		Data []*registry.Profile
   173  		Meta struct {
   174  			Code int
   175  		}
   176  	}
   177  
   178  	b5 := &registry.Profile{
   179  		ProfileID: "QmZePf5LeXow3RW5U1AgEiNbW46YnRGhZ7HPvm1UmPFPwt",
   180  		Username:  "b5",
   181  		PublicKey: "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/7Q7fILQ8hc9g07a4HAiDKE4FahzL2eO8OlB1K99Ad4L1zc2dCg+gDVuGwdbOC29IngMA7O3UXijycckOSChgFyW3PafXoBF8Zg9MRBDIBo0lXRhW4TrVytm4Etzp4pQMyTeRYyWR8e2hGXeHArXM1R/A/SjzZUbjJYHhgvEE4OZy7WpcYcW6K3qqBGOU5GDMPuCcJWac2NgXzw6JeNsZuTimfVCJHupqG/dLPMnBOypR22dO7yJIaQ3d0PFLxiDG84X9YupF914RzJlopfdcuipI+6gFAgBw3vi6gbECEzcohjKf/4nqBOEvCDD6SXfl5F/MxoHurbGBYB2CJp+FAgMBAAE=",
   182  	}
   183  
   184  	b6 := &registry.Profile{
   185  		ProfileID: "QmZePf5LeXow3RW5U1AgEiNbW46YnRGhZ7HPvm1UmPFPwt",
   186  		Username:  "b6",
   187  		PublicKey: "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/7Q7fILQ8hc9g07a4HAiDKE4FahzL2eO8OlB1K99Ad4L1zc2dCg+gDVuGwdbOC29IngMA7O3UXijycckOSChgFyW3PafXoBF8Zg9MRBDIBo0lXRhW4TrVytm4Etzp4pQMyTeRYyWR8e2hGXeHArXM1R/A/SjzZUbjJYHhgvEE4OZy7WpcYcW6K3qqBGOU5GDMPuCcJWac2NgXzw6JeNsZuTimfVCJHupqG/dLPMnBOypR22dO7yJIaQ3d0PFLxiDG84X9YupF914RzJlopfdcuipI+6gFAgBw3vi6gbECEzcohjKf/4nqBOEvCDD6SXfl5F/MxoHurbGBYB2CJp+FAgMBAAE=",
   188  	}
   189  
   190  	cases := []struct {
   191  		method      string
   192  		endpoint    string
   193  		contentType string
   194  		profile     *registry.Profile
   195  		resStatus   int
   196  		res         *env
   197  	}{
   198  		{"GET", "/registry/profiles", "", nil, http.StatusOK, &env{}},
   199  		{"POST", "/registry/profile", "application/json", p1, http.StatusOK, nil},
   200  		{"GET", "/registry/profiles", "", nil, http.StatusOK, &env{Data: []*registry.Profile{b5}}},
   201  		{"POST", "/registry/profile", "application/json", p1Rename, http.StatusOK, nil},
   202  		{"GET", "/registry/profiles", "", nil, http.StatusOK, &env{Data: []*registry.Profile{b6}}},
   203  		{"DELETE", "/registry/profile", "application/json", p1Rename, http.StatusOK, nil},
   204  		{"GET", "/registry/profiles", "", nil, http.StatusOK, &env{Data: []*registry.Profile{}}},
   205  	}
   206  
   207  	for i, c := range cases {
   208  		req, err := http.NewRequest(c.method, fmt.Sprintf("%s%s", s.URL, c.endpoint), nil)
   209  		if err != nil {
   210  			t.Errorf("case %d error creating request: %s", i, err.Error())
   211  			continue
   212  		}
   213  
   214  		if c.contentType != "" {
   215  			req.Header.Set("Content-Type", c.contentType)
   216  		}
   217  		if c.profile != nil {
   218  			data, err := json.Marshal(c.profile)
   219  			if err != nil {
   220  				t.Errorf("error marshaling json body: %s", err.Error())
   221  				return
   222  			}
   223  			req.Body = ioutil.NopCloser(bytes.NewReader([]byte(data)))
   224  		}
   225  
   226  		res, err := http.DefaultClient.Do(req)
   227  		if res.StatusCode != c.resStatus {
   228  			t.Errorf("case %d res status mismatch. expected: %d, got: %d", i, c.resStatus, res.StatusCode)
   229  			continue
   230  		}
   231  
   232  		if c.res != nil {
   233  			e := &env{}
   234  			if err := json.NewDecoder(res.Body).Decode(e); err != nil {
   235  				t.Errorf("case %d error reading response body: %s", i, err.Error())
   236  				continue
   237  			}
   238  
   239  			if len(e.Data) != len(c.res.Data) {
   240  				t.Errorf("case %d reponse body mismatch. expected %d, got: %d", i, len(e.Data), len(c.res.Data))
   241  				continue
   242  			}
   243  
   244  			// TODO - check each response for profile matches
   245  		}
   246  	}
   247  }
   248  
   249  func TestPostProfiles(t *testing.T) {
   250  	un := "username"
   251  	pw := "password"
   252  	s := httptest.NewServer(NewRoutes(registry.Registry{Profiles: registry.NewMemProfiles()}, AddProtector(NewBAProtector(un, pw))))
   253  	const profiles = `[
   254  	{
   255      "ProfileID": "QmamJUR83rGtDMEvugcC2gtLDx2nhZUTzpzhH6MA2Pb3Md",
   256      "Handle": "EDGI",
   257      "PublicKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmTFRx/6dKmoxje8AG+jFv94IcGUGnjrupa7XEr12J/c4ZLn3aPrD8F0tjRbstt1y/J+bO7Qb69DGiu2iSIqyE21nl2oex5+14jtxbupRq9jRTbpUHRj+y9I7uUDwl0E2FS1IQpBBfEGzDPIBVavxbhguC3O3XA7Aq7vea2lpJ1tWpr0GDRYSNmJAybkHS6k7dz1eVXFK+JE8FGFJi/AThQZKWRijvWFdlZvb8RyNFRHzpbr9fh38bRMTqhZpw/YGO5Ly8PNSiOOE4Y5cNUHLEYwG2/lpT4l53iKScsaOazlRkJ6NmkM1il7riCa55fcIAQZDtaAx+CT5ZKfmek4P5AgMBAAE=",
   258      "Created": "2018-05-01T22:31:18.288004308Z"
   259    },
   260    {
   261      "ProfileID": "QmSyDX5LYTiwQi861F5NAwdHrrnd1iRGsoEvCyzQMUyZ4W",
   262      "Handle": "b5",
   263      "PublicKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/W17VPFX+pjyM1MHI1CsvIe+JYQX45MJNITTd7hZZDX2rRWVavGXhsccmVDGU6ubeN3t6ewcBlgCxvyewwKhmZKCAs3/0xNGKXK/YMyZpRVjTWw9yPU9gOzjd9GuNJtL7d1Hl7dPt9oECa7WBCh0W9u2IoHTda4g8B2mK92awLOZTjXeA7vbhKKX+QVHKDxEI0U2/ooLYJUVxEoHRc+DUYNPahX5qRgJ1ZDP4ep1RRRoZR+HjGhwgJP+IwnAnO5cRCWUbZvE1UBJUZDvYMqW3QvDp+TtXwqUWVvt69tp8EnlBgfyXU91A58IEQtLgZ7klOzdSEJDP+S8HIwhG/vbTAgMBAAE=",
   264      "Created": "2018-04-19T22:10:49.909268968Z"
   265    }
   266  ]`
   267  
   268  	req, err := http.NewRequest("POST", fmt.Sprintf("%s/registry/profiles", s.URL), strings.NewReader(profiles))
   269  	if err != nil {
   270  		t.Error(err.Error())
   271  		return
   272  	}
   273  
   274  	req.Header.Set("Content-Type", "application/json")
   275  	req.SetBasicAuth(un, pw)
   276  
   277  	res, err := http.DefaultClient.Do(req)
   278  	if err != nil {
   279  		t.Error(err.Error())
   280  	}
   281  
   282  	if res.StatusCode != 200 {
   283  		t.Errorf("response status mismatch. expected 200, got: %d", res.StatusCode)
   284  	}
   285  
   286  }