summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Minko <vitaly.minko@gmail.com>2019-02-01 13:27:31 +0300
committerVitaly Minko <vitaly.minko@gmail.com>2019-02-01 13:27:31 +0300
commitee5cada1b69920724dcd4ad4bb50dacb2de0d6d6 (patch)
tree69fa561ce0c2089c8bc1c27f2d62e2cdcc25c292
parenta68a34c96007f86345fa34008a2d1eac64bf93ca (diff)
Added several new autotests.
-rw-r--r--cmd/dscuss-cli/main.go2
-rw-r--r--config.go5
-rw-r--r--dscuss.go14
-rw-r--r--log/log.go10
-rw-r--r--p2p/connection_provider.go2
-rw-r--r--p2p/dht_crawler.go14
-rwxr-xr-xtestbed/dht.exp82
-rwxr-xr-xtestbed/saving_history.exp4
-rwxr-xr-xtestbed/syncing_messages.exp5
-rwxr-xr-xtestbed/syncing_operations.exp127
-rwxr-xr-xtestbed/updating_history.exp2
11 files changed, 251 insertions, 16 deletions
diff --git a/cmd/dscuss-cli/main.go b/cmd/dscuss-cli/main.go
index a3d665b..3531d63 100644
--- a/cmd/dscuss-cli/main.go
+++ b/cmd/dscuss-cli/main.go
@@ -27,6 +27,7 @@ import (
"os/signal"
"path/filepath"
"runtime"
+ "sort"
"strings"
"syscall"
"time"
@@ -291,6 +292,7 @@ func doListPeers(c *ishell.Context) {
}
peers := loginHandle.ListPeers()
if len(peers) > 0 {
+ sort.Sort(dscuss.ByNickname(peers))
if len(peers) > 1 {
c.Printf("There are %d connected peers:\n", len(peers))
} else {
diff --git a/config.go b/config.go
index c545fa9..69edf85 100644
--- a/config.go
+++ b/config.go
@@ -33,6 +33,7 @@ type NetworkConfig struct {
Port int
AddressProvider string
DHTPort int
+ DHTBootstrap string
MaxInConnCount uint32
MaxOutConnCount uint32
}
@@ -44,7 +45,9 @@ type config struct {
var defaultConfig = config{
Network: NetworkConfig{
Port: 8004,
- AddressProvider: "addrlist",
+ AddressProvider: "dht",
+ DHTPort: 0,
+ DHTBootstrap: "dscuss.org:6881",
MaxInConnCount: 10,
MaxOutConnCount: 10,
},
diff --git a/dscuss.go b/dscuss.go
index 0e4ca0c..d51fc16 100644
--- a/dscuss.go
+++ b/dscuss.go
@@ -46,6 +46,14 @@ type LoginHandle struct {
pp *p2p.PeerPool
}
+// ByNickname implements sort.Interface for []*peer.Info based on
+// the Nickname field.
+type ByNickname []*peer.Info
+
+func (a ByNickname) Len() int { return len(a) }
+func (a ByNickname) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByNickname) Less(i, j int) bool { return a[i].Nickname < a[j].Nickname }
+
const (
Name string = "Dscuss"
Version string = "0.1.0"
@@ -98,7 +106,9 @@ func Init(initDir string) error {
return errors.Filesystem
}
log.SetOutput(logFile)
- log.SetDebug(debug)
+ if debug {
+ log.EnableDebug()
+ }
var cfgPath string = filepath.Join(dir, cfgFileName)
cfg, err = newConfig(cfgPath)
@@ -165,7 +175,7 @@ func Login(nickname string) (*LoginHandle, error) {
ap = p2p.NewDHTCrawler(
cfg.Network.Address,
cfg.Network.DHTPort,
- "localhost:9117",
+ cfg.Network.DHTBootstrap,
cfg.Network.Port,
ownr.Profile.GetSubscriptions(),
)
diff --git a/log/log.go b/log/log.go
index db69468..67d55c9 100644
--- a/log/log.go
+++ b/log/log.go
@@ -26,7 +26,7 @@ import (
"strings"
)
-var debug bool
+var debug bool = false
// caller returns the name of the third function in the current stack.
func caller() string {
@@ -38,8 +38,12 @@ func caller() string {
return fmt.Sprintf("[%s]", trimmedName)
}
-func SetDebug(d bool) {
- debug = d
+func EnableDebug() {
+ debug = true
+}
+
+func IsDebugEnabled() bool {
+ return debug
}
func SetOutput(w io.Writer) {
diff --git a/p2p/connection_provider.go b/p2p/connection_provider.go
index aa7ad15..55d59cf 100644
--- a/p2p/connection_provider.go
+++ b/p2p/connection_provider.go
@@ -29,7 +29,7 @@ import (
const (
ConnectionProviderLatency time.Duration = 1 // in seconds
- DefaultBootstrapAddress string = "vminko.org:8004"
+ DefaultBootstrapAddress string = "dscuss.org:8004"
)
type addressMap struct {
diff --git a/p2p/dht_crawler.go b/p2p/dht_crawler.go
index 456dc57..3d06428 100644
--- a/p2p/dht_crawler.go
+++ b/p2p/dht_crawler.go
@@ -41,6 +41,7 @@ type DHTCrawler struct {
ac AddressConsumer
stopChan chan struct{}
wg sync.WaitGroup
+ processed map[string]struct{}
}
const (
@@ -61,6 +62,7 @@ func NewDHTCrawler(
advPort: advPort,
subs: s.ToCombinations(),
stopChan: make(chan struct{}),
+ processed: make(map[string]struct{}),
}
}
@@ -87,8 +89,10 @@ func (dc *DHTCrawler) Start() {
if err != nil {
log.Fatalf("Failed to create a DHT node: %v", err)
}
- dl := &dhtLogger{}
- dc.dht.DebugLogger = dl
+ if log.IsDebugEnabled() {
+ dl := &dhtLogger{}
+ dc.dht.DebugLogger = dl
+ }
err = dc.dht.Start()
if err != nil {
log.Fatalf("Failed to start DHT node: %v", err)
@@ -147,16 +151,20 @@ func (dc *DHTCrawler) drainAddresses() {
func (dc *DHTCrawler) handleNewAddress(a string) {
log.Debugf("Found new address: %s", a)
- // TBD: remove duplicates
if !address.IsValid(a) {
log.Warningf("DHT is poisoned, found malformed address %s", a)
return
}
+ if _, ok := dc.processed[a]; ok {
+ log.Debugf("Address '%s' has already been processed, skipping it", a)
+ return
+ }
if !isAddressLocal(a, dc.advPort) {
dc.ac.AddressFound(a)
} else {
log.Debugf("Skipping local address %s", a)
}
+ dc.processed[a] = struct{}{}
}
func localIPs() []string {
diff --git a/testbed/dht.exp b/testbed/dht.exp
new file mode 100755
index 0000000..4086f37
--- /dev/null
+++ b/testbed/dht.exp
@@ -0,0 +1,82 @@
+#!/usr/bin/expect -f
+#
+# Test assertion: peers A can use DHT to find address of other peers sharing common
+# interests.
+#
+# This file is part of Dscuss.
+# Copyright (C) 2019 Vitaly Minko
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+
+source testbed.exp
+
+say "Starting Adam's peer"
+spawn ../main -config "$tmp_dir/dht1"
+set adam_id $spawn_id
+expect "Welcome to Dscuss.\r\n"
+send "login adam\r"
+send "whoami\r"
+expect -re "adam (.*)\r\n"
+
+say "Starting Eve's peer"
+spawn ../main -config "$tmp_dir/dht2"
+set eve_id $spawn_id
+expect "Welcome to Dscuss.\r\n"
+send "login eve\r"
+send "whoami\r"
+expect -re "eve (.*)\r\n"
+
+say "Starting Cain's peer"
+spawn ../main -config "$tmp_dir/dht3"
+set cain_id $spawn_id
+expect "Welcome to Dscuss.\r\n"
+send "login cain\r"
+send "whoami\r"
+expect -re "cain (.*)\r\n"
+
+say "Giving peers some time to perform handshaking"
+sleep 20
+
+say "Checking whether peers see each other"
+set spawn_id $adam_id
+send "lspeers\r"
+expect "There are 2 connected peers:\r\n"
+expect -re "cain-.*? is Idle\r\n"
+expect -re "eve-.*? is Idle\r\n"
+
+set spawn_id $eve_id
+send "lspeers\r"
+expect "There are 2 connected peers:\r\n"
+expect -re "adam-.*? is Idle\r\n"
+expect -re "cain-.*? is Idle\r\n"
+
+set spawn_id $cain_id
+send "lspeers\r"
+expect "There are 2 connected peers:\r\n"
+expect -re "adam-.*? is Idle\r\n"
+expect -re "eve-.*? is Idle\r\n"
+
+say "Stopping all peers"
+set spawn_id $adam_id
+send "exit\r"
+expect eof
+wait
+set spawn_id $eve_id
+send "exit\r"
+expect eof
+wait
+set spawn_id $cain_id
+send "exit\r"
+expect eof
+wait
+pass
diff --git a/testbed/saving_history.exp b/testbed/saving_history.exp
index 2775251..a6a2120 100755
--- a/testbed/saving_history.exp
+++ b/testbed/saving_history.exp
@@ -1,7 +1,7 @@
#!/usr/bin/expect -f
#
-# Test assertion: when a synced user disconnects, owner will update user history
-# with the last user's subscriptions and the disconnection time.
+# Test assertion: when a synced user disconnects for the first time, owner will
+# save user's history (user's subscriptions and the disconnection time).
#
# This file is part of Dscuss.
# Copyright (C) 2019 Vitaly Minko
diff --git a/testbed/syncing_messages.exp b/testbed/syncing_messages.exp
index 766d1f0..3e1ee25 100755
--- a/testbed/syncing_messages.exp
+++ b/testbed/syncing_messages.exp
@@ -1,10 +1,9 @@
#!/usr/bin/expect -f
#
-# Test assertion: a newly created thread will be delivered only to the peers,
-# which are interested in the topic of the thread.
+# Test assertion: when a known user reconnects, he/she will receive missed messages.
#
# This file is part of Dscuss.
-# Copyright (C) 2018 Vitaly Minko
+# Copyright (C) 2018-2019 Vitaly Minko
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
diff --git a/testbed/syncing_operations.exp b/testbed/syncing_operations.exp
new file mode 100755
index 0000000..76cf559
--- /dev/null
+++ b/testbed/syncing_operations.exp
@@ -0,0 +1,127 @@
+#!/usr/bin/expect -f
+#
+# Test assertion: when a known user reconnects, he/she will receive missed
+# operations.
+#
+# This file is part of Dscuss.
+# Copyright (C) 2019 Vitaly Minko
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+
+source testbed.exp
+
+say "Starting Adam's peer"
+spawn ../main -config "$tmp_dir/1"
+set adam_id $spawn_id
+expect "> "
+send "login adam\r"
+expect "> "
+send "whoami\r"
+expect -re "adam (.*)\r\n"
+
+say "Removing message KBOAel96xEa77/emOI0omi4KxXkpzDJ5o8+HCG9Dw9A="
+set spawn_id $adam_id
+send "rmmsg KBOAel96xEa77/emOI0omi4KxXkpzDJ5o8+HCG9Dw9A= SPAM\r"
+expect "Enter optional comment: "
+send "Testing remove-message operation\r"
+expect "> "
+
+say "Starting Eve's peer"
+spawn ../main -config "$tmp_dir/2"
+set eve_id $spawn_id
+expect "> "
+send "login eve\r"
+expect "> "
+send "whoami\r"
+expect -re "eve (.*)\r\n"
+send "mkmdr 8vBHkCKnH/QiLeN8cXduVLG8BGfAMkiFtwKELEH3Gyc=\r"
+expect "> "
+
+say "Starting Cain's peer"
+spawn ../main -config "$tmp_dir/3"
+set cain_id $spawn_id
+expect "> "
+send "login cain\r"
+expect "> "
+send "whoami\r"
+expect -re "cain (.*)\r\n"
+send "mkmdr 8vBHkCKnH/QiLeN8cXduVLG8BGfAMkiFtwKELEH3Gyc=\r"
+expect "> "
+
+say "Giving peers some time to perform handshaking and syncing"
+sleep 10
+
+say "Checking whether Eve has applied the operation"
+set spawn_id $eve_id
+send "lsthread 9ErpRDUJMUBd5NirpnLWeDRefi+tr4VuN+5BwA7HQRs=\r"
+expect -re "Topic:.*?ID: 9ErpRDUJMUBd5NirpnLWeDRefi\\+tr4VuN\\+5BwA7HQRs=\r\n"
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "B5j6JtxfI5j3/P0BBqZ4BEZiRKalHW8FHJSZ1CZJoJ0=" } {
+ fail
+}
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "6rMa+H3M+RKGfsjb0m/pUkG9sUYi/nlaqw9pTfEjMOk=" } {
+ fail
+}
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "w3u/8l/S1PbTJ1TYR+mKjnr1obIXJzUDkIIgrKgmkS0=" } {
+ fail
+}
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "4IRs5MOl/eyfaEoEoRO5kE/9zHJRRuf3Pvk8lil/VpU=" } {
+ fail
+}
+expect {
+ -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n" { fail }
+ ">"
+}
+
+say "Checking whether Cain has applied the operation"
+set spawn_id $cain_id
+send "lsthread 9ErpRDUJMUBd5NirpnLWeDRefi+tr4VuN+5BwA7HQRs=\r"
+expect -re "Topic:.*?ID: 9ErpRDUJMUBd5NirpnLWeDRefi\\+tr4VuN\\+5BwA7HQRs=\r\n"
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "B5j6JtxfI5j3/P0BBqZ4BEZiRKalHW8FHJSZ1CZJoJ0=" } {
+ fail
+}
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "6rMa+H3M+RKGfsjb0m/pUkG9sUYi/nlaqw9pTfEjMOk=" } {
+ fail
+}
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "w3u/8l/S1PbTJ1TYR+mKjnr1obIXJzUDkIIgrKgmkS0=" } {
+ fail
+}
+expect -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n"
+if { $expect_out(1,string) != "4IRs5MOl/eyfaEoEoRO5kE/9zHJRRuf3Pvk8lil/VpU=" } {
+ fail
+}
+expect {
+ -re "\\s+?Subject:.*?ID: (\[a-zA-Z0-9/=\\+\]+)\r\n" { fail }
+ ">"
+}
+
+say "Stopping all peers"
+set spawn_id $adam_id
+send "exit\r"
+expect eof
+wait
+set spawn_id $eve_id
+send "exit\r"
+expect eof
+wait
+set spawn_id $cain_id
+send "exit\r"
+expect eof
+wait
+pass
diff --git a/testbed/updating_history.exp b/testbed/updating_history.exp
index 69ae8ad..9711d50 100755
--- a/testbed/updating_history.exp
+++ b/testbed/updating_history.exp
@@ -1,6 +1,6 @@
#!/usr/bin/expect -f
#
-# Test assertion: when a synced user disconnects, owner will update user history
+# Test assertion: when a synced user disconnects, owner will update user's history
# with the last user's subscriptions and the disconnection time.
#
# This file is part of Dscuss.