<commit_before>package gogl

import (
	"fmt"
)

/* Vertex structures */

// As a rule, gogl tries to place as low a requirement on its vertices as
// possible. This is because, from a purely graph theoretic perspective,
// vertices are inert. Boring, even. Graphs are more about the topology, the
// characteristics of the edges connecting the points than the points
// themselves. Your use case cares about the content of your vertices, but gogl
// does not.  Consequently, anything can act as a vertex.
type Vertex interface{}

/* Graph structures */

// A VertexEnumerator iteratively enumerates vertices.
type VertexEnumerator interface {
	EachVertex(f func(vertex Vertex))
}

// An EdgeEnumerator iteratively enumerates edges.
type EdgeEnumerator interface {
	EachEdge(f func(edge Edge))
}

// An AdjacencyEnumerator iteratively enumerates a given vertex's adjacent vertices.
type AdjacencyEnumerator interface {
	EachAdjacent(from Vertex, f func(to Vertex))
}

// A GraphEnumerator can iteratively enumerate several graph properties.
type GraphEnumerator interface {
	VertexEnumerator
	EdgeEnumerator
	AdjacencyEnumerator
}

type VertexInspector interface {
	InDegree(vertex Vertex) (int, bool)
	OutDegree(vertex Vertex) (int, bool)
	HasVertex(vertex Vertex) bool
	Order() int
}

type EdgeInspector interface {
	HasEdge(e Edge) bool
	Size() int
}

type VertexMutator interface {
	EnsureVertex(vertices ...Vertex)
	RemoveVertex(vertices ...Vertex)
}

// Graph is gogl's most basic interface: it contains only the methods that
// *every* type of graph implements.
//
// Graph is intentionally underspecified: both directed and undirected graphs
// implement it; simple graphs, multigraphs, weighted, labeled, or any
// combination thereof.
//
// The semantics of some of these methods vary slightly from one graph type
// to another, but in general, the basic Graph methods are supplemented, not
// superceded, by the methods in more specific interfaces.
//
// Graph is a purely read oriented interface; the various Mutable*Graph
// interfaces contain the methods for writing.
type Graph interface {
	GraphEnumerator
	VertexInspector
	EdgeInspector
}

// DirectedGraph describes a Graph all of whose edges are directed.
//
// Implementing DirectedGraph is the only unambiguous signal gogl provides
// that a graph's edges are directed.
type DirectedGraph interface {
	Graph
	Transpose() DirectedGraph
}

// MutableGraph describes a graph with basic edges (no weighting, labeling, etc.)
// that can be modified freely by adding or removing vertices or edges.
type MutableGraph interface {
	Graph
	VertexMutator
	AddEdges(edges ...Edge)
	RemoveEdges(edges ...Edge)
}

// A simple graph is in opposition to a multigraph: it disallows loops and
// parallel edges.
type SimpleGraph interface {
	Graph
	Density() float64
}

// A weighted graph is a graph subtype where the edges have a numeric weight;
// as described by the WeightedEdge interface, this weight is a signed int.
//
// WeightedGraphs have both the HasEdge() and HasWeightedEdge() methods.
// Correct implementations should treat the difference as a matter of strictness:
//
// HasEdge() should return true as long as an edge exists
// connecting the two given vertices (respecting directed or undirected as
// appropriate), regardless of its weight.
//
// HasWeightedEdge() should return true iff an edge exists connecting the
// two given vertices (respecting directed or undirected as appropriate),
// AND if the edge weights are the same.
type WeightedGraph interface {
	Graph
	HasWeightedEdge(e WeightedEdge) bool
	EachWeightedEdge(f func(edge WeightedEdge))
}

// MutableWeightedGraph is the mutable version of a weighted graph. Its
// AddEdges() method is incompatible with MutableGraph, guaranteeing
// only weighted edges can be present in the graph.
type MutableWeightedGraph interface {
	WeightedGraph
	VertexMutator
	AddEdges(edges ...WeightedEdge)
	RemoveEdges(edges ...WeightedEdge)
}

// A labeled graph is a graph subtype where the edges have an identifier;
// as described by the LabeledEdge interface, this identifier is a string.
//
// LabeledGraphs have both the HasEdge() and HasLabeledEdge() methods.
// Correct implementations should treat the difference as a matter of strictness:
//
// HasEdge() should return true as long as an edge exists
// connecting the two given vertices (respecting directed or undirected as
// appropriate), regardless of its label.
//
// HasLabeledEdge() should return true iff an edge exists connecting the
// two given vertices (respecting directed or undirected as appropriate),
// AND if the edge labels are the same.
type LabeledGraph interface {
	Graph
	HasLabeledEdge(e LabeledEdge) bool
	EachLabeledEdge(f func(edge LabeledEdge))
}

// LabeledWeightedGraph is the mutable version of a labeled graph. Its
// AddEdges() method is incompatible with MutableGraph, guaranteeing
// only weighted edges can be present in the graph.
type MutableLabeledGraph interface {
	LabeledGraph
	VertexMutator
	AddEdges(edges ...LabeledEdge)
	RemoveEdges(edges ...LabeledEdge)
}

// A data graph is a graph subtype where the edges carry arbitrary Go data;
// as described by the DataEdge interface, this identifier is an interface{}.
//
// DataGraphs have both the HasEdge() and HasDataEdge() methods.
// Correct implementations should treat the difference as a matter of strictness:
//
// HasEdge() should return true as long as an edge exists
// connecting the two given vertices (respecting directed or undirected as
// appropriate), regardless of its label.
//
// HasDataEdge() should return true iff an edge exists connecting the
// two given vertices (respecting directed or undirected as appropriate),
// AND if the edge data is the same. Simple comparison will typically be used
// to establish data equality, which means that using noncomparables (a slice,
// map, or non-pointer struct containing a slice or a map) for the data will
// cause a panic.
type DataGraph interface {
	Graph
	HasDataEdge(e DataEdge) bool
	EachDataEdge(f func(edge DataEdge))
}

// DataWeightedGraph is the mutable version of a labeled graph. Its
// AddEdges() method is incompatible with MutableGraph, guaranteeing
// only weighted edges can be present in the graph.
type MutableDataGraph interface {
	DataGraph
	VertexMutator
	AddEdges(edges ...DataEdge)
	RemoveEdges(edges ...DataEdge)
}

/* Graph creation */

type GraphFactory func() interface{}

var Graphs = make(map[string]GraphFactory, 0)

// Creates a new graph instance.
//
// You will need to type assert the returned graph to the interface appropriate
// for your use case: Graph, DirectedGraph, MutableGraph, WeightedGraph, etc.
func New(name string) (graph interface{}, err error) {
	if _, exists := Graphs[name]; !exists {
		return nil, fmt.Errorf("No graph is registered with the name %q", name)
	}

	return Graphs[name](), nil
}

func RegisterGraph(name string, factory GraphFactory) error {
	if _, exists := Graphs[name]; exists {
		return fmt.Errorf("A graph is already registered with the name %q", name)
	}

	g := factory()

	if _, ok := g.(Graph); ok {
		return nil
	} else if _, ok := g.(WeightedGraph); ok {
		return nil
	}

	return fmt.Errorf("Value returned from factory does not implement a known Graph interface")
}

func init() {
	RegisterGraph("basic.directed", func() interface{} {
		return NewDirected()
	})
	RegisterGraph("basic.undirected", func() interface{} {
		return NewUndirected()
	})
	RegisterGraph("weighted.directed", func() interface{} {
		return NewWeightedDirected()
	})
	RegisterGraph("weighted.undirected", func() interface{} {
		return NewWeightedUndirected()
	})
}
<commit_msg>Bunch more docs and more separating of interfaces.<commit_after>package gogl

import (
	"fmt"
)

/* Vertex structures */

// As a rule, gogl tries to place as low a requirement on its vertices as
// possible. This is because, from a purely graph theoretic perspective,
// vertices are inert. Boring, even. Graphs are more about the topology, the
// characteristics of the edges connecting the points than the points
// themselves. Your use case cares about the content of your vertices, but gogl
// does not.  Consequently, anything can act as a vertex.
type Vertex interface{}

/* Atomic graph interfaces */

// A VertexEnumerator iteratively enumerates vertices.
type VertexEnumerator interface {
	EachVertex(f func(Vertex))
}

// An EdgeEnumerator iteratively enumerates edges.
type EdgeEnumerator interface {
	EachEdge(f func(Edge))
}

// An AdjacencyEnumerator iteratively enumerates a given vertex's adjacent vertices.
type AdjacencyEnumerator interface {
	EachAdjacent(from Vertex, f func(to Vertex))
}

// A GraphEnumerator can iteratively enumerate several graph properties.
type GraphEnumerator interface {
	VertexEnumerator
	EdgeEnumerator
	AdjacencyEnumerator
}

// A VertexSetInspector indicates the presence and degree of vertices within a set, and the size of the set as a whole.
type VertexSetInspector interface {
	HasVertex(Vertex) bool                      // Whether or not the vertex is present in the set
	InDegree(Vertex) (degree int, exists bool)  // Number of in-edges; if vertex is present
	OutDegree(Vertex) (degree int, exists bool) // Number of out-edges; if vertex is present
	Order() int                                 // Total number of vertices in the set
}

// An EdgeSetInspector indicates the presence of an edge in a set, and the size of the set as a whole.
type EdgeSetInspector interface {
	HasEdge(Edge) bool
	Size() int
}

// A VertexSetMutator allows the addition and removal of vertices from a set.
type VertexSetMutator interface {
	EnsureVertex(...Vertex)
	RemoveVertex(...Vertex)
}

// An EdgeSetMutator allows the addition and removal of edges from a set.
type EdgeSetMutator interface {
	AddEdges(edges ...Edge)
	RemoveEdges(edges ...Edge)
}

/* Aggregate Graph interfaces */

// Graph is gogl's most basic interface: it contains only the methods that
// *every* type of graph implements.
//
// Graph is intentionally underspecified: both directed and undirected graphs
// implement it; simple graphs, multigraphs, weighted, labeled, or any
// combination thereof.
//
// The semantics of some of these methods vary slightly from one graph type
// to another, but in general, the basic Graph methods are supplemented, not
// superceded, by the methods in more specific interfaces.
//
// Graph is a purely read oriented interface; the various Mutable*Graph
// interfaces contain the methods for writing.
type Graph interface {
	GraphEnumerator
	VertexSetInspector
	EdgeSetInspector
}

// DirectedGraph describes a Graph all of whose edges are directed.
//
// Implementing DirectedGraph is the only unambiguous signal gogl provides
// that a graph's edges are directed.
type DirectedGraph interface {
	Graph
	Transpose() DirectedGraph
}

// MutableGraph describes a graph with basic edges (no weighting, labeling, etc.)
// that can be modified freely by adding or removing vertices or edges.
type MutableGraph interface {
	Graph
	VertexSetMutator
	EdgeSetMutator
}

// A simple graph is in opposition to a multigraph: it disallows loops and
// parallel edges.
type SimpleGraph interface {
	Graph
	Density() float64
}

// A weighted graph is a graph subtype where the edges have a numeric weight;
// as described by the WeightedEdge interface, this weight is a signed int.
//
// WeightedGraphs have both the HasEdge() and HasWeightedEdge() methods.
// Correct implementations should treat the difference as a matter of strictness:
//
// HasEdge() should return true as long as an edge exists
// connecting the two given vertices (respecting directed or undirected as
// appropriate), regardless of its weight.
//
// HasWeightedEdge() should return true iff an edge exists connecting the
// two given vertices (respecting directed or undirected as appropriate),
// AND if the edge weights are the same.
type WeightedGraph interface {
	Graph
	HasWeightedEdge(e WeightedEdge) bool
	EachWeightedEdge(f func(edge WeightedEdge))
}

// MutableWeightedGraph is the mutable version of a weighted graph. Its
// AddEdges() method is incompatible with MutableGraph, guaranteeing
// only weighted edges can be present in the graph.
type MutableWeightedGraph interface {
	WeightedGraph
	VertexSetMutator
	AddEdges(edges ...WeightedEdge)
	RemoveEdges(edges ...WeightedEdge)
}

// A labeled graph is a graph subtype where the edges have an identifier;
// as described by the LabeledEdge interface, this identifier is a string.
//
// LabeledGraphs have both the HasEdge() and HasLabeledEdge() methods.
// Correct implementations should treat the difference as a matter of strictness:
//
// HasEdge() should return true as long as an edge exists
// connecting the two given vertices (respecting directed or undirected as
// appropriate), regardless of its label.
//
// HasLabeledEdge() should return true iff an edge exists connecting the
// two given vertices (respecting directed or undirected as appropriate),
// AND if the edge labels are the same.
type LabeledGraph interface {
	Graph
	HasLabeledEdge(e LabeledEdge) bool
	EachLabeledEdge(f func(edge LabeledEdge))
}

// LabeledWeightedGraph is the mutable version of a labeled graph. Its
// AddEdges() method is incompatible with MutableGraph, guaranteeing
// only weighted edges can be present in the graph.
type MutableLabeledGraph interface {
	LabeledGraph
	VertexSetMutator
	AddEdges(edges ...LabeledEdge)
	RemoveEdges(edges ...LabeledEdge)
}

// A data graph is a graph subtype where the edges carry arbitrary Go data;
// as described by the DataEdge interface, this identifier is an interface{}.
//
// DataGraphs have both the HasEdge() and HasDataEdge() methods.
// Correct implementations should treat the difference as a matter of strictness:
//
// HasEdge() should return true as long as an edge exists
// connecting the two given vertices (respecting directed or undirected as
// appropriate), regardless of its label.
//
// HasDataEdge() should return true iff an edge exists connecting the
// two given vertices (respecting directed or undirected as appropriate),
// AND if the edge data is the same. Simple comparison will typically be used
// to establish data equality, which means that using noncomparables (a slice,
// map, or non-pointer struct containing a slice or a map) for the data will
// cause a panic.
type DataGraph interface {
	Graph
	HasDataEdge(e DataEdge) bool
	EachDataEdge(f func(edge DataEdge))
}

// DataWeightedGraph is the mutable version of a labeled graph. Its
// AddEdges() method is incompatible with MutableGraph, guaranteeing
// only weighted edges can be present in the graph.
type MutableDataGraph interface {
	DataGraph
	VertexSetMutator
	AddEdges(edges ...DataEdge)
	RemoveEdges(edges ...DataEdge)
}

/* Graph creation */

type GraphFactory func() interface{}

var Graphs = make(map[string]GraphFactory, 0)

// Creates a new graph instance.
//
// You will need to type assert the returned graph to the interface appropriate
// for your use case: Graph, DirectedGraph, MutableGraph, WeightedGraph, etc.
func New(name string) (graph interface{}, err error) {
	if _, exists := Graphs[name]; !exists {
		return nil, fmt.Errorf("No graph is registered with the name %q", name)
	}

	return Graphs[name](), nil
}

func RegisterGraph(name string, factory GraphFactory) error {
	if _, exists := Graphs[name]; exists {
		return fmt.Errorf("A graph is already registered with the name %q", name)
	}

	g := factory()

	if _, ok := g.(Graph); ok {
		return nil
	} else if _, ok := g.(WeightedGraph); ok {
		return nil
	}

	return fmt.Errorf("Value returned from factory does not implement a known Graph interface")
}

func init() {
	RegisterGraph("basic.directed", func() interface{} {
		return NewDirected()
	})
	RegisterGraph("basic.undirected", func() interface{} {
		return NewUndirected()
	})
	RegisterGraph("weighted.directed", func() interface{} {
		return NewWeightedDirected()
	})
	RegisterGraph("weighted.undirected", func() interface{} {
		return NewWeightedUndirected()
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"math"
)

var (
	amount   = flag.Float64("amount", 0.0, "loan amount")
	interest = flag.Float64("rate", 0.0, "interest rate")
	months   = flag.Int("months", 360, "length of the loan (360 = 30 years)")
)

func main() {
	flag.Parse()
	if *amount == 0 || *interest == 0 {
		flag.Usage()
		return
	}

	discount := calculateDiscount(*interest/100, *months)
	payment := *amount / discount

	fmt.Printf("Monthly Payment: $%.2f\n", payment)

	periodic := (*interest / 100) / 12
	interestPayment := *amount * periodic
	fmt.Printf("First Interest Payment: $%.2f\n", interestPayment)
	fmt.Printf("First Principal Payment: $%.2f\n", payment-interestPayment)

}

func calculateDiscount(interest float64, months int) float64 {
	periodic := interest / 12
	daily := math.Pow(periodic+1, 360)
	return (daily - 1) / (periodic * daily)
}
<commit_msg>add Money type for printing money pretty<commit_after>package main

import (
	"flag"
	"fmt"
	"math"
)

// Money lets is print money numbers pretty
type Money float64

func (m Money) String() string {
	return fmt.Sprintf("$%.2f", m)
}

var (
	amount   = flag.Float64("amount", 0.0, "loan amount")
	interest = flag.Float64("rate", 0.0, "interest rate")
	months   = flag.Int("months", 360, "length of the loan (360 = 30 years)")
)

func main() {
	flag.Parse()
	if *amount == 0 || *interest == 0 {
		flag.Usage()
		return
	}

	discount := calculateDiscount(*interest/100, *months)
	payment := *amount / discount

	fmt.Println("Monthly Payment:", Money(payment))

	periodic := (*interest / 100) / 12
	interestPayment := *amount * periodic
	fmt.Println("First Interest Payment: $%.2f\n", Money(interestPayment))
	fmt.Println("First Principal Payment: $%.2f\n", Money(payment-interestPayment))

}

func calculateDiscount(interest float64, months int) float64 {
	periodic := interest / 12
	daily := math.Pow(periodic+1, 360)
	return (daily - 1) / (periodic * daily)
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gm (geometry and meshes) implements auxiliary functions for
// handling geometry and mesh structures
package gm

import (
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/utl"
)

// Bspline holds B-spline data
//  Reference:
//   [1] Piegl L and Tiller W (1995) The NURBS book, Springer, 646p
type Bspline struct {

	// essential
	T    []float64 // array of knots: e.g: T = [t_0, t_1, ..., t_{m-1}]
	p    int       // order/degreee (has to call SetOrder to change this)
	m    int       // number of knots == len(T)
	tmin float64   // minimum T
	tmax float64   // maximum T

	// optional
	Q   [][]float64 // control points (has to call SetControl to change this)
	okQ bool        // flag telling that Q was properly set

	// auxiliary
	span int         // the span computed by CalcBasis or CalcBasisAndDerivs to be used in GetBasis or GetDeriv
	le   []float64   // left
	ri   []float64   // right
	ndu  [][]float64 // basis functions and knots differences
	der  [][]float64 // derivatives
	daux [][]float64 // auxiliary array for computing derivatives
}

// NewBspline returns a new B-spline
func NewBspline(T []float64, p int) (o *Bspline) {

	// check
	if len(T) < 2*(p+1) {
		chk.Panic("at least %d knots are required to define clamped B-spline of order p==%d. m==%d is invalid", 2*(p+1), p, len(T))
	}

	// essential
	o = new(Bspline)
	o.T, o.p, o.m = T, p, len(T)
	o.tmin, o.tmax = utl.MinMax(T)

	// auxiliary
	o.le = make([]float64, o.p+1)
	o.ri = make([]float64, o.p+1)
	o.ndu = utl.Alloc(o.p+1, o.p+1)
	o.der = utl.Alloc(o.p+1, o.p+1)
	o.daux = utl.Alloc(2, o.p+1)
	return
}

// SetOrder sets B-spline order (p)
func (o *Bspline) SetOrder(p int) {
	o.p = p
}

// NumBasis returns the number (n) of basis functions == number of control points
func (o *Bspline) NumBasis() int {
	return o.m - o.p - 1
}

// SetControl sets B-spline control points
func (o *Bspline) SetControl(Q [][]float64) {
	if len(Q) != o.NumBasis() {
		chk.Panic("B-spline of order %d needs %d control points", o.p, o.NumBasis())
	}
	o.Q, o.okQ = Q, true
}

// CalcBasis computes all non-zero basis functions N[i] @ t
// Note: use GetBasis to get a particular basis function value
func (o *Bspline) CalcBasis(t float64) {
	// check
	if t < o.tmin || t > o.tmax {
		chk.Panic("t must be within [%g, %g]. t=%g is incorrect", t, o.tmin, o.tmax)
	}
	// using basis_funs (Piegl & Tiller, algorithm A2.2)
	o.span = o.findSpan(t)
	o.basisFuns(t, o.span)
}

// CalcBasisAndDerivs computes all non-zero basis functions N[i] and corresponding
// first order derivatives of basis functions w.r.t t => dR[i]dt @ t
// Note: use GetBasis to get a particular basis function value
//       use GetDeriv to get a particular derivative
func (o *Bspline) CalcBasisAndDerivs(t float64) {
	// check
	if t < o.tmin || t > o.tmax {
		chk.Panic("t must be within [%g, %g]. t=%g is incorrect", t, o.tmin, o.tmax)
	}
	// using ders_basis_funs (Piegl & Tiller, algorithm A2.3)
	o.span = o.findSpan(t)
	o.dersBasisFuns(t, o.span, 1)
}

// GetBasis returns the basis function N[i] just computed by CalcBasis or CalcBasisAndDerivs
func (o *Bspline) GetBasis(i int) float64 {
	j := i + o.p - o.span
	if j >= 0 && j <= o.p {
		return o.ndu[j][o.p]
	}
	return 0
}

// GetDeriv returns the derivative dN[i]dt just computed by CalcBasisAndDerivs
func (o *Bspline) GetDeriv(i int) float64 {
	j := i + o.p - o.span
	if j >= 0 && j <= o.p {
		return o.der[1][j]
	}
	return 0
}

// RecursiveBasis computes one particular basis function N[i] recursively (not efficient)
func (o *Bspline) RecursiveBasis(t float64, i int) float64 {
	// check
	if t < o.tmin || t > o.tmax {
		chk.Panic("t must be within [%g, %g]. t=%g is incorrect", t, o.tmin, o.tmax)
	}
	// using Cox-DeBoor formula
	return o.recursiveN(t, i, o.p)
}

// Point returns the x-y-z coordinates of a point on B-spline
// option =  0 : use CalcBasis
//           1 : use RecursiveBasis
func (o *Bspline) Point(t float64, option int) (C []float64) {
	// check
	if !o.okQ {
		chk.Panic("Q must be set before calling this method")
	}
	// compute point on curve
	ncp := len(o.Q[0]) // number of components in Q
	C = make([]float64, ncp)
	switch option {
	case 0: // recursive
		for i, q := range o.Q {
			for j := 0; j < ncp; j++ {
				C[j] += o.RecursiveBasis(t, i) * q[j]
			}
		}
	case 1: // Piegl & Tiller: A3.1 p82
		span := o.findSpan(t)
		o.basisFuns(t, span)
		for i := 0; i <= o.p; i++ {
			for j := 0; j < ncp; j++ {
				C[j] += o.ndu[i][o.p] * o.Q[span-o.p+i][j]
			}
		}
	}
	return
}

// Elements returns the indices of nonzero spans
func (o *Bspline) Elements() (spans [][]int) {
	nspans := 0
	for i := 0; i < o.m-1; i++ {
		l := o.T[i+1] - o.T[i]
		if math.Abs(l) > 1e-14 {
			nspans++
		}
	}
	spans = utl.IntAlloc(nspans, 2)
	ispan := 0
	for i := 0; i < o.m-1; i++ {
		l := o.T[i+1] - o.T[i]
		if math.Abs(l) > 1e-14 {
			spans[ispan][0] = i
			spans[ispan][1] = i + 1
			ispan++
		}
	}
	return
}

// auxiliary methods /////////////////////////////////////////////////////////////////////////////////

// findSpan returns the span where t falls in
func (o *Bspline) findSpan(t float64) int {
	// Piegl & Tiller: A2.1 p68
	n := o.NumBasis()
	if t >= o.T[n] {
		return n - 1
	}
	if t <= o.T[o.p] {
		return o.p
	}
	low, high, mid := o.p, n, (o.p+n)/2
	for t < o.T[mid] || t >= o.T[mid+1] {
		if t < o.T[mid] {
			high = mid
		} else {
			low = mid
		}
		mid = (low + high) / 2
	}
	return mid
}

// recursiveN computes basis functions using Cox-DeBoors recursive formula
func (o *Bspline) recursiveN(t float64, i int, p int) float64 {
	if math.Abs(t-o.tmax) < 1e-14 {
		t = o.tmax - 1e-14 // remove noise. e.g. 1.000000000000002
	}
	if p == 0 {
		if t < o.T[i] {
			return 0.0
		}
		if t < o.T[i+1] {
			return 1.0
		}
		return 0.0
	}
	d1 := o.T[i+p] - o.T[i]
	d2 := o.T[i+p+1] - o.T[i+1]
	var N1, N2 float64
	if math.Abs(d1) < 1e-14 {
		N1, d1 = 0.0, 1.0
	} else {
		N1 = o.recursiveN(t, i, p-1)
	}
	if math.Abs(d2) < 1e-14 {
		N2, d2 = 0.0, 1.0
	} else {
		N2 = o.recursiveN(t, i+1, p-1)
	}
	return (t-o.T[i])*N1/d1 + (o.T[i+p+1]-t)*N2/d2
}

// basisFuns computes basis functions using Piegl-Tiller algorithm A2.2/2.3 p70/p72
func (o *Bspline) basisFuns(t float64, span int) {
	// Piegl & Tiller: A2.3 p72
	// compute basis functions and knot differences
	var temp, saved float64
	o.ndu[0][0] = 1
	for j := 1; j <= o.p; j++ {
		o.le[j] = t - o.T[span+1-j]
		o.ri[j] = o.T[span+j] - t
		saved = 0
		for r := 0; r < j; r++ {
			o.ndu[j][r] = o.ri[r+1] + o.le[j-r]
			temp = o.ndu[r][j-1] / o.ndu[j][r]
			o.ndu[r][j] = saved + o.ri[r+1]*temp
			saved = o.le[j-r] * temp
		}
		o.ndu[j][j] = saved
	}
}

// dersBasisFuns computes derivatives of basis functions using Piegl-Tiller algorithm A2.3 p72
func (o *Bspline) dersBasisFuns(t float64, span, upto int) {
	// compute and load the basis functions
	o.basisFuns(t, span)
	for j := 0; j <= o.p; j++ {
		o.der[0][j] = o.ndu[j][o.p]
	}
	// compute the derivatives (Eq 2.9)
	var d float64
	var s1, s2, rk, pk, j1, j2 int
	for r := 0; r <= o.p; r++ {
		s1, s2 = 0, 1 // alternate rows in array
		o.daux[0][0] = 1
		// loop to compute k-th derivative
		for k := 1; k <= upto; k++ {
			d, rk, pk = 0, r-k, o.p-k
			if r >= k {
				o.daux[s2][0] = o.daux[s1][0] / o.ndu[pk+1][rk]
				d = o.daux[s2][0] * o.ndu[rk][pk]
			}
			if rk >= -1 {
				j1 = 1
			} else {
				j1 = -rk
			}
			if r-1 <= pk {
				j2 = k - 1
			} else {
				j2 = o.p - r
			}
			for j := j1; j <= j2; j++ {
				o.daux[s2][j] = (o.daux[s1][j] - o.daux[s1][j-1]) / o.ndu[pk+1][rk+j]
				d += o.daux[s2][j] * o.ndu[rk+j][pk]
			}
			if r <= pk {
				o.daux[s2][k] = -o.daux[s1][k-1] / o.ndu[pk+1][r]
				d += o.daux[s2][k] * o.ndu[r][pk]
			}
			o.der[k][r] = d
			s1, s2 = s2, s1
		}
	}
	// multiply through by the correct factors
	d = float64(o.p)
	for k := 1; k <= upto; k++ {
		for j := 0; j <= o.p; j++ {
			o.der[k][j] *= d
		}
		d *= float64(o.p - k)
	}
}
<commit_msg>Improve comment<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gm (geometry and meshes) implements auxiliary functions for
// handling geometry and mesh structures
package gm

import (
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/utl"
)

// Bspline holds B-spline data
//  Reference:
//   [1] Piegl L and Tiller W (1995) The NURBS book, Springer, 646p
type Bspline struct {

	// essential
	T    []float64 // array of knots: e.g: T = [t_0, t_1, ..., t_{m-1}]
	p    int       // order/degreee (has to call SetOrder to change this)
	m    int       // number of knots == len(T)
	tmin float64   // minimum T
	tmax float64   // maximum T

	// optional
	Q   [][]float64 // control points (has to call SetControl to change this)
	okQ bool        // flag telling that Q was properly set

	// auxiliary
	span int         // the span computed by CalcBasis or CalcBasisAndDerivs to be used in GetBasis or GetDeriv
	le   []float64   // left
	ri   []float64   // right
	ndu  [][]float64 // basis functions and knots differences
	der  [][]float64 // derivatives
	daux [][]float64 // auxiliary array for computing derivatives
}

// NewBspline returns a new B-spline
func NewBspline(T []float64, p int) (o *Bspline) {

	// check
	if len(T) < 2*(p+1) {
		chk.Panic("at least %d knots are required to define clamped B-spline of order p==%d. m==%d is invalid", 2*(p+1), p, len(T))
	}

	// essential
	o = new(Bspline)
	o.T, o.p, o.m = T, p, len(T)
	o.tmin, o.tmax = utl.MinMax(T)

	// auxiliary
	o.le = make([]float64, o.p+1)
	o.ri = make([]float64, o.p+1)
	o.ndu = utl.Alloc(o.p+1, o.p+1)
	o.der = utl.Alloc(o.p+1, o.p+1)
	o.daux = utl.Alloc(2, o.p+1)
	return
}

// SetOrder sets B-spline order (p)
func (o *Bspline) SetOrder(p int) {
	o.p = p
}

// NumBasis returns the number (n) of basis functions == number of control points
func (o *Bspline) NumBasis() int {
	return o.m - o.p - 1
}

// SetControl sets B-spline control points
func (o *Bspline) SetControl(Q [][]float64) {
	if len(Q) != o.NumBasis() {
		chk.Panic("B-spline of order %d needs %d control points", o.p, o.NumBasis())
	}
	o.Q, o.okQ = Q, true
}

// CalcBasis computes all non-zero basis functions N[i] @ t
// Note: use GetBasis to get a particular basis function value
func (o *Bspline) CalcBasis(t float64) {
	// check
	if t < o.tmin || t > o.tmax {
		chk.Panic("t must be within [%g, %g]. t=%g is incorrect", t, o.tmin, o.tmax)
	}
	// using basis_funs (Piegl & Tiller, algorithm A2.2)
	o.span = o.findSpan(t)
	o.basisFuns(t, o.span)
}

// CalcBasisAndDerivs computes all non-zero basis functions N[i] and corresponding
// first order derivatives of basis functions w.r.t t => dR[i]dt @ t
// Note: use GetBasis to get a particular basis function value
//       use GetDeriv to get a particular derivative
func (o *Bspline) CalcBasisAndDerivs(t float64) {
	// check
	if t < o.tmin || t > o.tmax {
		chk.Panic("t must be within [%g, %g]. t=%g is incorrect", t, o.tmin, o.tmax)
	}
	// using ders_basis_funs (Piegl & Tiller, algorithm A2.3)
	o.span = o.findSpan(t)
	o.dersBasisFuns(t, o.span, 1)
}

// GetBasis returns the basis function N[i] just computed by CalcBasis or CalcBasisAndDerivs
func (o *Bspline) GetBasis(i int) float64 {
	j := i + o.p - o.span
	if j >= 0 && j <= o.p {
		return o.ndu[j][o.p]
	}
	return 0
}

// GetDeriv returns the derivative dN[i]dt just computed by CalcBasisAndDerivs
func (o *Bspline) GetDeriv(i int) float64 {
	j := i + o.p - o.span
	if j >= 0 && j <= o.p {
		return o.der[1][j]
	}
	return 0
}

// RecursiveBasis computes one particular basis function N[i] recursively (not efficient)
func (o *Bspline) RecursiveBasis(t float64, i int) float64 {
	// check
	if t < o.tmin || t > o.tmax {
		chk.Panic("t must be within [%g, %g]. t=%g is incorrect", t, o.tmin, o.tmax)
	}
	// using Cox-DeBoor formula
	return o.recursiveN(t, i, o.p)
}

// Point returns the x-y-z coordinates of a point on B-spline
// option =  0 : use CalcBasis
//           1 : use RecursiveBasis
func (o *Bspline) Point(t float64, option int) (C []float64) {
	// check
	if !o.okQ {
		chk.Panic("Q must be set before calling this method")
	}
	// compute point on curve
	ncp := len(o.Q[0]) // number of components in Q
	C = make([]float64, ncp)
	switch option {
	case 0: // recursive
		for i, q := range o.Q {
			for j := 0; j < ncp; j++ {
				C[j] += o.RecursiveBasis(t, i) * q[j]
			}
		}
	case 1: // Piegl & Tiller: A3.1 p82
		span := o.findSpan(t)
		o.basisFuns(t, span)
		for i := 0; i <= o.p; i++ {
			for j := 0; j < ncp; j++ {
				C[j] += o.ndu[i][o.p] * o.Q[span-o.p+i][j]
			}
		}
	}
	return
}

// Elements returns the indices of nonzero spans
func (o *Bspline) Elements() (spans [][]int) {
	nspans := 0
	for i := 0; i < o.m-1; i++ {
		l := o.T[i+1] - o.T[i]
		if math.Abs(l) > 1e-14 {
			nspans++
		}
	}
	spans = utl.IntAlloc(nspans, 2)
	ispan := 0
	for i := 0; i < o.m-1; i++ {
		l := o.T[i+1] - o.T[i]
		if math.Abs(l) > 1e-14 {
			spans[ispan][0] = i
			spans[ispan][1] = i + 1
			ispan++
		}
	}
	return
}

// auxiliary methods /////////////////////////////////////////////////////////////////////////////////

// findSpan returns the span where t falls in
func (o *Bspline) findSpan(t float64) int {
	// Piegl & Tiller: A2.1 p68
	n := o.NumBasis()
	if t >= o.T[n] {
		return n - 1
	}
	if t <= o.T[o.p] {
		return o.p
	}
	low, high, mid := o.p, n, (o.p+n)/2
	for t < o.T[mid] || t >= o.T[mid+1] {
		if t < o.T[mid] {
			high = mid
		} else {
			low = mid
		}
		mid = (low + high) / 2
	}
	return mid
}

// recursiveN computes basis functions using Cox-DeBoors recursive formula
func (o *Bspline) recursiveN(t float64, i int, p int) float64 {
	if math.Abs(t-o.tmax) < 1e-14 {
		t = o.tmax - 1e-14 // remove noise. e.g. 1.000000000000002
	}
	if p == 0 {
		if t < o.T[i] {
			return 0.0
		}
		if t < o.T[i+1] {
			return 1.0
		}
		return 0.0
	}
	d1 := o.T[i+p] - o.T[i]
	d2 := o.T[i+p+1] - o.T[i+1]
	var N1, N2 float64
	if math.Abs(d1) < 1e-14 {
		N1, d1 = 0.0, 1.0
	} else {
		N1 = o.recursiveN(t, i, p-1)
	}
	if math.Abs(d2) < 1e-14 {
		N2, d2 = 0.0, 1.0
	} else {
		N2 = o.recursiveN(t, i+1, p-1)
	}
	return (t-o.T[i])*N1/d1 + (o.T[i+p+1]-t)*N2/d2
}

// basisFuns computes basis functions using Piegl-Tiller algorithm A2.2/2.3 p70/p72
func (o *Bspline) basisFuns(t float64, span int) {
	// Piegl & Tiller: A2.3 p72
	// compute basis functions and knot differences
	var temp, saved float64
	o.ndu[0][0] = 1
	for j := 1; j <= o.p; j++ {
		o.le[j] = t - o.T[span+1-j]
		o.ri[j] = o.T[span+j] - t
		saved = 0
		for r := 0; r < j; r++ {
			o.ndu[j][r] = o.ri[r+1] + o.le[j-r]
			temp = o.ndu[r][j-1] / o.ndu[j][r]
			o.ndu[r][j] = saved + o.ri[r+1]*temp
			saved = o.le[j-r] * temp
		}
		o.ndu[j][j] = saved
	}
}

// dersBasisFuns computes derivatives of basis functions using Piegl-Tiller algorithm A2.3 p72
// NOTE: this function also computes basis functions by calling basisFuns()
func (o *Bspline) dersBasisFuns(t float64, span, upto int) {
	// compute and load the basis functions
	o.basisFuns(t, span)
	for j := 0; j <= o.p; j++ {
		o.der[0][j] = o.ndu[j][o.p]
	}
	// compute the derivatives (Eq 2.9)
	var d float64
	var s1, s2, rk, pk, j1, j2 int
	for r := 0; r <= o.p; r++ {
		s1, s2 = 0, 1 // alternate rows in array
		o.daux[0][0] = 1
		// loop to compute k-th derivative
		for k := 1; k <= upto; k++ {
			d, rk, pk = 0, r-k, o.p-k
			if r >= k {
				o.daux[s2][0] = o.daux[s1][0] / o.ndu[pk+1][rk]
				d = o.daux[s2][0] * o.ndu[rk][pk]
			}
			if rk >= -1 {
				j1 = 1
			} else {
				j1 = -rk
			}
			if r-1 <= pk {
				j2 = k - 1
			} else {
				j2 = o.p - r
			}
			for j := j1; j <= j2; j++ {
				o.daux[s2][j] = (o.daux[s1][j] - o.daux[s1][j-1]) / o.ndu[pk+1][rk+j]
				d += o.daux[s2][j] * o.ndu[rk+j][pk]
			}
			if r <= pk {
				o.daux[s2][k] = -o.daux[s1][k-1] / o.ndu[pk+1][r]
				d += o.daux[s2][k] * o.ndu[r][pk]
			}
			o.der[k][r] = d
			s1, s2 = s2, s1
		}
	}
	// multiply through by the correct factors
	d = float64(o.p)
	for k := 1; k <= upto; k++ {
		for j := 0; j <= o.p; j++ {
			o.der[k][j] *= d
		}
		d *= float64(o.p - k)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/pkg"
	"github.com/coreos/coreos-cloudinit/system"
)

const (
	version               = "0.7.7+git"
	datasourceInterval    = 100 * time.Millisecond
	datasourceMaxInterval = 30 * time.Second
	datasourceTimeout     = 5 * time.Minute
)

var (
	printVersion  bool
	ignoreFailure bool
	sources       struct {
		file            string
		configDrive     string
		metadataService bool
		url             string
		procCmdLine     bool
	}
	convertNetconf string
	workspace      string
	sshKeyName     string
)

func init() {
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")
	flag.BoolVar(&ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")
	flag.StringVar(&sources.file, "from-file", "", "Read user-data from provided file")
	flag.StringVar(&sources.configDrive, "from-configdrive", "", "Read data from provided cloud-drive directory")
	flag.BoolVar(&sources.metadataService, "from-metadata-service", false, "Download data from metadata service")
	flag.StringVar(&sources.url, "from-url", "", "Download user-data from provided url")
	flag.BoolVar(&sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", datasource.ProcCmdlineLocation, datasource.ProcCmdlineCloudConfigFlag))
	flag.StringVar(&convertNetconf, "convert-netconf", "", "Read the network config provided in cloud-drive and translate it from the specified format into networkd unit files (requires the -from-configdrive flag)")
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")
	flag.StringVar(&sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")
}

func main() {
	flag.Parse()

	die := func() {
		if ignoreFailure {
			os.Exit(0)
		}
		os.Exit(1)
	}

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	if convertNetconf != "" && sources.configDrive == "" {
		fmt.Println("-convert-netconf flag requires -from-configdrive")
		os.Exit(1)
	}

	switch convertNetconf {
	case "":
	case "debian":
	default:
		fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian'\n", convertNetconf)
		os.Exit(1)
	}

	dss := getDatasources()
	if len(dss) == 0 {
		fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-metadata-service, --from-url or --from-proc-cmdline")
		os.Exit(1)
	}

	ds := selectDatasource(dss)
	if ds == nil {
		fmt.Println("No datasources available in time")
		die()
	}

	fmt.Printf("Fetching user-data from datasource of type %q\n", ds.Type())
	userdataBytes, err := ds.FetchUserdata()
	if err != nil {
		fmt.Printf("Failed fetching user-data from datasource: %v\n", err)
		die()
	}

	fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
	metadataBytes, err := ds.FetchMetadata()
	if err != nil {
		fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
		die()
	}

	var subs map[string]string
	if len(metadataBytes) > 0 {
		subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
		if err != nil {
			fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
			die()
		}
	}
	env := initialize.NewEnvironment("/", ds.ConfigRoot(), workspace, convertNetconf, sshKeyName, subs)

	if len(metadataBytes) > 0 {
		if err := processMetadata(string(metadataBytes), env); err != nil {
			fmt.Printf("Failed to process meta-data: %v\n", err)
			die()
		}
	} else {
		fmt.Println("No meta-data to handle.")
	}

	if len(userdataBytes) > 0 {
		if err := processUserdata(string(userdataBytes), env); err != nil {
			fmt.Printf("Failed to process user-data: %v\n", err)
			if !ignoreFailure {
				die()
			}
		}
	} else {
		fmt.Println("No user-data to handle.")
	}
}

func getDatasources() []datasource.Datasource {
	dss := make([]datasource.Datasource, 0, 5)
	if sources.file != "" {
		dss = append(dss, datasource.NewLocalFile(sources.file))
	}
	if sources.url != "" {
		dss = append(dss, datasource.NewRemoteFile(sources.url))
	}
	if sources.configDrive != "" {
		dss = append(dss, datasource.NewConfigDrive(sources.configDrive))
	}
	if sources.metadataService {
		dss = append(dss, datasource.NewMetadataService())
	}
	if sources.procCmdLine {
		dss = append(dss, datasource.NewProcCmdline())
	}
	return dss
}

func selectDatasource(sources []datasource.Datasource) datasource.Datasource {
	ds := make(chan datasource.Datasource)
	stop := make(chan struct{})
	var wg sync.WaitGroup

	for _, s := range sources {
		wg.Add(1)
		go func(s datasource.Datasource) {
			defer wg.Done()

			duration := datasourceInterval
			for {
				fmt.Printf("Checking availability of %q\n", s.Type())
				if s.IsAvailable() {
					ds <- s
					return
				} else if !s.AvailabilityChanges() {
					return
				}
				select {
				case <-stop:
					return
				case <-time.Tick(duration):
					duration = pkg.ExpBackoff(duration, datasourceMaxInterval)
				}
			}
		}(s)
	}

	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	var s datasource.Datasource
	select {
	case s = <-ds:
	case <-done:
	case <-time.Tick(datasourceTimeout):
	}

	close(stop)
	return s
}

func processUserdata(userdata string, env *initialize.Environment) error {
	userdata = env.Apply(userdata)

	parsed, err := initialize.ParseUserData(userdata)
	if err != nil {
		fmt.Printf("Failed parsing user-data: %v\n", err)
		return err
	}

	err = initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}

	switch t := parsed.(type) {
	case initialize.CloudConfig:
		err = initialize.Apply(t, env)
	case system.Script:
		var path string
		path, err = initialize.PersistScriptInWorkspace(t, env.Workspace())
		if err == nil {
			var name string
			name, err = system.ExecuteScript(path)
			initialize.PersistUnitNameInWorkspace(name, env.Workspace())
		}
	}

	return err
}

func processMetadata(metadata string, env *initialize.Environment) error {
	parsed, err := initialize.ParseMetaData(metadata)
	if err != nil {
		fmt.Printf("Failed parsing meta-data: %v\n", err)
		return err
	}
	err = initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}

	return initialize.Apply(parsed, env)
}
<commit_msg>coreos-cloudinit: bump to 0.8.0<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/pkg"
	"github.com/coreos/coreos-cloudinit/system"
)

const (
	version               = "0.8.0"
	datasourceInterval    = 100 * time.Millisecond
	datasourceMaxInterval = 30 * time.Second
	datasourceTimeout     = 5 * time.Minute
)

var (
	printVersion  bool
	ignoreFailure bool
	sources       struct {
		file            string
		configDrive     string
		metadataService bool
		url             string
		procCmdLine     bool
	}
	convertNetconf string
	workspace      string
	sshKeyName     string
)

func init() {
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")
	flag.BoolVar(&ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")
	flag.StringVar(&sources.file, "from-file", "", "Read user-data from provided file")
	flag.StringVar(&sources.configDrive, "from-configdrive", "", "Read data from provided cloud-drive directory")
	flag.BoolVar(&sources.metadataService, "from-metadata-service", false, "Download data from metadata service")
	flag.StringVar(&sources.url, "from-url", "", "Download user-data from provided url")
	flag.BoolVar(&sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", datasource.ProcCmdlineLocation, datasource.ProcCmdlineCloudConfigFlag))
	flag.StringVar(&convertNetconf, "convert-netconf", "", "Read the network config provided in cloud-drive and translate it from the specified format into networkd unit files (requires the -from-configdrive flag)")
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")
	flag.StringVar(&sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")
}

func main() {
	flag.Parse()

	die := func() {
		if ignoreFailure {
			os.Exit(0)
		}
		os.Exit(1)
	}

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	if convertNetconf != "" && sources.configDrive == "" {
		fmt.Println("-convert-netconf flag requires -from-configdrive")
		os.Exit(1)
	}

	switch convertNetconf {
	case "":
	case "debian":
	default:
		fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian'\n", convertNetconf)
		os.Exit(1)
	}

	dss := getDatasources()
	if len(dss) == 0 {
		fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-metadata-service, --from-url or --from-proc-cmdline")
		os.Exit(1)
	}

	ds := selectDatasource(dss)
	if ds == nil {
		fmt.Println("No datasources available in time")
		die()
	}

	fmt.Printf("Fetching user-data from datasource of type %q\n", ds.Type())
	userdataBytes, err := ds.FetchUserdata()
	if err != nil {
		fmt.Printf("Failed fetching user-data from datasource: %v\n", err)
		die()
	}

	fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
	metadataBytes, err := ds.FetchMetadata()
	if err != nil {
		fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
		die()
	}

	var subs map[string]string
	if len(metadataBytes) > 0 {
		subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
		if err != nil {
			fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
			die()
		}
	}
	env := initialize.NewEnvironment("/", ds.ConfigRoot(), workspace, convertNetconf, sshKeyName, subs)

	if len(metadataBytes) > 0 {
		if err := processMetadata(string(metadataBytes), env); err != nil {
			fmt.Printf("Failed to process meta-data: %v\n", err)
			die()
		}
	} else {
		fmt.Println("No meta-data to handle.")
	}

	if len(userdataBytes) > 0 {
		if err := processUserdata(string(userdataBytes), env); err != nil {
			fmt.Printf("Failed to process user-data: %v\n", err)
			if !ignoreFailure {
				die()
			}
		}
	} else {
		fmt.Println("No user-data to handle.")
	}
}

func getDatasources() []datasource.Datasource {
	dss := make([]datasource.Datasource, 0, 5)
	if sources.file != "" {
		dss = append(dss, datasource.NewLocalFile(sources.file))
	}
	if sources.url != "" {
		dss = append(dss, datasource.NewRemoteFile(sources.url))
	}
	if sources.configDrive != "" {
		dss = append(dss, datasource.NewConfigDrive(sources.configDrive))
	}
	if sources.metadataService {
		dss = append(dss, datasource.NewMetadataService())
	}
	if sources.procCmdLine {
		dss = append(dss, datasource.NewProcCmdline())
	}
	return dss
}

func selectDatasource(sources []datasource.Datasource) datasource.Datasource {
	ds := make(chan datasource.Datasource)
	stop := make(chan struct{})
	var wg sync.WaitGroup

	for _, s := range sources {
		wg.Add(1)
		go func(s datasource.Datasource) {
			defer wg.Done()

			duration := datasourceInterval
			for {
				fmt.Printf("Checking availability of %q\n", s.Type())
				if s.IsAvailable() {
					ds <- s
					return
				} else if !s.AvailabilityChanges() {
					return
				}
				select {
				case <-stop:
					return
				case <-time.Tick(duration):
					duration = pkg.ExpBackoff(duration, datasourceMaxInterval)
				}
			}
		}(s)
	}

	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	var s datasource.Datasource
	select {
	case s = <-ds:
	case <-done:
	case <-time.Tick(datasourceTimeout):
	}

	close(stop)
	return s
}

func processUserdata(userdata string, env *initialize.Environment) error {
	userdata = env.Apply(userdata)

	parsed, err := initialize.ParseUserData(userdata)
	if err != nil {
		fmt.Printf("Failed parsing user-data: %v\n", err)
		return err
	}

	err = initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}

	switch t := parsed.(type) {
	case initialize.CloudConfig:
		err = initialize.Apply(t, env)
	case system.Script:
		var path string
		path, err = initialize.PersistScriptInWorkspace(t, env.Workspace())
		if err == nil {
			var name string
			name, err = system.ExecuteScript(path)
			initialize.PersistUnitNameInWorkspace(name, env.Workspace())
		}
	}

	return err
}

func processMetadata(metadata string, env *initialize.Environment) error {
	parsed, err := initialize.ParseMetaData(metadata)
	if err != nil {
		fmt.Printf("Failed parsing meta-data: %v\n", err)
		return err
	}
	err = initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}

	return initialize.Apply(parsed, env)
}
<|endoftext|>


<commit_before>// +build enterprise

package admin

import (
	"fmt"

	"enterprise.getqor.com/promotion"
	"github.com/qor/admin"
	"github.com/qor/qor"
	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/db"
)

func init() {
	// Benefits Definations
	discountRateArgument := Admin.NewResource(&struct {
		Percentage uint
	}{})
	discountRateArgument.Meta(&admin.Meta{Name: "Percentage", Label: "Percentage (e.g enter 10 for a 10% discount)"})
	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name:     "Discount Rate",
		Resource: discountRateArgument,
	})

	discountAmountArgument := Admin.NewResource(&struct {
		Amount float32
	}{})
	discountAmountArgument.Meta(&admin.Meta{Name: "Amount", Label: "Amount (e.g enter 10 for a $10 discount)"})
	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name:     "Discount Amount",
		Resource: discountAmountArgument,
	})

	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name: "Shipping Fee",
		Resource: Admin.NewResource(&struct {
			Price float32
		}{}),
	})

	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name: "2nd Day Shipping Fee",
		Resource: Admin.NewResource(&struct {
			Price float32
		}{}),
	})

	productCodeCollection := func(value interface{}, context *qor.Context) [][]string {
		var products []models.Product
		var results [][]string
		context.GetDB().Find(&products)
		for _, product := range products {
			results = append(results, []string{fmt.Sprint(product.ID), product.Code})
		}
		return results
	}
	combinedDiscountArgument := Admin.NewResource(&struct {
		ProductCodes []string
		Category     string
		Quantity     uint
		Price        float32
		Percentage   uint
		Discount     uint
	}{})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "ProductCodes", Type: "select_many", Collection: productCodeCollection})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "Percentage", Label: "Discount Percentage (e.g enter 10 for a 10% discount)"})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "Discount", Label: "Discount Amount (e.g enter 10 for a $10 discount)"})
	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name:     "Combined Discounts",
		Resource: combinedDiscountArgument,
	})

	// Rules Definations
	amountGreaterThanArgument := Admin.NewResource(&struct {
		Amount   int
		Category string
	}{})
	amountGreaterThanArgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "Amount Greater Than",
		Resource: amountGreaterThanArgument,
	})

	quantityGreaterThanArgument := Admin.NewResource(&struct {
		ProductCodes []string
		Category     string
		Quantity     int
	}{})
	quantityGreaterThanArgument.Meta(&admin.Meta{Name: "ProductCodes", Type: "select_many", Collection: productCodeCollection})
	quantityGreaterThanArgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "Quantity Greater Than",
		Resource: quantityGreaterThanArgument,
	})

	userGroupArgument := Admin.NewResource(&struct {
		Group string
	}{})
	userGroupArgument.Meta(&admin.Meta{Name: "Group", Type: "select_one", Collection: []string{"VIP", "Employee", "Normal"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "User Group",
		Resource: userGroupArgument,
	})

	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name: "From Link",
		Resource: Admin.NewResource(&struct {
			VariableName string
			Value        string
		}{}),
	})

	hasProductrgument := Admin.NewResource(&struct {
		ProductCodes []string
		Category     string
	}{})
	hasProductrgument.Meta(&admin.Meta{Name: "ProductCodes", Type: "select_many", Collection: productCodeCollection})
	hasProductrgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "Has Product",
		Resource: hasProductrgument,
	})

	// Auto migrations
	promotion.AutoMigrate(db.DB)

	// Add Promotions to Admin
	Admin.AddResource(&promotion.PromotionDiscount{}, &admin.Config{Name: "Promotions", Menu: []string{"Site Management"}, Priority: 3})
}
<commit_msg>Upgrade promotion<commit_after>// +build enterprise

package admin

import (
	"fmt"

	"enterprise.getqor.com/promotion"
	"github.com/qor/admin"
	"github.com/qor/qor"
	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/db"
)

func init() {
	// Benefits Definations
	discountRateArgument := Admin.NewResource(&struct {
		Percentage uint
	}{})
	discountRateArgument.Meta(&admin.Meta{Name: "Percentage", Label: "Percentage (e.g enter 10 for a 10% discount)"})
	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name:     "Discount Rate",
		Resource: discountRateArgument,
	})

	discountAmountArgument := Admin.NewResource(&struct {
		Amount float32
	}{})
	discountAmountArgument.Meta(&admin.Meta{Name: "Amount", Label: "Amount (e.g enter 10 for a $10 discount)"})
	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name:     "Discount Amount",
		Resource: discountAmountArgument,
	})

	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name: "Shipping Fee",
		Resource: Admin.NewResource(&struct {
			Price float32
		}{}),
	})

	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name: "2nd Day Shipping Fee",
		Resource: Admin.NewResource(&struct {
			Price float32
		}{}),
	})

	productCodeCollection := func(value interface{}, context *qor.Context) [][]string {
		var products []models.Product
		var results [][]string
		context.GetDB().Find(&products)
		for _, product := range products {
			results = append(results, []string{fmt.Sprint(product.ID), product.Code})
		}
		return results
	}
	combinedDiscountArgument := Admin.NewResource(&struct {
		ProductCodes []string
		Category     string
		Quantity     uint
		Price        float32
		Percentage   uint
		Discount     uint
	}{})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "ProductCodes", Type: "select_many", Collection: productCodeCollection})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "Percentage", Label: "Discount Percentage (e.g enter 10 for a 10% discount)"})
	combinedDiscountArgument.Meta(&admin.Meta{Name: "Discount", Label: "Discount Amount (e.g enter 10 for a $10 discount)"})
	promotion.RegisterBenefitHandler(promotion.BenefitHandler{
		Name:     "Combined Discounts",
		Resource: combinedDiscountArgument,
	})

	// Rules Definations
	amountGreaterThanArgument := Admin.NewResource(&struct {
		Amount   int
		Category string
	}{})
	amountGreaterThanArgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "Amount Greater Than",
		Resource: amountGreaterThanArgument,
	})

	quantityGreaterThanArgument := Admin.NewResource(&struct {
		ProductCodes []string
		Category     string
		Quantity     int
	}{})
	quantityGreaterThanArgument.Meta(&admin.Meta{Name: "ProductCodes", Type: "select_many", Collection: productCodeCollection})
	quantityGreaterThanArgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "Quantity Greater Than",
		Resource: quantityGreaterThanArgument,
	})

	userGroupArgument := Admin.NewResource(&struct {
		Group string
	}{})
	userGroupArgument.Meta(&admin.Meta{Name: "Group", Type: "select_one", Collection: []string{"VIP", "Employee", "Normal"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "User Group",
		Resource: userGroupArgument,
	})

	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name: "From Link",
		Resource: Admin.NewResource(&struct {
			VariableName string
			Value        string
		}{}),
	})

	hasProductrgument := Admin.NewResource(&struct {
		ProductCodes []string
		Category     string
	}{})
	hasProductrgument.Meta(&admin.Meta{Name: "ProductCodes", Type: "select_many", Collection: productCodeCollection})
	hasProductrgument.Meta(&admin.Meta{Name: "Category", Type: "select_one", Collection: []string{"All Products", "Bags", "Summer Shirts", "Pants"}})
	promotion.RegisterRuleHandler(promotion.RuleHandler{
		Name:     "Has Product",
		Resource: hasProductrgument,
	})

	// Auto migrations
	promotion.AutoMigrate(db.DB)

	// Add Promotions to Admin
	Admin.AddResource(&promotion.Discount{}, &admin.Config{Name: "Promotions", Menu: []string{"Site Management"}, Priority: 3})
}
<|endoftext|>


<commit_before>package views

import (
	"encoding/json"
	"net/http"
	"strconv"
	"time"

	"github.com/antihax/evedata/services/vanguard"
	"github.com/antihax/evedata/services/vanguard/models"
)

func init() {
	vanguard.AddRoute("ContactSync", "GET", "/contactSync", func(w http.ResponseWriter, r *http.Request) {
		renderTemplate(w,
			"contactSync.html",
			time.Hour*24*31,
			newPage(r, "War Contact Syncronization"))
	})
	vanguard.AddAuthRoute("ContactSync", "PUT", "/U/contactSync", apiAddContactSync)
	vanguard.AddAuthRoute("ContactSync", "GET", "/U/contactSync", apiGetContactSyncs)
	vanguard.AddAuthRoute("ContactSync", "DELETE", "/U/contactSync", apiDeleteContactSync)
}

func apiAddContactSync(w http.ResponseWriter, r *http.Request) {
	s := vanguard.SessionFromContext(r.Context())

	type localContactSync struct {
		Source      int `json:",string"`
		Destination int `json:",string"`
	}
	var cc localContactSync

	characterID, ok := s.Values["characterID"].(int32)
	if !ok {
		httpErrCode(w, nil, http.StatusUnauthorized)
		return
	}

	if r.Body == nil {
		httpErrCode(w, nil, http.StatusBadRequest)
		return
	}

	err := json.NewDecoder(r.Body).Decode(&cc)
	if err != nil {
		httpErrCode(w, err, http.StatusNotFound)
		return
	}

	if err := models.AddContactSync(characterID, cc.Source, cc.Destination); err != nil {
		httpErrCode(w, err, http.StatusConflict)
		return
	}
}

func apiGetContactSyncs(w http.ResponseWriter, r *http.Request) {
	s := vanguard.SessionFromContext(r.Context())

	characterID, ok := s.Values["characterID"].(int32)
	if !ok {
		httpErrCode(w, nil, http.StatusUnauthorized)
		return
	}

	v, err := models.GetContactSyncs(characterID)
	if err != nil {
		httpErrCode(w, err, http.StatusNotFound)
		return
	}
	renderJSON(w, v, 0)
}

func apiDeleteContactSync(w http.ResponseWriter, r *http.Request) {
	s := vanguard.SessionFromContext(r.Context())

	characterID, ok := s.Values["characterID"].(int32)
	if !ok {
		httpErrCode(w, nil, http.StatusUnauthorized)
		return
	}

	destination, err := strconv.Atoi(r.FormValue("destination"))
	if err != nil {
		httpErrCode(w, err, http.StatusNotFound)
		return
	}

	if err := models.DeleteContactSync(characterID, destination); err != nil {
		httpErrCode(w, err, http.StatusConflict)
		return
	}
}
<commit_msg>spelling<commit_after>package views

import (
	"encoding/json"
	"net/http"
	"strconv"
	"time"

	"github.com/antihax/evedata/services/vanguard"
	"github.com/antihax/evedata/services/vanguard/models"
)

func init() {
	vanguard.AddRoute("ContactSync", "GET", "/contactSync", func(w http.ResponseWriter, r *http.Request) {
		renderTemplate(w,
			"contactSync.html",
			time.Hour*24*31,
			newPage(r, "War Contact Synchronization"))
	})
	vanguard.AddAuthRoute("ContactSync", "PUT", "/U/contactSync", apiAddContactSync)
	vanguard.AddAuthRoute("ContactSync", "GET", "/U/contactSync", apiGetContactSyncs)
	vanguard.AddAuthRoute("ContactSync", "DELETE", "/U/contactSync", apiDeleteContactSync)
}

func apiAddContactSync(w http.ResponseWriter, r *http.Request) {
	s := vanguard.SessionFromContext(r.Context())

	type localContactSync struct {
		Source      int `json:",string"`
		Destination int `json:",string"`
	}
	var cc localContactSync

	characterID, ok := s.Values["characterID"].(int32)
	if !ok {
		httpErrCode(w, nil, http.StatusUnauthorized)
		return
	}

	if r.Body == nil {
		httpErrCode(w, nil, http.StatusBadRequest)
		return
	}

	err := json.NewDecoder(r.Body).Decode(&cc)
	if err != nil {
		httpErrCode(w, err, http.StatusNotFound)
		return
	}

	if err := models.AddContactSync(characterID, cc.Source, cc.Destination); err != nil {
		httpErrCode(w, err, http.StatusConflict)
		return
	}
}

func apiGetContactSyncs(w http.ResponseWriter, r *http.Request) {
	s := vanguard.SessionFromContext(r.Context())

	characterID, ok := s.Values["characterID"].(int32)
	if !ok {
		httpErrCode(w, nil, http.StatusUnauthorized)
		return
	}

	v, err := models.GetContactSyncs(characterID)
	if err != nil {
		httpErrCode(w, err, http.StatusNotFound)
		return
	}
	renderJSON(w, v, 0)
}

func apiDeleteContactSync(w http.ResponseWriter, r *http.Request) {
	s := vanguard.SessionFromContext(r.Context())

	characterID, ok := s.Values["characterID"].(int32)
	if !ok {
		httpErrCode(w, nil, http.StatusUnauthorized)
		return
	}

	destination, err := strconv.Atoi(r.FormValue("destination"))
	if err != nil {
		httpErrCode(w, err, http.StatusNotFound)
		return
	}

	if err := models.DeleteContactSync(characterID, destination); err != nil {
		httpErrCode(w, err, http.StatusConflict)
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"time"
)

var (
	backendCert   = flag.String("backendCert", "", "Override self-signed cert for backend TLS")
	backendKey    = flag.String("backendKey", "", "Override self-signed cert, must be provided with -backendCert")
	backupPort1   = flag.Int("backupPort1", 8081, "Backup1 port to listen on for requests")
	backupPort2   = flag.Int("backupPort2", 8082, "Backup2 port to listen on for requests")
	edgeHost      = flag.String("edgeHost", "", "Hostname of edge")
	originPort    = flag.Int("originPort", 8080, "Origin port to listen on for requests")
	skipFailover  = flag.Bool("skipFailover", false, "Skip failover tests and only setup the origin backend")
	skipVerifyTLS = flag.Bool("skipVerifyTLS", false, "Skip TLS cert verification if set")
	usage         = flag.Bool("usage", false, "Print usage")
	vendor        = flag.String("vendor", "", "Name of vendor; run tests specific to vendor")
	// This only works with tests that use RoundTripCheckError(), that either
	// are either failing or run with the -v flag.
	debugResp = flag.Bool("debugResp", false, "Log responses for debugging")
)

var (
	vendorFastly     bool = false
	vendorCloudflare bool = false
)

// These consts and vars are available to all tests.
const requestTimeout = time.Second * 5
const requestSlowThreshold = time.Second
const notImplementedForVendor = "Test not yet implemented for your selected vendor or no vendor specified"
const notSupportedByVendor = "Feature not supported by your selected vendor"

var (
	client             *http.Transport
	originServer       *CDNBackendServer
	backupServer1      *CDNBackendServer
	backupServer2      *CDNBackendServer
	backendsByPriority []*CDNBackendServer
)

var hardCachedEdgeHostIp string

// Setup clients and servers.
func init() {

	flag.Parse()

	if *usage {
		flag.Usage()
		os.Exit(0)
	}

	if *edgeHost == "" {
		fmt.Printf("ERROR: -edgeHost must be set to the CDN edge hostname we wish to test against\n\n")
		flag.Usage()
		os.Exit(1)
	}

	switch *vendor {
	case "cloudflare":
		vendorCloudflare = true
	case "fastly":
		vendorFastly = true
	case "":
		log.Println("No vendor specified")
	default:
		log.Fatalf("Vendor %q unrecognised; aborting", *vendor)
	}

	tlsOptions := &tls.Config{}
	if *skipVerifyTLS {
		tlsOptions.InsecureSkipVerify = true
	}
	client = &http.Transport{
		ResponseHeaderTimeout: requestTimeout,
		TLSClientConfig:       tlsOptions,
		Dial:                  HardCachedHostDial,
	}

	var backendCerts []tls.Certificate
	if *backendCert != "" || *backendKey != "" {
		var err error
		backendCerts = make([]tls.Certificate, 1)
		backendCerts[0], err = tls.LoadX509KeyPair(*backendCert, *backendKey)

		if err != nil {
			log.Fatal(err)
		}
	}

	originServer = &CDNBackendServer{
		Name:     "origin",
		Port:     *originPort,
		TLSCerts: backendCerts,
	}
	backendsByPriority = []*CDNBackendServer{
		originServer,
	}

	if !*skipFailover {
		backupServer1 = &CDNBackendServer{
			Name:     "backup1",
			Port:     *backupPort1,
			TLSCerts: backendCerts,
		}
		backupServer2 = &CDNBackendServer{
			Name:     "backup2",
			Port:     *backupPort2,
			TLSCerts: backendCerts,
		}
		backendsByPriority = append(
			backendsByPriority,
			backupServer1,
			backupServer2,
		)
	}

	log.Println("Confirming that CDN is healthy")
	ResetBackends(backendsByPriority)

}

// CachedHostIpAddress looks up the IP address for a given host name,
// and caches the first IP address returned. Subsequent requests always
// return this address, preventing further DNS requests.
func CachedHostIpAddress(host string) string {
	if hardCachedEdgeHostIp == "" {
		ipAddresses, err := net.LookupHost(host)
		if err != nil {
			log.Fatal(err)
		}
		hardCachedEdgeHostIp = ipAddresses[0]
	}
	return hardCachedEdgeHostIp
}

// HardCachedHostDial acts as a replacement Dial function, ostensibly for
// http.Transport. It uses the IP address returned by CachedHostIpAddress
// and passes that to the stock net.Dial function, to prevent repeat DNS
// lookups of the provided hostname in addr. This is to prevent us from switching
// from one CDN location to another mid-test.
func HardCachedHostDial(network, addr string) (net.Conn, error) {
	host, port, err := net.SplitHostPort(addr)
	if err != nil {
		log.Fatal(err)
	}
	if host != *edgeHost {
		return net.Dial(network, addr)
	}
	ipAddr := CachedHostIpAddress(host)
	return net.Dial(network, net.JoinHostPort(ipAddr, port))
}
<commit_msg>Alphabetise constants<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"time"
)

var (
	backendCert   = flag.String("backendCert", "", "Override self-signed cert for backend TLS")
	backendKey    = flag.String("backendKey", "", "Override self-signed cert, must be provided with -backendCert")
	backupPort1   = flag.Int("backupPort1", 8081, "Backup1 port to listen on for requests")
	backupPort2   = flag.Int("backupPort2", 8082, "Backup2 port to listen on for requests")
	edgeHost      = flag.String("edgeHost", "", "Hostname of edge")
	originPort    = flag.Int("originPort", 8080, "Origin port to listen on for requests")
	skipFailover  = flag.Bool("skipFailover", false, "Skip failover tests and only setup the origin backend")
	skipVerifyTLS = flag.Bool("skipVerifyTLS", false, "Skip TLS cert verification if set")
	usage         = flag.Bool("usage", false, "Print usage")
	vendor        = flag.String("vendor", "", "Name of vendor; run tests specific to vendor")
	// This only works with tests that use RoundTripCheckError(), that either
	// are either failing or run with the -v flag.
	debugResp = flag.Bool("debugResp", false, "Log responses for debugging")
)

var (
	vendorFastly     bool = false
	vendorCloudflare bool = false
)

// These consts and vars are available to all tests.
const notImplementedForVendor = "Test not yet implemented for your selected vendor or no vendor specified"
const notSupportedByVendor = "Feature not supported by your selected vendor"
const requestSlowThreshold = time.Second
const requestTimeout = time.Second * 5

var (
	client             *http.Transport
	originServer       *CDNBackendServer
	backupServer1      *CDNBackendServer
	backupServer2      *CDNBackendServer
	backendsByPriority []*CDNBackendServer
)

var hardCachedEdgeHostIp string

// Setup clients and servers.
func init() {

	flag.Parse()

	if *usage {
		flag.Usage()
		os.Exit(0)
	}

	if *edgeHost == "" {
		fmt.Printf("ERROR: -edgeHost must be set to the CDN edge hostname we wish to test against\n\n")
		flag.Usage()
		os.Exit(1)
	}

	switch *vendor {
	case "cloudflare":
		vendorCloudflare = true
	case "fastly":
		vendorFastly = true
	case "":
		log.Println("No vendor specified")
	default:
		log.Fatalf("Vendor %q unrecognised; aborting", *vendor)
	}

	tlsOptions := &tls.Config{}
	if *skipVerifyTLS {
		tlsOptions.InsecureSkipVerify = true
	}
	client = &http.Transport{
		ResponseHeaderTimeout: requestTimeout,
		TLSClientConfig:       tlsOptions,
		Dial:                  HardCachedHostDial,
	}

	var backendCerts []tls.Certificate
	if *backendCert != "" || *backendKey != "" {
		var err error
		backendCerts = make([]tls.Certificate, 1)
		backendCerts[0], err = tls.LoadX509KeyPair(*backendCert, *backendKey)

		if err != nil {
			log.Fatal(err)
		}
	}

	originServer = &CDNBackendServer{
		Name:     "origin",
		Port:     *originPort,
		TLSCerts: backendCerts,
	}
	backendsByPriority = []*CDNBackendServer{
		originServer,
	}

	if !*skipFailover {
		backupServer1 = &CDNBackendServer{
			Name:     "backup1",
			Port:     *backupPort1,
			TLSCerts: backendCerts,
		}
		backupServer2 = &CDNBackendServer{
			Name:     "backup2",
			Port:     *backupPort2,
			TLSCerts: backendCerts,
		}
		backendsByPriority = append(
			backendsByPriority,
			backupServer1,
			backupServer2,
		)
	}

	log.Println("Confirming that CDN is healthy")
	ResetBackends(backendsByPriority)

}

// CachedHostIpAddress looks up the IP address for a given host name,
// and caches the first IP address returned. Subsequent requests always
// return this address, preventing further DNS requests.
func CachedHostIpAddress(host string) string {
	if hardCachedEdgeHostIp == "" {
		ipAddresses, err := net.LookupHost(host)
		if err != nil {
			log.Fatal(err)
		}
		hardCachedEdgeHostIp = ipAddresses[0]
	}
	return hardCachedEdgeHostIp
}

// HardCachedHostDial acts as a replacement Dial function, ostensibly for
// http.Transport. It uses the IP address returned by CachedHostIpAddress
// and passes that to the stock net.Dial function, to prevent repeat DNS
// lookups of the provided hostname in addr. This is to prevent us from switching
// from one CDN location to another mid-test.
func HardCachedHostDial(network, addr string) (net.Conn, error) {
	host, port, err := net.SplitHostPort(addr)
	if err != nil {
		log.Fatal(err)
	}
	if host != *edgeHost {
		return net.Dial(network, addr)
	}
	ipAddr := CachedHostIpAddress(host)
	return net.Dial(network, net.JoinHostPort(ipAddr, port))
}
<|endoftext|>


<commit_before>// Reflect is a small name server which sends back the IP address of its client, the
// recursive resolver.
// When queried for type A (resp. AAAA), it sends back the IPv4 (resp. v6) address.
// In the additional section the port number and transport are shown.
//
// Basic use pattern:
//
//	dig @localhost -p 8053 whoami.miek.nl A
//
//	;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2157
//	;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
//	;; QUESTION SECTION:
//	;whoami.miek.nl.			IN	A
//
//	;; ANSWER SECTION:
//	whoami.miek.nl.		0	IN	A	127.0.0.1
//
//	;; ADDITIONAL SECTION:
//	whoami.miek.nl.		0	IN	TXT	"Port: 56195 (udp)"
//
// Similar services: whoami.ultradns.net, whoami.akamai.net. Also (but it
// is not their normal goal): rs.dns-oarc.net, porttest.dns-oarc.net,
// amiopen.openresolvers.org.
//
// Original version is from: Stephane Bortzmeyer <stephane+grong@bortzmeyer.org>.
//
// Adapted to Go (i.e. completely rewritten) by Miek Gieben <miek@miek.nl>.
package main

import (
	"flag"
	"fmt"
	"github.com/miekg/dns"
	"log"
	"net"
	"os"
	"os/signal"
	"runtime/pprof"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var (
	printf   *bool
	compress *bool
	tsig     *string
)

const dom = "whoami.miek.nl."

func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
	var (
		v4  bool
		rr  dns.RR
		str string
		a   net.IP
	)
	// TC must be done here
	m := new(dns.Msg)
	m.SetReply(r)
	m.Compress = *compress
	if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
		a = ip.IP
		v4 = a.To4() != nil
	}
	if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
		a = ip.IP
		v4 = a.To4() != nil
	}

	if v4 {
		rr = new(dns.RR_A)
		rr.(*dns.RR_A).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_A).A = a.To4()
	} else {
		rr = new(dns.RR_AAAA)
		rr.(*dns.RR_AAAA).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_AAAA).AAAA = a
	}

	t := new(dns.RR_TXT)
	t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
	t.Txt = []string{str}

	switch r.Question[0].Qtype {
	case dns.TypeAXFR:
		c := make(chan *dns.XfrToken)
		var e *error
		if err := dns.XfrSend(w, r, c, e); err != nil {
			close(c)
			return
		}
		soa, _ := dns.NewRR(`whoami.miek.nl. IN SOA elektron.atoom.net. miekg.atoom.net. (
			2009032802
			21600
			7200
			604800
			3600)`)
		c <- &dns.XfrToken{RR: []dns.RR{soa, t, rr, soa}}
		close(c)
		w.Hijack()
		// w.Close() // Client closes
		return
	case dns.TypeTXT:
		m.Answer = append(m.Answer, t)
		m.Extra = append(m.Extra, rr)
	default:
		fallthrough
	case dns.TypeAAAA, dns.TypeA:
		m.Answer = append(m.Answer, rr)
		m.Extra = append(m.Extra, t)
	}

	if r.IsTsig() != nil {
		if w.TsigStatus() == nil {
			m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.RR_TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix())
		} else {
			println("Status", w.TsigStatus().Error())
		}
	}
	if *printf {
		fmt.Printf("%v\n", m.String())
	}
	w.Write(m)
}

func serve(net, name, secret string) {
	switch name {
	case "":
		err := dns.ListenAndServe(":8053", net, nil)
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	default:
		server := &dns.Server{Addr: ":8053", Net: net, TsigSecret: map[string]string{name: secret}}
		err := server.ListenAndServe()
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	}
}

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	printf = flag.Bool("print", false, "print replies")
	compress = flag.Bool("compress", false, "compress replies")
	tsig = flag.String("tsig", "", "use MD5 hmac tsig: keyname:base64")
	var name, secret string
	flag.Usage = func() {
		flag.PrintDefaults()
	}
	flag.Parse()
	if *tsig != "" {
		a := strings.SplitN(*tsig, ":", 2)
		name, secret = dns.Fqdn(a[0]), a[1] // fqdn the name, which everybody forgets...
	}
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	dns.HandleFunc("miek.nl.", handleReflect)
	dns.HandleFunc("authors.bind.", dns.HandleAuthors)
	dns.HandleFunc("authors.server.", dns.HandleAuthors)
	dns.HandleFunc("version.bind.", dns.HandleVersion)
	dns.HandleFunc("version.server.", dns.HandleVersion)
	go serve("tcp", name, secret)
	go serve("udp", name, secret)
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
forever:
	for {
		select {
		case s := <-sig:
			fmt.Printf("Signal (%d) received, stopping\n", s)
			break forever
		}
	}
}
<commit_msg>Fix reflect<commit_after>// Reflect is a small name server which sends back the IP address of its client, the
// recursive resolver.
// When queried for type A (resp. AAAA), it sends back the IPv4 (resp. v6) address.
// In the additional section the port number and transport are shown.
//
// Basic use pattern:
//
//	dig @localhost -p 8053 whoami.miek.nl A
//
//	;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2157
//	;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
//	;; QUESTION SECTION:
//	;whoami.miek.nl.			IN	A
//
//	;; ANSWER SECTION:
//	whoami.miek.nl.		0	IN	A	127.0.0.1
//
//	;; ADDITIONAL SECTION:
//	whoami.miek.nl.		0	IN	TXT	"Port: 56195 (udp)"
//
// Similar services: whoami.ultradns.net, whoami.akamai.net. Also (but it
// is not their normal goal): rs.dns-oarc.net, porttest.dns-oarc.net,
// amiopen.openresolvers.org.
//
// Original version is from: Stephane Bortzmeyer <stephane+grong@bortzmeyer.org>.
//
// Adapted to Go (i.e. completely rewritten) by Miek Gieben <miek@miek.nl>.
package main

import (
	"flag"
	"fmt"
	"github.com/miekg/dns"
	"log"
	"net"
	"os"
	"os/signal"
	"runtime/pprof"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var (
	printf   *bool
	compress *bool
	tsig     *string
)

const dom = "whoami.miek.nl."

func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
	var (
		v4  bool
		rr  dns.RR
		str string
		a   net.IP
	)
	// TC must be done here
	m := new(dns.Msg)
	m.SetReply(r)
	m.Compress = *compress
	if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
		a = ip.IP
		v4 = a.To4() != nil
	}
	if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
		a = ip.IP
		v4 = a.To4() != nil
	}

	if v4 {
		rr = new(dns.RR_A)
		rr.(*dns.RR_A).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_A).A = a.To4()
	} else {
		rr = new(dns.RR_AAAA)
		rr.(*dns.RR_AAAA).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_AAAA).AAAA = a
	}

	t := new(dns.RR_TXT)
	t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
	t.Txt = []string{str}

	switch r.Question[0].Qtype {
	case dns.TypeAXFR:
		c := make(chan *dns.XfrToken)
		var e *error
		if err := dns.XfrSend(w, r, c, e); err != nil {
			close(c)
			return
		}
		soa, _ := dns.NewRR(`whoami.miek.nl. IN SOA elektron.atoom.net. miekg.atoom.net. (
			2009032802
			21600
			7200
			604800
			3600)`)
		c <- &dns.XfrToken{RR: []dns.RR{soa, t, rr, soa}}
		close(c)
		w.Hijack()
		// w.Close() // Client closes
		return
	case dns.TypeTXT:
		m.Answer = append(m.Answer, t)
		m.Extra = append(m.Extra, rr)
	default:
		fallthrough
	case dns.TypeAAAA, dns.TypeA:
		m.Answer = append(m.Answer, rr)
		m.Extra = append(m.Extra, t)
	}

	if r.IsTsig() != nil {
		if w.TsigStatus() == nil {
			m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.RR_TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix())
		} else {
			println("Status", w.TsigStatus().Error())
		}
	}
	if *printf {
		fmt.Printf("%v\n", m.String())
	}
	w.WriteMsg(m)
}

func serve(net, name, secret string) {
	switch name {
	case "":
		err := dns.ListenAndServe(":8053", net, nil)
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	default:
		server := &dns.Server{Addr: ":8053", Net: net, TsigSecret: map[string]string{name: secret}}
		err := server.ListenAndServe()
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	}
}

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	printf = flag.Bool("print", false, "print replies")
	compress = flag.Bool("compress", false, "compress replies")
	tsig = flag.String("tsig", "", "use MD5 hmac tsig: keyname:base64")
	var name, secret string
	flag.Usage = func() {
		flag.PrintDefaults()
	}
	flag.Parse()
	if *tsig != "" {
		a := strings.SplitN(*tsig, ":", 2)
		name, secret = dns.Fqdn(a[0]), a[1] // fqdn the name, which everybody forgets...
	}
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	dns.HandleFunc("miek.nl.", handleReflect)
	dns.HandleFunc("authors.bind.", dns.HandleAuthors)
	dns.HandleFunc("authors.server.", dns.HandleAuthors)
	dns.HandleFunc("version.bind.", dns.HandleVersion)
	dns.HandleFunc("version.server.", dns.HandleVersion)
	go serve("tcp", name, secret)
	go serve("udp", name, secret)
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
forever:
	for {
		select {
		case s := <-sig:
			fmt.Printf("Signal (%d) received, stopping\n", s)
			break forever
		}
	}
}
<|endoftext|>


<commit_before>/*

Copyright 2014 Zola Mahlaza <adeebnqo@gmail.com>
02 December 2014

This is the driver class. It is resposible for creating the
BNF loader/parser and generating the sublime text syntax highligting
file.

*/

package main

import (
	"flag"
	"fmt"
	"github.com/nu7hatch/gouuid"
	"os"
)

var name = flag.String("name", "default", "This is the name of the syntax.")
var scope = flag.String("scope", "source.default", "This is the scope of the syntax file")
var fileTypes = flag.String("fileTypes", "default", "Comma seperated list of file types.")

func main() {
	flag.Parse()

	jsonhighlight := `

		{ "name": "%v",
		  "scopeName": "%v",
		  "fileTypes": [%v],
		  "repository": {
		  	%v
		  },
		  "uuid": "%v"
		}
	`
	u, err := uuid.NewV4()
	if (err!=nil){
		fmt.Println("Could not generate uuid.")
		os.Exit(1)
	}else{

		repositoryfield := "COMING..."
		//0. Generate repository field from bnf file

		result := fmt.Sprintf(jsonhighlight, *name, *scope, *fileTypes, repositoryfield, u)

		//1. save result in a JSON file.

		//2. convert result to a plist file and save it.

		fmt.Println(result)
	}
}<commit_msg>added gocc. unsure if this is how it is used<commit_after>/*

Copyright 2014 Zola Mahlaza <adeebnqo@gmail.com>
02 December 2014

This is the driver class. It is resposible for creating the
BNF loader/parser and generating the sublime text syntax highligting
file.

*/

package main

import (
	"flag"
	"fmt"
	"github.com/nu7hatch/gouuid"
	"code.google.com/p/gocc/frontend/scanner"
	"code.google.com/p/gocc/frontend/token"
	"code.google.com/p/gocc/frontend/parser"
	"os"
	"io/ioutil"
)

var name = flag.String("name", "default", "This is the name of the syntax.")
var scope = flag.String("scope", "source.default", "This is the scope of the syntax file.")
var fileTypes = flag.String("fileTypes", "default", "Comma seperated list of file types.")
var source = flag.String("source","defaultinput", "the bnf file for the language you want to highlight.")

func main() {
	//zola
	flag.Parse()

	scanner := &scanner.Scanner{}
	srcBuffer, err := ioutil.ReadFile(*source)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	scanner.Init(srcBuffer, token.FRONTENDTokens)
	parser := parser.NewParser(parser.ActionTable, parser.GotoTable, parser.ProductionsTable, token.FRONTENDTokens)
	grammar, err := parser.Parse(scanner)
	if err != nil {
		fmt.Printf("Parse error: %s\n", err)
		os.Exit(1)
	}
	fmt.Println(grammar)

	//zola
	jsonhighlight := `

		{ "name": "%v",
		  "scopeName": "%v",
		  "fileTypes": [%v],
		  "repository": {
		  	%v
		  },
		  "uuid": "%v"
		}
	`
	u, err := uuid.NewV4()
	if (err!=nil){
		fmt.Println("Could not generate uuid.")
		os.Exit(1)
	}else{

		repositoryfield := "COMING..."
		//0. Generate repository field from bnf file

		result := fmt.Sprintf(jsonhighlight, *name, *scope, *fileTypes, repositoryfield, u)

		//1. save result in a JSON file.

		//2. convert result to a plist file and save it.

		fmt.Println(result)
	}
}
<|endoftext|>


<commit_before>package resource

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/terraform"
)

const TestEnvVar = "TF_ACC"

// TestCheckFunc is the callback type used with acceptance tests to check
// the state of a resource. The state passed in is the latest state known,
// or in the case of being after a destroy, it is the last known state when
// it was created.
type TestCheckFunc func(*terraform.State) error

// TestCase is a single acceptance test case used to test the apply/destroy
// lifecycle of a resource in a specific configuration.
//
// When the destroy plan is executed, the config from the last TestStep
// is used to plan it.
type TestCase struct {
	// Provider is the ResourceProvider that will be under test.
	Providers map[string]terraform.ResourceProvider

	// CheckDestroy is called after the resource is finally destroyed
	// to allow the tester to test that the resource is truly gone.
	CheckDestroy TestCheckFunc

	// Steps are the apply sequences done within the context of the
	// same state. Each step can have its own check to verify correctness.
	Steps []TestStep
}

// TestStep is a single apply sequence of a test, done within the
// context of a state.
//
// Multiple TestSteps can be sequenced in a Test to allow testing
// potentially complex update logic. In general, simply create/destroy
// tests will only need one step.
type TestStep struct {
	// Config a string of the configuration to give to Terraform.
	Config string

	// Check is called after the Config is applied. Use this step to
	// make your own API calls to check the status of things, and to
	// inspect the format of the ResourceState itself.
	//
	// If an error is returned, the test will fail. In this case, a
	// destroy plan will still be attempted.
	//
	// If this is nil, no check is done on this step.
	Check TestCheckFunc

	// Destroy will create a destroy plan if set to true.
	Destroy bool
}

// Test performs an acceptance test on a resource.
//
// Tests are not run unless an environmental variable "TF_ACC" is
// set to some non-empty value. This is to avoid test cases surprising
// a user by creating real resources.
//
// Tests will fail unless the verbose flag (`go test -v`, or explicitly
// the "-test.v" flag) is set. Because some acceptance tests take quite
// long, we require the verbose flag so users are able to see progress
// output.
func Test(t TestT, c TestCase) {
	// We only run acceptance tests if an env var is set because they're
	// slow and generally require some outside configuration.
	if os.Getenv(TestEnvVar) == "" {
		t.Skip(fmt.Sprintf(
			"Acceptance tests skipped unless env '%s' set",
			TestEnvVar))
		return
	}

	// We require verbose mode so that the user knows what is going on.
	if !testTesting && !testing.Verbose() {
		t.Fatal("Acceptance tests must be run with the -v flag on tests")
		return
	}

	// Build our context options that we can
	ctxProviders := make(map[string]terraform.ResourceProviderFactory)
	for k, p := range c.Providers {
		ctxProviders[k] = terraform.ResourceProviderFactoryFixed(p)
	}
	opts := terraform.ContextOpts{Providers: ctxProviders}

	// A single state variable to track the lifecycle, starting with no state
	var state *terraform.State

	// Go through each step and run it
	for i, step := range c.Steps {
		var err error
		state, err = testStep(opts, state, step)
		println(fmt.Sprintf("FOO: %#v", state))
		if err != nil {
			t.Error(fmt.Sprintf(
				"Step %d error: %s", i, err))
			break
		}
	}

	// If we have a state, then run the destroy
	if state != nil {
		destroyStep := TestStep{
			Config:  c.Steps[len(c.Steps)-1].Config,
			Check:   c.CheckDestroy,
			Destroy: true,
		}

		state, err := testStep(opts, state, destroyStep)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Error destroying resource! WARNING: Dangling resources\n"+
					"may exist. The full state and error is shown below.\n\n"+
					"Error: %s\n\nState: %s",
				err,
				state))
		}
	}
}

func testStep(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	// Write the configuration
	cfgF, err := ioutil.TempFile("", "tf-test")
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}
	cfgPath := cfgF.Name() + ".tf"
	cfgF.Close()
	os.Remove(cfgF.Name())

	cfgF, err = os.Create(cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}
	defer os.Remove(cfgPath)

	_, err = io.Copy(cfgF, strings.NewReader(step.Config))
	cfgF.Close()
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}

	// Parse the configuration
	config, err := config.Load(cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error parsing configuration: %s", err)
	}

	// Build the context
	opts.Config = config
	ctx := terraform.NewContext(&opts)
	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
		return state, fmt.Errorf(
			"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
			ws, es)
	}

	// Plan!
	if _, err := ctx.Plan(&terraform.PlanOpts{Destroy: step.Destroy}); err != nil {
		return state, fmt.Errorf(
			"Error planning: %s", err)
	}

	// Apply!
	state, err = ctx.Apply()
	if err != nil {
		return state, fmt.Errorf("Error applying: %s", err)
	}

	// Check! Excitement!
	if step.Check != nil {
		if err = step.Check(state); err != nil {
			err = fmt.Errorf("Check failed: %s", err)
		}
	}

	return state, err
}

// TestT is the interface used to handle the test lifecycle of a test.
//
// Users should just use a *testing.T object, which implements this.
type TestT interface {
	Error(args ...interface{})
	Fatal(args ...interface{})
	Skip(args ...interface{})
}

// This is set to true by unit tests to alter some behavior
var testTesting = false
<commit_msg>helper/resource: remove debugging stuff<commit_after>package resource

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/terraform"
)

const TestEnvVar = "TF_ACC"

// TestCheckFunc is the callback type used with acceptance tests to check
// the state of a resource. The state passed in is the latest state known,
// or in the case of being after a destroy, it is the last known state when
// it was created.
type TestCheckFunc func(*terraform.State) error

// TestCase is a single acceptance test case used to test the apply/destroy
// lifecycle of a resource in a specific configuration.
//
// When the destroy plan is executed, the config from the last TestStep
// is used to plan it.
type TestCase struct {
	// Provider is the ResourceProvider that will be under test.
	Providers map[string]terraform.ResourceProvider

	// CheckDestroy is called after the resource is finally destroyed
	// to allow the tester to test that the resource is truly gone.
	CheckDestroy TestCheckFunc

	// Steps are the apply sequences done within the context of the
	// same state. Each step can have its own check to verify correctness.
	Steps []TestStep
}

// TestStep is a single apply sequence of a test, done within the
// context of a state.
//
// Multiple TestSteps can be sequenced in a Test to allow testing
// potentially complex update logic. In general, simply create/destroy
// tests will only need one step.
type TestStep struct {
	// Config a string of the configuration to give to Terraform.
	Config string

	// Check is called after the Config is applied. Use this step to
	// make your own API calls to check the status of things, and to
	// inspect the format of the ResourceState itself.
	//
	// If an error is returned, the test will fail. In this case, a
	// destroy plan will still be attempted.
	//
	// If this is nil, no check is done on this step.
	Check TestCheckFunc

	// Destroy will create a destroy plan if set to true.
	Destroy bool
}

// Test performs an acceptance test on a resource.
//
// Tests are not run unless an environmental variable "TF_ACC" is
// set to some non-empty value. This is to avoid test cases surprising
// a user by creating real resources.
//
// Tests will fail unless the verbose flag (`go test -v`, or explicitly
// the "-test.v" flag) is set. Because some acceptance tests take quite
// long, we require the verbose flag so users are able to see progress
// output.
func Test(t TestT, c TestCase) {
	// We only run acceptance tests if an env var is set because they're
	// slow and generally require some outside configuration.
	if os.Getenv(TestEnvVar) == "" {
		t.Skip(fmt.Sprintf(
			"Acceptance tests skipped unless env '%s' set",
			TestEnvVar))
		return
	}

	// We require verbose mode so that the user knows what is going on.
	if !testTesting && !testing.Verbose() {
		t.Fatal("Acceptance tests must be run with the -v flag on tests")
		return
	}

	// Build our context options that we can
	ctxProviders := make(map[string]terraform.ResourceProviderFactory)
	for k, p := range c.Providers {
		ctxProviders[k] = terraform.ResourceProviderFactoryFixed(p)
	}
	opts := terraform.ContextOpts{Providers: ctxProviders}

	// A single state variable to track the lifecycle, starting with no state
	var state *terraform.State

	// Go through each step and run it
	for i, step := range c.Steps {
		var err error
		state, err = testStep(opts, state, step)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Step %d error: %s", i, err))
			break
		}
	}

	// If we have a state, then run the destroy
	if state != nil {
		destroyStep := TestStep{
			Config:  c.Steps[len(c.Steps)-1].Config,
			Check:   c.CheckDestroy,
			Destroy: true,
		}

		state, err := testStep(opts, state, destroyStep)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Error destroying resource! WARNING: Dangling resources\n"+
					"may exist. The full state and error is shown below.\n\n"+
					"Error: %s\n\nState: %s",
				err,
				state))
		}
	}
}

func testStep(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	// Write the configuration
	cfgF, err := ioutil.TempFile("", "tf-test")
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}
	cfgPath := cfgF.Name() + ".tf"
	cfgF.Close()
	os.Remove(cfgF.Name())

	cfgF, err = os.Create(cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}
	defer os.Remove(cfgPath)

	_, err = io.Copy(cfgF, strings.NewReader(step.Config))
	cfgF.Close()
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}

	// Parse the configuration
	config, err := config.Load(cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error parsing configuration: %s", err)
	}

	// Build the context
	opts.Config = config
	ctx := terraform.NewContext(&opts)
	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
		return state, fmt.Errorf(
			"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
			ws, es)
	}

	// Plan!
	if _, err := ctx.Plan(&terraform.PlanOpts{Destroy: step.Destroy}); err != nil {
		return state, fmt.Errorf(
			"Error planning: %s", err)
	}

	// Apply!
	state, err = ctx.Apply()
	if err != nil {
		return state, fmt.Errorf("Error applying: %s", err)
	}

	// Check! Excitement!
	if step.Check != nil {
		if err = step.Check(state); err != nil {
			err = fmt.Errorf("Check failed: %s", err)
		}
	}

	return state, err
}

// TestT is the interface used to handle the test lifecycle of a test.
//
// Users should just use a *testing.T object, which implements this.
type TestT interface {
	Error(args ...interface{})
	Fatal(args ...interface{})
	Skip(args ...interface{})
}

// This is set to true by unit tests to alter some behavior
var testTesting = false
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/akyoto/assert"
	"github.com/animenotifier/notify.moe/arn"
	"github.com/animenotifier/notify.moe/server"
	"github.com/animenotifier/notify.moe/utils/routetests"
)

func TestRoutes(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	// Iterate through every route
	for _, examples := range routetests.All() {
		// Iterate through every example specified for that route
		for _, example := range examples {
			fetch(t, app, example)
		}
	}
}

func TestAnime(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for anime := range arn.StreamAnime() {
		fetch(t, app, anime.Link())
	}
}

func TestSoundTracks(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for soundtrack := range arn.StreamSoundTracks() {
		fetch(t, app, soundtrack.Link())
		assert.NotNil(t, soundtrack.Creator())
	}
}

func TestAMVs(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for amv := range arn.StreamAMVs() {
		fetch(t, app, amv.Link())
		assert.NotNil(t, amv.Creator())
	}
}

func TestCompanies(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for company := range arn.StreamCompanies() {
		fetch(t, app, company.Link())
	}
}

func TestThreads(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for thread := range arn.StreamThreads() {
		fetch(t, app, thread.Link())
		assert.NotNil(t, thread.Creator())
	}
}

func TestPosts(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for post := range arn.StreamPosts() {
		fetch(t, app, post.Link())
		assert.NotNil(t, post.Creator())
	}
}

func TestQuotes(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for quote := range arn.StreamQuotes() {
		fetch(t, app, quote.Link())
		assert.NotNil(t, quote.Creator())
	}
}

// func TestUsers(t *testing.T) {
// 	app := server.New()
// 	app.BindMiddleware()

// 	for user := range arn.StreamUsers() {
// 		fetch(t, app, user.Link())
// 	}
// }

func fetch(t *testing.T, app http.Handler, route string) {
	request := httptest.NewRequest("GET", strings.ReplaceAll(route, " ", "%20"), nil)
	response := httptest.NewRecorder()
	app.ServeHTTP(response, request)
	status := response.Code

	switch status {
	case http.StatusOK, http.StatusTemporaryRedirect, http.StatusPermanentRedirect:
		// OK
	default:
		t.Fatalf("%s | Wrong status code | %v instead of %v", route, status, http.StatusOK)
	}
}
<commit_msg>Improved tests<commit_after>package main

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/akyoto/assert"
	"github.com/animenotifier/notify.moe/arn"
	"github.com/animenotifier/notify.moe/server"
	"github.com/animenotifier/notify.moe/utils/routetests"
)

func TestRoutes(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	// Iterate through every route
	for _, examples := range routetests.All() {
		// Iterate through every example specified for that route
		for _, example := range examples {
			fetch(t, app, example)
		}
	}
}

func TestAnime(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for anime := range arn.StreamAnime() {
		assert.True(t, anime.Title.Canonical != "")
		fetch(t, app, anime.Link())
	}
}

func TestSoundTracks(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for soundtrack := range arn.StreamSoundTracks() {
		assert.NotNil(t, soundtrack.Creator())
		fetch(t, app, soundtrack.Link())
	}
}

func TestAMVs(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for amv := range arn.StreamAMVs() {
		assert.NotNil(t, amv.Creator())
		fetch(t, app, amv.Link())
	}
}

func TestCompanies(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for company := range arn.StreamCompanies() {
		fetch(t, app, company.Link())
	}
}

func TestThreads(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for thread := range arn.StreamThreads() {
		assert.NotNil(t, thread.Creator())
		fetch(t, app, thread.Link())
	}
}

func TestPosts(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for post := range arn.StreamPosts() {
		assert.NotNil(t, post.Creator())
		fetch(t, app, post.Link())
	}
}

func TestQuotes(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for quote := range arn.StreamQuotes() {
		fetch(t, app, quote.Link())
		assert.NotNil(t, quote.Creator())
	}
}

func TestUsers(t *testing.T) {
	app := server.New()
	app.BindMiddleware()

	for user := range arn.StreamUsers() {
		assert.True(t, user.Nick != "")
		// fetch(t, app, user.Link())
	}
}

func fetch(t *testing.T, app http.Handler, route string) {
	request := httptest.NewRequest("GET", strings.ReplaceAll(route, " ", "%20"), nil)
	response := httptest.NewRecorder()
	app.ServeHTTP(response, request)
	status := response.Code

	switch status {
	case http.StatusOK, http.StatusTemporaryRedirect, http.StatusPermanentRedirect:
		// OK
	default:
		t.Fatalf("%s | Wrong status code | %v instead of %v", route, status, http.StatusOK)
	}
}
<|endoftext|>