github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/schemareplicant/perfschema/tables_test.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package perfschema_test 15 16 import ( 17 "fmt" 18 "io" 19 "net/http" 20 "net/http/httptest" 21 "os" 22 "path/filepath" 23 "runtime" 24 "runtime/pprof" 25 "strings" 26 "testing" 27 28 "github.com/whtcorpsinc/BerolinaSQL/terror" 29 . "github.com/whtcorpsinc/check" 30 "github.com/whtcorpsinc/failpoint" 31 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 32 "github.com/whtcorpsinc/milevadb/ekv" 33 "github.com/whtcorpsinc/milevadb/petri" 34 "github.com/whtcorpsinc/milevadb/schemareplicant/perfschema" 35 "github.com/whtcorpsinc/milevadb/soliton/testkit" 36 "github.com/whtcorpsinc/milevadb/soliton/testleak" 37 "github.com/whtcorpsinc/milevadb/stochastik" 38 ) 39 40 func TestT(t *testing.T) { 41 CustomVerboseFlag = true 42 TestingT(t) 43 } 44 45 var _ = Suite(&testBlockSuite{}) 46 47 type testBlockSuite struct { 48 causetstore ekv.CausetStorage 49 dom *petri.Petri 50 } 51 52 func (s *testBlockSuite) SetUpSuite(c *C) { 53 testleak.BeforeTest() 54 55 var err error 56 s.causetstore, err = mockstore.NewMockStore() 57 c.Assert(err, IsNil) 58 stochastik.DisableStats4Test() 59 s.dom, err = stochastik.BootstrapStochastik(s.causetstore) 60 c.Assert(err, IsNil) 61 } 62 63 func (s *testBlockSuite) TearDownSuite(c *C) { 64 defer testleak.AfterTest(c)() 65 s.dom.Close() 66 s.causetstore.Close() 67 } 68 69 func (s *testBlockSuite) TestPredefinedBlocks(c *C) { 70 c.Assert(perfschema.IsPredefinedBlock("EVENTS_memexs_summary_by_digest"), IsTrue) 71 c.Assert(perfschema.IsPredefinedBlock("memexs"), IsFalse) 72 } 73 74 func (s *testBlockSuite) TestPerfSchemaBlocks(c *C) { 75 tk := testkit.NewTestKit(c, s.causetstore) 76 77 tk.MustInterDirc("use performance_schema") 78 tk.MustQuery("select * from global_status where variable_name = 'Ssl_verify_mode'").Check(testkit.Events()) 79 tk.MustQuery("select * from stochastik_status where variable_name = 'Ssl_verify_mode'").Check(testkit.Events()) 80 tk.MustQuery("select * from setup_actors").Check(testkit.Events()) 81 tk.MustQuery("select * from events_stages_history_long").Check(testkit.Events()) 82 } 83 84 func currentSourceDir() string { 85 _, file, _, _ := runtime.Caller(0) 86 return filepath.Dir(file) 87 } 88 89 func (s *testBlockSuite) TestEinsteinDBProfileCPU(c *C) { 90 router := http.NewServeMux() 91 mockServer := httptest.NewServer(router) 92 mockAddr := strings.TrimPrefix(mockServer.URL, "http://") 93 defer mockServer.Close() 94 95 copyHandler := func(filename string) http.HandlerFunc { 96 return func(w http.ResponseWriter, _ *http.Request) { 97 file, err := os.Open(filepath.Join(currentSourceDir(), filename)) 98 if err != nil { 99 http.Error(w, err.Error(), http.StatusBadRequest) 100 return 101 } 102 defer func() { terror.Log(file.Close()) }() 103 _, err = io.Copy(w, file) 104 terror.Log(err) 105 } 106 } 107 // mock einsteindb profile 108 router.HandleFunc("/debug/pprof/profile", copyHandler("testdata/einsteindb.cpu.profile")) 109 110 // failpoint setting 111 servers := []string{ 112 strings.Join([]string{"einsteindb", mockAddr, mockAddr}, ","), 113 strings.Join([]string{"fidel", mockAddr, mockAddr}, ","), 114 } 115 fpExpr := strings.Join(servers, ";") 116 fpName := "github.com/whtcorpsinc/milevadb/schemareplicant/perfschema/mockRemoteNodeStatusAddress" 117 c.Assert(failpoint.Enable(fpName, fmt.Sprintf(`return("%s")`, fpExpr)), IsNil) 118 defer func() { c.Assert(failpoint.Disable(fpName), IsNil) }() 119 120 tk := testkit.NewTestKit(c, s.causetstore) 121 122 tk.MustInterDirc("use performance_schema") 123 result := tk.MustQuery("select function, percent_abs, percent_rel from einsteindb_profile_cpu where depth < 3") 124 125 warnings := tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 126 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 127 128 result.Check(testkit.Events( 129 "root 100% 100%", 130 "├─einsteindb::server::load_statistics::linux::ThreadLoadStatistics::record::h59facb8d680e7794 75.00% 75.00%", 131 "│ └─procinfo::pid::stat::stat_task::h69e1aa2c331aebb6 75.00% 100%", 132 "├─nom::nom::digit::h905aaaeff7d8ec8e 16.07% 16.07%", 133 "│ ├─<embedded::iter::adapters::Enumerate<I> as embedded::iter::traits::iterator::Iterator>::next::h16936f9061bb75e4 6.25% 38.89%", 134 "│ ├─Unknown 3.57% 22.22%", 135 "│ ├─<&u8 as nom::traits::AsChar>::is_dec_digit::he9eacc3fad26ab81 2.68% 16.67%", 136 "│ ├─<&[u8] as nom::traits::InputIter>::iter_indices::h6192338433683bff 1.79% 11.11%", 137 "│ └─<&[T] as nom::traits::Slice<embedded::ops::range::RangeFrom<usize>>>::slice::h38d31f11f84aa302 1.79% 11.11%", 138 "├─<jemallocator::Jemalloc as embedded::alloc::GlobalAlloc>::realloc::h5199c50710ab6f9d 1.79% 1.79%", 139 "│ └─rallocx 1.79% 100%", 140 "├─<jemallocator::Jemalloc as embedded::alloc::GlobalAlloc>::dealloc::hea83459aa98dd2dc 1.79% 1.79%", 141 "│ └─sdallocx 1.79% 100%", 142 "├─<jemallocator::Jemalloc as embedded::alloc::GlobalAlloc>::alloc::hc7962e02169a5c56 0.89% 0.89%", 143 "│ └─mallocx 0.89% 100%", 144 "├─engine::rocks::soliton::engine_metrics::flush_engine_iostall_properties::h64a7661c95aa1db7 0.89% 0.89%", 145 "│ └─lmdb::lmdb::EDB::get_map_property_cf::h9722f9040411af44 0.89% 100%", 146 "├─embedded::ptr::real_drop_in_place::h8def0d99e7136f33 0.89% 0.89%", 147 "│ └─<alloc::raw_vec::RawVec<T,A> as embedded::ops::drop::Drop>::drop::h9b59b303bffde02c 0.89% 100%", 148 "├─einsteindb_util::metrics::threads_linux::ThreadInfoStatistics::record::ha8cc290b3f46af88 0.89% 0.89%", 149 "│ └─procinfo::pid::stat::stat_task::h69e1aa2c331aebb6 0.89% 100%", 150 "├─crossbeam_utils::backoff::Backoff::snooze::h5c121ef4ce616a3c 0.89% 0.89%", 151 "│ └─embedded::iter::range::<impl embedded::iter::traits::iterator::Iterator for embedded::ops::range::Range<A>>::next::hdb23ceb766e7a91f 0.89% 100%", 152 "└─<hashbrown::raw::bitmask::BitMaskIter as embedded::iter::traits::iterator::Iterator>::next::he129c78b3deb639d 0.89% 0.89%", 153 " └─Unknown 0.89% 100%")) 154 155 // We can use current processe profile to mock profile of FIDel because the FIDel has the 156 // same way of retrieving profile with MilevaDB. And the purpose of this test case is used 157 // to make sure all profile HTTP API have been accessed. 158 accessed := map[string]struct{}{} 159 handlerFactory := func(name string, debug ...int) func(w http.ResponseWriter, _ *http.Request) { 160 debugLevel := 0 161 if len(debug) > 0 { 162 debugLevel = debug[0] 163 } 164 return func(w http.ResponseWriter, _ *http.Request) { 165 profile := pprof.Lookup(name) 166 if profile == nil { 167 http.Error(w, fmt.Sprintf("profile %s not found", name), http.StatusBadRequest) 168 return 169 } 170 if err := profile.WriteTo(w, debugLevel); err != nil { 171 http.Error(w, err.Error(), http.StatusBadRequest) 172 return 173 } 174 accessed[name] = struct{}{} 175 } 176 } 177 178 // mock FIDel profile 179 router.HandleFunc("/fidel/api/v1/debug/pprof/profile", copyHandler("../../soliton/profile/testdata/test.pprof")) 180 router.HandleFunc("/fidel/api/v1/debug/pprof/heap", handlerFactory("heap")) 181 router.HandleFunc("/fidel/api/v1/debug/pprof/mutex", handlerFactory("mutex")) 182 router.HandleFunc("/fidel/api/v1/debug/pprof/allocs", handlerFactory("allocs")) 183 router.HandleFunc("/fidel/api/v1/debug/pprof/causet", handlerFactory("causet")) 184 router.HandleFunc("/fidel/api/v1/debug/pprof/goroutine", handlerFactory("goroutine", 2)) 185 186 tk.MustQuery("select * from FIDel_profile_cpu where depth < 3") 187 warnings = tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 188 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 189 190 tk.MustQuery("select * from FIDel_profile_memory where depth < 3") 191 warnings = tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 192 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 193 194 tk.MustQuery("select * from FIDel_profile_mutex where depth < 3") 195 warnings = tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 196 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 197 198 tk.MustQuery("select * from FIDel_profile_allocs where depth < 3") 199 warnings = tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 200 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 201 202 tk.MustQuery("select * from FIDel_profile_block where depth < 3") 203 warnings = tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 204 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 205 206 tk.MustQuery("select * from FIDel_profile_goroutines") 207 warnings = tk.Se.GetStochastikVars().StmtCtx.GetWarnings() 208 c.Assert(len(warnings), Equals, 0, Commentf("expect no warnings, but found: %+v", warnings)) 209 210 c.Assert(len(accessed), Equals, 5, Commentf("expect all HTTP API had been accessed, but found: %v", accessed)) 211 }