vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/messager/engine_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package messager
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"vitess.io/vitess/go/mysql/fakesqldb"
    25  	"vitess.io/vitess/go/sqltypes"
    26  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    27  	"vitess.io/vitess/go/vt/vterrors"
    28  	"vitess.io/vitess/go/vt/vttablet/tabletserver/schema"
    29  	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"
    30  )
    31  
    32  var meTable = &schema.Table{
    33  	Type:        schema.Message,
    34  	MessageInfo: newMMTable().MessageInfo,
    35  }
    36  
    37  func TestEngineSchemaChanged(t *testing.T) {
    38  	db := fakesqldb.New(t)
    39  	defer db.Close()
    40  	engine := newTestEngine(db)
    41  	defer engine.Close()
    42  	tables := map[string]*schema.Table{
    43  		"t1": meTable,
    44  		"t2": {
    45  			Type: schema.NoType,
    46  		},
    47  	}
    48  	engine.schemaChanged(tables, []string{"t1", "t2"}, nil, nil)
    49  	got := extractManagerNames(engine.managers)
    50  	want := map[string]bool{"t1": true}
    51  	if !reflect.DeepEqual(got, want) {
    52  		t.Errorf("got: %+v, want %+v", got, want)
    53  	}
    54  	tables = map[string]*schema.Table{
    55  		"t1": meTable,
    56  		"t2": {
    57  			Type: schema.NoType,
    58  		},
    59  		"t3": meTable,
    60  	}
    61  	engine.schemaChanged(tables, []string{"t3"}, nil, nil)
    62  	got = extractManagerNames(engine.managers)
    63  	want = map[string]bool{"t1": true, "t3": true}
    64  	if !reflect.DeepEqual(got, want) {
    65  		t.Errorf("got: %+v, want %+v", got, want)
    66  	}
    67  	tables = map[string]*schema.Table{
    68  		"t1": meTable,
    69  		"t2": {
    70  			Type: schema.NoType,
    71  		},
    72  		"t4": meTable,
    73  	}
    74  	engine.schemaChanged(tables, []string{"t4"}, nil, []string{"t3", "t5"})
    75  	got = extractManagerNames(engine.managers)
    76  	want = map[string]bool{"t1": true, "t4": true}
    77  	if !reflect.DeepEqual(got, want) {
    78  		t.Errorf("got: %+v, want %+v", got, want)
    79  	}
    80  	// Test update
    81  	tables = map[string]*schema.Table{
    82  		"t1": meTable,
    83  		"t2": meTable,
    84  		"t4": {
    85  			Type: schema.NoType,
    86  		},
    87  	}
    88  	engine.schemaChanged(tables, nil, []string{"t2", "t4"}, nil)
    89  	got = extractManagerNames(engine.managers)
    90  	want = map[string]bool{"t1": true, "t2": true}
    91  	if !reflect.DeepEqual(got, want) {
    92  		t.Errorf("got: %+v, want %+v", got, want)
    93  	}
    94  }
    95  
    96  func extractManagerNames(in map[string]*messageManager) map[string]bool {
    97  	out := make(map[string]bool)
    98  	for k := range in {
    99  		out[k] = true
   100  	}
   101  	return out
   102  }
   103  
   104  func TestSubscribe(t *testing.T) {
   105  	db := fakesqldb.New(t)
   106  	defer db.Close()
   107  	engine := newTestEngine(db)
   108  	tables := map[string]*schema.Table{
   109  		"t1": meTable,
   110  		"t2": meTable,
   111  	}
   112  	engine.schemaChanged(tables, []string{"t1", "t2"}, nil, nil)
   113  	f1, ch1 := newEngineReceiver()
   114  	f2, ch2 := newEngineReceiver()
   115  	// Each receiver is subscribed to different managers.
   116  	engine.Subscribe(context.Background(), "t1", f1)
   117  	<-ch1
   118  	engine.Subscribe(context.Background(), "t2", f2)
   119  	<-ch2
   120  	engine.managers["t1"].Add(&MessageRow{Row: []sqltypes.Value{sqltypes.NewVarBinary("1")}})
   121  	engine.managers["t2"].Add(&MessageRow{Row: []sqltypes.Value{sqltypes.NewVarBinary("2")}})
   122  	<-ch1
   123  	<-ch2
   124  
   125  	// Error case.
   126  	want := "message table t3 not found"
   127  	_, err := engine.Subscribe(context.Background(), "t3", f1)
   128  	if err == nil || err.Error() != want {
   129  		t.Errorf("Subscribe: %v, want %s", err, want)
   130  	}
   131  
   132  	// After close, Subscribe should return a closed channel.
   133  	engine.Close()
   134  	_, err = engine.Subscribe(context.Background(), "t1", nil)
   135  	if got, want := vterrors.Code(err), vtrpcpb.Code_UNAVAILABLE; got != want {
   136  		t.Errorf("Subscribed on closed engine error code: %v, want %v", got, want)
   137  	}
   138  }
   139  
   140  func TestEngineGenerate(t *testing.T) {
   141  	db := fakesqldb.New(t)
   142  	defer db.Close()
   143  	engine := newTestEngine(db)
   144  	defer engine.Close()
   145  	engine.schemaChanged(map[string]*schema.Table{
   146  		"t1": meTable,
   147  	}, []string{"t1"}, nil, nil)
   148  
   149  	if _, err := engine.GetGenerator("t1"); err != nil {
   150  		t.Error(err)
   151  	}
   152  	want := "message table t2 not found in schema"
   153  	if _, err := engine.GetGenerator("t2"); err == nil || err.Error() != want {
   154  		t.Errorf("engine.GenerateAckQuery(invalid): %v, want %s", err, want)
   155  	}
   156  }
   157  
   158  func newTestEngine(db *fakesqldb.DB) *Engine {
   159  	config := tabletenv.NewDefaultConfig()
   160  	tsv := &fakeTabletServer{
   161  		Env: tabletenv.NewEnv(config, "MessagerTest"),
   162  	}
   163  	se := schema.NewEngine(tsv)
   164  	te := NewEngine(tsv, se, newFakeVStreamer())
   165  	te.Open()
   166  	return te
   167  }
   168  
   169  func newEngineReceiver() (f func(qr *sqltypes.Result) error, ch chan *sqltypes.Result) {
   170  	ch = make(chan *sqltypes.Result, 1)
   171  	return func(qr *sqltypes.Result) error {
   172  		ch <- qr
   173  		return nil
   174  	}, ch
   175  }