mirror of
https://github.com/DanielLavrushin/b4.git
synced 2026-07-09 16:00:05 +00:00
fix: correct version number in Swagger documentation and enhance config loading with improved JSON parsing
This commit is contained in:
parent
8a5821511c
commit
d7d6933a0b
5 changed files with 154 additions and 10 deletions
2
docs/static/swagger.json
vendored
2
docs/static/swagger.json
vendored
|
|
@ -4,7 +4,7 @@
|
|||
"description": "B4 network packet processor REST API",
|
||||
"title": "B4 API",
|
||||
"contact": {},
|
||||
"version": "1.47.0"
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"basePath": "/api",
|
||||
"paths": {
|
||||
|
|
|
|||
|
|
@ -65,17 +65,37 @@ func (c *Config) LoadFromFile(path string) error {
|
|||
if err != nil {
|
||||
return log.Errorf("failed to read config file: %v", err)
|
||||
}
|
||||
err = json.Unmarshal(data, c)
|
||||
|
||||
if err != nil {
|
||||
var raw map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &raw); err != nil {
|
||||
return log.Errorf("failed to parse config file: %v", err)
|
||||
}
|
||||
|
||||
ApplyConfigDefaults(c)
|
||||
for _, set := range c.Sets {
|
||||
ApplySetDefaults(set)
|
||||
rawSets := raw["sets"]
|
||||
delete(raw, "sets")
|
||||
|
||||
withoutSets, _ := json.Marshal(raw)
|
||||
if err := json.Unmarshal(withoutSets, c); err != nil {
|
||||
return log.Errorf("failed to parse config file: %v", err)
|
||||
}
|
||||
|
||||
if rawSets != nil {
|
||||
var setArray []json.RawMessage
|
||||
if err := json.Unmarshal(rawSets, &setArray); err != nil {
|
||||
return log.Errorf("failed to parse sets: %v", err)
|
||||
}
|
||||
c.Sets = make([]*SetConfig, 0, len(setArray))
|
||||
for _, rawSet := range setArray {
|
||||
set := NewSetConfig()
|
||||
if err := json.Unmarshal(rawSet, &set); err != nil {
|
||||
return log.Errorf("failed to parse set: %v", err)
|
||||
}
|
||||
c.Sets = append(c.Sets, &set)
|
||||
}
|
||||
}
|
||||
|
||||
ApplyConfigDefaults(c)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -443,15 +443,36 @@ func (c *Config) LoadWithMigration(path string) error {
|
|||
return log.Errorf("failed to parse config file: %v", err)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, c); err != nil {
|
||||
var raw map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &raw); err != nil {
|
||||
return log.Errorf("failed to parse config file: %v", err)
|
||||
}
|
||||
|
||||
ApplyConfigDefaults(c)
|
||||
for _, set := range c.Sets {
|
||||
ApplySetDefaults(set)
|
||||
rawSets := raw["sets"]
|
||||
delete(raw, "sets")
|
||||
|
||||
withoutSets, _ := json.Marshal(raw)
|
||||
if err := json.Unmarshal(withoutSets, c); err != nil {
|
||||
return log.Errorf("failed to parse config file: %v", err)
|
||||
}
|
||||
|
||||
if rawSets != nil {
|
||||
var setArray []json.RawMessage
|
||||
if err := json.Unmarshal(rawSets, &setArray); err != nil {
|
||||
return log.Errorf("failed to parse sets: %v", err)
|
||||
}
|
||||
c.Sets = make([]*SetConfig, 0, len(setArray))
|
||||
for _, rs := range setArray {
|
||||
set := NewSetConfig()
|
||||
if err := json.Unmarshal(rs, &set); err != nil {
|
||||
return log.Errorf("failed to parse set: %v", err)
|
||||
}
|
||||
c.Sets = append(c.Sets, &set)
|
||||
}
|
||||
}
|
||||
|
||||
ApplyConfigDefaults(c)
|
||||
|
||||
if c.Version < CurrentConfigVersion {
|
||||
log.Infof("Config version %d is older than current version %d, migrating",
|
||||
c.Version, CurrentConfigVersion)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,46 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func deepCompareFields(prefix string, expected, actual reflect.Value) []string {
|
||||
var diffs []string
|
||||
if expected.Kind() == reflect.Ptr {
|
||||
if expected.IsNil() && actual.IsNil() {
|
||||
return nil
|
||||
}
|
||||
if expected.IsNil() != actual.IsNil() {
|
||||
return []string{fmt.Sprintf("%s: nil mismatch", prefix)}
|
||||
}
|
||||
return deepCompareFields(prefix, expected.Elem(), actual.Elem())
|
||||
}
|
||||
if expected.Kind() == reflect.Struct {
|
||||
t := expected.Type()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
if !f.IsExported() {
|
||||
continue
|
||||
}
|
||||
name := prefix + "." + f.Name
|
||||
if prefix == "" {
|
||||
name = f.Name
|
||||
}
|
||||
diffs = append(diffs, deepCompareFields(name, expected.Field(i), actual.Field(i))...)
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
if !reflect.DeepEqual(expected.Interface(), actual.Interface()) {
|
||||
diffs = append(diffs, fmt.Sprintf("%s: want %v, got %v", prefix, expected.Interface(), actual.Interface()))
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
func TestLoadWithMigration(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
|
|
@ -70,6 +104,31 @@ func TestLoadWithMigration(t *testing.T) {
|
|||
t.Errorf("version should remain %d", CurrentConfigVersion)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("sparse roundtrip preserves all set defaults", func(t *testing.T) {
|
||||
path := filepath.Join(tmpDir, "sparse_all.json")
|
||||
cfg := NewConfig()
|
||||
set := NewSetConfig()
|
||||
set.Id = "all-defaults"
|
||||
set.Name = "AllDefaults"
|
||||
cfg.Sets = []*SetConfig{&set}
|
||||
cfg.SaveToFile(path)
|
||||
|
||||
loaded := NewConfig()
|
||||
if err := loaded.LoadWithMigration(path); err != nil {
|
||||
t.Fatalf("LoadWithMigration failed: %v", err)
|
||||
}
|
||||
|
||||
ls := loaded.Sets[0]
|
||||
expected := NewSetConfig()
|
||||
expected.Id = "all-defaults"
|
||||
expected.Name = "AllDefaults"
|
||||
|
||||
diffs := deepCompareFields("", reflect.ValueOf(expected), reflect.ValueOf(*ls))
|
||||
for _, d := range diffs {
|
||||
t.Errorf("%s", d)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDiscoverConfigPath(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -202,6 +202,50 @@ func TestSparseSaveLoadRoundtrip_BoolDefaults(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSparseSaveLoadRoundtrip_TrueBoolDefaultsSurvive(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
path := filepath.Join(tmpDir, "config.json")
|
||||
|
||||
cfg := NewConfig()
|
||||
set := NewSetConfig()
|
||||
set.Id = "bool-defaults"
|
||||
set.Name = "BoolDefaults"
|
||||
set.Faking.TTL = 8
|
||||
cfg.Sets = []*SetConfig{&set}
|
||||
|
||||
if err := cfg.SaveToFile(path); err != nil {
|
||||
t.Fatalf("SaveToFile failed: %v", err)
|
||||
}
|
||||
|
||||
loaded := NewConfig()
|
||||
if err := loaded.LoadFromFile(path); err != nil {
|
||||
t.Fatalf("LoadFromFile failed: %v", err)
|
||||
}
|
||||
|
||||
ls := loaded.Sets[0]
|
||||
if ls.Faking.SNI != DefaultSetConfig.Faking.SNI {
|
||||
t.Errorf("expected Faking.SNI=%v (default), got %v", DefaultSetConfig.Faking.SNI, ls.Faking.SNI)
|
||||
}
|
||||
if ls.Fragmentation.ReverseOrder != DefaultSetConfig.Fragmentation.ReverseOrder {
|
||||
t.Errorf("expected ReverseOrder=%v (default), got %v", DefaultSetConfig.Fragmentation.ReverseOrder, ls.Fragmentation.ReverseOrder)
|
||||
}
|
||||
if ls.Fragmentation.MiddleSNI != DefaultSetConfig.Fragmentation.MiddleSNI {
|
||||
t.Errorf("expected MiddleSNI=%v (default), got %v", DefaultSetConfig.Fragmentation.MiddleSNI, ls.Fragmentation.MiddleSNI)
|
||||
}
|
||||
if ls.Fragmentation.Combo.FirstByteSplit != DefaultSetConfig.Fragmentation.Combo.FirstByteSplit {
|
||||
t.Errorf("expected FirstByteSplit=%v (default), got %v", DefaultSetConfig.Fragmentation.Combo.FirstByteSplit, ls.Fragmentation.Combo.FirstByteSplit)
|
||||
}
|
||||
if ls.Fragmentation.Combo.ExtensionSplit != DefaultSetConfig.Fragmentation.Combo.ExtensionSplit {
|
||||
t.Errorf("expected ExtensionSplit=%v (default), got %v", DefaultSetConfig.Fragmentation.Combo.ExtensionSplit, ls.Fragmentation.Combo.ExtensionSplit)
|
||||
}
|
||||
if ls.Enabled != DefaultSetConfig.Enabled {
|
||||
t.Errorf("expected Enabled=%v (default), got %v", DefaultSetConfig.Enabled, ls.Enabled)
|
||||
}
|
||||
if ls.UDP.FilterSTUN != DefaultSetConfig.UDP.FilterSTUN {
|
||||
t.Errorf("expected FilterSTUN=%v (default), got %v", DefaultSetConfig.UDP.FilterSTUN, ls.UDP.FilterSTUN)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalSparse_OmitsDerivedDiscoveryMarks(t *testing.T) {
|
||||
cfg := NewConfig()
|
||||
set := NewSetConfig()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue