You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
7.4 KiB
282 lines
7.4 KiB
// Copyright 2012-present Oliver Eilhard. All rights reserved. |
|
// Use of this source code is governed by a MIT-license. |
|
// See http://olivere.mit-license.org/license.txt for details. |
|
|
|
package elastic |
|
|
|
import ( |
|
"encoding/json" |
|
"net/url" |
|
"reflect" |
|
"sort" |
|
"testing" |
|
) |
|
|
|
func TestFieldStatsURLs(t *testing.T) { |
|
tests := []struct { |
|
Service *FieldStatsService |
|
ExpectedPath string |
|
ExpectedParams url.Values |
|
}{ |
|
{ |
|
Service: &FieldStatsService{}, |
|
ExpectedPath: "/_field_stats", |
|
ExpectedParams: url.Values{}, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsClusterLevel, |
|
}, |
|
ExpectedPath: "/_field_stats", |
|
ExpectedParams: url.Values{"level": []string{FieldStatsClusterLevel}}, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsIndicesLevel, |
|
}, |
|
ExpectedPath: "/_field_stats", |
|
ExpectedParams: url.Values{"level": []string{FieldStatsIndicesLevel}}, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsClusterLevel, |
|
index: []string{"index1"}, |
|
}, |
|
ExpectedPath: "/index1/_field_stats", |
|
ExpectedParams: url.Values{"level": []string{FieldStatsClusterLevel}}, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsIndicesLevel, |
|
index: []string{"index1", "index2"}, |
|
}, |
|
ExpectedPath: "/index1%2Cindex2/_field_stats", |
|
ExpectedParams: url.Values{"level": []string{FieldStatsIndicesLevel}}, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsIndicesLevel, |
|
index: []string{"index_*"}, |
|
}, |
|
ExpectedPath: "/index_%2A/_field_stats", |
|
ExpectedParams: url.Values{"level": []string{FieldStatsIndicesLevel}}, |
|
}, |
|
} |
|
|
|
for _, test := range tests { |
|
gotPath, gotParams, err := test.Service.buildURL() |
|
if err != nil { |
|
t.Fatalf("expected no error; got: %v", err) |
|
} |
|
if gotPath != test.ExpectedPath { |
|
t.Errorf("expected URL path = %q; got: %q", test.ExpectedPath, gotPath) |
|
} |
|
if gotParams.Encode() != test.ExpectedParams.Encode() { |
|
t.Errorf("expected URL params = %v; got: %v", test.ExpectedParams, gotParams) |
|
} |
|
} |
|
} |
|
|
|
func TestFieldStatsValidate(t *testing.T) { |
|
tests := []struct { |
|
Service *FieldStatsService |
|
Valid bool |
|
}{ |
|
{ |
|
Service: &FieldStatsService{}, |
|
Valid: true, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
fields: []string{"field"}, |
|
}, |
|
Valid: true, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
bodyJson: &FieldStatsRequest{ |
|
Fields: []string{"field"}, |
|
}, |
|
}, |
|
Valid: true, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsClusterLevel, |
|
bodyJson: &FieldStatsRequest{ |
|
Fields: []string{"field"}, |
|
}, |
|
}, |
|
Valid: true, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: FieldStatsIndicesLevel, |
|
bodyJson: &FieldStatsRequest{ |
|
Fields: []string{"field"}, |
|
}, |
|
}, |
|
Valid: true, |
|
}, |
|
{ |
|
Service: &FieldStatsService{ |
|
level: "random", |
|
}, |
|
Valid: false, |
|
}, |
|
} |
|
|
|
for _, test := range tests { |
|
err := test.Service.Validate() |
|
isValid := err == nil |
|
if isValid != test.Valid { |
|
t.Errorf("expected validity to be %v, got %v", test.Valid, isValid) |
|
} |
|
} |
|
} |
|
|
|
func TestFieldStatsRequestSerialize(t *testing.T) { |
|
req := &FieldStatsRequest{ |
|
Fields: []string{"creation_date", "answer_count"}, |
|
IndexConstraints: map[string]*FieldStatsConstraints{ |
|
"creation_date": &FieldStatsConstraints{ |
|
Min: &FieldStatsComparison{Gte: "2014-01-01T00:00:00.000Z"}, |
|
Max: &FieldStatsComparison{Lt: "2015-01-01T10:00:00.000Z"}, |
|
}, |
|
}, |
|
} |
|
data, err := json.Marshal(req) |
|
if err != nil { |
|
t.Fatalf("marshaling to JSON failed: %v", err) |
|
} |
|
got := string(data) |
|
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"}}}}` |
|
if got != expected { |
|
t.Errorf("expected\n%s\n,got:\n%s", expected, got) |
|
} |
|
} |
|
|
|
func TestFieldStatsRequestDeserialize(t *testing.T) { |
|
body := `{ |
|
"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" |
|
} |
|
} |
|
} |
|
}` |
|
|
|
var request FieldStatsRequest |
|
if err := json.Unmarshal([]byte(body), &request); err != nil { |
|
t.Errorf("unexpected error during unmarshalling: %v", err) |
|
} |
|
|
|
sort.Sort(lexicographically{request.Fields}) |
|
|
|
expectedFields := []string{"answer_count", "creation_date"} |
|
if !reflect.DeepEqual(request.Fields, expectedFields) { |
|
t.Errorf("expected fields to be %v, got %v", expectedFields, request.Fields) |
|
} |
|
|
|
constraints, ok := request.IndexConstraints["creation_date"] |
|
if !ok { |
|
t.Errorf("expected field creation_date, didn't find it!") |
|
} |
|
if constraints.Min.Lt != nil { |
|
t.Errorf("expected min value less than constraint to be empty, got %v", constraints.Min.Lt) |
|
} |
|
if constraints.Min.Gte != "2014-01-01T00:00:00.000Z" { |
|
t.Errorf("expected min value >= %v, found %v", "2014-01-01T00:00:00.000Z", constraints.Min.Gte) |
|
} |
|
if constraints.Max.Lt != "2015-01-01T10:00:00.000Z" { |
|
t.Errorf("expected max value < %v, found %v", "2015-01-01T10:00:00.000Z", constraints.Max.Lt) |
|
} |
|
} |
|
|
|
func TestFieldStatsResponseUnmarshalling(t *testing.T) { |
|
clusterStats := `{ |
|
"_shards": { |
|
"total": 1, |
|
"successful": 1, |
|
"failed": 0 |
|
}, |
|
"indices": { |
|
"_all": { |
|
"fields": { |
|
"creation_date": { |
|
"type": "date", |
|
"max_doc": 1326564, |
|
"doc_count": 564633, |
|
"density": 42, |
|
"sum_doc_freq": 2258532, |
|
"sum_total_term_freq": -1, |
|
"searchable": true, |
|
"aggregatable": true, |
|
"min_value":1483016404000, |
|
"min_value_as_string": "2016-12-29T13:00:04.000Z", |
|
"max_value":1484152326000, |
|
"max_value_as_string": "2017-01-11T16:32:06.000Z" |
|
}, |
|
"answer_count": { |
|
"max_doc": 1326564, |
|
"doc_count": 139885, |
|
"density": 10, |
|
"sum_doc_freq": 559540, |
|
"sum_total_term_freq": -1, |
|
"searchable": true, |
|
"aggregatable": true, |
|
"min_value":1483016404000, |
|
"min_value_as_string": "2016-12-29T13:00:04.000Z", |
|
"max_value":1484152326000, |
|
"max_value_as_string": "2017-01-11T16:32:06.000Z" |
|
} |
|
} |
|
} |
|
} |
|
}` |
|
|
|
var response FieldStatsResponse |
|
if err := json.Unmarshal([]byte(clusterStats), &response); err != nil { |
|
t.Errorf("unexpected error during unmarshalling: %v", err) |
|
} |
|
|
|
stats, ok := response.Indices["_all"] |
|
if !ok { |
|
t.Errorf("expected _all to be in the indices map, didn't find it") |
|
} |
|
|
|
fieldStats, ok := stats.Fields["creation_date"] |
|
if !ok { |
|
t.Errorf("expected creation_date to be in the fields map, didn't find it") |
|
} |
|
if want, have := true, fieldStats.Searchable; want != have { |
|
t.Errorf("expected creation_date searchable to be %v, got %v", want, have) |
|
} |
|
if want, have := true, fieldStats.Aggregatable; want != have { |
|
t.Errorf("expected creation_date aggregatable to be %v, got %v", want, have) |
|
} |
|
if want, have := "2016-12-29T13:00:04.000Z", fieldStats.MinValueAsString; want != have { |
|
t.Errorf("expected creation_date min value string to be %q, got %q", want, have) |
|
} |
|
} |
|
|
|
type lexicographically struct { |
|
strings []string |
|
} |
|
|
|
func (l lexicographically) Len() int { |
|
return len(l.strings) |
|
} |
|
|
|
func (l lexicographically) Less(i, j int) bool { |
|
return l.strings[i] < l.strings[j] |
|
} |
|
|
|
func (l lexicographically) Swap(i, j int) { |
|
l.strings[i], l.strings[j] = l.strings[j], l.strings[i] |
|
}
|
|
|