//go:build integration // Live integration against public Quicknet relays (plan ยง7.8), run nightly: // // go test -tags integration ./capsule ./provider/drand package capsule_test import ( "bytes" "context" "errors" "testing" "time" "filippo.io/age" datekeys "g.activething.com/go/DateKeys" "g.activething.com/go/DateKeys/capsule" "g.activething.com/go/DateKeys/profile" "g.activething.com/go/DateKeys/provider/drand" ) // Encrypt to now + 30 s, check that the capsule stays locked without any // request, wait, and open it with a release fetched from real relays. func TestLiveLifecycle(t *testing.T) { p := profile.Quicknet() reg, err := profile.Default() if err != nil { t.Fatal(err) } holder, _ := age.GenerateX25519Identity() for _, policy := range []capsule.Policy{capsule.TimeOnly, capsule.TimeAndKey} { t.Run(policy.String(), func(t *testing.T) { unlock := time.Now().Add(30 * time.Second) opts := capsule.EncryptOptions{Profile: p, UnlockAt: unlock, Policy: policy, Now: time.Now} if policy == capsule.TimeAndKey { opts.Recipients = []age.Recipient{holder.Recipient()} } const msg = "DateKeys live integration: this stays on the local machine." var dkc bytes.Buffer res, err := capsule.EncryptFiles(&dkc, []capsule.Source{source("live.txt", msg)}, opts) if err != nil { t.Fatal(err) } files := &memorySink{} o := capsule.OpenOptions{Registry: reg, Source: drand.New(), Now: time.Now, Identities: []age.Identity{holder}, Sink: files} if _, err := capsule.Open(context.Background(), nil, bytes.NewReader(dkc.Bytes()), o); !errors.Is(err, datekeys.ErrReleaseUnavailable) { t.Fatalf("opened before the round: %v", err) } t.Logf("locked for round %d until %s", res.DateKey.Round, res.UnlockAt.Format(time.RFC3339)) time.Sleep(time.Until(res.UnlockAt) + 2*time.Second) deadline := time.Now().Add(30 * time.Second) for { _, err = capsule.Open(context.Background(), nil, bytes.NewReader(dkc.Bytes()), o) if err == nil || !errors.Is(err, datekeys.ErrReleaseUnavailable) || time.Now().After(deadline) { break } time.Sleep(time.Second) } if err != nil || len(files.files) != 1 || files.files[0].String() != msg { t.Fatalf("open after the round: %v", err) } }) } }