165 lines
4.4 KiB
Go
165 lines
4.4 KiB
Go
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package model
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/casbin/casbin/v3/config"
|
|
"github.com/casbin/casbin/v3/constant"
|
|
)
|
|
|
|
var (
|
|
basicExample = filepath.Join("..", "examples", "basic_model.conf")
|
|
basicConfig = &MockConfig{
|
|
data: map[string]string{
|
|
"request_definition::r": "sub, obj, act",
|
|
"policy_definition::p": "sub, obj, act",
|
|
"policy_effect::e": "some(where (p.eft == allow))",
|
|
"matchers::m": "r.sub == p.sub && r.obj == p.obj && r.act == p.act",
|
|
},
|
|
}
|
|
)
|
|
|
|
type MockConfig struct {
|
|
data map[string]string
|
|
config.ConfigInterface
|
|
}
|
|
|
|
func (mc *MockConfig) String(key string) string {
|
|
return mc.data[key]
|
|
}
|
|
|
|
func TestNewModel(t *testing.T) {
|
|
m := NewModel()
|
|
if m == nil {
|
|
t.Error("new model should not be nil")
|
|
}
|
|
}
|
|
|
|
func TestNewModelFromFile(t *testing.T) {
|
|
m, err := NewModelFromFile(basicExample)
|
|
if err != nil {
|
|
t.Errorf("model failed to load from file: %s", err)
|
|
}
|
|
if m == nil {
|
|
t.Error("model should not be nil")
|
|
}
|
|
}
|
|
|
|
func TestNewModelFromString(t *testing.T) {
|
|
modelBytes, _ := os.ReadFile(basicExample)
|
|
modelString := string(modelBytes)
|
|
m, err := NewModelFromString(modelString)
|
|
if err != nil {
|
|
t.Errorf("model failed to load from string: %s", err)
|
|
}
|
|
if m == nil {
|
|
t.Error("model should not be nil")
|
|
}
|
|
}
|
|
|
|
func TestLoadModelFromConfig(t *testing.T) {
|
|
m := NewModel()
|
|
err := m.loadModelFromConfig(basicConfig)
|
|
if err != nil {
|
|
t.Error("basic config should not return an error")
|
|
}
|
|
m = NewModel()
|
|
err = m.loadModelFromConfig(&MockConfig{})
|
|
if err == nil {
|
|
t.Error("empty config should return error")
|
|
} else {
|
|
// check for missing sections in message
|
|
for _, rs := range requiredSections {
|
|
if !strings.Contains(err.Error(), sectionNameMap[rs]) {
|
|
t.Errorf("section name: %s should be in message", sectionNameMap[rs])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHasSection(t *testing.T) {
|
|
m := NewModel()
|
|
_ = m.loadModelFromConfig(basicConfig)
|
|
for _, sec := range requiredSections {
|
|
if !m.hasSection(sec) {
|
|
t.Errorf("%s section was expected in model", sec)
|
|
}
|
|
}
|
|
m = NewModel()
|
|
_ = m.loadModelFromConfig(&MockConfig{})
|
|
for _, sec := range requiredSections {
|
|
if m.hasSection(sec) {
|
|
t.Errorf("%s section was not expected in model", sec)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestModel_AddDef(t *testing.T) {
|
|
m := NewModel()
|
|
s := "r"
|
|
v := "sub, obj, act"
|
|
ok := m.AddDef(s, s, v)
|
|
if !ok {
|
|
t.Errorf("non empty assertion should be added")
|
|
}
|
|
ok = m.AddDef(s, s, "")
|
|
if ok {
|
|
t.Errorf("empty assertion value should not be added")
|
|
}
|
|
}
|
|
|
|
func TestModelToTest(t *testing.T) {
|
|
testModelToText(t, "r.sub == p.sub && r.obj == p.obj && r_func(r.act, p.act) && testr_func(r.act, p.act)", "r_sub == p_sub && r_obj == p_obj && r_func(r_act, p_act) && testr_func(r_act, p_act)")
|
|
testModelToText(t, "r.sub == p.sub && r.obj == p.obj && p_func(r.act, p.act) && testp_func(r.act, p.act)", "r_sub == p_sub && r_obj == p_obj && p_func(r_act, p_act) && testp_func(r_act, p_act)")
|
|
}
|
|
|
|
func testModelToText(t *testing.T, mData, mExpected string) {
|
|
m := NewModel()
|
|
data := map[string]string{
|
|
"r": "sub, obj, act",
|
|
"p": "sub, obj, act",
|
|
"e": "some(where (p.eft == allow))",
|
|
"m": mData,
|
|
}
|
|
expected := map[string]string{
|
|
"r": "sub, obj, act",
|
|
"p": "sub, obj, act",
|
|
"e": constant.AllowOverrideEffect,
|
|
"m": mExpected,
|
|
}
|
|
addData := func(ptype string) {
|
|
m.AddDef(ptype, ptype, data[ptype])
|
|
}
|
|
for ptype := range data {
|
|
addData(ptype)
|
|
}
|
|
newM := NewModel()
|
|
print(m.ToText())
|
|
_ = newM.LoadModelFromText(m.ToText())
|
|
for ptype := range data {
|
|
if newM[ptype][ptype].Value != expected[ptype] {
|
|
t.Errorf("\"%s\" assertion value changed, current value: %s, it should be: %s", ptype, newM[ptype][ptype].Value, expected[ptype])
|
|
}
|
|
}
|
|
}
|