1 // This file is part of OpenTSDB.
2 // Copyright (C) 2013  The OpenTSDB Authors.
3 //
4 // This program is free software: you can redistribute it and/or modify it
5 // under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 2.1 of the License, or (at your
7 // option) any later version.  This program is distributed in the hope that it
8 // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
10 // General Public License for more details.  You should have received a copy
11 // of the GNU Lesser General Public License along with this program.  If not,
12 // see <http://www.gnu.org/licenses/>.
13 package net.opentsdb.tsd;
14 
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertTrue;
17 import static org.mockito.Mockito.doThrow;
18 import static org.mockito.Mockito.when;
19 import static org.powermock.api.mockito.PowerMockito.mock;
20 
21 import java.lang.reflect.Field;
22 import java.nio.charset.Charset;
23 import java.util.ArrayList;
24 import java.util.List;
25 
26 import net.opentsdb.core.TSDB;
27 import net.opentsdb.meta.TSMeta;
28 import net.opentsdb.meta.UIDMeta;
29 import net.opentsdb.storage.MockBase;
30 import net.opentsdb.uid.UniqueId;
31 import net.opentsdb.uid.UniqueId.UniqueIdType;
32 import net.opentsdb.utils.Config;
33 
34 import org.hbase.async.Bytes;
35 import org.hbase.async.GetRequest;
36 import org.hbase.async.HBaseClient;
37 import org.hbase.async.KeyValue;
38 import org.hbase.async.RowLock;
39 import org.hbase.async.Scanner;
40 import org.jboss.netty.handler.codec.http.HttpResponseStatus;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.powermock.core.classloader.annotations.PowerMockIgnore;
45 import org.powermock.core.classloader.annotations.PrepareForTest;
46 import org.powermock.modules.junit4.PowerMockRunner;
47 
48 import com.stumbleupon.async.Deferred;
49 
50 @PowerMockIgnore({"javax.management.*", "javax.xml.*",
51   "ch.qos.*", "org.slf4j.*",
52   "com.sum.*", "org.xml.*"})
53 @RunWith(PowerMockRunner.class)
54 @PrepareForTest({TSDB.class, Config.class, TSMeta.class, UIDMeta.class,
55   HBaseClient.class, RowLock.class, UniqueIdRpc.class, KeyValue.class,
56   GetRequest.class, Scanner.class, UniqueId.class})
57 public final class TestUniqueIdRpc {
58   private final static byte[] NAME_FAMILY = "name".getBytes(MockBase.ASCII());
59   private final static byte[] UID_TABLE = "tsdb-uid".getBytes(MockBase.ASCII());
60   private final static byte[] META_TABLE = "tsdb-meta".getBytes();
61   private TSDB tsdb = null;
62   private HBaseClient client = mock(HBaseClient.class);
63   private UniqueId metrics = mock(UniqueId.class);
64   private UniqueId tag_names = mock(UniqueId.class);
65   private UniqueId tag_values = mock(UniqueId.class);
66   private MockBase storage;
67   private UniqueIdRpc rpc = new UniqueIdRpc();
68 
69   @Before
before()70   public void before() throws Exception {
71     tsdb = NettyMocks.getMockedHTTPTSDB();
72   }
73 
74   @Test
constructor()75   public void constructor() throws Exception {
76     new TestUniqueIdRpc();
77   }
78 
79   @Test (expected = BadRequestException.class)
badMethod()80   public void badMethod() throws Exception {
81     HttpQuery query = NettyMocks.getQuery(tsdb, "/api/uid/assign");
82     rpc.execute(tsdb, query);
83   }
84 
85   @Test (expected = BadRequestException.class)
notImplemented()86   public void notImplemented() throws Exception {
87     HttpQuery query = NettyMocks.getQuery(tsdb, "/api/uid");
88     this.rpc.execute(tsdb, query);
89   }
90 
91   // Test /api/uid/assign ----------------------
92 
93   @Test
assignQsMetricSingle()94   public void assignQsMetricSingle() throws Exception {
95     setupAssign();
96     HttpQuery query = NettyMocks.getQuery(tsdb,
97         "/api/uid/assign?metric=sys.cpu.0");
98     this.rpc.execute(tsdb, query);
99     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
100     assertEquals("{\"metric\":{\"sys.cpu.0\":\"000001\"}}",
101         query.response().getContent().toString(Charset.forName("UTF-8")));
102   }
103 
104   @Test
assignQsMetricDouble()105   public void assignQsMetricDouble() throws Exception {
106     setupAssign();
107     HttpQuery query = NettyMocks.getQuery(tsdb,
108         "/api/uid/assign?metric=sys.cpu.0,sys.cpu.2");
109     this.rpc.execute(tsdb, query);
110     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
111     final String json = query.response().getContent()
112         .toString(Charset.forName("UTF-8"));
113     assertTrue(json.contains("\"sys.cpu.0\":\"000001\""));
114     assertTrue(json.contains("\"sys.cpu.2\":\"000003\""));
115   }
116 
117   @Test
assignQsMetricSingleBad()118   public void assignQsMetricSingleBad() throws Exception {
119     setupAssign();
120     HttpQuery query = NettyMocks.getQuery(tsdb,
121         "/api/uid/assign?metric=sys.cpu.1");
122     this.rpc.execute(tsdb, query);
123     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
124     final String json = query.response().getContent()
125         .toString(Charset.forName("UTF-8"));
126     assertTrue(json.contains("{\"sys.cpu.1\":\"Name already exists with "
127         + "UID: 000002\"}"));
128   }
129 
130   @Test
assignQsMetric2Good1Bad()131   public void assignQsMetric2Good1Bad() throws Exception {
132     setupAssign();
133     HttpQuery query = NettyMocks.getQuery(tsdb,
134         "/api/uid/assign?metric=sys.cpu.0,sys.cpu.1,sys.cpu.2");
135     this.rpc.execute(tsdb, query);
136     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
137     final String json = query.response().getContent()
138         .toString(Charset.forName("UTF-8"));
139     assertTrue(json.contains("{\"sys.cpu.1\":\"Name already exists with "
140         + "UID: 000002\"}"));
141     assertTrue(json.contains("{\"sys.cpu.0\":\"000001\",\"sys.cpu.2\":"
142         + "\"000003\"}"));
143   }
144 
145   @Test
assignQsTagkSingle()146   public void assignQsTagkSingle() throws Exception {
147     setupAssign();
148     HttpQuery query = NettyMocks.getQuery(tsdb,
149         "/api/uid/assign?tagk=host");
150     this.rpc.execute(tsdb, query);
151     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
152     assertEquals("{\"tagk\":{\"host\":\"000001\"}}",
153         query.response().getContent().toString(Charset.forName("UTF-8")));
154   }
155 
156   @Test
assignQsTagkDouble()157   public void assignQsTagkDouble() throws Exception {
158     setupAssign();
159     HttpQuery query = NettyMocks.getQuery(tsdb,
160         "/api/uid/assign?tagk=host,fqdn");
161     this.rpc.execute(tsdb, query);
162     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
163     final String json = query.response().getContent()
164         .toString(Charset.forName("UTF-8"));
165     assertTrue(json.contains("\"fqdn\":\"000003\""));
166     assertTrue(json.contains("\"host\":\"000001\""));
167   }
168 
169   @Test
assignQsTagkSingleBad()170   public void assignQsTagkSingleBad() throws Exception {
171     setupAssign();
172     HttpQuery query = NettyMocks.getQuery(tsdb,
173         "/api/uid/assign?tagk=datacenter");
174     this.rpc.execute(tsdb, query);
175     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
176     final String json = query.response().getContent()
177         .toString(Charset.forName("UTF-8"));
178     assertTrue(json.contains("\"tagk_errors\":{\"datacenter\":"
179         + "\"Name already exists with UID: 000002\"}"));
180   }
181 
182   @Test
assignQsTagk2Good1Bad()183   public void assignQsTagk2Good1Bad() throws Exception {
184     setupAssign();
185     HttpQuery query = NettyMocks.getQuery(tsdb,
186         "/api/uid/assign?tagk=host,datacenter,fqdn");
187     this.rpc.execute(tsdb, query);
188     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
189     final String json = query.response().getContent()
190         .toString(Charset.forName("UTF-8"));
191     assertTrue(json.contains("{\"datacenter\":\"Name already exists with "
192         + "UID: 000002\"}"));
193     assertTrue(json.contains("\"fqdn\":\"000003\""));
194     assertTrue(json.contains("\"host\":\"000001\""));
195   }
196 
197   @Test
assignQsTagvSingle()198   public void assignQsTagvSingle() throws Exception {
199     setupAssign();
200     HttpQuery query = NettyMocks.getQuery(tsdb,
201         "/api/uid/assign?tagv=localhost");
202     this.rpc.execute(tsdb, query);
203     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
204     assertEquals("{\"tagv\":{\"localhost\":\"000001\"}}",
205         query.response().getContent().toString(Charset.forName("UTF-8")));
206   }
207 
208   @Test
assignQsTagvDouble()209   public void assignQsTagvDouble() throws Exception {
210     setupAssign();
211     HttpQuery query = NettyMocks.getQuery(tsdb,
212         "/api/uid/assign?tagv=localhost,foo");
213     this.rpc.execute(tsdb, query);
214     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
215     final String json = query.response().getContent()
216         .toString(Charset.forName("UTF-8"));
217     assertTrue(json.contains("\"foo\":\"000003\""));
218     assertTrue(json.contains("\"localhost\":\"000001\""));
219   }
220 
221   @Test
assignQsTagvSingleBad()222   public void assignQsTagvSingleBad() throws Exception {
223     setupAssign();
224     HttpQuery query = NettyMocks.getQuery(tsdb,
225         "/api/uid/assign?tagv=myserver");
226     this.rpc.execute(tsdb, query);
227     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
228     final String json = query.response().getContent()
229         .toString(Charset.forName("UTF-8"));
230     assertTrue(json.contains("\"tagv_errors\":{\"myserver\":\"Name already "
231         + "exists with UID: 000002\"}"));
232   }
233 
234   @Test
assignQsTagv2Good1Bad()235   public void assignQsTagv2Good1Bad() throws Exception {
236     setupAssign();
237     HttpQuery query = NettyMocks.getQuery(tsdb,
238         "/api/uid/assign?tagv=localhost,myserver,foo");
239     this.rpc.execute(tsdb, query);
240     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
241     final String json = query.response().getContent()
242         .toString(Charset.forName("UTF-8"));
243     assertTrue(json.contains("\"foo\":\"000003\""));
244     assertTrue(json.contains("\"localhost\":\"000001\""));
245     assertTrue(json.contains("{\"myserver\":\"Name already exists with "
246         + "UID: 000002\"}"));
247   }
248 
249   @Test
assignQsFull()250   public void assignQsFull() throws Exception {
251     setupAssign();
252     HttpQuery query = NettyMocks.getQuery(tsdb,
253         "/api/uid/assign?tagv=localhost,foo" +
254         "&metric=sys.cpu.0,sys.cpu.2" +
255         "&tagk=host,fqdn");
256     this.rpc.execute(tsdb, query);
257     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
258     // contents may shift in flight, hence no parsing
259   }
260 
261   @Test
assignQsFullBad()262   public void assignQsFullBad() throws Exception {
263     setupAssign();
264     HttpQuery query = NettyMocks.getQuery(tsdb,
265         "/api/uid/assign?tagv=localhost,myserver,foo" +
266         "&metric=sys.cpu.0,sys.cpu.1,sys.cpu.2" +
267         "&tagk=host,datacenter,fqdn");
268     this.rpc.execute(tsdb, query);
269     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
270     // contents may shift in flight, hence no parsing
271   }
272 
273   @Test (expected = BadRequestException.class)
assignQsNoParamValue()274   public void assignQsNoParamValue() throws Exception {
275     setupAssign();
276     HttpQuery query = NettyMocks.getQuery(tsdb,
277         "/api/uid/assign?tagv=");
278     this.rpc.execute(tsdb, query);
279   }
280 
281   @Test (expected = BadRequestException.class)
assignQsEmpty()282   public void assignQsEmpty() throws Exception {
283     setupAssign();
284     HttpQuery query = NettyMocks.getQuery(tsdb,
285         "/api/uid/assign");
286     this.rpc.execute(tsdb, query);
287   }
288 
289   @Test (expected = BadRequestException.class)
assignQsTypo()290   public void assignQsTypo() throws Exception {
291     setupAssign();
292     HttpQuery query = NettyMocks.getQuery(tsdb,
293         "/api/uid/assign/metrics=hello");
294     this.rpc.execute(tsdb, query);
295   }
296 
297   @Test
assignPostMetricSingle()298   public void assignPostMetricSingle() throws Exception {
299     setupAssign();
300     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
301         "{\"metric\":[\"sys.cpu.0\"]}");
302     this.rpc.execute(tsdb, query);
303     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
304     assertEquals("{\"metric\":{\"sys.cpu.0\":\"000001\"}}",
305         query.response().getContent().toString(Charset.forName("UTF-8")));
306   }
307 
assignPostMetricDouble()308   public void assignPostMetricDouble() throws Exception {
309     setupAssign();
310     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
311     "{\"metric\":[\"sys.cpu.0\",\"sys.cpu.2\"]}");
312     this.rpc.execute(tsdb, query);
313     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
314     final String json = query.response().getContent()
315         .toString(Charset.forName("UTF-8"));
316     assertTrue(json.contains("\"sys.cpu.0\":\"000001\""));
317     assertTrue(json.contains("\"sys.cpu.2\":\"000003\""));
318   }
319 
assignPostMetricSingleBad()320   public void assignPostMetricSingleBad() throws Exception {
321     setupAssign();
322     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
323     "{\"metric\":[\"sys.cpu.2\"]}");
324     this.rpc.execute(tsdb, query);
325     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
326     final String json = query.response().getContent()
327         .toString(Charset.forName("UTF-8"));
328     assertTrue(json.contains("{\"sys.cpu.1\":\"Name already exists with "
329         + "UID: 000002\"}"));
330   }
331 
assignPostMetric2Good1Bad()332   public void assignPostMetric2Good1Bad() throws Exception {
333     setupAssign();
334     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
335     "{\"metric\":[\"sys.cpu.0\",\"sys.cpu.1\",\"sys.cpu.2\"]}");
336     this.rpc.execute(tsdb, query);
337     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
338     final String json = query.response().getContent()
339         .toString(Charset.forName("UTF-8"));
340     assertTrue(json.contains("{\"sys.cpu.1\":\"Name already exists with "
341         + "UID: 000002\"}"));
342     assertTrue(json.contains("\"sys.cpu.0\":\"000001\""));
343     assertTrue(json.contains("\"sys.cpu.2\":\"000003\""));
344   }
345 
346   @Test
assignPostTagkSingle()347   public void assignPostTagkSingle() throws Exception {
348     setupAssign();
349     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
350         "{\"tagk\":[\"host\"]}");
351     this.rpc.execute(tsdb, query);
352     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
353     assertEquals("{\"tagk\":{\"host\":\"000001\"}}",
354         query.response().getContent().toString(Charset.forName("UTF-8")));
355   }
356 
assignPostTagkDouble()357   public void assignPostTagkDouble() throws Exception {
358     setupAssign();
359     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
360     "{\"tagk\":[\"host\",\"fqdn\"]}");
361     this.rpc.execute(tsdb, query);
362     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
363     final String json = query.response().getContent()
364         .toString(Charset.forName("UTF-8"));
365     assertTrue(json.contains("\"fqdn\":\"000003\""));
366     assertTrue(json.contains("\"host\":\"000001\""));
367   }
368 
assignPostTagkSingleBad()369   public void assignPostTagkSingleBad() throws Exception {
370     setupAssign();
371     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
372     "{\"tagk\":[\"datacenter\"]}");
373     this.rpc.execute(tsdb, query);
374     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
375     final String json = query.response().getContent()
376         .toString(Charset.forName("UTF-8"));
377     assertTrue(json.contains("\"datacenter\":\"Name already exists with "
378         + "UID: 000002\""));
379   }
380 
assignPostTagk2Good1Bad()381   public void assignPostTagk2Good1Bad() throws Exception {
382     setupAssign();
383     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
384     "{\"tagk\":[\"host\",\"datacenter\",\"fqdn\"]}");
385     this.rpc.execute(tsdb, query);
386     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
387     final String json = query.response().getContent()
388         .toString(Charset.forName("UTF-8"));
389     assertTrue(json.contains("{\"datacenter\":\"Name already exists with "
390         + "UID: 000002\"}"));
391     assertTrue(json.contains("\"fqdn\":\"000003\""));
392     assertTrue(json.contains("\"host\":\"000001\""));
393   }
394 
395   @Test
assignPostTagvSingle()396   public void assignPostTagvSingle() throws Exception {
397     setupAssign();
398     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
399         "{\"tagv\":[\"localhost\"]}");
400     this.rpc.execute(tsdb, query);
401     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
402     assertEquals("{\"tagv\":{\"localhost\":\"000001\"}}",
403         query.response().getContent().toString(Charset.forName("UTF-8")));
404   }
405 
assignPostTagvDouble()406   public void assignPostTagvDouble() throws Exception {
407     setupAssign();
408     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
409     "{\"tagv\":[\"localhost\",\"foo\"]}");
410     this.rpc.execute(tsdb, query);
411     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
412     final String json = query.response().getContent()
413         .toString(Charset.forName("UTF-8"));
414     assertTrue(json.contains("\"foo\":\"000003\""));
415     assertTrue(json.contains("\"localhost\":\"000001\""));
416   }
417 
assignPostTagvSingleBad()418   public void assignPostTagvSingleBad() throws Exception {
419     setupAssign();
420     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
421     "{\"tagv\":[\"myserver\"]}");
422     this.rpc.execute(tsdb, query);
423     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
424     final String json = query.response().getContent()
425         .toString(Charset.forName("UTF-8"));
426     assertTrue(json.contains("\"tagv_errors\":{\"myserver\":\"Name already "
427         + "exists with UID: 000002\"}"));
428   }
429 
assignPostTagv2Good1Bad()430   public void assignPostTagv2Good1Bad() throws Exception {
431     setupAssign();
432     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
433     "{\"tagv\":[\"localhost\",\"myserver\",\"foo\"]}");
434     this.rpc.execute(tsdb, query);
435     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
436     final String json = query.response().getContent()
437         .toString(Charset.forName("UTF-8"));
438     assertTrue(json.contains("\"foo\":\"000003\""));
439     assertTrue(json.contains("\"localhost\":\"000001\""));
440     assertTrue(json.contains("\"tagv_errors\":{\"myserver\":\"Name already exists with "
441         + "UID: 000002\"}"));
442   }
443 
444   @Test
assignPostFull()445   public void assignPostFull() throws Exception {
446     setupAssign();
447     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
448         "{\"tagv\":[\"localhost\",\"foo\"],"
449         + "\"metric\":[\"sys.cpu.0\",\"sys.cpu.2\"],"
450         + "\"tagk\":[\"host\",\"fqdn\"]}");
451     this.rpc.execute(tsdb, query);
452     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
453     // contents may shift in flight, hence no parsing
454   }
455 
456   @Test
assignPostFullBad()457   public void assignPostFullBad() throws Exception {
458     setupAssign();
459     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
460         "{\"tagv\":[\"localhost\",\"myserver\",\"foo\"],"
461         + "\"metric\":[\"sys.cpu.0\",\"sys.cpu.1\",\"sys.cpu.2\"],"
462         + "\"tagk\":[\"host\",\"datacenter\",\"fqdn\"]}");
463     this.rpc.execute(tsdb, query);
464     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
465     // contents may shift in flight, hence no parsing
466   }
467 
468   @Test (expected = BadRequestException.class)
assignPostBadJSON()469   public void assignPostBadJSON() throws Exception {
470     setupAssign();
471     // missing a quotation mark
472     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign",
473         "{\"tagv\":[\"localhost\",myserver\",\"foo\"],"
474         + "\"metric\":[\"sys.cpu.0\",\"sys.cpu.1\",\"sys.cpu.2\"],"
475         + "\"tagk\":[\"host\",\"datacenter\",\"fqdn\"]}");
476     this.rpc.execute(tsdb, query);
477   }
478 
479   @Test (expected = BadRequestException.class)
assignPostNotJSON()480   public void assignPostNotJSON() throws Exception {
481     setupAssign();
482     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign", "Hello");
483     this.rpc.execute(tsdb, query);
484   }
485 
486   @Test (expected = BadRequestException.class)
assignPostNoContent()487   public void assignPostNoContent() throws Exception {
488     setupAssign();
489     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign", "");
490     this.rpc.execute(tsdb, query);
491   }
492 
493   @Test (expected = BadRequestException.class)
assignPostEmptyJSON()494   public void assignPostEmptyJSON() throws Exception {
495     setupAssign();
496     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/assign", "{}");
497     this.rpc.execute(tsdb, query);
498   }
499 
500   @Test
stringToUniqueIdTypeMetric()501   public void stringToUniqueIdTypeMetric() throws Exception {
502     setupAssign();
503     assertEquals(UniqueIdType.METRIC, UniqueId.stringToUniqueIdType("Metric"));
504   }
505 
506   @Test
stringToUniqueIdTypeTagk()507   public void stringToUniqueIdTypeTagk() throws Exception {
508     setupAssign();
509     assertEquals(UniqueIdType.TAGK, UniqueId.stringToUniqueIdType("TagK"));
510   }
511 
512   @Test
stringToUniqueIdTypeTagv()513   public void stringToUniqueIdTypeTagv() throws Exception {
514     setupAssign();
515     assertEquals(UniqueIdType.TAGV, UniqueId.stringToUniqueIdType("TagV"));
516   }
517 
518   @Test (expected = NullPointerException.class)
stringToUniqueIdTypeNull()519   public void stringToUniqueIdTypeNull() throws Exception {
520     setupAssign();
521     UniqueId.stringToUniqueIdType(null);
522   }
523 
524   @Test (expected = IllegalArgumentException.class)
stringToUniqueIdTypeEmpty()525   public void stringToUniqueIdTypeEmpty() throws Exception {
526     setupAssign();
527     UniqueId.stringToUniqueIdType("");
528   }
529 
530   @Test (expected = IllegalArgumentException.class)
stringToUniqueIdTypeInvalid()531   public void stringToUniqueIdTypeInvalid() throws Exception {setupAssign();
532     UniqueId.stringToUniqueIdType("Not a type");
533   }
534 
535   // Test /api/uid/rename ----------------------
536 
537   @Test (expected = BadRequestException.class)
renameBadMethod()538   public void renameBadMethod() throws Exception {
539     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/rename", "");
540     rpc.execute(tsdb, query);
541   }
542 
543   @Test
renamePostMetric()544   public void renamePostMetric() throws Exception {
545     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename",
546         "{\"metric\":\"sys.cpu.1\",\"name\":\"sys.cpu.2\"}");
547     rpc.execute(tsdb, query);
548     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
549     assertEquals("{\"result\":\"true\"}",
550         query.response().getContent().toString(Charset.forName("UTF-8")));
551   }
552 
553   @Test
renamePostTagk()554   public void renamePostTagk() throws Exception {
555     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename",
556         "{\"tagk\":\"datacenter\",\"name\":\"datacluster\"}");
557     rpc.execute(tsdb, query);
558     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
559     assertEquals("{\"result\":\"true\"}",
560         query.response().getContent().toString(Charset.forName("UTF-8")));
561   }
562 
563   @Test
renamePostTagv()564   public void renamePostTagv() throws Exception {
565     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename",
566         "{\"tagv\":\"localhost\",\"name\":\"127.0.0.1\"}");
567     rpc.execute(tsdb, query);
568     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
569     assertEquals("{\"result\":\"true\"}",
570         query.response().getContent().toString(Charset.forName("UTF-8")));
571   }
572 
573   @Test (expected = BadRequestException.class)
renamePostNoName()574   public void renamePostNoName() throws Exception {
575     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename",
576         "{\"tagk\":\"localhost\",\"not_name\":\"127.0.0.1\"}");
577     rpc.execute(tsdb, query);
578   }
579 
580   @Test (expected = BadRequestException.class)
renamePostNoType()581   public void renamePostNoType() throws Exception {
582     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename",
583         "{\"name\":\"127.0.0.1\"}");
584     rpc.execute(tsdb, query);
585   }
586 
587   @Test (expected = BadRequestException.class)
renamePostNotJSON()588   public void renamePostNotJSON() throws Exception {
589     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename", "Not JSON");
590     rpc.execute(tsdb, query);
591   }
592 
593   @Test (expected = BadRequestException.class)
renamePostZeroLengthContent()594   public void renamePostZeroLengthContent() throws Exception {
595     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename", "");
596     rpc.execute(tsdb, query);
597   }
598 
599   @Test (expected = BadRequestException.class)
renamePostEmptyJSON()600   public void renamePostEmptyJSON() throws Exception {
601     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/rename", "{}");
602     rpc.execute(tsdb, query);
603   }
604 
605   @Test
renameQsMetric()606   public void renameQsMetric() throws Exception {
607     HttpQuery query = NettyMocks.getQuery(tsdb,
608         "/api/uid/rename?metric=sys.cpu.1&name=sys.cpu.2");
609     rpc.execute(tsdb, query);
610     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
611     assertEquals("{\"result\":\"true\"}",
612         query.response().getContent().toString(Charset.forName("UTF-8")));
613   }
614 
615   @Test
renameQsTagk()616   public void renameQsTagk() throws Exception {
617     HttpQuery query = NettyMocks.getQuery(tsdb,
618         "/api/uid/rename?tagk=datacenter&name=datacluster");
619     rpc.execute(tsdb, query);
620     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
621     assertEquals("{\"result\":\"true\"}",
622         query.response().getContent().toString(Charset.forName("UTF-8")));
623   }
624 
625   @Test
renameQsTagv()626   public void renameQsTagv() throws Exception {
627     HttpQuery query = NettyMocks.getQuery(tsdb,
628         "/api/uid/rename?tagv=localhost&name=127.0.0.1");
629     rpc.execute(tsdb, query);
630     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
631     assertEquals("{\"result\":\"true\"}",
632         query.response().getContent().toString(Charset.forName("UTF-8")));
633   }
634 
635   @Test
renameQsSkipUnsupportedParam()636   public void renameQsSkipUnsupportedParam() throws Exception {
637     HttpQuery query = NettyMocks.getQuery(tsdb,
638         "/api/uid/rename?tagv=localhost&name=127.0.0.1&drop=db");
639     rpc.execute(tsdb, query);
640     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
641     assertEquals("{\"result\":\"true\"}",
642         query.response().getContent().toString(Charset.forName("UTF-8")));
643   }
644 
645   @Test (expected = BadRequestException.class)
renameQsMissingType()646   public void renameQsMissingType() throws Exception {
647     HttpQuery query = NettyMocks.getQuery(tsdb,
648         "/api/uid/rename?name=127.0.0.1");
649     rpc.execute(tsdb, query);
650   }
651 
652   @Test (expected = BadRequestException.class)
renameQsMissingName()653   public void renameQsMissingName() throws Exception {
654     HttpQuery query = NettyMocks.getQuery(tsdb,
655         "/api/uid/rename?metric=sys.cpu.1");
656     rpc.execute(tsdb, query);
657   }
658 
659   @Test (expected = BadRequestException.class)
renameQsNoParamValue()660   public void renameQsNoParamValue() throws Exception {
661     HttpQuery query = NettyMocks.getQuery(tsdb,
662         "/api/uid/rename?metric=&name=sys.cpu.2");
663     rpc.execute(tsdb, query);
664   }
665 
666   @Test (expected = BadRequestException.class)
renameQsNoParam()667   public void renameQsNoParam() throws Exception {
668     HttpQuery query = NettyMocks.getQuery(tsdb,
669         "/api/uid/rename?");
670     rpc.execute(tsdb, query);
671   }
672 
673   @Test
renameRenameException()674   public void renameRenameException() throws Exception {
675     final String message = "New name already exists";
676     doThrow(new IllegalArgumentException(message)).when(tsdb).renameUid("tagv",
677         "localhost", "localhost");
678     HttpQuery query = NettyMocks.getQuery(tsdb,
679         "/api/uid/rename?tagv=localhost&name=localhost");
680     rpc.execute(tsdb, query);
681     assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
682     final String json = query.response().getContent()
683         .toString(Charset.forName("UTF-8"));
684     assertTrue(json.contains("\"error\":\"" + message + "\""));
685     assertTrue(json.contains("\"result\":\"false\""));
686   }
687 
688   // Teset /api/uid/uidmeta --------------------
689 
690   @Test
uidGet()691   public void uidGet() throws Exception {
692     setupUID();
693     HttpQuery query = NettyMocks.getQuery(tsdb,
694         "/api/uid/uidmeta?type=metric&uid=000001");
695     rpc.execute(tsdb, query);
696     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
697   }
698 
699   @Test (expected = BadRequestException.class)
uidGetNoUID()700   public void uidGetNoUID() throws Exception {
701     setupUID();
702     HttpQuery query = NettyMocks.getQuery(tsdb,
703         "/api/uid/uidmeta?type=metric");
704     rpc.execute(tsdb, query);
705   }
706 
707   @Test (expected = BadRequestException.class)
uidGetNoType()708   public void uidGetNoType() throws Exception {
709     setupUID();
710     HttpQuery query = NettyMocks.getQuery(tsdb,
711         "/api/uid/uidmeta?uid=000001");
712     rpc.execute(tsdb, query);
713   }
714 
715   @Test (expected = BadRequestException.class)
uidGetNSU()716   public void uidGetNSU() throws Exception {
717     setupUID();
718     HttpQuery query = NettyMocks.getQuery(tsdb,
719         "/api/uid/uidmeta?type=metric&uid=000002");
720     rpc.execute(tsdb, query);
721   }
722 
723   @Test
uidPost()724   public void uidPost() throws Exception {
725     setupUID();
726     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/uidmeta",
727         "{\"uid\":\"000001\",\"type\":\"metric\",\"displayName\":\"Hello!\"}");
728     rpc.execute(tsdb, query);
729     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
730   }
731 
732   @Test
uidPostNotModified()733   public void uidPostNotModified() throws Exception {
734     setupUID();
735     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/uidmeta",
736         "{\"uid\":\"000001\",\"type\":\"metric\"}");
737     rpc.execute(tsdb, query);
738     assertEquals(HttpResponseStatus.NOT_MODIFIED, query.response().getStatus());
739   }
740 
741   @Test (expected = BadRequestException.class)
uidPostMissingUID()742   public void uidPostMissingUID() throws Exception {
743     setupUID();
744     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/uidmeta",
745         "{\"type\":\"metric\",\"displayName\":\"Hello!\"}");
746     rpc.execute(tsdb, query);
747   }
748 
749   @Test (expected = BadRequestException.class)
uidPostMissingType()750   public void uidPostMissingType() throws Exception {
751     setupUID();
752     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/uidmeta",
753         "{\"uid\":\"000001\",\"displayName\":\"Hello!\"}");
754     rpc.execute(tsdb, query);
755   }
756 
757   @Test (expected = BadRequestException.class)
uidPostNSU()758   public void uidPostNSU() throws Exception {
759     setupUID();
760     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/uidmeta",
761         "{\"uid\":\"000002\",\"type\":\"metric\",\"displayName\":\"Hello!\"}");
762     rpc.execute(tsdb, query);
763   }
764 
765   @Test
uidPostQS()766   public void uidPostQS() throws Exception {
767     setupUID();
768     HttpQuery query = NettyMocks.getQuery(tsdb,
769         "/api/uid/uidmeta?uid=000001&type=metric&display_name=Hello&method_override=post");
770     rpc.execute(tsdb, query);
771     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
772   }
773 
774   @Test
uidPut()775   public void uidPut() throws Exception {
776     setupUID();
777     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/uidmeta",
778         "{\"uid\":\"000001\",\"type\":\"metric\",\"displayName\":\"Hello!\"}");
779     rpc.execute(tsdb, query);
780     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
781   }
782 
783   @Test
uidPutNotModified()784   public void uidPutNotModified() throws Exception {
785     setupUID();
786     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/uidmeta",
787         "{\"uid\":\"000001\",\"type\":\"metric\"}");
788     rpc.execute(tsdb, query);
789     assertEquals(HttpResponseStatus.NOT_MODIFIED, query.response().getStatus());
790   }
791 
792   @Test (expected = BadRequestException.class)
uidPutMissingUID()793   public void uidPutMissingUID() throws Exception {
794     setupUID();
795     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/uidmeta",
796         "{\"type\":\"metric\",\"displayName\":\"Hello!\"}");
797     rpc.execute(tsdb, query);
798   }
799 
800   @Test (expected = BadRequestException.class)
uidPutMissingType()801   public void uidPutMissingType() throws Exception {
802     setupUID();
803     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/uidmeta",
804         "{\"uid\":\"000001\",\"displayName\":\"Hello!\"}");
805     rpc.execute(tsdb, query);
806   }
807 
808   @Test (expected = BadRequestException.class)
uidPutNSU()809   public void uidPutNSU() throws Exception {
810     setupUID();
811     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/uidmeta",
812         "{\"uid\":\"000002\",\"type\":\"metric\",\"displayName\":\"Hello!\"}");
813     rpc.execute(tsdb, query);
814   }
815 
816   @Test
uidPutQS()817   public void uidPutQS() throws Exception {
818     setupUID();
819     HttpQuery query = NettyMocks.getQuery(tsdb,
820         "/api/uid/uidmeta?uid=000001&type=metric&display_name=Hello&method_override=put");
821     rpc.execute(tsdb, query);
822     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
823   }
824 
825   @Test
uidDelete()826   public void uidDelete() throws Exception {
827     setupUID();
828     HttpQuery query = NettyMocks.deleteQuery(tsdb, "/api/uid/uidmeta",
829         "{\"uid\":\"000001\",\"type\":\"metric\",\"displayName\":\"Hello!\"}");
830     rpc.execute(tsdb, query);
831     assertEquals(HttpResponseStatus.NO_CONTENT, query.response().getStatus());
832   }
833 
834   @Test (expected = BadRequestException.class)
uidDeleteMissingUID()835   public void uidDeleteMissingUID() throws Exception {
836     setupUID();
837     HttpQuery query = NettyMocks.deleteQuery(tsdb, "/api/uid/uidmeta",
838         "{\"type\":\"metric\",\"displayName\":\"Hello!\"}");
839     rpc.execute(tsdb, query);
840   }
841 
842   @Test (expected = BadRequestException.class)
uidDeleteMissingType()843   public void uidDeleteMissingType() throws Exception {
844     setupUID();
845     HttpQuery query = NettyMocks.deleteQuery(tsdb, "/api/uid/uidmeta",
846         "{\"uid\":\"000001\",\"displayName\":\"Hello!\"}");
847     rpc.execute(tsdb, query);
848   }
849 
850   @Test
uidDeleteQS()851   public void uidDeleteQS() throws Exception {
852     setupUID();
853     HttpQuery query = NettyMocks.getQuery(tsdb,
854         "/api/uid/uidmeta?uid=000001&type=metric&method_override=delete");
855     rpc.execute(tsdb, query);
856     assertEquals(HttpResponseStatus.NO_CONTENT, query.response().getStatus());
857   }
858 
859   // Test /api/uid/tsmeta ----------------------
860 
861   @Test
tsuidGet()862   public void tsuidGet() throws Exception {
863     setupTSUID();
864     HttpQuery query = NettyMocks.getQuery(tsdb,
865         "/api/uid/tsmeta?tsuid=000001000001000001");
866     rpc.execute(tsdb, query);
867     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
868   }
869 
870   @Test
tsuidGetByM()871   public void tsuidGetByM() throws Exception {
872     setupTSUID();
873     HttpQuery query = NettyMocks.getQuery(tsdb,
874         "/api/uid/tsmeta?m=sys.cpu.0{host=web01}");
875     rpc.execute(tsdb, query);
876     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
877   }
878 
879   @Test
tsuidPostByM()880   public void tsuidPostByM() throws Exception {
881     setupTSUID();
882     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/tsmeta?m=sys.cpu.0{host=web02}&create=true",
883         "{\"displayName\":\"Hello World\"}");
884     rpc.execute(tsdb, query);
885     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
886   }
887 
888   @Test (expected = BadRequestException.class)
tsuidPostByMNoCreate()889   public void tsuidPostByMNoCreate() throws Exception {
890     setupTSUID();
891     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/tsmeta?m=sys.cpu.0{host=web02}",
892         "{\"displayName\":\"Hello World\"}");
893     rpc.execute(tsdb, query);
894   }
895 
896   @Test
tsuidGetByMMultiTagWrongOrder()897   public void tsuidGetByMMultiTagWrongOrder() throws Exception {
898     setupTSUID();
899     HttpQuery query = NettyMocks.getQuery(tsdb,
900         "/api/uid/tsmeta?m=sys.cpu.2{datacenter=dc01,host=web01}");
901     rpc.execute(tsdb, query);
902     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
903   }
904 
905   @Test
tsuidGetByMMultiTag()906   public void tsuidGetByMMultiTag() throws Exception {
907     setupTSUID();
908     HttpQuery query = NettyMocks.getQuery(tsdb,
909         "/api/uid/tsmeta?m=sys.cpu.2{host=web01,datacenter=dc01}");
910     rpc.execute(tsdb, query);
911     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
912   }
913 
914   @Test (expected = BadRequestException.class)
tsuidGetByMEmpty()915   public void tsuidGetByMEmpty() throws Exception {
916     setupTSUID();
917     HttpQuery query = NettyMocks.getQuery(tsdb,
918         "/api/uid/tsmeta?m=");
919     rpc.execute(tsdb, query);
920   }
921 
922   @Test (expected = BadRequestException.class)
tsuidGetByMBadSyntax()923   public void tsuidGetByMBadSyntax() throws Exception {
924     setupTSUID();
925     HttpQuery query = NettyMocks.getQuery(tsdb,
926         "/api/uid/tsmeta?m=sys.cpu.0{datacenter=dc");
927     rpc.execute(tsdb, query);
928   }
929 
930   @Test (expected = BadRequestException.class)
tsuidGetNotFound()931   public void tsuidGetNotFound() throws Exception {
932     setupTSUID();
933     HttpQuery query = NettyMocks.getQuery(tsdb,
934         "/api/uid/tsmeta?tsuid=000001000001000002");
935     rpc.execute(tsdb, query);
936   }
937 
938   @Test (expected = BadRequestException.class)
tsuidGetMissingTSUID()939   public void tsuidGetMissingTSUID() throws Exception {
940     setupTSUID();
941     HttpQuery query = NettyMocks.getQuery(tsdb,
942         "/api/uid/tsmeta");
943     rpc.execute(tsdb, query);
944   }
945 
946   @Test
tsuidPost()947   public void tsuidPost() throws Exception {
948     setupTSUID();
949     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/tsmeta",
950         "{\"tsuid\":\"000001000001000001\", \"displayName\":\"Hello World\"}");
951     rpc.execute(tsdb, query);
952     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
953     assertTrue(query.response().getContent().toString(Charset.forName("UTF-8"))
954         .contains("\"displayName\":\"Hello World\""));
955   }
956 
957   @Test (expected = BadRequestException.class)
tsuidPostNoTSUID()958   public void tsuidPostNoTSUID() throws Exception {
959     setupTSUID();
960     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/tsmeta",
961         "{\"displayName\":\"Hello World\"}");
962     rpc.execute(tsdb, query);
963   }
964 
965   @Test
tsuidPostNotModified()966   public void tsuidPostNotModified() throws Exception {
967     setupTSUID();
968     HttpQuery query = NettyMocks.postQuery(tsdb, "/api/uid/tsmeta",
969         "{\"tsuid\":\"000001000001000001\"}");
970     rpc.execute(tsdb, query);
971     assertEquals(HttpResponseStatus.NOT_MODIFIED, query.response().getStatus());
972   }
973 
974   @Test
tsuidPostQS()975   public void tsuidPostQS() throws Exception {
976     setupTSUID();
977     HttpQuery query = NettyMocks.getQuery(tsdb,
978     "/api/uid/tsmeta?tsuid=000001000001000001&display_name=42&method_override=post");
979     rpc.execute(tsdb, query);
980     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
981     assertTrue(query.response().getContent().toString(Charset.forName("UTF-8"))
982         .contains("\"displayName\":\"42\""));
983   }
984 
985   @Test (expected = BadRequestException.class)
tsuidPostQSNoTSUID()986   public void tsuidPostQSNoTSUID() throws Exception {
987     setupTSUID();
988     HttpQuery query = NettyMocks.getQuery(tsdb,
989     "/api/uid/tsmeta?display_name=42&method_override=post");
990     rpc.execute(tsdb, query);
991   }
992 
993   @Test
tsuidPut()994   public void tsuidPut() throws Exception {
995     setupTSUID();
996     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/tsmeta",
997         "{\"tsuid\":\"000001000001000001\", \"displayName\":\"Hello World\"}");
998     rpc.execute(tsdb, query);
999     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
1000     assertTrue(query.response().getContent().toString(Charset.forName("UTF-8"))
1001         .contains("\"displayName\":\"Hello World\""));
1002   }
1003 
1004   @Test (expected = BadRequestException.class)
tsuidPutNoTSUID()1005   public void tsuidPutNoTSUID() throws Exception {
1006     setupTSUID();
1007     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/tsmeta",
1008         "{\"displayName\":\"Hello World\"}");
1009     rpc.execute(tsdb, query);
1010   }
1011 
1012   @Test
tsuidPutNotModified()1013   public void tsuidPutNotModified() throws Exception {
1014     setupTSUID();
1015     HttpQuery query = NettyMocks.putQuery(tsdb, "/api/uid/tsmeta",
1016         "{\"tsuid\":\"000001000001000001\"}");
1017     rpc.execute(tsdb, query);
1018     assertEquals(HttpResponseStatus.NOT_MODIFIED, query.response().getStatus());
1019   }
1020 
1021   @Test
tsuidPutQS()1022   public void tsuidPutQS() throws Exception {
1023     setupTSUID();
1024     HttpQuery query = NettyMocks.getQuery(tsdb,
1025     "/api/uid/tsmeta?tsuid=000001000001000001&display_name=42&method_override=put");
1026     rpc.execute(tsdb, query);
1027     assertEquals(HttpResponseStatus.OK, query.response().getStatus());
1028     assertTrue(query.response().getContent().toString(Charset.forName("UTF-8"))
1029         .contains("\"displayName\":\"42\""));
1030   }
1031 
1032   @Test (expected = BadRequestException.class)
tsuidPutQSNoTSUID()1033   public void tsuidPutQSNoTSUID() throws Exception {
1034     setupTSUID();
1035     HttpQuery query = NettyMocks.getQuery(tsdb,
1036     "/api/uid/tsmeta?display_name=42&method_override=put");
1037     rpc.execute(tsdb, query);
1038   }
1039 
1040   @Test
tsuidDelete()1041   public void tsuidDelete() throws Exception {
1042     setupTSUID();
1043     HttpQuery query = NettyMocks.deleteQuery(tsdb, "/api/uid/tsmeta",
1044         "{\"tsuid\":\"000001000001000001\", \"displayName\":\"Hello World\"}");
1045     rpc.execute(tsdb, query);
1046     assertEquals(HttpResponseStatus.NO_CONTENT, query.response().getStatus());
1047   }
1048 
1049   @Test
tsuidDeleteQS()1050   public void tsuidDeleteQS() throws Exception {
1051     setupTSUID();
1052     HttpQuery query = NettyMocks.getQuery(tsdb,
1053     "/api/uid/tsmeta?tsuid=000001000001000001&method_override=delete");
1054     rpc.execute(tsdb, query);
1055     assertEquals(HttpResponseStatus.NO_CONTENT, query.response().getStatus());
1056   }
1057 
1058   /**
1059    * Sets up common mocks for UID assignment tests
1060    * @throws Exception if something goes pear shaped
1061    */
setupAssign()1062   private void setupAssign() throws Exception {
1063     when(tsdb.assignUid("metric", "sys.cpu.0")).thenReturn(new byte[] { 0, 0, 1 });
1064     when(tsdb.assignUid("metric", "sys.cpu.1")).thenThrow(
1065         new IllegalArgumentException("Name already exists with UID: 000002"));
1066     when(tsdb.assignUid("metric", "sys.cpu.2")).thenReturn(new byte[] { 0, 0, 3 });
1067 
1068     when(tsdb.assignUid("tagk", "host")).thenReturn(new byte[] { 0, 0, 1 });
1069     when(tsdb.assignUid("tagk", "datacenter")).thenThrow(
1070         new IllegalArgumentException("Name already exists with UID: 000002"));
1071     when(tsdb.assignUid("tagk", "fqdn")).thenReturn(new byte[] { 0, 0, 3 });
1072 
1073     when(tsdb.assignUid("tagv", "localhost")).thenReturn(new byte[] { 0, 0, 1 });
1074     when(tsdb.assignUid("tagv", "myserver")).thenThrow(
1075         new IllegalArgumentException("Name already exists with UID: 000002"));
1076     when(tsdb.assignUid("tagv", "foo")).thenReturn(new byte[] { 0, 0, 3 });
1077 
1078     // setup UIDMeta objects for testing
1079     UIDMeta metric = new UIDMeta(UniqueIdType.METRIC, new byte[] {0, 0, 1},
1080         "sys.cpu.0");
1081     metric.setDisplayName("System CPU");
1082     UIDMeta tagk = new UIDMeta(UniqueIdType.TAGK, new byte[] {0, 0, 1},
1083         "host");
1084     tagk.setDisplayName("Server Name");
1085     UIDMeta tagv = new UIDMeta(UniqueIdType.TAGV, new byte[] {0, 0, 1},
1086         "web01");
1087     tagv.setDisplayName("Web Server 1");
1088   }
1089 
1090   /**
1091    * Sets up common mocks for UID tests
1092    * @throws Exception if something goes pear shaped
1093    */
setupUID()1094   private void setupUID() throws Exception {
1095     final Config config = new Config(false);
1096     tsdb = new TSDB(client, config);
1097 
1098     storage = new MockBase(tsdb, client, true, true, true, true);
1099 
1100     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1101         NAME_FAMILY,
1102         "metrics".getBytes(MockBase.ASCII()),
1103         "sys.cpu.0".getBytes(MockBase.ASCII()));
1104 
1105     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 3 },
1106         NAME_FAMILY,
1107         "metrics".getBytes(MockBase.ASCII()),
1108         "sys.cpu.2".getBytes(MockBase.ASCII()));
1109 
1110     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1111         NAME_FAMILY,
1112         "metric_meta".getBytes(MockBase.ASCII()),
1113         ("{\"uid\":\"000001\",\"type\":\"METRIC\",\"name\":\"sys.cpu.0\"," +
1114         "\"displayName\":\"System CPU\",\"description\":\"Description\"," +
1115         "\"notes\":\"MyNotes\",\"created\":1328140801,\"custom\":null}")
1116         .getBytes(MockBase.ASCII()));
1117   }
1118 
1119   /**
1120    * Sets up common mocks for TSUID tests
1121    * @throws Exception if something goes pear shaped
1122    */
setupTSUID()1123   private void setupTSUID() throws Exception {
1124     final Config config = new Config(false);
1125     tsdb = new TSDB(client, config);
1126 
1127     Field met = tsdb.getClass().getDeclaredField("metrics");
1128     met.setAccessible(true);
1129     met.set(tsdb, metrics);
1130 
1131     Field tagk = tsdb.getClass().getDeclaredField("tag_names");
1132     tagk.setAccessible(true);
1133     tagk.set(tsdb, tag_names);
1134 
1135     Field tagv = tsdb.getClass().getDeclaredField("tag_values");
1136     tagv.setAccessible(true);
1137     tagv.set(tsdb, tag_values);
1138 
1139     storage = new MockBase(tsdb, client, true, true, true, true);
1140     final List<byte[]> families = new ArrayList<byte[]>(1);
1141     families.add(TSMeta.FAMILY);
1142     storage.addTable(META_TABLE, families);
1143 
1144     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1145         NAME_FAMILY,
1146         "metrics".getBytes(MockBase.ASCII()),
1147         "sys.cpu.0".getBytes(MockBase.ASCII()));
1148     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1149         NAME_FAMILY,
1150         "metric_meta".getBytes(MockBase.ASCII()),
1151         ("{\"uid\":\"000001\",\"type\":\"METRIC\",\"name\":\"sys.cpu.0\"," +
1152         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1153         "1328140801,\"displayName\":\"System CPU\"}").getBytes(MockBase.ASCII()));
1154     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 2 }, NAME_FAMILY,
1155         "metrics".getBytes(MockBase.ASCII()),
1156         "sys.cpu.2".getBytes(MockBase.ASCII()));
1157     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 2 }, NAME_FAMILY,
1158         "metric_meta".getBytes(MockBase.ASCII()),
1159         ("{\"uid\":\"000002\",\"type\":\"METRIC\",\"name\":\"sys.cpu.2\"," +
1160         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1161         "1328140801,\"displayName\":\"System CPU\"}").getBytes(MockBase.ASCII()));
1162 
1163     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1164         NAME_FAMILY,
1165         "tagk".getBytes(MockBase.ASCII()),
1166         "host".getBytes(MockBase.ASCII()));
1167     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1168         NAME_FAMILY,
1169         "tagk_meta".getBytes(MockBase.ASCII()),
1170         ("{\"uid\":\"000001\",\"type\":\"TAGK\",\"name\":\"host\"," +
1171         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1172         "1328140801,\"displayName\":\"Host server name\"}").getBytes(MockBase.ASCII()));
1173     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 2 }, NAME_FAMILY,
1174         "tagk".getBytes(MockBase.ASCII()),
1175         "datacenter".getBytes(MockBase.ASCII()));
1176     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 2 }, NAME_FAMILY,
1177         "tagk_meta".getBytes(MockBase.ASCII()),
1178         ("{\"uid\":\"000002\",\"type\":\"TAGK\",\"name\":\"datacenter\"," +
1179         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1180         "1328140801,\"displayName\":\"Host server name\"}").getBytes(MockBase.ASCII()));
1181 
1182     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1183         NAME_FAMILY,
1184         "tagv".getBytes(MockBase.ASCII()),
1185         "web01".getBytes(MockBase.ASCII()));
1186     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 1 },
1187         NAME_FAMILY,
1188         "tagv_meta".getBytes(MockBase.ASCII()),
1189         ("{\"uid\":\"000001\",\"type\":\"TAGV\",\"name\":\"web01\"," +
1190         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1191         "1328140801,\"displayName\":\"Web server 1\"}").getBytes(MockBase.ASCII()));
1192     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 3 }, NAME_FAMILY,
1193         "tagv".getBytes(MockBase.ASCII()),
1194         "web02".getBytes(MockBase.ASCII()));
1195     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 3 }, NAME_FAMILY,
1196         "tagv_meta".getBytes(MockBase.ASCII()),
1197         ("{\"uid\":\"000003\",\"type\":\"TAGV\",\"name\":\"web02\"," +
1198         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1199         "1328140801,\"displayName\":\"Web server 1\"}").getBytes(MockBase.ASCII()));
1200     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 2 }, NAME_FAMILY,
1201         "tagv".getBytes(MockBase.ASCII()),
1202         "dc01".getBytes(MockBase.ASCII()));
1203     storage.addColumn(UID_TABLE, new byte[] { 0, 0, 2 }, NAME_FAMILY,
1204         "tagv_meta".getBytes(MockBase.ASCII()),
1205         ("{\"uid\":\"000002\",\"type\":\"TAGV\",\"name\":\"dc01\"," +
1206         "\"description\":\"Description\",\"notes\":\"MyNotes\",\"created\":" +
1207         "1328140801,\"displayName\":\"Web server 1\"}").getBytes(MockBase.ASCII()));
1208 
1209     storage.addColumn(META_TABLE, new byte[] { 0, 0, 1, 0, 0, 1, 0, 0, 1 },
1210         TSMeta.FAMILY,
1211         "ts_meta".getBytes(MockBase.ASCII()),
1212         ("{\"tsuid\":\"000001000001000001\",\"displayName\":\"Display\"," +
1213             "\"description\":\"Description\",\"notes\":\"Notes\",\"created" +
1214             "\":1366671600,\"custom\":null,\"units\":\"\",\"dataType\":" +
1215             "\"Data\",\"retention\":42,\"max\":1.0,\"min\":\"NaN\"}")
1216             .getBytes(MockBase.ASCII()));
1217     storage.addColumn(META_TABLE, new byte[] { 0, 0, 1, 0, 0, 1, 0, 0, 1 },
1218         TSMeta.FAMILY,
1219         "ts_ctr".getBytes(MockBase.ASCII()),
1220         Bytes.fromLong(1L));
1221 
1222     storage.addColumn(META_TABLE,
1223         new byte[] { 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 2 },
1224         TSMeta.FAMILY,
1225         "ts_meta".getBytes(MockBase.ASCII()),
1226         ("{\"tsuid\":\"000002000001000001000002000002\",\"displayName\":\"Display\"," +
1227             "\"description\":\"Description\",\"notes\":\"Notes\",\"created" +
1228             "\":1366671600,\"custom\":null,\"units\":\"\",\"dataType\":" +
1229             "\"Data\",\"retention\":42,\"max\":1.0,\"min\":\"NaN\"}")
1230             .getBytes(MockBase.ASCII()));
1231     storage.addColumn(META_TABLE,
1232         new byte[] { 0, 0, 2, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 2 },
1233         TSMeta.FAMILY,
1234         "ts_ctr".getBytes(MockBase.ASCII()),
1235         Bytes.fromLong(1L));
1236     storage.addColumn(META_TABLE,
1237         new byte[] { 0, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 2, 0, 0, 2 },
1238         TSMeta.FAMILY,
1239         "ts_meta".getBytes(MockBase.ASCII()),
1240         ("{\"tsuid\":\"000002000001000003000002000002\",\"displayName\":\"Display\"," +
1241             "\"description\":\"Description\",\"notes\":\"Notes\",\"created" +
1242             "\":1366671600,\"custom\":null,\"units\":\"\",\"dataType\":" +
1243             "\"Data\",\"retention\":42,\"max\":1.0,\"min\":\"NaN\"}")
1244             .getBytes(MockBase.ASCII()));
1245     storage.addColumn(META_TABLE,
1246         new byte[] { 0, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 2, 0, 0, 2 },
1247         TSMeta.FAMILY,
1248         "ts_ctr".getBytes(MockBase.ASCII()),
1249         Bytes.fromLong(1L));
1250 
1251     when(metrics.getId("sys.cpu.0")).thenReturn(new byte[] { 0, 0, 1 });
1252     when(metrics.getIdAsync("sys.cpu.0")).thenReturn(
1253         Deferred.fromResult(new byte[] { 0, 0, 1 }));
1254     when(metrics.getNameAsync(new byte[] { 0, 0, 1 }))
1255       .thenReturn(Deferred.fromResult("sys.cpu.0"));
1256     when(metrics.getId("sys.cpu.2")).thenReturn(new byte[] { 0, 0, 2 });
1257     when(metrics.getIdAsync("sys.cpu.2")).thenReturn(
1258         Deferred.fromResult(new byte[] { 0, 0, 2 }));
1259     when(metrics.getNameAsync(new byte[] { 0, 0, 2 }))
1260       .thenReturn(Deferred.fromResult("sys.cpu.2"));
1261 
1262     when(tag_names.getId("host")).thenReturn(new byte[] { 0, 0, 1 });
1263     when(tag_names.getIdAsync("host")).thenReturn(
1264         Deferred.fromResult(new byte[] { 0, 0, 1 }));
1265     when(tag_names.getNameAsync(new byte[] { 0, 0, 1 }))
1266       .thenReturn(Deferred.fromResult("host"));
1267     when(tag_values.getId("web01")).thenReturn(new byte[] { 0, 0, 1 });
1268     when(tag_values.getIdAsync("web01")).thenReturn(
1269         Deferred.fromResult(new byte[] { 0, 0, 1 }));
1270     when(tag_values.getNameAsync(new byte[] { 0, 0, 1 }))
1271       .thenReturn(Deferred.fromResult("web01"));
1272     when(tag_values.getId("web02")).thenReturn(new byte[] { 0, 0, 3 });
1273     when(tag_values.getIdAsync("web02")).thenReturn(
1274         Deferred.fromResult(new byte[] { 0, 0, 3 }));
1275     when(tag_values.getNameAsync(new byte[] { 0, 0, 3 }))
1276       .thenReturn(Deferred.fromResult("web02"));
1277 
1278     when(tag_names.getId("datacenter")).thenReturn(new byte[] { 0, 0, 2 });
1279     when(tag_names.getIdAsync("datacenter")).thenReturn(
1280         Deferred.fromResult(new byte[] { 0, 0, 2 }));
1281     when(tag_names.getNameAsync(new byte[] { 0, 0, 2 }))
1282       .thenReturn(Deferred.fromResult("datacenter"));
1283     when(tag_values.getId("dc01")).thenReturn(new byte[] { 0, 0, 2 });
1284     when(tag_values.getIdAsync("dc01")).thenReturn(
1285         Deferred.fromResult(new byte[] { 0, 0, 2 }));
1286     when(tag_values.getNameAsync(new byte[] { 0, 0, 2 }))
1287       .thenReturn(Deferred.fromResult("dc01"));
1288 
1289   }
1290 }
1291