package toxiproxy
import (
    "context"
    "fmt"
    "testing"
    "time"
    toxiproxy "github.com/Shopify/toxiproxy/v2/client"
    "github.com/go-redis/redis/v8"
    "github.com/google/uuid"
    "github.com/testcontainers/testcontainers-go/network"
)
func TestToxiproxy(t *testing.T) {
    ctx := context.Background()
    newNetwork, err := network.New(ctx, network.WithCheckDuplicate())
    if err != nil {
        t.Fatal(err)
    }
    networkName := newNetwork.Name
    toxiproxyContainer, err := startContainer(ctx, networkName, []string{"toxiproxy"})
    if err != nil {
        t.Fatal(err)
    }
    redisContainer, err := setupRedis(ctx, networkName, []string{"redis"})
    if err != nil {
        t.Fatal(err)
    }
    // Clean up the container after the test is complete
    t.Cleanup(func() {
        if err := toxiproxyContainer.Terminate(ctx); err != nil {
            t.Fatalf("failed to terminate container: %s", err)
        }
        if err := redisContainer.Terminate(ctx); err != nil {
            t.Fatalf("failed to terminate container: %s", err)
        }
        if err := newNetwork.Remove(ctx); err != nil {
            t.Fatalf("failed to terminate network: %s", err)
        }
    })
    toxiproxyClient := toxiproxy.NewClient(toxiproxyContainer.URI)
    proxy, err := toxiproxyClient.CreateProxy("redis", "0.0.0.0:8666", "redis:6379")
    if err != nil {
        t.Fatal(err)
    }
    toxiproxyProxyPort, err := toxiproxyContainer.MappedPort(ctx, "8666")
    if err != nil {
        t.Fatal(err)
    }
    toxiproxyProxyHostIP, err := toxiproxyContainer.Host(ctx)
    if err != nil {
        t.Fatal(err)
    }
    redisUri := fmt.Sprintf("redis://%s:%s?read_timeout=2s", toxiproxyProxyHostIP, toxiproxyProxyPort.Port())
    options, err := redis.ParseURL(redisUri)
    if err != nil {
        t.Fatal(err)
    }
    redisClient := redis.NewClient(options)
    defer func() {
        err := flushRedis(ctx, *redisClient)
        if err != nil {
            t.Fatal(err)
        }
    }()
    // Set data
    key := fmt.Sprintf("{user.%s}.favoritefood", uuid.NewString())
    value := "Cabbage Biscuits"
    ttl, _ := time.ParseDuration("2h")
    err = redisClient.Set(ctx, key, value, ttl).Err()
    if err != nil {
        t.Fatal(err)
    }
    _, err = proxy.AddToxic("latency_down", "latency", "downstream", 1.0, toxiproxy.Attributes{
        "latency": 1000,
        "jitter":  100,
    })
    if err != nil {
        return
    }
    // Get data
    savedValue, err := redisClient.Get(ctx, key).Result()
    if err != nil {
        t.Fatal(err)
    }
    // perform assertions
    if savedValue != value {
        t.Fatalf("Expected value %s. Got %s.", savedValue, value)
    }
}
func flushRedis(ctx context.Context, client redis.Client) error {
    return client.FlushAll(ctx).Err()
}