github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/executor/transform/exec_test.go (about) 1 // Copyright (c) 2019 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package transform 22 23 import ( 24 "context" 25 "errors" 26 "testing" 27 "time" 28 29 "github.com/m3db/m3/src/query/block" 30 "github.com/m3db/m3/src/query/functions/utils" 31 "github.com/m3db/m3/src/query/models" 32 "github.com/m3db/m3/src/query/parser" 33 "github.com/m3db/m3/src/query/test" 34 xtest "github.com/m3db/m3/src/x/test" 35 36 "github.com/golang/mock/gomock" 37 "github.com/opentracing/opentracing-go" 38 "github.com/opentracing/opentracing-go/mocktracer" 39 "github.com/stretchr/testify/assert" 40 "github.com/stretchr/testify/require" 41 ) 42 43 func TestProcessSimpleBlock(t *testing.T) { 44 type testContext struct { 45 MockCtrl *gomock.Controller 46 Controller *Controller 47 ChildNode *MockOpNode 48 Node *MocksimpleOpNode 49 ResultBlock *block.MockBlock 50 SourceBlock block.Block 51 QueryCtx *models.QueryContext 52 } 53 54 setup := func(t *testing.T) (*testContext, func()) { 55 ctrl := xtest.NewController(t) 56 57 controller := &Controller{ 58 ID: parser.NodeID("foo"), 59 } 60 child := NewMockOpNode(ctrl) 61 controller.AddTransform(child) 62 63 step := time.Second 64 bounds := models.Bounds{ 65 StepSize: step, 66 Duration: step, 67 } 68 69 return &testContext{ 70 MockCtrl: ctrl, 71 Controller: controller, 72 SourceBlock: test.NewBlockFromValues(bounds, [][]float64{{1.0}}), 73 ResultBlock: block.NewMockBlock(ctrl), 74 Node: NewMocksimpleOpNode(ctrl), 75 ChildNode: child, 76 QueryCtx: models.NoopQueryContext(), 77 }, ctrl.Finish 78 } 79 80 doCall := func(tctx *testContext) error { 81 return ProcessSimpleBlock(tctx.Node, tctx.Controller, tctx.QueryCtx, tctx.Controller.ID, tctx.SourceBlock) 82 } 83 84 configureNode := func( 85 tctx *testContext, 86 blockType block.BlockType, 87 closeExpected bool, 88 ) { 89 tctx.Node.EXPECT().Params().Return(utils.StaticParams("foo")) 90 tctx.Node.EXPECT().ProcessBlock(gomock.Any(), gomock.Any(), gomock.Any()).Return(tctx.ResultBlock, nil) 91 tctx.ChildNode.EXPECT().Process(gomock.Any(), gomock.Any(), gomock.Any()) 92 tctx.ResultBlock.EXPECT().Info().Return(block.NewBlockInfo(blockType)) 93 if closeExpected { 94 tctx.ResultBlock.EXPECT().Close() 95 } 96 } 97 98 configureSuccessfulNode := func(tctx *testContext) { 99 configureNode(tctx, block.BlockM3TSZCompressed, true) 100 } 101 102 t.Run("closes next block", func(t *testing.T) { 103 tctx, closer := setup(t) 104 defer closer() 105 106 configureSuccessfulNode(tctx) 107 108 require.NoError(t, doCall(tctx)) 109 }) 110 111 configureLazyNode := func(tctx *testContext) { 112 configureNode(tctx, block.BlockLazy, false) 113 } 114 115 t.Run("does not close lazy block", func(t *testing.T) { 116 tctx, closer := setup(t) 117 defer closer() 118 119 configureLazyNode(tctx) 120 121 require.NoError(t, doCall(tctx)) 122 }) 123 124 t.Run("errors on process error", func(t *testing.T) { 125 tctx, closer := setup(t) 126 defer closer() 127 128 expectedErr := errors.New("test err") 129 tctx.Node.EXPECT().Params().Return(utils.StaticParams("foo")) 130 tctx.Node.EXPECT().ProcessBlock(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, expectedErr) 131 132 require.EqualError(t, doCall(tctx), expectedErr.Error()) 133 }) 134 135 t.Run("starts span with op type", func(t *testing.T) { 136 tctx, closer := setup(t) 137 defer closer() 138 139 configureSuccessfulNode(tctx) 140 tctx.Node.EXPECT().Params().Return(utils.StaticParams("foo")) 141 142 mtr := mocktracer.New() 143 144 sp := mtr.StartSpan("root") 145 tctx.QueryCtx.Ctx = opentracing.ContextWithSpan(context.Background(), sp) 146 147 require.NoError(t, doCall(tctx)) 148 sp.Finish() 149 150 spans := mtr.FinishedSpans() 151 152 require.Len(t, spans, 2) 153 assert.Equal(t, tctx.Node.Params().OpType(), spans[0].OperationName) 154 }) 155 }