github.com/ghodss/etcd@v0.3.1-0.20140417172404-cc329bfa55cb/server/v2/tests/get_handler_test.go (about)

     1  package v2
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/coreos/etcd/server"
    11  	"github.com/coreos/etcd/tests"
    12  	"github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"
    13  )
    14  
    15  // Ensures that a value can be retrieve for a given key.
    16  //
    17  //   $ curl localhost:4001/v2/keys/foo/bar -> fail
    18  //   $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
    19  //   $ curl localhost:4001/v2/keys/foo/bar
    20  //
    21  func TestV2GetKey(t *testing.T) {
    22  	tests.RunServer(func(s *server.Server) {
    23  		v := url.Values{}
    24  		v.Set("value", "XXX")
    25  		fullURL := fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar")
    26  		resp, _ := tests.Get(fullURL)
    27  		assert.Equal(t, resp.StatusCode, http.StatusNotFound)
    28  
    29  		resp, _ = tests.PutForm(fullURL, v)
    30  		tests.ReadBody(resp)
    31  
    32  		resp, _ = tests.Get(fullURL)
    33  		assert.Equal(t, resp.StatusCode, http.StatusOK)
    34  		body := tests.ReadBodyJSON(resp)
    35  		assert.Equal(t, body["action"], "get", "")
    36  		node := body["node"].(map[string]interface{})
    37  		assert.Equal(t, node["key"], "/foo/bar", "")
    38  		assert.Equal(t, node["value"], "XXX", "")
    39  		assert.Equal(t, node["modifiedIndex"], 2, "")
    40  	})
    41  }
    42  
    43  // Ensures that a directory of values can be recursively retrieved for a given key.
    44  //
    45  //   $ curl -X PUT localhost:4001/v2/keys/foo/x -d value=XXX
    46  //   $ curl -X PUT localhost:4001/v2/keys/foo/y/z -d value=YYY
    47  //   $ curl localhost:4001/v2/keys/foo -d recursive=true
    48  //
    49  func TestV2GetKeyRecursively(t *testing.T) {
    50  	tests.RunServer(func(s *server.Server) {
    51  		v := url.Values{}
    52  		v.Set("value", "XXX")
    53  		v.Set("ttl", "10")
    54  		resp, _ := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/x"), v)
    55  		tests.ReadBody(resp)
    56  
    57  		v.Set("value", "YYY")
    58  		resp, _ = tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/y/z"), v)
    59  		tests.ReadBody(resp)
    60  
    61  		resp, _ = tests.Get(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?recursive=true"))
    62  		assert.Equal(t, resp.StatusCode, http.StatusOK)
    63  		body := tests.ReadBodyJSON(resp)
    64  		assert.Equal(t, body["action"], "get", "")
    65  		node := body["node"].(map[string]interface{})
    66  		assert.Equal(t, node["key"], "/foo", "")
    67  		assert.Equal(t, node["dir"], true, "")
    68  		assert.Equal(t, node["modifiedIndex"], 2, "")
    69  		assert.Equal(t, len(node["nodes"].([]interface{})), 2, "")
    70  
    71  		node0 := node["nodes"].([]interface{})[0].(map[string]interface{})
    72  		assert.Equal(t, node0["key"], "/foo/x", "")
    73  		assert.Equal(t, node0["value"], "XXX", "")
    74  		assert.Equal(t, node0["ttl"], 10, "")
    75  
    76  		node1 := node["nodes"].([]interface{})[1].(map[string]interface{})
    77  		assert.Equal(t, node1["key"], "/foo/y", "")
    78  		assert.Equal(t, node1["dir"], true, "")
    79  
    80  		node2 := node1["nodes"].([]interface{})[0].(map[string]interface{})
    81  		assert.Equal(t, node2["key"], "/foo/y/z", "")
    82  		assert.Equal(t, node2["value"], "YYY", "")
    83  	})
    84  }
    85  
    86  // Ensures that a watcher can wait for a value to be set and return it to the client.
    87  //
    88  //   $ curl localhost:4001/v2/keys/foo/bar?wait=true
    89  //   $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
    90  //
    91  func TestV2WatchKey(t *testing.T) {
    92  	tests.RunServer(func(s *server.Server) {
    93  		var watchResp *http.Response
    94  		c := make(chan bool)
    95  		go func() {
    96  			watchResp, _ = tests.Get(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar?wait=true"))
    97  			c <- true
    98  		}()
    99  
   100  		// Make sure response didn't fire early.
   101  		time.Sleep(1 * time.Millisecond)
   102  
   103  		// Set a value.
   104  		v := url.Values{}
   105  		v.Set("value", "XXX")
   106  		resp, _ := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar"), v)
   107  		tests.ReadBody(resp)
   108  
   109  		// A response should follow from the GET above.
   110  		time.Sleep(1 * time.Millisecond)
   111  
   112  		select {
   113  		case <-c:
   114  
   115  		default:
   116  			t.Fatal("cannot get watch result")
   117  		}
   118  
   119  		body := tests.ReadBodyJSON(watchResp)
   120  		assert.NotNil(t, body, "")
   121  		assert.Equal(t, body["action"], "set", "")
   122  
   123  		node := body["node"].(map[string]interface{})
   124  		assert.Equal(t, node["key"], "/foo/bar", "")
   125  		assert.Equal(t, node["value"], "XXX", "")
   126  		assert.Equal(t, node["modifiedIndex"], 2, "")
   127  	})
   128  }
   129  
   130  // Ensures that a watcher can wait for a value to be set after a given index.
   131  //
   132  //   $ curl localhost:4001/v2/keys/foo/bar?wait=true&waitIndex=4
   133  //   $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
   134  //   $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=YYY
   135  //
   136  func TestV2WatchKeyWithIndex(t *testing.T) {
   137  	tests.RunServer(func(s *server.Server) {
   138  		var body map[string]interface{}
   139  		c := make(chan bool)
   140  		go func() {
   141  			resp, _ := tests.Get(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar?wait=true&waitIndex=3"))
   142  			body = tests.ReadBodyJSON(resp)
   143  			c <- true
   144  		}()
   145  
   146  		// Make sure response didn't fire early.
   147  		time.Sleep(1 * time.Millisecond)
   148  		assert.Nil(t, body, "")
   149  
   150  		// Set a value (before given index).
   151  		v := url.Values{}
   152  		v.Set("value", "XXX")
   153  		resp, _ := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar"), v)
   154  		tests.ReadBody(resp)
   155  
   156  		// Make sure response didn't fire early.
   157  		time.Sleep(1 * time.Millisecond)
   158  		assert.Nil(t, body, "")
   159  
   160  		// Set a value (before given index).
   161  		v.Set("value", "YYY")
   162  		resp, _ = tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar"), v)
   163  		tests.ReadBody(resp)
   164  
   165  		// A response should follow from the GET above.
   166  		time.Sleep(1 * time.Millisecond)
   167  
   168  		select {
   169  		case <-c:
   170  
   171  		default:
   172  			t.Fatal("cannot get watch result")
   173  		}
   174  
   175  		assert.NotNil(t, body, "")
   176  		assert.Equal(t, body["action"], "set", "")
   177  
   178  		node := body["node"].(map[string]interface{})
   179  		assert.Equal(t, node["key"], "/foo/bar", "")
   180  		assert.Equal(t, node["value"], "YYY", "")
   181  		assert.Equal(t, node["modifiedIndex"], 3, "")
   182  	})
   183  }
   184  
   185  // Ensures that a watcher can wait for a value to be set after a given index.
   186  //
   187  //   $ curl localhost:4001/v2/keys/keyindir/bar?wait=true
   188  //   $ curl -X PUT localhost:4001/v2/keys/keyindir -d dir=true -d ttl=1
   189  //   $ curl -X PUT localhost:4001/v2/keys/keyindir/bar -d value=YYY
   190  //
   191  func TestV2WatchKeyInDir(t *testing.T) {
   192  	tests.RunServer(func(s *server.Server) {
   193  		var body map[string]interface{}
   194  		c := make(chan bool)
   195  
   196  		// Set a value (before given index).
   197  		v := url.Values{}
   198  		v.Set("dir", "true")
   199  		v.Set("ttl", "1")
   200  		resp, _ := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/keyindir"), v)
   201  		tests.ReadBody(resp)
   202  
   203  		// Set a value (before given index).
   204  		v = url.Values{}
   205  		v.Set("value", "XXX")
   206  		resp, _ = tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/keyindir/bar"), v)
   207  		tests.ReadBody(resp)
   208  
   209  		go func() {
   210  			resp, _ := tests.Get(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/keyindir/bar?wait=true"))
   211  			body = tests.ReadBodyJSON(resp)
   212  			c <- true
   213  		}()
   214  
   215  		// wait for expiration, we do have a up to 500 millisecond delay
   216  		time.Sleep(2000 * time.Millisecond)
   217  
   218  		select {
   219  		case <-c:
   220  
   221  		default:
   222  			t.Fatal("cannot get watch result")
   223  		}
   224  
   225  		assert.NotNil(t, body, "")
   226  		assert.Equal(t, body["action"], "expire", "")
   227  
   228  		node := body["node"].(map[string]interface{})
   229  		assert.Equal(t, node["key"], "/keyindir", "")
   230  	})
   231  }
   232  
   233  // Ensures that HEAD could work.
   234  //
   235  //   $ curl -I localhost:4001/v2/keys/foo/bar -> fail
   236  //   $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
   237  //   $ curl -I localhost:4001/v2/keys/foo/bar
   238  //
   239  func TestV2HeadKey(t *testing.T) {
   240  	tests.RunServer(func(s *server.Server) {
   241  		v := url.Values{}
   242  		v.Set("value", "XXX")
   243  		fullURL := fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar")
   244  		resp, _ := tests.Head(fullURL)
   245  		assert.Equal(t, resp.StatusCode, http.StatusNotFound)
   246  		assert.Equal(t, resp.ContentLength, -1)
   247  
   248  		resp, _ = tests.PutForm(fullURL, v)
   249  		tests.ReadBody(resp)
   250  
   251  		resp, _ = tests.Head(fullURL)
   252  		assert.Equal(t, resp.StatusCode, http.StatusOK)
   253  		assert.Equal(t, resp.ContentLength, -1)
   254  	})
   255  }