update tests and discovery
Some checks failed
Build and Publish / Metadata (push) Has been cancelled
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled
Build and Publish / BuildAndDeployArm64 (push) Has been cancelled

This commit is contained in:
matst80
2025-11-18 16:40:25 +01:00
parent 718225164f
commit ea247e2600
6 changed files with 146 additions and 36 deletions

View File

@@ -133,3 +133,106 @@ func TestPriceMultiplyMethod(t *testing.T) {
t.Fatalf("expected exVat %d got %d", exBefore*2, p.ValueExVat())
}
}
func TestGetTaxAmount(t *testing.T) {
tests := []struct {
total int64
tax int
expected int64
desc string
}{
{1250, 2500, 250, "25% VAT"}, // 1250 / (1 + 100/25) = 1250 / 5 = 250
{1000, 2000, 166, "20% VAT"}, // 1000 / (1 + 100/20) = 1000 / 6 ≈ 166
{1200, 2500, 240, "25% VAT on 1200"},
{0, 2500, 0, "zero total"},
{100, 1000, 9, "10% VAT"}, // tax=1000 for 10%, 100 / (1 + 100/10) = 100 / 11 ≈ 9
{100, 10000, 50, "100% VAT"}, // tax=10000 for 100%, 100 / (1 + 100/100) = 100 / 2 = 50
}
for _, tt := range tests {
result := GetTaxAmount(tt.total, tt.tax)
if result != tt.expected {
t.Errorf("GetTaxAmount(%d, %d) [%s] = %d; expected %d", tt.total, tt.tax, tt.desc, result, tt.expected)
}
}
}
func TestNewPriceFromIncVatEdgeCases(t *testing.T) {
// Zero VAT rate
p := NewPriceFromIncVat(1000, 0)
if p.IncVat != 1000 {
t.Errorf("expected IncVat 1000, got %d", p.IncVat)
}
if len(p.VatRates) != 1 || p.VatRates[0] != 0 {
t.Errorf("expected VAT 0 for rate 0, got %v", p.VatRates)
}
if p.ValueExVat() != 1000 {
t.Errorf("expected exVat 1000, got %d", p.ValueExVat())
}
// High VAT rate, e.g., 50%
p = NewPriceFromIncVat(1500, 50)
expectedVat := int64(1500 / (1 + 100/50)) // 1500 / 3 = 500
if p.VatRates[50] != expectedVat {
t.Errorf("expected VAT %d for 50%%, got %d", expectedVat, p.VatRates[50])
}
if p.ValueExVat() != 1500-expectedVat {
t.Errorf("expected exVat %d, got %d", 1500-expectedVat, p.ValueExVat())
}
}
func TestPriceValueExVatAndTotalVat(t *testing.T) {
p := Price{IncVat: 13700, VatRates: map[float32]int64{25: 2500, 12: 1200}}
exVat := p.ValueExVat()
totalVat := p.TotalVat()
if exVat != 10000 {
t.Errorf("expected exVat 10000, got %d", exVat)
}
if totalVat != 3700 {
t.Errorf("expected totalVat 3700, got %d", totalVat)
}
if exVat+totalVat != p.IncVat {
t.Errorf("exVat + totalVat should equal IncVat: %d + %d != %d", exVat, totalVat, p.IncVat)
}
// Empty VAT rates
p2 := Price{IncVat: 500, VatRates: nil}
if p2.ValueExVat() != 500 {
t.Errorf("expected exVat 500 for no VAT, got %d", p2.ValueExVat())
}
if p2.TotalVat() != 0 {
t.Errorf("expected totalVat 0, got %d", p2.TotalVat())
}
}
func TestMultiplyPriceWithZeroQty(t *testing.T) {
base := Price{IncVat: 1250, VatRates: map[float32]int64{25: 250}}
multiplied := MultiplyPrice(base, 0)
if multiplied.IncVat != 0 {
t.Errorf("expected IncVat 0, got %d", multiplied.IncVat)
}
if len(multiplied.VatRates) != 1 || multiplied.VatRates[25] != 0 {
t.Errorf("expected VAT 0, got %v", multiplied.VatRates)
}
}
func TestPriceAddSubtractEdgeCases(t *testing.T) {
a := Price{IncVat: 1000, VatRates: map[float32]int64{25: 200}}
b := Price{IncVat: 500, VatRates: map[float32]int64{12: 54}} // Different rate
acc := NewPrice()
acc.Add(a)
acc.Add(b)
if acc.VatRates[25] != 200 || acc.VatRates[12] != 54 {
t.Errorf("expected VAT 25:200, 12:54, got %v", acc.VatRates)
}
// Subtract more than added (negative VAT)
acc.Subtract(a)
acc.Subtract(b)
acc.Subtract(a) // Subtract extra a
if acc.VatRates[25] != -200 || acc.VatRates[12] != 0 {
t.Errorf("expected negative VAT for 25 after over-subtract, got %v", acc.VatRates)
}
}

View File

@@ -2,6 +2,8 @@ package discovery
import (
"context"
"slices"
"sync"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -33,13 +35,10 @@ func (k *K8sDiscovery) DiscoverInNamespace(namespace string) ([]string, error) {
return hosts, nil
}
type HostChange struct {
Host string
Type watch.EventType
}
func (k *K8sDiscovery) Watch() (<-chan HostChange, error) {
timeout := int64(30)
ipsThatAreReady := make(map[string]bool)
m := sync.Mutex{}
watcherFn := func(options metav1.ListOptions) (watch.Interface, error) {
return k.client.CoreV1().Pods("").Watch(k.ctx, metav1.ListOptions{
LabelSelector: "actor-pool=cart",
@@ -55,10 +54,22 @@ func (k *K8sDiscovery) Watch() (<-chan HostChange, error) {
for event := range watcher.ResultChan() {
pod := event.Object.(*v1.Pod)
// log.Printf("pod change %+v", pod.Status.Phase == v1.PodRunning)
isReady := slices.ContainsFunc(pod.Status.Conditions, func(condition v1.PodCondition) bool {
return condition.Type == v1.PodReady && condition.Status == v1.ConditionTrue
})
m.Lock()
oldState := ipsThatAreReady[pod.Status.PodIP]
ipsThatAreReady[pod.Status.PodIP] = isReady
m.Unlock()
if oldState != isReady {
ch <- HostChange{
Host: pod.Status.PodIP,
IsReady: isReady,
}
}
ch <- HostChange{
Host: pod.Status.PodIP,
Type: event.Type,
Host: pod.Status.PodIP,
IsReady: isReady,
}
}
}()

View File

@@ -2,9 +2,8 @@ package discovery
import (
"context"
"slices"
"sync"
"k8s.io/apimachinery/pkg/watch"
)
// MockDiscovery is an in-memory Discovery implementation for tests.
@@ -56,14 +55,12 @@ func (m *MockDiscovery) AddHost(host string) {
if m.closed {
return
}
for _, h := range m.hosts {
if h == host {
return
}
if slices.Contains(m.hosts, host) {
return
}
m.hosts = append(m.hosts, host)
if m.started {
m.events <- HostChange{Host: host, Type: watch.Added}
m.events <- HostChange{Host: host, IsReady: true}
}
}
@@ -86,7 +83,7 @@ func (m *MockDiscovery) RemoveHost(host string) {
}
m.hosts = append(m.hosts[:idx], m.hosts[idx+1:]...)
if m.started {
m.events <- HostChange{Host: host, Type: watch.Deleted}
m.events <- HostChange{Host: host, IsReady: false}
}
}

View File

@@ -1,5 +1,10 @@
package discovery
type HostChange struct {
Host string
IsReady bool
}
type Discovery interface {
Discover() ([]string, error)
Watch() (<-chan HostChange, error)