github.com/lbryio/lbcd@v0.22.119/config_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "regexp" 10 "runtime" 11 "testing" 12 ) 13 14 var ( 15 rpcuserRegexp = regexp.MustCompile("(?m)^rpcuser=.+$") 16 rpcpassRegexp = regexp.MustCompile("(?m)^rpcpass=.+$") 17 ) 18 19 // Define a struct "configCmdLineOnly" containing a subset of configuration 20 // parameters which are command-line only. These fields are copied line-by-line 21 // from "config" struct in "config.go", and the field names, types, and tags must 22 // match for the test to work. 23 type configCmdLineOnly struct { 24 ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` 25 DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` 26 DropCfIndex bool `long:"dropcfindex" description:"Deletes the index used for committed filtering (CF) support from the database on start up and then exits."` 27 DropTxIndex bool `long:"droptxindex" description:"Deletes the hash-based transaction index from the database on start up and then exits."` 28 DisableCheckpoints bool `long:"nocheckpoints" description:"Disable built-in checkpoints. Don't do this unless you know what you're doing."` 29 NoWinService bool `long:"nowinservice" description:"Do not start as a background service on Windows -- NOTE: This flag only works on the command line, not in the config file"` 30 DisableStallHandler bool `long:"nostalldetect" description:"Disables the stall handler system for each peer, useful in simnet/regtest integration tests frameworks"` 31 RegressionTest bool `long:"regtest" description:"Use the regression test network"` 32 SimNet bool `long:"simnet" description:"Use the simulation test network"` 33 SigNet bool `long:"signet" description:"Use the signet test network"` 34 SigNetChallenge string `long:"signetchallenge" description:"Connect to a custom signet network defined by this challenge instead of using the global default signet test network -- Can be specified multiple times"` 35 SigNetSeedNode []string `long:"signetseednode" description:"Specify a seed node for the signet network instead of using the global default signet network seed nodes"` 36 ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` 37 } 38 39 func fieldEq(f1, f2 reflect.StructField) bool { 40 return (f1.Name == f2.Name) && (f1.Type == f2.Type) && (f1.Tag == f2.Tag) 41 } 42 43 func TestSampleConfigFileComplete(t *testing.T) { 44 // find out where the sample config lives 45 _, path, _, ok := runtime.Caller(0) 46 if !ok { 47 t.Fatalf("Failed finding config file path") 48 } 49 sampleConfigFile := filepath.Join(filepath.Dir(path), sampleConfigFilename) 50 51 // Read the sample config file 52 content, err := ioutil.ReadFile(sampleConfigFile) 53 if err != nil { 54 t.Fatalf("Failed reading sample config file: %v", err) 55 } 56 57 allFields := reflect.VisibleFields(reflect.TypeOf(config{})) 58 cmdlineFields := reflect.VisibleFields(reflect.TypeOf(configCmdLineOnly{})) 59 60 // Verify cmdlineFields is a subset of allFields. 61 for _, cf := range cmdlineFields { 62 // Check for presence of field "cf" in config struct. 63 var field *reflect.StructField 64 for _, f := range allFields { 65 f := f // new instance of loop var for return 66 if fieldEq(cf, f) { 67 field = &f 68 break 69 } 70 } 71 if field == nil { 72 t.Errorf("cmdline field: %s type: %s is not present in type %s", 73 cf.Name, cf.Type, reflect.TypeOf(config{})) 74 } 75 } 76 77 // Verify sample config covers all parameters. 78 for _, f := range allFields { 79 longname, ok := f.Tag.Lookup("long") 80 if !ok { 81 // Field has no long-form name, so not eligible for 82 // inclusion in sample config. 83 continue 84 } 85 86 // Check for presence of field "f" in our configCmdLineOnly struct. 87 var cmdline *reflect.StructField 88 for _, cf := range cmdlineFields { 89 cf := cf // new instance of loop var for return 90 if fieldEq(cf, f) { 91 cmdline = &cf 92 break 93 } 94 } 95 96 // Look for assignment (<longname>="), or commented assignment ("; <longname>="). 97 pattern := fmt.Sprintf("(?m)^(;\\s*)?%s=.*$", longname) 98 assignment, err := regexp.Compile(pattern) 99 if err != nil { 100 t.Errorf("config field: %s longname: %s failed compiling regexp (%s): %v", 101 f.Name, longname, pattern, err) 102 continue 103 } 104 105 assigned := assignment.Match(content) 106 107 // Field "f" must be present in either the sample config (<longname>=X), 108 // or it must be one of the command line only fields, but not both. 109 if !assigned && (cmdline == nil) { 110 t.Errorf("config field: %s longname: %s assignment (%s) should be present in %s", 111 f.Name, longname, assignment, sampleConfigFilename) 112 } 113 if assigned && (cmdline != nil) { 114 t.Errorf("config field: %s longname: %s should not be present in both %s and type %s", 115 f.Name, longname, sampleConfigFilename, reflect.TypeOf(configCmdLineOnly{}).Name()) 116 } 117 } 118 } 119 120 func TestCreateDefaultConfigFile(t *testing.T) { 121 // find out where the sample config lives 122 _, path, _, ok := runtime.Caller(0) 123 if !ok { 124 t.Fatalf("Failed finding config file path") 125 } 126 sampleConfigFile := filepath.Join(filepath.Dir(path), "sample-lbcd.conf") 127 128 // Setup a temporary directory 129 tmpDir, err := ioutil.TempDir("", "lbcd") 130 if err != nil { 131 t.Fatalf("Failed creating a temporary directory: %v", err) 132 } 133 testpath := filepath.Join(tmpDir, "test.conf") 134 135 // copy config file to location of lbcd binary 136 data, err := ioutil.ReadFile(sampleConfigFile) 137 if err != nil { 138 t.Fatalf("Failed reading sample config file: %v", err) 139 } 140 appPath, err := filepath.Abs(filepath.Dir(os.Args[0])) 141 if err != nil { 142 t.Fatalf("Failed obtaining app path: %v", err) 143 } 144 tmpConfigFile := filepath.Join(appPath, "sample-lbcd.conf") 145 err = ioutil.WriteFile(tmpConfigFile, data, 0644) 146 if err != nil { 147 t.Fatalf("Failed copying sample config file: %v", err) 148 } 149 150 // Clean-up 151 defer func() { 152 os.Remove(testpath) 153 os.Remove(tmpConfigFile) 154 os.Remove(tmpDir) 155 }() 156 157 err = createDefaultConfigFile(testpath) 158 159 if err != nil { 160 t.Fatalf("Failed to create a default config file: %v", err) 161 } 162 163 content, err := ioutil.ReadFile(testpath) 164 if err != nil { 165 t.Fatalf("Failed to read generated default config file: %v", err) 166 } 167 168 if !rpcuserRegexp.Match(content) { 169 t.Error("Could not find rpcuser in generated default config file.") 170 } 171 172 if !rpcpassRegexp.Match(content) { 173 t.Error("Could not find rpcpass in generated default config file.") 174 } 175 }