// Reads the command line flags and the optional config file. func ParseCommandLine() *ServerConfig { siteURL := flag.String("personaOrigin", "", "Base URL that clients use to connect to the server") addr := flag.String("interface", DefaultInterface, "Address to bind to") authAddr := flag.String("adminInterface", DefaultAdminInterface, "Address to bind admin interface to") couchbaseURL := flag.String("url", DefaultServer, "Address of Couchbase server") poolName := flag.String("pool", DefaultPool, "Name of pool") bucketName := flag.String("bucket", "sync_gateway", "Name of bucket") dbName := flag.String("dbname", "", "Name of CouchDB database (defaults to name of bucket)") pretty := flag.Bool("pretty", false, "Pretty-print JSON responses") verbose := flag.Bool("verbose", false, "Log more info about requests") logKeys := flag.String("log", "", "Log keywords, comma separated") flag.Parse() var config *ServerConfig if flag.NArg() > 0 { // Read the configuration file(s), if any: for i := 0; i < flag.NArg(); i++ { filename := flag.Arg(i) c, err := ReadConfig(filename) if err != nil { base.LogFatal("Error reading config file %s: %v", filename, err) } if config == nil { config = c } else { if err := config.MergeWith(c); err != nil { base.LogFatal("Error reading config file %s: %v", filename, err) } } } // Override the config file with global settings from command line flags: if *addr != DefaultInterface { config.Interface = addr } if *authAddr != DefaultAdminInterface { config.AdminInterface = authAddr } if *pretty { config.Pretty = *pretty } if config.Log != nil { base.ParseLogFlags(config.Log) } if len(config.Databases) == 0 { base.LogFatal("No databases!") } if config.Interface == nil { config.Interface = &DefaultInterface } if config.AdminInterface == nil { config.AdminInterface = &DefaultAdminInterface } } else { // If no config file is given, create a default config, filled in from command line flags: if *dbName == "" { *dbName = *bucketName } config = &ServerConfig{ Interface: addr, AdminInterface: authAddr, Pretty: *pretty, Databases: map[string]*DbConfig{ *dbName: { Server: couchbaseURL, Bucket: bucketName, Pool: poolName, }, }, } } if *siteURL != "" { config.Persona = &PersonaConfig{Origin: *siteURL} } base.LogKeys["HTTP"] = true base.LogKeys["HTTP+"] = *verbose base.ParseLogFlag(*logKeys) return config }
//Test for wrong _changes entries for user joining a populated channel func TestUserJoiningPopulatedChannel(t *testing.T) { base.ParseLogFlags([]string{"Cache", "Cache+", "Changes", "Changes+", "CRUD"}) rt := restTester{syncFn: `function(doc) {channel(doc.channels)}`} a := rt.ServerContext().Database("db").Authenticator() guest, err := a.GetUser("") assert.Equals(t, err, nil) guest.SetDisabled(false) err = a.Save(guest) assert.Equals(t, err, nil) // Create user1 response := rt.sendAdminRequest("PUT", "/db/_user/user1", `{"email":"*****@*****.**", "password":"******", "admin_channels":["alpha"]}`) assertStatus(t, response, 201) // Create 100 docs for i := 0; i < 100; i++ { docpath := fmt.Sprintf("/db/doc%d", i) assertStatus(t, rt.send(request("PUT", docpath, `{"foo": "bar", "channels":["alpha"]}`)), 201) } // Check the _changes feed with limit, to split feed into two var changes struct { Results []db.ChangeEntry } limit := 50 response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes?limit=%d", limit), "", "user1")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 50) since := changes.Results[49].Seq assert.Equals(t, changes.Results[49].ID, "doc48") assert.Equals(t, since, db.SequenceID{Seq: 50}) //// Check the _changes feed with since and limit, to get second half of feed response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes?since=%s&limit=%d", since, limit), "", "user1")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 50) since = changes.Results[49].Seq assert.Equals(t, changes.Results[49].ID, "doc98") assert.Equals(t, since, db.SequenceID{Seq: 100}) // Create user2 response = rt.sendAdminRequest("PUT", "/db/_user/user2", `{"email":"*****@*****.**", "password":"******", "admin_channels":["alpha"]}`) assertStatus(t, response, 201) //Retrieve all changes for user2 with no limits response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes"), "", "user2")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 101) assert.Equals(t, changes.Results[99].ID, "doc99") // Create user3 response = rt.sendAdminRequest("PUT", "/db/_user/user3", `{"email":"*****@*****.**", "password":"******", "admin_channels":["alpha"]}`) assertStatus(t, response, 201) //Get first 50 document changes response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes?limit=%d", limit), "", "user3")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 50) since = changes.Results[49].Seq assert.Equals(t, changes.Results[49].ID, "doc49") assert.Equals(t, since, db.SequenceID{TriggeredBy: 103, Seq: 51}) //// Get remainder of changes i.e. no limit parameter response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes?since=%s", since), "", "user3")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 51) assert.Equals(t, changes.Results[49].ID, "doc99") // Create user4 response = rt.sendAdminRequest("PUT", "/db/_user/user4", `{"email":"*****@*****.**", "password":"******", "admin_channels":["alpha"]}`) assertStatus(t, response, 201) response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes?limit=%d", limit), "", "user4")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 50) since = changes.Results[49].Seq assert.Equals(t, changes.Results[49].ID, "doc49") assert.Equals(t, since, db.SequenceID{TriggeredBy: 104, Seq: 51}) //// Check the _changes feed with since and limit, to get second half of feed response = rt.send(requestByUser("GET", fmt.Sprintf("/db/_changes?since=%s&limit=%d", since, limit), "", "user4")) log.Printf("_changes looks like: %s", response.Body.Bytes()) err = json.Unmarshal(response.Body.Bytes(), &changes) assert.Equals(t, err, nil) assert.Equals(t, len(changes.Results), 50) assert.Equals(t, changes.Results[49].ID, "doc99") }