| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- package ovpm
- import (
- "fmt"
- "io"
- "reflect"
- "strings"
- "testing"
- "time"
- "github.com/cad/ovpm/pki"
- "github.com/cad/ovpm/supervisor"
- "github.com/sirupsen/logrus"
- )
- var fs map[string]string
- func setupTestCase() {
- // Initialize.
- fs = make(map[string]string)
- vpnProc.Stop()
- }
- func TestVPNInit(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Prepare:
- // Test:
- // Check database if the database has no server.
- var server dbServerModel
- db.First(&server)
- // Isn't server empty struct?
- if !db.NewRecord(&server) {
- t.Fatalf("server is expected to be empty struct(new record) but it isn't %+v", server)
- }
- // Wrongfully initialize server.
- if err := TheServer().Init("localhost", "asdf", UDPProto, "", "", "", "", false); err == nil {
- t.Fatalf("error is expected to be not nil but it's nil instead")
- }
- // Initialize the server.
- TheServer().Init("localhost", "", UDPProto, "", "", "", "", false)
- // Check database if the database has no server.
- var server2 dbServerModel
- db.First(&server2)
- // Is server empty struct?
- if db.NewRecord(&server2) {
- t.Fatalf("server is expected to be not empty struct(new record) but it is %+v", server2)
- }
- }
- func TestVPNDeinit(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Prepare:
- // Initialize the server.
- TheServer().Init("localhost", "", UDPProto, "", "", "", "", false)
- u, err := CreateNewUser("user", "p", false, 0, true, "description")
- if err != nil {
- t.Fatal(err)
- }
- u.Delete()
- // Test:
- var server dbServerModel
- db.First(&server)
- // Isn't server empty struct?
- if db.NewRecord(&server) {
- t.Fatalf("server is expected to be not empty struct(new record) but it is %+v", server)
- }
- // Test if Revoked table contains the removed user's entries.
- var revoked dbRevokedModel
- db.First(&revoked)
- if db.NewRecord(&revoked) {
- t.Errorf("revoked shouldn't be empty")
- }
- // Deinitialize.
- TheServer().Deinit()
- // Get server from db.
- var server2 dbServerModel
- db.First(&server2)
- // Isn't server empty struct?
- if !db.NewRecord(&server2) {
- t.Fatalf("server is expected to be empty struct(new record) but it is not %+v", server2)
- }
- // Test if Revoked table contains the removed user's entries.
- var revoked2 dbRevokedModel
- db.First(&revoked2)
- // Is revoked empty?
- if !db.NewRecord(&revoked2) {
- t.Errorf("revoked should be empty")
- }
- }
- func TestVPNUpdate(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Prepare:
- TheServer().Init("localhost", "", UDPProto, "", "", "", "", false)
- // Test:
- var updatetests = []struct {
- vpnnet string
- dns string
- useLZO *bool
- vpnChanged bool
- dnsChanged bool
- }{
- {"", "", nil, false, false},
- {"192.168.9.0/24", "", nil, true, false},
- {"", "2.2.2.2", nil, false, true},
- {"9.9.9.0/24", "1.1.1.1", nil, true, true},
- {"9.9.9.0/24", "1.1.1.1", nil, true, true},
- }
- for i, tt := range updatetests {
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- oldIP := svr.Net
- oldDNS := svr.DNS
- svr.Update(tt.vpnnet, tt.dns, tt.useLZO)
- svr = nil
- svr = TheServer()
- if (svr.Net != oldIP) != tt.vpnChanged {
- fmt.Println(i, svr.Net, oldIP, svr.Net == oldIP, tt.vpnChanged)
- t.Fatalf("expected vpn change: %t but opposite happened", tt.vpnChanged)
- }
- if (svr.DNS != oldDNS) != tt.dnsChanged {
- t.Fatalf("expected vpn change: %t but opposite happened", tt.dnsChanged)
- }
- }
- }
- func TestVPNIsInitialized(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Prepare:
- // Test:
- // Is initialized?
- if TheServer().IsInitialized() {
- t.Fatalf("IsInitialized() is expected to return false but it returned true")
- }
- // Initialize the server.
- TheServer().Init("localhost", "", UDPProto, "", "", "", "", false)
- // Isn't initialized?
- if !TheServer().IsInitialized() {
- t.Fatalf("IsInitialized() is expected to return true but it returned false")
- }
- }
- func TestVPNTheServer(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Prepare:
- // Test:
- svr := TheServer()
- // Isn't server nil?
- if svr.IsInitialized() {
- t.Fatal("server is expected to be not initialized it is")
- }
- // Initialize server.
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- svr = TheServer()
- // Is server nil?
- if !svr.IsInitialized() {
- t.Fatal("server is expected to be initialized but it's not")
- }
- }
- func TestVPNDumpsClientConfig(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Prepare:
- user, _ := CreateNewUser("user", "password", false, 0, true, "description")
- // Test:
- clientConfigBlob, err := svr.DumpsClientConfig(user.GetUsername())
- if err != nil {
- t.Fatalf("expected to dump client config but we got error instead: %v", err)
- }
- // Is empty?
- if len(clientConfigBlob) == 0 {
- t.Fatal("expected the dump not empty but it's empty instead")
- }
- }
- func TestVPNDumpClientConfig(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Prepare:
- noGW := false
- user, err := CreateNewUser("user", "password", noGW, 0, true, "description")
- if err != nil {
- t.Fatalf("can not create user: %v", err)
- }
- // Test:
- if err = svr.DumpClientConfig(user.GetUsername(), "/tmp/user.ovpn"); err != nil {
- t.Fatalf("expected to dump client config but we got error instead: %v", err)
- }
- // Read file.
- clientConfigBlob := fs["/tmp/user.ovpn"]
- // Is empty?
- if len(clientConfigBlob) == 0 {
- t.Fatal("expected the dump not empty but it's empty instead")
- }
- // Is noGW honored?
- if strings.Contains(clientConfigBlob, "route-nopull") != noGW {
- logrus.Info(clientConfigBlob)
- t.Fatalf("client config generator doesn't honor NoGW")
- }
- user.Delete()
- noGW = true
- user, err = CreateNewUser("user", "password", noGW, 0, true, "description")
- if err != nil {
- t.Fatalf("can not create user: %v", err)
- }
- if err = TheServer().DumpClientConfig(user.GetUsername(), "/tmp/user.ovpn"); err != nil {
- t.Fatalf("expected to dump client config but we got error instead: %v", err)
- }
- // Read file.
- clientConfigBlob = fs["/tmp/user.ovpn"]
- }
- func TestVPNGetSystemCA(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Prepare:
- svr := TheServer()
- // Test:
- ca, err := svr.GetSystemCA()
- if err == nil {
- t.Fatalf("GetSystemCA() is expected to give error but it didn't instead")
- }
- // Initialize system.
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- ca, err = svr.GetSystemCA()
- if err != nil {
- t.Fatalf("GetSystemCA() is expected to get system ca, but it gave us an error instead: %v", err)
- }
- // Is it empty?
- if len(ca.Cert) == 0 {
- t.Fatalf("ca.Cert is expected to be not empty, but it's empty instead")
- }
- if len(ca.Key) == 0 {
- t.Fatalf("ca.Key is expected to be not empty, but it's empty instead")
- }
- }
- func TestVPNStartVPNProc(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- // Prepare:
- // Test:
- // Isn't it stopped?
- if vpnProc.Status() != supervisor.STOPPED {
- t.Fatalf("expected state is STOPPED, got %s instead", vpnProc.Status())
- }
- // Call start without server initialization.
- svr.StartVPNProc()
- // Isn't it still stopped?
- if vpnProc.Status() != supervisor.STOPPED {
- t.Fatalf("expected state is STOPPED, got %s instead", vpnProc.Status())
- }
- // Initialize OVPM server.
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Call start again..
- svr.StartVPNProc()
- // Isn't it RUNNING?
- if vpnProc.Status() != supervisor.RUNNING {
- t.Fatalf("expected state is RUNNING, got %s instead", vpnProc.Status())
- }
- }
- func TestVPNStopVPNProc(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Prepare:
- vpnProc.Start()
- // Test:
- // Isn't it running?
- if vpnProc.Status() != supervisor.RUNNING {
- t.Fatalf("expected state is RUNNING, got %s instead", vpnProc.Status())
- }
- // Call stop.
- svr.StopVPNProc()
- // Isn't it stopped?
- if vpnProc.Status() != supervisor.STOPPED {
- t.Fatalf("expected state is STOPPED, got %s instead", vpnProc.Status())
- }
- }
- func TestVPNRestartVPNProc(t *testing.T) {
- // Init:
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Prepare:
- // Test:
- // Call restart.
- svr.RestartVPNProc()
- // Isn't it running?
- if vpnProc.Status() != supervisor.RUNNING {
- t.Fatalf("expected state is RUNNING, got %s instead", vpnProc.Status())
- }
- // Call restart again.
- svr.RestartVPNProc()
- // Isn't it running?
- if vpnProc.Status() != supervisor.RUNNING {
- t.Fatalf("expected state is RUNNING, got %s instead", vpnProc.Status())
- }
- }
- func TestVPNEmit(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Prepare:
- // Test:
- svr.Emit()
- var emittests = []string{
- _DefaultVPNConfPath,
- _DefaultKeyPath,
- _DefaultCertPath,
- _DefaultCRLPath,
- _DefaultCACertPath,
- _DefaultCAKeyPath,
- _DefaultDHParamsPath,
- }
- for _, tt := range emittests {
- if len(fs[tt]) == 0 {
- t.Errorf("%s is expected to be not empty but it is", tt)
- }
- }
- // TODO(cad): Write test cases for ccd/ files as well.
- }
- func TestVPNemitToFile(t *testing.T) {
- // Initialize:
- // Prepare:
- path := "/test/file"
- content := "blah blah blah"
- // Test:
- // Is path exist?
- if _, ok := fs[path]; ok {
- t.Fatalf("key '%s' expected to be non-existent on fs, but it is instead", path)
- }
- // Emit the contents.
- if err := TheServer().emitToFile(path, content, 0); err != nil {
- t.Fatalf("expected to be able to emit to the filesystem but we got this error instead: %v", err)
- }
- // Is the content on the filesystem correct?
- if fs[path] != content {
- t.Fatalf("content on the filesytem is expected to be same with '%s' but it's '%s' instead", content, fs[path])
- }
- }
- type fakeProcess struct {
- state supervisor.State
- }
- func (f *fakeProcess) Start() {
- f.state = supervisor.RUNNING
- }
- func (f *fakeProcess) Stop() {
- f.state = supervisor.STOPPED
- }
- func (f *fakeProcess) Restart() {
- f.state = supervisor.RUNNING
- }
- func (f *fakeProcess) Status() supervisor.State {
- return f.state
- }
- func TestGetConnectedUsers(t *testing.T) {
- // Init:
- setupTestCase()
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Mock funcs.
- svr.openFunc = func(path string) (io.Reader, error) {
- return nil, nil
- }
- // Create the corresponding users for test.
- usr1, err := CreateNewUser("usr1", "1234", true, 0, false, "description")
- if err != nil {
- t.Fatalf("user creation failed: %v", err)
- }
- usr2, err := CreateNewUser("usr2", "1234", true, 0, false, "description")
- if err != nil {
- t.Fatalf("user creation failed: %v", err)
- }
- now := time.Now()
- svr.parseStatusLogFunc = func(f io.Reader) ([]clEntry, []rtEntry) {
- clt := []clEntry{
- clEntry{
- CommonName: usr1.GetUsername(),
- RealAddress: "1.1.1.1",
- ConnectedSince: now,
- BytesReceived: 1,
- BytesSent: 5,
- },
- clEntry{
- CommonName: usr2.GetUsername(),
- RealAddress: "1.1.1.2",
- ConnectedSince: now,
- BytesReceived: 2,
- BytesSent: 6,
- },
- }
- rtt := []rtEntry{
- rtEntry{
- CommonName: usr1.GetUsername(),
- RealAddress: "1.1.1.1",
- LastRef: now,
- VirtualAddress: "10.10.10.1",
- },
- rtEntry{
- CommonName: usr2.GetUsername(),
- RealAddress: "1.1.1.2",
- LastRef: now,
- VirtualAddress: "10.10.10.2",
- },
- }
- return clt, rtt
- }
- // Test:
- tests := []struct {
- name string
- want []User
- wantErr bool
- }{
- {"default", []User{*usr2, *usr1}, false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := TheServer().GetConnectedUsers()
- if (err != nil) != tt.wantErr {
- t.Errorf("GetConnectedUsers() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- for _, wu := range tt.want {
- var found bool
- for _, u := range got {
- if wu.GetUsername() == u.GetUsername() {
- found = true
- }
- }
- if !found {
- t.Errorf("wanted user (%s) is not present in the response we got %v", wu.GetUsername(), got)
- }
- }
- })
- }
- }
- func TestVPN_ExpiresAt(t *testing.T) {
- // Initialize:
- db := CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Test:
- cert, err := pki.ReadCertFromPEM(svr.Cert)
- if err != nil {
- t.Fatalf("test preperation failed: %v", err)
- }
- if !reflect.DeepEqual(svr.ExpiresAt(), cert.NotAfter) {
- t.Errorf("got (%s), want (%s)", svr.ExpiresAt(), cert.NotAfter)
- }
- }
- func TestVPN_CAExpiresAt(t *testing.T) {
- // Initialize:
- db := CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- svr := TheServer()
- svr.Init("localhost", "", UDPProto, "", "", "", "", false)
- // Test:
- cert, err := pki.ReadCertFromPEM(svr.CACert)
- if err != nil {
- t.Fatalf("test preperation failed: %v", err)
- }
- if !reflect.DeepEqual(svr.CAExpiresAt(), cert.NotAfter) {
- t.Errorf("got (%s), want (%s)", svr.CAExpiresAt(), cert.NotAfter)
- }
- }
- func init() {
- // Init
- Testing = true
- fs = make(map[string]string)
- CreateDB("sqlite3", ":memory:")
- defer db.Cease()
- // Monkeypatch emitToFile()
- TheServer().emitToFileFunc = func(path, content string, mode uint) error {
- fs[path] = content
- return nil
- }
- vpnProc = &fakeProcess{state: supervisor.STOPPED}
- }
|