Skip to content
Snippets Groups Projects
Select Git revision
  • 4eb287822511b6957bcea144e4ed39bfc8d467b2
  • master default protected
2 results

gitlab-deps.service

Blame
  • manager_test.go 3.79 KiB
    package acmeserver
    
    import (
    	"context"
    	"crypto"
    	"crypto/x509"
    	"errors"
    	"io/ioutil"
    	"os"
    	"path/filepath"
    	"testing"
    	"time"
    )
    
    // A CertGenerator that is just very slow (and will return an error
    // in any case).
    type slowACME struct{}
    
    func (s *slowACME) GetCertificate(ctx context.Context, _ crypto.Signer, _ *certConfig) ([][]byte, *x509.Certificate, error) {
    	t := time.After(60 * time.Second)
    	select {
    	case <-t:
    		return nil, nil, errors.New("timed out")
    	case <-ctx.Done():
    		return nil, nil, ctx.Err()
    	}
    }
    
    func newTestConfig(dir string) *Config {
    	c := Config{
    		Dirs:           []string{filepath.Join(dir, "config")},
    		AccountKeyPath: filepath.Join(dir, "account.key"),
    		Email:          "test@example.com",
    	}
    	c.Output.Path = filepath.Join(dir, "certs")
    	return &c
    }
    
    // Create a new test function.
    // The first function returned is a cleanup callback.
    // The second function returned is the cancel callback.
    func newTestManager(t testing.TB, g CertGenerator) (func(), context.CancelFunc, *Manager) {
    	dir, err := ioutil.TempDir("", "")
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	os.Mkdir(filepath.Join(dir, "config"), 0700)
    	ioutil.WriteFile(
    		filepath.Join(dir, "config", "test.yml"),
    		[]byte("- { names: [example.com] }\n"),
    		0644,
    	)
    
    	m, err := NewManager(newTestConfig(dir), g)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	ctx, cancel := context.WithCancel(context.Background())
    	if err := m.Start(ctx); err != nil {
    		t.Fatal("Start:", err)
    	}
    
    	// Wait just a little bit to give a chance to m.loop() to run.
    	time.Sleep(50 * time.Millisecond)
    
    	return func() {
    		cancel()
    		m.Wait()
    		os.RemoveAll(dir)
    	}, cancel, m
    }
    
    func TestManager_Reload(t *testing.T) {
    	cleanup, _, m := newTestManager(t, NewSelfSignedCertGenerator())
    	defer cleanup()
    
    	// Data race: we read data owned by another goroutine!
    	if len(m.certs) < 1 {
    		t.Fatal("configuration not loaded?")
    	}
    	if m.certs[0].cn() != "example.com" {
    		t.Fatalf("certs[0].cn() is %s, expected example.com", m.certs[0].cn())
    	}
    
    	// Try a reload, catch obvious errors.
    	m.Reload()
    	time.Sleep(50 * time.Millisecond)
    
    	if len(m.certs) != 1 {
    		t.Fatalf("certs count is %d, expected 1", len(m.certs))
    	}
    	if m.certs[0].cn() != "example.com" {
    		t.Fatalf("certs[0].cn() is %s, expected example.com", m.certs[0].cn())
    	}
    }
    
    func TestManager_NewCert(t *testing.T) {
    	cleanup, _, m := newTestManager(t, NewSelfSignedCertGenerator())
    	defer cleanup()
    
    	now := time.Now()
    	ci := m.certs[0]
    	if ci.retryDeadline.After(now) {
    		t.Fatalf("retry deadline is in the future: %v", ci.retryDeadline)
    	}
    
    	testUpdateCh <- true
    	time.Sleep(100 * time.Millisecond)
    
    	// Verify that the retry/renewal timestamp is in the future.
    	if ci.retryDeadline.Before(now) {
    		t.Fatalf("retry deadline is in the past after renewal: %v", ci.retryDeadline)
    	}
    
    	// Do we think we have a valid certificate?
    	if !ci.valid {
    		t.Fatal("we don't have a valid certificate")
    	}
    
    	// Verify that the credentials have successfully been written
    	// to storage.
    	p := filepath.Join(m.configDirs[0], "../certs/example.com/cert.pem")
    	if _, err := os.Stat(p); err != nil {
    		t.Fatalf("file not created: %v", err)
    	}
    	p = filepath.Join(m.configDirs[0], "../certs/example.com/privkey.pem")
    	if _, err := os.Stat(p); err != nil {
    		t.Fatalf("file not created: %v", err)
    	}
    
    	// By triggering a reload now, we should cause the Manager to
    	// reload the certificate from storage.
    	m.Reload()
    	time.Sleep(50 * time.Millisecond)
    
    	ci = m.certs[0]
    	if !ci.valid {
    		t.Fatal("certificate is invalid after a reload")
    	}
    }
    
    func TestManager_CancelUpdate(t *testing.T) {
    	start := time.Now()
    	cleanup, cancel, m := newTestManager(t, &slowACME{})
    	defer cleanup()
    
    	time.Sleep(100 * time.Millisecond)
    	cancel()
    	m.Wait()
    	elapsed := time.Since(start)
    	if elapsed > 1*time.Second {
    		t.Fatalf("too much time elapsed (%fs), canceling didn't work?", elapsed.Seconds())
    	}
    }