field_stats_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic
  5. import (
  6. "encoding/json"
  7. "net/url"
  8. "reflect"
  9. "sort"
  10. "testing"
  11. )
  12. func TestFieldStatsURLs(t *testing.T) {
  13. tests := []struct {
  14. Service *FieldStatsService
  15. ExpectedPath string
  16. ExpectedParams url.Values
  17. }{
  18. {
  19. Service: &FieldStatsService{},
  20. ExpectedPath: "/_field_stats",
  21. ExpectedParams: url.Values{},
  22. },
  23. {
  24. Service: &FieldStatsService{
  25. level: FieldStatsClusterLevel,
  26. },
  27. ExpectedPath: "/_field_stats",
  28. ExpectedParams: url.Values{"level": []string{FieldStatsClusterLevel}},
  29. },
  30. {
  31. Service: &FieldStatsService{
  32. level: FieldStatsIndicesLevel,
  33. },
  34. ExpectedPath: "/_field_stats",
  35. ExpectedParams: url.Values{"level": []string{FieldStatsIndicesLevel}},
  36. },
  37. {
  38. Service: &FieldStatsService{
  39. level: FieldStatsClusterLevel,
  40. index: []string{"index1"},
  41. },
  42. ExpectedPath: "/index1/_field_stats",
  43. ExpectedParams: url.Values{"level": []string{FieldStatsClusterLevel}},
  44. },
  45. {
  46. Service: &FieldStatsService{
  47. level: FieldStatsIndicesLevel,
  48. index: []string{"index1", "index2"},
  49. },
  50. ExpectedPath: "/index1%2Cindex2/_field_stats",
  51. ExpectedParams: url.Values{"level": []string{FieldStatsIndicesLevel}},
  52. },
  53. {
  54. Service: &FieldStatsService{
  55. level: FieldStatsIndicesLevel,
  56. index: []string{"index_*"},
  57. },
  58. ExpectedPath: "/index_%2A/_field_stats",
  59. ExpectedParams: url.Values{"level": []string{FieldStatsIndicesLevel}},
  60. },
  61. }
  62. for _, test := range tests {
  63. gotPath, gotParams, err := test.Service.buildURL()
  64. if err != nil {
  65. t.Fatalf("expected no error; got: %v", err)
  66. }
  67. if gotPath != test.ExpectedPath {
  68. t.Errorf("expected URL path = %q; got: %q", test.ExpectedPath, gotPath)
  69. }
  70. if gotParams.Encode() != test.ExpectedParams.Encode() {
  71. t.Errorf("expected URL params = %v; got: %v", test.ExpectedParams, gotParams)
  72. }
  73. }
  74. }
  75. func TestFieldStatsValidate(t *testing.T) {
  76. tests := []struct {
  77. Service *FieldStatsService
  78. Valid bool
  79. }{
  80. {
  81. Service: &FieldStatsService{},
  82. Valid: true,
  83. },
  84. {
  85. Service: &FieldStatsService{
  86. fields: []string{"field"},
  87. },
  88. Valid: true,
  89. },
  90. {
  91. Service: &FieldStatsService{
  92. bodyJson: &FieldStatsRequest{
  93. Fields: []string{"field"},
  94. },
  95. },
  96. Valid: true,
  97. },
  98. {
  99. Service: &FieldStatsService{
  100. level: FieldStatsClusterLevel,
  101. bodyJson: &FieldStatsRequest{
  102. Fields: []string{"field"},
  103. },
  104. },
  105. Valid: true,
  106. },
  107. {
  108. Service: &FieldStatsService{
  109. level: FieldStatsIndicesLevel,
  110. bodyJson: &FieldStatsRequest{
  111. Fields: []string{"field"},
  112. },
  113. },
  114. Valid: true,
  115. },
  116. {
  117. Service: &FieldStatsService{
  118. level: "random",
  119. },
  120. Valid: false,
  121. },
  122. }
  123. for _, test := range tests {
  124. err := test.Service.Validate()
  125. isValid := err == nil
  126. if isValid != test.Valid {
  127. t.Errorf("expected validity to be %v, got %v", test.Valid, isValid)
  128. }
  129. }
  130. }
  131. func TestFieldStatsRequestSerialize(t *testing.T) {
  132. req := &FieldStatsRequest{
  133. Fields: []string{"creation_date", "answer_count"},
  134. IndexConstraints: map[string]*FieldStatsConstraints{
  135. "creation_date": &FieldStatsConstraints{
  136. Min: &FieldStatsComparison{Gte: "2014-01-01T00:00:00.000Z"},
  137. Max: &FieldStatsComparison{Lt: "2015-01-01T10:00:00.000Z"},
  138. },
  139. },
  140. }
  141. data, err := json.Marshal(req)
  142. if err != nil {
  143. t.Fatalf("marshaling to JSON failed: %v", err)
  144. }
  145. got := string(data)
  146. expected := `{"fields":["creation_date","answer_count"],"index_constraints":{"creation_date":{"min_value":{"gte":"2014-01-01T00:00:00.000Z"},"max_value":{"lt":"2015-01-01T10:00:00.000Z"}}}}`
  147. if got != expected {
  148. t.Errorf("expected\n%s\n,got:\n%s", expected, got)
  149. }
  150. }
  151. func TestFieldStatsRequestDeserialize(t *testing.T) {
  152. body := `{
  153. "fields" : ["creation_date", "answer_count"],
  154. "index_constraints" : {
  155. "creation_date" : {
  156. "min_value" : {
  157. "gte" : "2014-01-01T00:00:00.000Z"
  158. },
  159. "max_value" : {
  160. "lt" : "2015-01-01T10:00:00.000Z"
  161. }
  162. }
  163. }
  164. }`
  165. var request FieldStatsRequest
  166. if err := json.Unmarshal([]byte(body), &request); err != nil {
  167. t.Errorf("unexpected error during unmarshalling: %v", err)
  168. }
  169. sort.Sort(lexicographically{request.Fields})
  170. expectedFields := []string{"answer_count", "creation_date"}
  171. if !reflect.DeepEqual(request.Fields, expectedFields) {
  172. t.Errorf("expected fields to be %v, got %v", expectedFields, request.Fields)
  173. }
  174. constraints, ok := request.IndexConstraints["creation_date"]
  175. if !ok {
  176. t.Errorf("expected field creation_date, didn't find it!")
  177. }
  178. if constraints.Min.Lt != nil {
  179. t.Errorf("expected min value less than constraint to be empty, got %v", constraints.Min.Lt)
  180. }
  181. if constraints.Min.Gte != "2014-01-01T00:00:00.000Z" {
  182. t.Errorf("expected min value >= %v, found %v", "2014-01-01T00:00:00.000Z", constraints.Min.Gte)
  183. }
  184. if constraints.Max.Lt != "2015-01-01T10:00:00.000Z" {
  185. t.Errorf("expected max value < %v, found %v", "2015-01-01T10:00:00.000Z", constraints.Max.Lt)
  186. }
  187. }
  188. func TestFieldStatsResponseUnmarshalling(t *testing.T) {
  189. clusterStats := `{
  190. "_shards": {
  191. "total": 1,
  192. "successful": 1,
  193. "failed": 0
  194. },
  195. "indices": {
  196. "_all": {
  197. "fields": {
  198. "creation_date": {
  199. "type": "date",
  200. "max_doc": 1326564,
  201. "doc_count": 564633,
  202. "density": 42,
  203. "sum_doc_freq": 2258532,
  204. "sum_total_term_freq": -1,
  205. "searchable": true,
  206. "aggregatable": true,
  207. "min_value":1483016404000,
  208. "min_value_as_string": "2016-12-29T13:00:04.000Z",
  209. "max_value":1484152326000,
  210. "max_value_as_string": "2017-01-11T16:32:06.000Z"
  211. },
  212. "answer_count": {
  213. "max_doc": 1326564,
  214. "doc_count": 139885,
  215. "density": 10,
  216. "sum_doc_freq": 559540,
  217. "sum_total_term_freq": -1,
  218. "searchable": true,
  219. "aggregatable": true,
  220. "min_value":1483016404000,
  221. "min_value_as_string": "2016-12-29T13:00:04.000Z",
  222. "max_value":1484152326000,
  223. "max_value_as_string": "2017-01-11T16:32:06.000Z"
  224. }
  225. }
  226. }
  227. }
  228. }`
  229. var response FieldStatsResponse
  230. if err := json.Unmarshal([]byte(clusterStats), &response); err != nil {
  231. t.Errorf("unexpected error during unmarshalling: %v", err)
  232. }
  233. stats, ok := response.Indices["_all"]
  234. if !ok {
  235. t.Errorf("expected _all to be in the indices map, didn't find it")
  236. }
  237. fieldStats, ok := stats.Fields["creation_date"]
  238. if !ok {
  239. t.Errorf("expected creation_date to be in the fields map, didn't find it")
  240. }
  241. if want, have := true, fieldStats.Searchable; want != have {
  242. t.Errorf("expected creation_date searchable to be %v, got %v", want, have)
  243. }
  244. if want, have := true, fieldStats.Aggregatable; want != have {
  245. t.Errorf("expected creation_date aggregatable to be %v, got %v", want, have)
  246. }
  247. if want, have := "2016-12-29T13:00:04.000Z", fieldStats.MinValueAsString; want != have {
  248. t.Errorf("expected creation_date min value string to be %q, got %q", want, have)
  249. }
  250. }
  251. type lexicographically struct {
  252. strings []string
  253. }
  254. func (l lexicographically) Len() int {
  255. return len(l.strings)
  256. }
  257. func (l lexicographically) Less(i, j int) bool {
  258. return l.strings[i] < l.strings[j]
  259. }
  260. func (l lexicographically) Swap(i, j int) {
  261. l.strings[i], l.strings[j] = l.strings[j], l.strings[i]
  262. }