github.com/go-kivik/kivik/v4@v4.3.2/mockdb/gen/main.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 12 13 // Package main generates the bulk of the mockdb driver. 14 package main 15 16 import ( 17 "os" 18 "reflect" 19 "sort" 20 21 "github.com/go-kivik/kivik/v4" 22 "github.com/go-kivik/kivik/v4/driver" 23 ) 24 25 var clientSkips = map[string]struct{}{ 26 "Driver": {}, 27 "DSN": {}, 28 "CreateDB": {}, 29 } 30 31 var dbSkips = map[string]struct{}{ 32 "Close": {}, 33 "Client": {}, 34 "Err": {}, 35 "Name": {}, 36 "Search": {}, 37 "SearchAnalyze": {}, 38 "SearchInfo": {}, 39 } 40 41 func main() { 42 initTemplates(os.Args[1]) 43 const openPerms = 0o777 44 if err := os.Mkdir("./other", openPerms); err != nil && !os.IsExist(err) { 45 panic(err) 46 } 47 if err := client(); err != nil { 48 panic(err) 49 } 50 if err := db(); err != nil { 51 panic(err) 52 } 53 } 54 55 type fullClient interface { 56 driver.Client 57 driver.DBsStatser 58 driver.AllDBsStatser 59 driver.Pinger 60 driver.Sessioner 61 driver.Cluster 62 driver.ClientCloser 63 driver.ClientReplicator 64 driver.DBUpdater 65 driver.Configer 66 } 67 68 func client() error { 69 dMethods, err := parseMethods(struct{ X fullClient }{}, false, clientSkips) // nolint: unused 70 if err != nil { 71 return err 72 } 73 74 client, err := parseMethods(struct{ X *kivik.Client }{}, true, clientSkips) // nolint: unused 75 if err != nil { 76 return err 77 } 78 same, cm, dm := compareMethods(client, dMethods) 79 80 if err := renderExpectationsGo("clientexpectations_gen.go", append(same, dm...)); err != nil { 81 return err 82 } 83 if err := renderClientGo("client_gen.go", append(same, dm...)); err != nil { 84 return err 85 } 86 return renderMockGo("clientmock_gen.go", append(same, cm...)) 87 } 88 89 type fullDB interface { 90 driver.DB 91 driver.DocCreator 92 driver.AttachmentMetaGetter 93 driver.BulkDocer 94 driver.BulkGetter 95 driver.Copier 96 driver.DesignDocer 97 driver.Finder 98 driver.Flusher 99 driver.LocalDocer 100 driver.RevGetter 101 driver.Purger 102 driver.RevsDiffer 103 driver.PartitionedDB 104 driver.SecurityDB 105 driver.OpenRever 106 } 107 108 func db() error { 109 dMethods, err := parseMethods(struct{ X fullDB }{}, false, dbSkips) // nolint: unused 110 if err != nil { 111 return err 112 } 113 114 client, err := parseMethods(struct{ X *kivik.DB }{}, true, dbSkips) // nolint: unused 115 if err != nil { 116 return err 117 } 118 same, cm, dm := compareMethods(client, dMethods) 119 120 for _, method := range same { 121 method.DBMethod = true 122 } 123 for _, method := range dm { 124 method.DBMethod = true 125 } 126 for _, method := range cm { 127 method.DBMethod = true 128 } 129 130 if err := renderExpectationsGo("dbexpectations_gen.go", append(same, dm...)); err != nil { 131 return err 132 } 133 if err := renderClientGo("db_gen.go", append(same, dm...)); err != nil { 134 return err 135 } 136 return renderMockGo("dbmock_gen.go", append(same, cm...)) 137 } 138 139 func compareMethods(client, driver []*method) (same []*method, differentClient []*method, differentDriver []*method) { 140 dMethods := toMap(driver) 141 cMethods := toMap(client) 142 sameMethods := make(map[string]*method) 143 for name, method := range dMethods { 144 if cMethod, ok := cMethods[name]; ok { 145 if reflect.DeepEqual(cMethod, method) { 146 sameMethods[name] = method 147 delete(dMethods, name) 148 delete(cMethods, name) 149 } 150 } else { 151 delete(dMethods, name) 152 delete(cMethods, name) 153 } 154 } 155 return toSlice(sameMethods), toSlice(cMethods), toSlice(dMethods) 156 } 157 158 func toSlice(methods map[string]*method) []*method { 159 result := make([]*method, 0, len(methods)) 160 for _, method := range methods { 161 result = append(result, method) 162 } 163 sort.Slice(result, func(i, j int) bool { 164 return result[i].Name < result[j].Name 165 }) 166 return result 167 } 168 169 func toMap(methods []*method) map[string]*method { 170 result := make(map[string]*method, len(methods)) 171 for _, method := range methods { 172 result[method.Name] = method 173 } 174 return result 175 }