github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/hll_test.go (about)

     1  //  Copyright (c) 2017-2018 Uber Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package query
    16  
    17  import (
    18  	"github.com/onsi/ginkgo"
    19  	memCom "github.com/uber/aresdb/memstore/common"
    20  	queryCom "github.com/uber/aresdb/query/common"
    21  	"unsafe"
    22  
    23  	"errors"
    24  	. "github.com/onsi/gomega"
    25  	"time"
    26  )
    27  
    28  var _ = ginkgo.Describe("hll", func() {
    29  	dimensionData := []byte{
    30  		0, 0, 0, 0,
    31  		1, 0, 0, 0,
    32  		0xFF, 0xFF, 0xFF, 0xFF, // dim0
    33  		0, 0, 0, 0,
    34  		0, 0, 0, 0,
    35  		0, 0, 0, 0, // res cap.
    36  		0, 0,
    37  		2, 0,
    38  		2, 2, // dim1
    39  		0, 0,
    40  		0, 0,
    41  		0, 0, // res cap
    42  		0, 2, 3, // dim2
    43  		0, 0, 0, // res cap
    44  		0, 1, 1, // dim0
    45  		0, 0, 0, // res cap
    46  		0, 1, 1, // dim1
    47  		0, 0, 0, // res cap
    48  		0, 1, 1, // dim2
    49  		0, 0, 0, // res cap
    50  	}
    51  
    52  	measureData := [3]uint32{}
    53  	counts := []uint16{3, queryCom.DenseDataLength, 4}
    54  	hllData := [queryCom.DenseDataLength + 28]byte{}
    55  	*(*uint32)(unsafe.Pointer(&hllData[0])) = 0X00FF0001
    56  	*(*uint32)(unsafe.Pointer(&hllData[4])) = 0X00FE0002
    57  	*(*uint32)(unsafe.Pointer(&hllData[8])) = 0X00FD0003
    58  
    59  	hllData[12] = 1
    60  	hllData[13] = 1
    61  
    62  	*(*uint32)(unsafe.Pointer(&hllData[12+queryCom.DenseDataLength])) = 0X000100FF
    63  	*(*uint32)(unsafe.Pointer(&hllData[16+queryCom.DenseDataLength])) = 0X000200FE
    64  	*(*uint32)(unsafe.Pointer(&hllData[20+queryCom.DenseDataLength])) = 0X000300FD
    65  	*(*uint32)(unsafe.Pointer(&hllData[24+queryCom.DenseDataLength])) = 0X000400FC
    66  
    67  	qc := AQLQueryContext{
    68  		OOPK: OOPKContext{
    69  			currentBatch: oopkBatchContext{
    70  				resultCapacity:   6,
    71  				dimensionVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&dimensionData[0])}, nullDevicePointer},
    72  				measureVectorD:   [2]devicePointer{{pointer: unsafe.Pointer(&measureData[0])}, nullDevicePointer},
    73  			},
    74  			hllVectorD:           devicePointer{pointer: unsafe.Pointer(&hllData[0])},
    75  			hllVectorSize:        queryCom.DenseDataLength + 28,
    76  			hllDimRegIDCountD:    devicePointer{pointer: unsafe.Pointer(&counts[0])},
    77  			ResultSize:           3,
    78  			NumDimsPerDimWidth:   queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 1},
    79  			DimensionVectorIndex: []int{0, 2, 1},
    80  		},
    81  	}
    82  
    83  	ginkgo.It("SerializeHLL should work", func() {
    84  		dataTypes := []memCom.DataType{memCom.Uint32, memCom.Uint8, memCom.Int16}
    85  		enumReverseDict := map[int][]string{1: {"a", "b", "c"}}
    86  		data, err := qc.SerializeHLL(dataTypes, enumReverseDict, nil)
    87  		Ω(err).Should(BeNil())
    88  		Ω(len(data)).Should(Equal(104 + queryCom.DenseDataLength + 32))
    89  		Ω(data[64:94]).Should(Equal([]byte{
    90  			0, 0, 0, 0,
    91  			1, 0, 0, 0,
    92  			0xFF, 0xFF, 0xFF, 0xFF, // dim0
    93  			0, 0,
    94  			2, 0,
    95  			2, 2, // dim1
    96  			0, 2, 3, // dim2
    97  			0, 1, 1, // dim0
    98  			0, 1, 1, // dim1
    99  			0, 1, 1, // dim2
   100  		}))
   101  		Ω(data[96:102]).Should(Equal((*(*[6]byte)(unsafe.Pointer(&counts[0])))[:]))
   102  		Ω(data[104 : 104+queryCom.DenseDataLength+28]).Should(Equal(hllData[:]))
   103  	})
   104  
   105  	ginkgo.It("Should work with timezone", func() {
   106  		timeDimensionData := []byte{
   107  			0, 0, 0, 0,
   108  			1, 0, 0, 0,
   109  			2, 0, 0, 0, // dim0
   110  			0, 0, 0, 0,
   111  			0, 0, 0, 0,
   112  			0, 0, 0, 0, // res cap.
   113  			0, 0,
   114  			2, 0,
   115  			2, 2, // dim1
   116  			0, 0,
   117  			0, 0,
   118  			0, 0, // res cap
   119  			0, 2, 3, // dim2
   120  			0, 0, 0, // res cap
   121  			0, 1, 1, // dim0
   122  			0, 0, 0, // res cap
   123  			0, 1, 1, // dim1
   124  			0, 0, 0, // res cap
   125  			0, 1, 1, // dim2
   126  			0, 0, 0, // res cap
   127  		}
   128  
   129  		measureData := [3]uint32{}
   130  		counts := []uint16{3, queryCom.DenseDataLength, 4}
   131  		hllData := [queryCom.DenseDataLength + 28]byte{}
   132  		*(*uint32)(unsafe.Pointer(&hllData[0])) = 0X00FF0001
   133  		*(*uint32)(unsafe.Pointer(&hllData[4])) = 0X00FE0002
   134  		*(*uint32)(unsafe.Pointer(&hllData[8])) = 0X00FD0003
   135  
   136  		hllData[12] = 1
   137  		hllData[13] = 1
   138  
   139  		*(*uint32)(unsafe.Pointer(&hllData[12+queryCom.DenseDataLength])) = 0X000100FF
   140  		*(*uint32)(unsafe.Pointer(&hllData[16+queryCom.DenseDataLength])) = 0X000200FE
   141  		*(*uint32)(unsafe.Pointer(&hllData[20+queryCom.DenseDataLength])) = 0X000300FD
   142  		*(*uint32)(unsafe.Pointer(&hllData[24+queryCom.DenseDataLength])) = 0X000400FC
   143  
   144  		loc, _ := time.LoadLocation("Africa/Algiers")
   145  		qc := AQLQueryContext{
   146  			OOPK: OOPKContext{
   147  				currentBatch: oopkBatchContext{
   148  					resultCapacity:   6,
   149  					dimensionVectorD: [2]devicePointer{{pointer: unsafe.Pointer(&timeDimensionData[0])}, nullDevicePointer},
   150  					measureVectorD:   [2]devicePointer{{pointer: unsafe.Pointer(&measureData[0])}, nullDevicePointer},
   151  				},
   152  				hllVectorD:           devicePointer{pointer: unsafe.Pointer(&hllData[0])},
   153  				hllVectorSize:        queryCom.DenseDataLength + 28,
   154  				hllDimRegIDCountD:    devicePointer{pointer: unsafe.Pointer(&counts[0])},
   155  				ResultSize:           3,
   156  				NumDimsPerDimWidth:   queryCom.DimCountsPerDimWidth{0, 0, 1, 1, 1},
   157  				DimensionVectorIndex: []int{0, 2, 1},
   158  			},
   159  			fixedTimezone: loc,
   160  			fromTime:      &alignedTime{Time: time.Now().In(loc), Unit: "week"},
   161  			toTime:        &alignedTime{Time: time.Now().In(loc), Unit: "week"},
   162  		}
   163  
   164  		dataTypes := []memCom.DataType{memCom.Uint32, memCom.Uint8, memCom.Int16}
   165  		enumReverseDict := map[int][]string{1: {"a", "b", "c", "d"}}
   166  		data, err := qc.SerializeHLL(dataTypes, enumReverseDict, []int{0})
   167  		Ω(err).Should(BeNil())
   168  		Ω(len(data)).Should(Equal(104 + queryCom.DenseDataLength + 32))
   169  		Ω(data[64:94]).Should(Equal([]byte{
   170  			0, 0, 0, 0,
   171  			0, 0, 0, 0,
   172  			0, 0, 0, 0, // dim0
   173  			0, 0,
   174  			2, 0,
   175  			2, 2, // dim1
   176  			0, 2, 3, // dim2
   177  			0, 1, 1, // dim0
   178  			0, 1, 1, // dim1
   179  			0, 1, 1, // dim2
   180  		}))
   181  		Ω(data[96:102]).Should(Equal((*(*[6]byte)(unsafe.Pointer(&counts[0])))[:]))
   182  		Ω(data[104 : 104+queryCom.DenseDataLength+28]).Should(Equal(hllData[:]))
   183  
   184  		// Then we deserialize it.
   185  		res, err := queryCom.NewTimeSeriesHLLResult(data, queryCom.HLLDataHeader)
   186  		Ω(err).Should(BeNil())
   187  		Ω(res).Should(Equal(queryCom.AQLQueryResult{
   188  			"NULL": map[string]interface{}{
   189  				"NULL": map[string]interface{}{
   190  					"NULL": queryCom.HLL{NonZeroRegisters: 3,
   191  						SparseData: []queryCom.HLLRegister{{Index: 1, Rho: 255}, {Index: 2, Rho: 254}, {Index: 3, Rho: 253}},
   192  					},
   193  				}},
   194  			"0": map[string]interface{}{
   195  				"c": map[string]interface{}{
   196  					"2": queryCom.HLL{NonZeroRegisters: 2, DenseData: hllData[12 : 12+queryCom.DenseDataLength]},
   197  				},
   198  				"d": map[string]interface{}{
   199  					"514": queryCom.HLL{NonZeroRegisters: 4, SparseData: []queryCom.HLLRegister{{Index: 255, Rho: 1}, {Index: 254, Rho: 2}, {Index: 253, Rho: 3}, {Index: 252, Rho: 4}}},
   200  				},
   201  			},
   202  		}))
   203  	})
   204  
   205  	ginkgo.It("Serialize and then deserialize should work", func() {
   206  		dataTypes := []memCom.DataType{memCom.Uint32, memCom.Uint8, memCom.Int16}
   207  		enumReverseDict := map[int][]string{1: {"a", "b", "c", "d"}}
   208  		data, err := qc.SerializeHLL(dataTypes, enumReverseDict, nil)
   209  		Ω(err).Should(BeNil())
   210  		//ioutil.WriteFile("../testing/data/query/hll", data, 0644)
   211  		res, err := queryCom.NewTimeSeriesHLLResult(data, queryCom.HLLDataHeader)
   212  		Ω(err).Should(BeNil())
   213  		Ω(res).Should(Equal(queryCom.AQLQueryResult{
   214  			"NULL": map[string]interface{}{
   215  				"NULL": map[string]interface{}{
   216  					"NULL": queryCom.HLL{NonZeroRegisters: 3,
   217  						SparseData: []queryCom.HLLRegister{{Index: 1, Rho: 255}, {Index: 2, Rho: 254}, {Index: 3, Rho: 253}},
   218  					},
   219  				}},
   220  			"1": map[string]interface{}{
   221  				"c": map[string]interface{}{
   222  					"2": queryCom.HLL{NonZeroRegisters: 2, DenseData: hllData[12 : 12+queryCom.DenseDataLength]},
   223  				},
   224  			},
   225  			"4294967295": map[string]interface{}{
   226  				"d": map[string]interface{}{
   227  					"514": queryCom.HLL{NonZeroRegisters: 4, SparseData: []queryCom.HLLRegister{{Index: 255, Rho: 1}, {Index: 254, Rho: 2}, {Index: 253, Rho: 3}, {Index: 252, Rho: 4}}},
   228  				},
   229  			}}))
   230  	})
   231  
   232  	ginkgo.It("write HLLQueryResults should work", func() {
   233  		dataTypes := []memCom.DataType{memCom.Uint32, memCom.Uint8, memCom.Int16}
   234  		enumReverseDict := map[int][]string{1: {"a", "b", "c", "d"}}
   235  
   236  		//queryE := NewHLLQueryResults()
   237  		//queryE.WriteResult([]byte{})
   238  		//err := ioutil.WriteFile("../testing/data/query/hll_empty_results", queryE.GetBytes(), 0644)
   239  
   240  		queryResults := NewHLLQueryResults()
   241  		data, err := qc.SerializeHLL(dataTypes, enumReverseDict, nil)
   242  		Ω(err).Should(BeNil())
   243  
   244  		queryResults.WriteResult(data)
   245  
   246  		results, errs, err := queryCom.ParseHLLQueryResults(queryResults.GetBytes())
   247  		Ω(err).Should(BeNil())
   248  		Ω(errs).Should(HaveLen(1))
   249  		Ω(errs[0]).Should(BeNil())
   250  		Ω(results).Should(HaveLen(1))
   251  		Ω(results[0]).Should(Equal(queryCom.AQLQueryResult{
   252  			"NULL": map[string]interface{}{
   253  				"NULL": map[string]interface{}{
   254  					"NULL": queryCom.HLL{NonZeroRegisters: 3,
   255  						SparseData: []queryCom.HLLRegister{{Index: 1, Rho: 255}, {Index: 2, Rho: 254}, {Index: 3, Rho: 253}},
   256  					},
   257  				}},
   258  			"1": map[string]interface{}{
   259  				"c": map[string]interface{}{
   260  					"2": queryCom.HLL{NonZeroRegisters: 2, DenseData: hllData[12 : 12+queryCom.DenseDataLength]},
   261  				},
   262  			},
   263  			"4294967295": map[string]interface{}{
   264  				"d": map[string]interface{}{
   265  					"514": queryCom.HLL{NonZeroRegisters: 4, SparseData: []queryCom.HLLRegister{{Index: 255, Rho: 1}, {Index: 254, Rho: 2}, {Index: 253, Rho: 3}, {Index: 252, Rho: 4}}},
   266  				},
   267  			}}))
   268  
   269  		queryResults.WriteError(errors.New("test"))
   270  		bs := queryResults.GetBytes()
   271  		//ioutil.WriteFile("../testing/data/query/hll_query_results", bs, 0644)
   272  
   273  		results, errs, err = queryCom.ParseHLLQueryResults(bs)
   274  		Ω(err).Should(BeNil())
   275  		Ω(errs).Should(HaveLen(2))
   276  		Ω(results).Should(HaveLen(2))
   277  		Ω(errs[1].Error()).Should(Equal("test"))
   278  	})
   279  })