mirror of
https://github.com/foxcpp/maddy.git
synced 2025-04-03 05:07:38 +03:00
495 lines
9.4 KiB
Go
495 lines
9.4 KiB
Go
/*
|
|
Maddy Mail Server - Composable all-in-one email server.
|
|
Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
|
|
|
|
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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package config
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestMapProcess(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"bar"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", false, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != "bar" {
|
|
t.Errorf("Incorrect value stored in variable, want 'bar', got '%s'", foo)
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_MissingRequired(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", false, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err == nil {
|
|
t.Errorf("Expected failure")
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_InheritGlobal(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{},
|
|
}
|
|
|
|
m := NewMap(map[string]interface{}{"foo": "bar"}, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", true, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != "bar" {
|
|
t.Errorf("Incorrect value stored in variable, want 'bar', got '%s'", foo)
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_InheritGlobal_MissingRequired(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{},
|
|
}
|
|
|
|
m := NewMap(map[string]interface{}{}, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", false, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err == nil {
|
|
t.Errorf("Expected failure")
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_InheritGlobal_Override(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"bar"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(map[string]interface{}{}, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", false, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != "bar" {
|
|
t.Errorf("Incorrect value stored in variable, want 'bar', got '%s'", foo)
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_DefaultValue(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", false, false, func() (interface{}, error) {
|
|
return "bar", nil
|
|
}, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != "bar" {
|
|
t.Errorf("Incorrect value stored in variable, want 'bar', got '%s'", foo)
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_InheritGlobal_DefaultValue(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{},
|
|
}
|
|
|
|
m := NewMap(map[string]interface{}{"foo": "baz"}, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", true, false, func() (interface{}, error) {
|
|
return "bar", nil
|
|
}, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != "baz" {
|
|
t.Errorf("Incorrect value stored in variable, want 'baz', got '%s'", foo)
|
|
}
|
|
|
|
t.Run("no global", func(t *testing.T) {
|
|
_, err := m.ProcessWith(map[string]interface{}{}, cfg)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != "bar" {
|
|
t.Errorf("Incorrect value stored in variable, want 'bar', got '%s'", foo)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestMapProcess_Duplicate(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"bar"},
|
|
},
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"bar"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("foo", false, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err == nil {
|
|
t.Errorf("Expected failure")
|
|
}
|
|
}
|
|
|
|
func TestMapProcess_Unexpected(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"baz"},
|
|
},
|
|
{
|
|
Name: "bar",
|
|
Args: []string{"baz"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := ""
|
|
m.Custom("bar", false, true, nil, func(_ *Map, n Node) (interface{}, error) {
|
|
return n.Args[0], nil
|
|
}, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err == nil {
|
|
t.Errorf("Expected failure")
|
|
}
|
|
|
|
m.AllowUnknown()
|
|
|
|
unknown, err := m.Process()
|
|
if err != nil {
|
|
t.Errorf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if len(unknown) != 1 {
|
|
t.Fatalf("Wrong amount of unknown nodes: %v", len(unknown))
|
|
}
|
|
|
|
if unknown[0].Name != "foo" {
|
|
t.Fatalf("Wrong node in unknown: %v", unknown[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestMapInt(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"1"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := 0
|
|
m.Int("foo", false, true, 0, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != 1 {
|
|
t.Errorf("Incorrect value stored in variable, want 1, got %d", foo)
|
|
}
|
|
}
|
|
|
|
func TestMapInt_Invalid(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"AAAA"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := 0
|
|
m.Int("foo", false, true, 0, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err == nil {
|
|
t.Errorf("Expected failure")
|
|
}
|
|
}
|
|
|
|
func TestMapFloat(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"1"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := 0.0
|
|
m.Float("foo", false, true, 0, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if foo != 1.0 {
|
|
t.Errorf("Incorrect value stored in variable, want 1, got %v", foo)
|
|
}
|
|
}
|
|
|
|
func TestMapFloat_Invalid(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
Args: []string{"AAAA"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo := 0.0
|
|
m.Float("foo", false, true, 0, &foo)
|
|
|
|
_, err := m.Process()
|
|
if err == nil {
|
|
t.Errorf("Expected failure")
|
|
}
|
|
}
|
|
|
|
func TestMapBool(t *testing.T) {
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "foo",
|
|
},
|
|
{
|
|
Name: "bar",
|
|
Args: []string{"yes"},
|
|
},
|
|
{
|
|
Name: "baz",
|
|
Args: []string{"no"},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := NewMap(nil, cfg)
|
|
|
|
foo, bar, baz, boo := false, false, false, false
|
|
m.Bool("foo", false, false, &foo)
|
|
m.Bool("bar", false, false, &bar)
|
|
m.Bool("baz", false, false, &baz)
|
|
m.Bool("boo", false, false, &boo)
|
|
|
|
_, err := m.Process()
|
|
if err != nil {
|
|
t.Fatalf("Unexpected failure: %v", err)
|
|
}
|
|
|
|
if !foo {
|
|
t.Errorf("Incorrect value stored in variable foo, want true, got false")
|
|
}
|
|
if !bar {
|
|
t.Errorf("Incorrect value stored in variable bar, want true, got false")
|
|
}
|
|
if baz {
|
|
t.Errorf("Incorrect value stored in variable baz, want false, got true")
|
|
}
|
|
if boo {
|
|
t.Errorf("Incorrect value stored in variable boo, want false, got true")
|
|
}
|
|
}
|
|
|
|
func TestParseDataSize(t *testing.T) {
|
|
check := func(s string, ok bool, expected int) {
|
|
val, err := ParseDataSize(s)
|
|
if err != nil && ok {
|
|
t.Errorf("unexpected parseDataSize('%s') fail: %v", s, err)
|
|
return
|
|
}
|
|
if err == nil && !ok {
|
|
t.Errorf("unexpected parseDataSize('%s') success, got %d", s, val)
|
|
return
|
|
}
|
|
if val != expected {
|
|
t.Errorf("parseDataSize('%s') != %d", s, expected)
|
|
return
|
|
}
|
|
}
|
|
|
|
check("1M", true, 1024*1024)
|
|
check("1K", true, 1024)
|
|
check("1b", true, 1)
|
|
check("1M 5b", true, 1024*1024+5)
|
|
check("1M 5K 5b", true, 1024*1024+5*1024+5)
|
|
check("0", true, 0)
|
|
check("1", false, 0)
|
|
check("1d", false, 0)
|
|
check("d", false, 0)
|
|
check("unrelated", false, 0)
|
|
check("1M5b", false, 0)
|
|
check("", false, 0)
|
|
check("-5M", false, 0)
|
|
}
|
|
|
|
func TestMap_Callback(t *testing.T) {
|
|
called := map[string]int{}
|
|
|
|
cfg := Node{
|
|
Children: []Node{
|
|
{
|
|
Name: "test2",
|
|
Args: []string{"a"},
|
|
},
|
|
{
|
|
Name: "test3",
|
|
Args: []string{"b"},
|
|
},
|
|
{
|
|
Name: "test3",
|
|
Args: []string{"b"},
|
|
},
|
|
{
|
|
Name: "unrelated",
|
|
Args: []string{"b"},
|
|
},
|
|
},
|
|
}
|
|
m := NewMap(nil, cfg)
|
|
m.Callback("test1", func(*Map, Node) error {
|
|
called["test1"]++
|
|
return nil
|
|
})
|
|
m.Callback("test2", func(_ *Map, n Node) error {
|
|
called["test2"]++
|
|
if n.Args[0] != "a" {
|
|
t.Fatal("Wrong n.Args[0] for test2:", n.Args[0])
|
|
}
|
|
return nil
|
|
})
|
|
m.Callback("test3", func(_ *Map, n Node) error {
|
|
called["test3"]++
|
|
if n.Args[0] != "b" {
|
|
t.Fatal("Wrong n.Args[0] for test2:", n.Args[0])
|
|
}
|
|
return nil
|
|
})
|
|
m.AllowUnknown()
|
|
others, err := m.Process()
|
|
if err != nil {
|
|
t.Fatal("Unexpected error:", err)
|
|
}
|
|
if called["test1"] != 0 {
|
|
t.Error("test1 CB was called when it should not")
|
|
}
|
|
if called["test2"] != 1 {
|
|
t.Error("test2 CB was not called when it should")
|
|
}
|
|
if called["test3"] != 2 {
|
|
t.Error("test3 CB was not called when it should")
|
|
}
|
|
if len(others) != 1 {
|
|
t.Error("Wrong amount of unmatched directives")
|
|
}
|
|
if others[0].Name != "unrelated" {
|
|
t.Error("Wrong directive returned in unmatched slice:", others[0].Name)
|
|
}
|
|
}
|