* Copyright (c) KylinSoft Co., Ltd. 2024.All rights reserved.
* ha-api licensed under the Mulan Permissive Software License, Version 2.
* See LICENSE file for more details.
* Author: bixiaoyan <bixiaoyan@kylinos.cn>
* Date: Thu Mar 27 09:32:28 2025 +0800
*/
package utils
import (
"fmt"
"os"
"path/filepath"
"reflect"
"testing"
"gitee.com/openeuler/ha-api/settings"
)
func TestGetCorosyncConfig(t *testing.T) {
result, err := GetCorosyncConfig()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result)
}
func TestGetCorosyncConfig2(t *testing.T) {
tmpDir := t.TempDir()
tests := []struct {
name string
configContent string
want CorosyncConfig
wantErr bool
}{
{
name: "configuration with qdevice",
configContent: `totem {
transport: knet
token: 8000
crypto_cipher: aes256
crypto_hash: sha256
cluster_uuid: d2caae471703440cbac34541cee7b396
version: 2
cluster_name: mycluster
}
nodelist {
node {
nodeid: 1
ring0_addr: node1
}
node {
nodeid: 2
ring0_addr: node2
}
}
quorum {
provider: corosync_votequorum
device {
model: net
votes: 1
net {
algorithm: ffsplit
host: host105
}
}
}
logging {
to_syslog: yes
timestamp: on
to_logfile: yes
}`,
want: CorosyncConfig{
Totem: map[string]string{
"token": "8000",
"crypto_cipher": "aes256",
"crypto_hash": "sha256",
"cluster_uuid": "d2caae471703440cbac34541cee7b396",
"version": "2",
"cluster_name": "mycluster",
"transport": "knet",
},
NodeList: []map[string]string{
{
"nodeid": "1",
"ring0_addr": "node1",
},
{
"nodeid": "2",
"ring0_addr": "node2",
},
},
Quorum: map[string]interface{}{
"provider": "corosync_votequorum",
"device": map[string]interface{}{
"model": "net",
"votes": "1",
"net": map[string]string{
"algorithm": "ffsplit",
"host": "host105",
},
},
},
Logging: map[string]interface{}{
"timestamp": "on",
"to_logfile": "yes",
"to_syslog": "yes",
},
},
wantErr: false,
},
{
name: "empty",
configContent: "",
want: CorosyncConfig{},
wantErr: false,
},
{
name: "configuration withpit qdevice",
configContent: `totem {
transport: knet
token: 8000
crypto_cipher: aes256
crypto_hash: sha256
cluster_uuid: d2caae471703440cbac34541cee7b396
version: 2
cluster_name: mycluster
}
nodelist {
node {
nodeid: 1
ring0_addr: node1
}
node {
nodeid: 2
ring0_addr: node2
}
}
quorum {
two_node: 1
provider: corosync_votequorum
}
logging {
to_syslog: yes
timestamp: on
to_logfile: yes
}`,
want: CorosyncConfig{
Totem: map[string]string{
"token": "8000",
"crypto_cipher": "aes256",
"crypto_hash": "sha256",
"cluster_uuid": "d2caae471703440cbac34541cee7b396",
"version": "2",
"cluster_name": "mycluster",
"transport": "knet",
},
NodeList: []map[string]string{
{
"nodeid": "1",
"ring0_addr": "node1",
},
{
"nodeid": "2",
"ring0_addr": "node2",
},
},
Quorum: map[string]interface{}{
"provider": "corosync_votequorum",
"two_node": "1",
},
Logging: map[string]interface{}{
"timestamp": "on",
"to_logfile": "yes",
"to_syslog": "yes",
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tmpFile := filepath.Join(tmpDir, "corosync.conf")
err := os.WriteFile(tmpFile, []byte(tt.configContent), 0644)
if err != nil {
t.Fatalf("Failed to create test config file: %v", err)
}
originalFile := settings.CorosyncConfFile
settings.CorosyncConfFile = tmpFile
defer func() {
settings.CorosyncConfFile = originalFile
}()
got, err := GetCorosyncConfig()
if (err != nil) != tt.wantErr {
t.Errorf("GetCorosyncConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
if !reflect.DeepEqual(got.Totem, tt.want.Totem) {
t.Errorf("GetCorosyncConfig() Totem = %v, want %v", got.Totem, tt.want.Totem)
}
if !reflect.DeepEqual(got.NodeList, tt.want.NodeList) {
t.Errorf("GetCorosyncConfig() NodeList = %v, want %v", got.NodeList, tt.want.NodeList)
}
if !reflect.DeepEqual(got.Quorum, tt.want.Quorum) {
t.Errorf("GetCorosyncConfig() Quorum = %v, want %v", got.Quorum, tt.want.Quorum)
}
if !reflect.DeepEqual(got.Logging, tt.want.Logging) {
t.Errorf("GetCorosyncConfig() Logging = %v, want %v", got.Logging, tt.want.Logging)
}
}
})
}
}
func TestGetCorosyncpcConfig_FileNotFound(t *testing.T) {
originalFile := settings.CorosyncConfFile
settings.CorosyncConfFile = "/nonexistent/path/corosync.conf"
defer func() {
settings.CorosyncConfFile = originalFile
}()
_, err := GetCorosyncConfig()
if err == nil {
t.Error("GetCorosyncConfig() expected error for nonexistent file, got nil")
}
}
func TestGetCorosyncConfig_EdgeCases(t *testing.T) {
tmpDir := t.TempDir()
edgeCases := []struct {
name string
content string
}{
{
name: "nested brackets in values",
content: `totem {
config: value{with}brackets
}`,
},
{
name: "multiple spaces",
content: `totem {
cluster_name: test
}`,
},
{
name: "tabs instead of spaces",
content: `totem {
cluster_name: test
}`,
},
}
for _, tc := range edgeCases {
t.Run(tc.name, func(t *testing.T) {
tmpFile := filepath.Join(tmpDir, "corosync.conf")
err := os.WriteFile(tmpFile, []byte(tc.content), 0644)
if err != nil {
t.Fatalf("Failed to create test config file: %v", err)
}
originalFile := settings.CorosyncConfFile
settings.CorosyncConfFile = tmpFile
defer func() {
settings.CorosyncConfFile = originalFile
}()
_, err = GetCorosyncConfig()
if err != nil {
t.Logf("GetCorosyncConfig() with edge case '%s' returned error (may be expected): %v", tc.name, err)
}
})
}
}