<commit_before>package mid

import (
	"gitlab.com/gomidi/midi/midimessage/meta/meter"
	// "bytes"
	// "encoding/binary"
	"fmt"
	// "github.com/gomidi/midi/internal/midilib"
	"gitlab.com/gomidi/midi/midimessage/channel"
	"gitlab.com/gomidi/midi/midimessage/meta"

	// "github.com/gomidi/midi/midimessage/realtime"
	// "github.com/gomidi/midi/midimessage/syscommon"
	"io"
	"os"

	"gitlab.com/gomidi/midi/smf"
	"gitlab.com/gomidi/midi/smf/smftimeline"
	"gitlab.com/gomidi/midi/smf/smfwriter"
	// "time"
)

// SMFWriter writes SMF MIDI data. Its methods must not be called concurrently
type SMFWriter struct {
	wr smf.Writer
	*midiWriter
	finishedTracks uint16
	dest           io.Writer
	smf.MetricTicks
	timeline *smftimeline.TimeLine
}

// NewSMF returns a new SMFWriter that writes to dest.
// It panics if numtracks is == 0.
func NewSMF(dest io.Writer, numtracks uint16, options ...smfwriter.Option) *SMFWriter {
	if numtracks == 0 {
		panic("numtracks must be > 0")
	}

	options = append(
		[]smfwriter.Option{
			smfwriter.NumTracks(numtracks),
			smfwriter.TimeFormat(smf.MetricTicks(960)),
		}, options...)

	wr := smfwriter.New(dest, options...)

	smfwr := &SMFWriter{
		dest:       dest,
		wr:         wr,
		midiWriter: &midiWriter{wr: wr, ch: channel.Channel0},
	}

	if metr, isMetric := wr.Header().TimeFormat.(smf.MetricTicks); isMetric {
		smfwr.MetricTicks = metr
		smfwr.timeline = smftimeline.New(metr)
	} else {
		panic("timeformat must be metric")
	}
	return smfwr
}

// NewSMFFile creates a new SMF file and allows writer to write to it.
// The file is guaranteed to be closed when returning.
// The last track is closed automatically, if needed.
// It panics if numtracks is == 0.
func NewSMFFile(file string, numtracks uint16, writer func(*SMFWriter) error, options ...smfwriter.Option) error {
	if numtracks == 0 {
		panic("numtracks must be > 0")
	}

	f, err := os.Create(file)
	if err != nil {
		return err
	}

	defer f.Close()

	wr := NewSMF(f, numtracks, options...)
	if writer != nil {
		err = writer(wr)
		if err != nil {
			return err
		}
	}

	if no := wr.wr.Header().NumTracks; wr.finishedTracks < no {
		err := wr.EndOfTrack()
		if err != nil && err != smf.ErrFinished {
			return err
		}
	}

	return nil
}

// SetDelta sets the delta ticks to the next message
// It should mostly not be needed, use Forward instead to advance in musical time.
func (w *SMFWriter) SetDelta(deltatime uint32) {
	w.wr.SetDelta(deltatime)
}

// Forward sets the cursor based on the given number of bars and ratio of whole notes.
// The cursor is the current position where the next event will be inserted. In the background
// it sets the delta to the next event. The cursor can only move forward.
//
// Examples:
//
// To move the cursor to the 2nd next bar (respecting time signature changes), use
//   Forward(2,0,0)
// To move the cursor by 23 8ths (independent from time signatures), use
//   Forward(0,23,8)
// To move the cursor to the 3rd 4th of the next bar (respecting time signature changes), use
//   Forward(1,3,4)
//
// Important notes:
//   1. Always put time signature changes at the beginning of a bar.
//   2. Never forward more than once without setting a event in between.
func (w *SMFWriter) Forward(nbars, num, denom uint32) {
	if nbars > 0 {
		w.timeline.ForwardNBars(nbars)
	}

	if num > 0 && denom > 0 {
	w.timeline.Forward(num,denom)
	}

	delta := w.timeline.GetDelta()
	if delta < 0 {
		panic("cursor before last delta, must not happen")
	}
	w.SetDelta(uint32(delta))
}

// EndOfTrack signals the end of a track
func (w *SMFWriter) EndOfTrack() error {
	w.midiWriter.noteState = [16][128]bool{}
	if no := w.wr.Header().NumTracks; w.finishedTracks >= no {
		return fmt.Errorf("too many tracks: in header: %v, closed: %v", no, w.finishedTracks+1)
	}
	w.finishedTracks++
	if w.timeline != nil {
		w.timeline.Reset()
	}
	return w.wr.Write(meta.EndOfTrack)
}

// Copyright writes the copyright meta message
func (w *SMFWriter) Copyright(text string) error {
	return w.wr.Write(meta.Copyright(text))
}

// Cuepoint writes the cuepoint meta message
func (w *SMFWriter) Cuepoint(text string) error {
	return w.wr.Write(meta.Cuepoint(text))
}

// Device writes the device port meta message
func (w *SMFWriter) Device(port string) error {
	return w.wr.Write(meta.Device(port))
}

// KeySig writes the key signature meta message.
// A more comfortable way is to use the Key method in conjunction
// with the gomidi/midi/midimessage/meta/key package
func (w *SMFWriter) KeySig(key uint8, ismajor bool, num uint8, isflat bool) error {
	return w.wr.Write(meta.Key{Key: key, IsMajor: ismajor, Num: num, IsFlat: isflat})
}

// Key writes the given key signature meta message.
// It is supposed to be used with the gomidi/midi/midimessage/meta/key package
func (w *SMFWriter) Key(keysig meta.Key) error {
	return w.wr.Write(keysig)
}

// Lyric writes the lyric meta message
func (w *SMFWriter) Lyric(text string) error {
	return w.wr.Write(meta.Lyric(text))
}

// Marker writes the marker meta message
func (w *SMFWriter) Marker(text string) error {
	return w.wr.Write(meta.Marker(text))
}

// DeprecatedChannel writes the deprecated MIDI channel meta message
func (w *SMFWriter) DeprecatedChannel(ch uint8) error {
	return w.wr.Write(meta.Channel(ch))
}

// DeprecatedPort writes the deprecated MIDI port meta message
func (w *SMFWriter) DeprecatedPort(port uint8) error {
	return w.wr.Write(meta.Port(port))
}

// Program writes the program name meta message
func (w *SMFWriter) Program(text string) error {
	return w.wr.Write(meta.Program(text))
}

// Sequence writes the sequence (name) meta message
func (w *SMFWriter) Sequence(text string) error {
	return w.wr.Write(meta.Sequence(text))
}

// SequenceNo writes the sequence number meta message
func (w *SMFWriter) SequenceNo(no uint16) error {
	return w.wr.Write(meta.SequenceNo(no))
}

// SequencerData writes a custom sequences specific meta message
func (w *SMFWriter) SequencerData(data []byte) error {
	return w.wr.Write(meta.SequencerData(data))
}

// SMPTE writes the SMPTE offset meta message
func (w *SMFWriter) SMPTE(hour, minute, second, frame, fractionalFrame byte) error {
	return w.wr.Write(meta.SMPTE{
		Hour:            hour,
		Minute:          minute,
		Second:          second,
		Frame:           frame,
		FractionalFrame: fractionalFrame,
	})
}

// Tempo writes the tempo meta message
func (w *SMFWriter) TempoBPM(bpm float64) error {
	return w.wr.Write(meta.FractionalBPM(bpm))
}

// Text writes the text meta message
func (w *SMFWriter) Text(text string) error {
	return w.wr.Write(meta.Text(text))
}

// Meter writes the time signature meta message in a more comfortable way.
// Numerator and Denominator are decimalw.
func (w *SMFWriter) Meter(numerator, denominator uint8) error {
	w.timeline.AddTimeSignature(numerator,denominator)
	return w.wr.Write(meter.Meter(numerator, denominator))
}

// TimeSig writes the time signature meta message.
// Numerator and Denominator are decimal.
// If you don't want to deal with clocks per click and demisemiquaverperquarter,
// user the Meter method instead.
func (w *SMFWriter) TimeSig(numerator, denominator, clocksPerClick, demiSemiQuaverPerQuarter uint8) error {
	w.timeline.AddTimeSignature(numerator,denominator)
	return w.wr.Write(meta.TimeSig{
		Numerator:                numerator,
		Denominator:              denominator,
		ClocksPerClick:           clocksPerClick,
		DemiSemiQuaverPerQuarter: demiSemiQuaverPerQuarter,
	})
}

// Track writes the track name aka instrument name meta message
func (w *SMFWriter) Track(track string) error {
	return w.wr.Write(meta.Track(track))
}
<commit_msg>go fmt writer_smf<commit_after>package mid

import (
	"gitlab.com/gomidi/midi/midimessage/meta/meter"
	// "bytes"
	// "encoding/binary"
	"fmt"
	// "github.com/gomidi/midi/internal/midilib"
	"gitlab.com/gomidi/midi/midimessage/channel"
	"gitlab.com/gomidi/midi/midimessage/meta"

	// "github.com/gomidi/midi/midimessage/realtime"
	// "github.com/gomidi/midi/midimessage/syscommon"
	"io"
	"os"

	"gitlab.com/gomidi/midi/smf"
	"gitlab.com/gomidi/midi/smf/smftimeline"
	"gitlab.com/gomidi/midi/smf/smfwriter"
	// "time"
)

// SMFWriter writes SMF MIDI data. Its methods must not be called concurrently
type SMFWriter struct {
	wr smf.Writer
	*midiWriter
	finishedTracks uint16
	dest           io.Writer
	smf.MetricTicks
	timeline *smftimeline.TimeLine
}

// NewSMF returns a new SMFWriter that writes to dest.
// It panics if numtracks is == 0.
func NewSMF(dest io.Writer, numtracks uint16, options ...smfwriter.Option) *SMFWriter {
	if numtracks == 0 {
		panic("numtracks must be > 0")
	}

	options = append(
		[]smfwriter.Option{
			smfwriter.NumTracks(numtracks),
			smfwriter.TimeFormat(smf.MetricTicks(960)),
		}, options...)

	wr := smfwriter.New(dest, options...)

	smfwr := &SMFWriter{
		dest:       dest,
		wr:         wr,
		midiWriter: &midiWriter{wr: wr, ch: channel.Channel0},
	}

	if metr, isMetric := wr.Header().TimeFormat.(smf.MetricTicks); isMetric {
		smfwr.MetricTicks = metr
		smfwr.timeline = smftimeline.New(metr)
	} else {
		panic("timeformat must be metric")
	}
	return smfwr
}

// NewSMFFile creates a new SMF file and allows writer to write to it.
// The file is guaranteed to be closed when returning.
// The last track is closed automatically, if needed.
// It panics if numtracks is == 0.
func NewSMFFile(file string, numtracks uint16, writer func(*SMFWriter) error, options ...smfwriter.Option) error {
	if numtracks == 0 {
		panic("numtracks must be > 0")
	}

	f, err := os.Create(file)
	if err != nil {
		return err
	}

	defer f.Close()

	wr := NewSMF(f, numtracks, options...)
	if writer != nil {
		err = writer(wr)
		if err != nil {
			return err
		}
	}

	if no := wr.wr.Header().NumTracks; wr.finishedTracks < no {
		err := wr.EndOfTrack()
		if err != nil && err != smf.ErrFinished {
			return err
		}
	}

	return nil
}

// SetDelta sets the delta ticks to the next message
// It should mostly not be needed, use Forward instead to advance in musical time.
func (w *SMFWriter) SetDelta(deltatime uint32) {
	w.wr.SetDelta(deltatime)
}

// Forward sets the cursor based on the given number of bars and ratio of whole notes.
// The cursor is the current position where the next event will be inserted. In the background
// it sets the delta to the next event. The cursor can only move forward.
//
// Examples:
//
// To move the cursor to the 2nd next bar (respecting time signature changes), use
//   Forward(2,0,0)
// To move the cursor by 23 8ths (independent from time signatures), use
//   Forward(0,23,8)
// To move the cursor to the 3rd 4th of the next bar (respecting time signature changes), use
//   Forward(1,3,4)
//
// Important notes:
//   1. Always put time signature changes at the beginning of a bar.
//   2. Never forward more than once without setting a event in between.
func (w *SMFWriter) Forward(nbars, num, denom uint32) {
	if nbars > 0 {
		w.timeline.ForwardNBars(nbars)
	}

	if num > 0 && denom > 0 {
		w.timeline.Forward(num, denom)
	}

	delta := w.timeline.GetDelta()
	if delta < 0 {
		panic("cursor before last delta, must not happen")
	}
	w.SetDelta(uint32(delta))
}

// EndOfTrack signals the end of a track
func (w *SMFWriter) EndOfTrack() error {
	w.midiWriter.noteState = [16][128]bool{}
	if no := w.wr.Header().NumTracks; w.finishedTracks >= no {
		return fmt.Errorf("too many tracks: in header: %v, closed: %v", no, w.finishedTracks+1)
	}
	w.finishedTracks++
	if w.timeline != nil {
		w.timeline.Reset()
	}
	return w.wr.Write(meta.EndOfTrack)
}

// Copyright writes the copyright meta message
func (w *SMFWriter) Copyright(text string) error {
	return w.wr.Write(meta.Copyright(text))
}

// Cuepoint writes the cuepoint meta message
func (w *SMFWriter) Cuepoint(text string) error {
	return w.wr.Write(meta.Cuepoint(text))
}

// Device writes the device port meta message
func (w *SMFWriter) Device(port string) error {
	return w.wr.Write(meta.Device(port))
}

// KeySig writes the key signature meta message.
// A more comfortable way is to use the Key method in conjunction
// with the gomidi/midi/midimessage/meta/key package
func (w *SMFWriter) KeySig(key uint8, ismajor bool, num uint8, isflat bool) error {
	return w.wr.Write(meta.Key{Key: key, IsMajor: ismajor, Num: num, IsFlat: isflat})
}

// Key writes the given key signature meta message.
// It is supposed to be used with the gomidi/midi/midimessage/meta/key package
func (w *SMFWriter) Key(keysig meta.Key) error {
	return w.wr.Write(keysig)
}

// Lyric writes the lyric meta message
func (w *SMFWriter) Lyric(text string) error {
	return w.wr.Write(meta.Lyric(text))
}

// Marker writes the marker meta message
func (w *SMFWriter) Marker(text string) error {
	return w.wr.Write(meta.Marker(text))
}

// DeprecatedChannel writes the deprecated MIDI channel meta message
func (w *SMFWriter) DeprecatedChannel(ch uint8) error {
	return w.wr.Write(meta.Channel(ch))
}

// DeprecatedPort writes the deprecated MIDI port meta message
func (w *SMFWriter) DeprecatedPort(port uint8) error {
	return w.wr.Write(meta.Port(port))
}

// Program writes the program name meta message
func (w *SMFWriter) Program(text string) error {
	return w.wr.Write(meta.Program(text))
}

// Sequence writes the sequence (name) meta message
func (w *SMFWriter) Sequence(text string) error {
	return w.wr.Write(meta.Sequence(text))
}

// SequenceNo writes the sequence number meta message
func (w *SMFWriter) SequenceNo(no uint16) error {
	return w.wr.Write(meta.SequenceNo(no))
}

// SequencerData writes a custom sequences specific meta message
func (w *SMFWriter) SequencerData(data []byte) error {
	return w.wr.Write(meta.SequencerData(data))
}

// SMPTE writes the SMPTE offset meta message
func (w *SMFWriter) SMPTE(hour, minute, second, frame, fractionalFrame byte) error {
	return w.wr.Write(meta.SMPTE{
		Hour:            hour,
		Minute:          minute,
		Second:          second,
		Frame:           frame,
		FractionalFrame: fractionalFrame,
	})
}

// Tempo writes the tempo meta message
func (w *SMFWriter) TempoBPM(bpm float64) error {
	return w.wr.Write(meta.FractionalBPM(bpm))
}

// Text writes the text meta message
func (w *SMFWriter) Text(text string) error {
	return w.wr.Write(meta.Text(text))
}

// Meter writes the time signature meta message in a more comfortable way.
// Numerator and Denominator are decimalw.
func (w *SMFWriter) Meter(numerator, denominator uint8) error {
	w.timeline.AddTimeSignature(numerator, denominator)
	return w.wr.Write(meter.Meter(numerator, denominator))
}

// TimeSig writes the time signature meta message.
// Numerator and Denominator are decimal.
// If you don't want to deal with clocks per click and demisemiquaverperquarter,
// user the Meter method instead.
func (w *SMFWriter) TimeSig(numerator, denominator, clocksPerClick, demiSemiQuaverPerQuarter uint8) error {
	w.timeline.AddTimeSignature(numerator, denominator)
	return w.wr.Write(meta.TimeSig{
		Numerator:                numerator,
		Denominator:              denominator,
		ClocksPerClick:           clocksPerClick,
		DemiSemiQuaverPerQuarter: demiSemiQuaverPerQuarter,
	})
}

// Track writes the track name aka instrument name meta message
func (w *SMFWriter) Track(track string) error {
	return w.wr.Write(meta.Track(track))
}
<|endoftext|>


<commit_before>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

//+build ignore

package main

import (
	"math"
	"net"
	"os"
	"os/signal"
	"syscall"

	"github.com/TheThingsNetwork/go-utils/log"
	"github.com/TheThingsNetwork/go-utils/log/apex"
	"github.com/TheThingsNetwork/ttn/api/monitor"
	"github.com/TheThingsNetwork/ttn/api/monitor/monitorserver"
	"google.golang.org/grpc"
)

func main() {
	log.Set(apex.Stdout())
	ctx := log.Get()

	if len(os.Args) != 2 {
		ctx.Fatal("Usage: ttn-monitor-server-example [listen]")
	}

	lis, err := net.Listen("tcp", os.Args[1])
	if err != nil {
		ctx.WithError(err).Fatal("Failed to listen")
	}
	s := grpc.NewServer(grpc.MaxConcurrentStreams(math.MaxUint16))
	server := monitorserver.NewReferenceMonitorServer(10)
	monitor.RegisterMonitorServer(s, server)
	go s.Serve(lis)
	ctx.Infof("Listening on %s", lis.Addr().String())

	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
	ctx.WithField("signal", <-sigChan).Info("signal received")

	s.Stop()
}
<commit_msg>Use TLS in example monitor server<commit_after>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

//+build ignore

package main

import (
	"crypto/tls"
	"math"
	"os"
	"os/signal"
	"syscall"

	"github.com/TheThingsNetwork/go-utils/log"
	"github.com/TheThingsNetwork/go-utils/log/apex"
	"github.com/TheThingsNetwork/ttn/api/monitor"
	"github.com/TheThingsNetwork/ttn/api/monitor/monitorserver"
	"google.golang.org/grpc"
)

func main() {
	log.Set(apex.Stdout())
	ctx := log.Get()

	if len(os.Args) != 2 {
		ctx.Fatal("Usage: ttn-monitor-server-example [listen]")
	}

	var tlsConfig tls.Config
	certificate, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
	if err != nil {
		ctx.WithError(err).Fatal("Could not load tls certificate and key")
	}
	tlsConfig.Certificates = append(tlsConfig.Certificates, certificate)
	lis, err := tls.Listen("tcp", os.Args[1], &tlsConfig)
	if err != nil {
		ctx.WithError(err).Fatal("Failed to listen")
	}
	s := grpc.NewServer(grpc.MaxConcurrentStreams(math.MaxUint16))
	server := monitorserver.NewReferenceMonitorServer(10)
	monitor.RegisterMonitorServer(s, server)
	go s.Serve(lis)
	ctx.Infof("Listening on %s", lis.Addr().String())

	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
	ctx.WithField("signal", <-sigChan).Info("signal received")

	s.Stop()
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zanzibar

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

	"time"

	"github.com/uber-go/zap"
)

// ServerHTTPResponse struct manages request
type ServerHTTPResponse struct {
	responseWriter http.ResponseWriter
	req            *ServerHTTPRequest
	gateway        *Gateway
	finishTime     time.Time
	finished       bool
	metrics        *EndpointMetrics

	StatusCode int
}

// NewServerHTTPResponse is helper function to alloc ServerHTTPResponse
func NewServerHTTPResponse(
	w http.ResponseWriter, req *ServerHTTPRequest,
) *ServerHTTPResponse {
	res := &ServerHTTPResponse{
		gateway:        req.gateway,
		req:            req,
		responseWriter: w,
		StatusCode:     200,
		metrics:        req.metrics,
	}

	return res
}

// finish will handle final logic, like metrics
func (res *ServerHTTPResponse) finish() {
	if !res.req.started {
		/* coverage ignore next line */
		res.req.Logger.Error(
			"Forgot to start incoming request",
			zap.String("path", res.req.URL.Path),
		)
		/* coverage ignore next line */
		return
	}
	if res.finished {
		/* coverage ignore next line */
		res.req.Logger.Error(
			"Finished an incoming request twice",
			zap.String("path", res.req.URL.Path),
		)
		/* coverage ignore next line */
		return
	}

	res.finished = true
	res.finishTime = time.Now()

	counter := res.metrics.statusCodes[res.StatusCode]
	if counter == nil {
		res.req.Logger.Error(
			"Could not emit statusCode metric",
			zap.Int("UnexpectedStatusCode", res.StatusCode),
		)
	} else {
		counter.Inc(1)
	}

	res.metrics.requestLatency.Record(
		res.finishTime.Sub(res.req.startTime),
	)
}

// SendError helper to send an error
func (res *ServerHTTPResponse) SendError(statusCode int, err error) {
	res.SendErrorString(statusCode, err.Error())
}

// SendErrorString helper to send an error string
func (res *ServerHTTPResponse) SendErrorString(
	statusCode int, err string,
) {
	res.req.Logger.Warn(
		"Sending error for endpoint request",
		zap.String("error", err),
		zap.String("path", res.req.URL.Path),
	)

	res.writeHeader(statusCode)
	res.writeString(err)

	res.finish()
}

// WriteJSONBytes writes a byte[] slice that is valid json to Response
func (res *ServerHTTPResponse) WriteJSONBytes(
	statusCode int, bytes []byte,
) {
	res.responseWriter.Header().Set("content-type", "application/json")
	res.writeHeader(statusCode)
	res.writeBytes(bytes)

	res.finish()
}

// WriteJSON writes a json serializable struct to Response
func (res *ServerHTTPResponse) WriteJSON(
	statusCode int, body json.Marshaler,
) {
	if body == nil {
		res.SendErrorString(500, "Could not serialize json response")
		res.req.Logger.Error("Could not serialize nil pointer body")
		return
	}

	bytes, err := body.MarshalJSON()
	if err != nil {
		res.SendErrorString(500, "Could not serialize json response")
		res.req.Logger.Error("Could not serialize json response",
			zap.String("error", err.Error()),
		)
		return
	}

	res.responseWriter.Header().Set("content-type", "application/json")
	res.writeHeader(statusCode)
	res.writeBytes(bytes)

	res.finish()
}

func (res *ServerHTTPResponse) writeHeader(statusCode int) {
	res.StatusCode = statusCode
	res.responseWriter.WriteHeader(statusCode)
}

// WriteBytes writes raw bytes to output
func (res *ServerHTTPResponse) writeBytes(bytes []byte) {
	_, err := res.responseWriter.Write(bytes)
	if err != nil {
		res.req.Logger.Error("Could not write string to resp body",
			zap.String("error", err.Error()),
		)
	}
}

// WriteString helper just writes a string to the response
func (res *ServerHTTPResponse) writeString(text string) {
	res.writeBytes([]byte(text))
}

// IsOKResponse checks if the status code is OK.
func (res *ServerHTTPResponse) IsOKResponse(
	statusCode int, okResponses []int,
) bool {
	for _, r := range okResponses {
		if statusCode == r {
			return true
		}
	}
	return false
}
<commit_msg>runtime/ServerResponse: add ignore on non-trivial line<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zanzibar

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

	"time"

	"github.com/uber-go/zap"
)

// ServerHTTPResponse struct manages request
type ServerHTTPResponse struct {
	responseWriter http.ResponseWriter
	req            *ServerHTTPRequest
	gateway        *Gateway
	finishTime     time.Time
	finished       bool
	metrics        *EndpointMetrics

	StatusCode int
}

// NewServerHTTPResponse is helper function to alloc ServerHTTPResponse
func NewServerHTTPResponse(
	w http.ResponseWriter, req *ServerHTTPRequest,
) *ServerHTTPResponse {
	res := &ServerHTTPResponse{
		gateway:        req.gateway,
		req:            req,
		responseWriter: w,
		StatusCode:     200,
		metrics:        req.metrics,
	}

	return res
}

// finish will handle final logic, like metrics
func (res *ServerHTTPResponse) finish() {
	if !res.req.started {
		/* coverage ignore next line */
		res.req.Logger.Error(
			"Forgot to start incoming request",
			zap.String("path", res.req.URL.Path),
		)
		/* coverage ignore next line */
		return
	}
	if res.finished {
		/* coverage ignore next line */
		res.req.Logger.Error(
			"Finished an incoming request twice",
			zap.String("path", res.req.URL.Path),
		)
		/* coverage ignore next line */
		return
	}

	res.finished = true
	res.finishTime = time.Now()

	counter := res.metrics.statusCodes[res.StatusCode]
	if counter == nil {
		res.req.Logger.Error(
			"Could not emit statusCode metric",
			zap.Int("UnexpectedStatusCode", res.StatusCode),
		)
	} else {
		counter.Inc(1)
	}

	res.metrics.requestLatency.Record(
		res.finishTime.Sub(res.req.startTime),
	)
}

// SendError helper to send an error
func (res *ServerHTTPResponse) SendError(statusCode int, err error) {
	res.SendErrorString(statusCode, err.Error())
}

// SendErrorString helper to send an error string
func (res *ServerHTTPResponse) SendErrorString(
	statusCode int, err string,
) {
	res.req.Logger.Warn(
		"Sending error for endpoint request",
		zap.String("error", err),
		zap.String("path", res.req.URL.Path),
	)

	res.writeHeader(statusCode)
	res.writeString(err)

	res.finish()
}

// WriteJSONBytes writes a byte[] slice that is valid json to Response
func (res *ServerHTTPResponse) WriteJSONBytes(
	statusCode int, bytes []byte,
) {
	res.responseWriter.Header().Set("content-type", "application/json")
	res.writeHeader(statusCode)
	res.writeBytes(bytes)

	res.finish()
}

// WriteJSON writes a json serializable struct to Response
func (res *ServerHTTPResponse) WriteJSON(
	statusCode int, body json.Marshaler,
) {
	if body == nil {
		res.SendErrorString(500, "Could not serialize json response")
		res.req.Logger.Error("Could not serialize nil pointer body")
		return
	}

	bytes, err := body.MarshalJSON()
	if err != nil {
		res.SendErrorString(500, "Could not serialize json response")
		res.req.Logger.Error("Could not serialize json response",
			zap.String("error", err.Error()),
		)
		return
	}

	res.responseWriter.Header().Set("content-type", "application/json")
	res.writeHeader(statusCode)
	res.writeBytes(bytes)

	res.finish()
}

func (res *ServerHTTPResponse) writeHeader(statusCode int) {
	res.StatusCode = statusCode
	res.responseWriter.WriteHeader(statusCode)
}

// WriteBytes writes raw bytes to output
func (res *ServerHTTPResponse) writeBytes(bytes []byte) {
	_, err := res.responseWriter.Write(bytes)
	if err != nil {
		/* coverage ignore next line */
		res.req.Logger.Error("Could not write string to resp body",
			zap.String("error", err.Error()),
		)
	}
}

// WriteString helper just writes a string to the response
func (res *ServerHTTPResponse) writeString(text string) {
	res.writeBytes([]byte(text))
}

// IsOKResponse checks if the status code is OK.
func (res *ServerHTTPResponse) IsOKResponse(
	statusCode int, okResponses []int,
) bool {
	for _, r := range okResponses {
		if statusCode == r {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package instance

import (
	"fmt"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

type uploadCmdData struct {
	AccessKey       string
	BucketName      string
	BundleDirectory string
	ManifestPath    string
	Region          string
	SecretKey       string
}

type StepUploadBundle struct {
	Debug bool
}

func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction {
	comm := state.Get("communicator").(packer.Communicator)
	config := state.Get("config").(*Config)
	manifestName := state.Get("manifest_name").(string)
	manifestPath := state.Get("manifest_path").(string)
	ui := state.Get("ui").(packer.Ui)

	region, err := config.Region()
	if err != nil {
		err := fmt.Errorf("Error retrieving region: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	config.ctx.Data = uploadCmdData{
		AccessKey:       config.AccessKey,
		BucketName:      config.S3Bucket,
		BundleDirectory: config.BundleDestination,
		ManifestPath:    manifestPath,
		Region:          region,
		SecretKey:       config.SecretKey,
	}
	config.BundleUploadCommand, err = interpolate.Render(config.BundleUploadCommand, &config.ctx)
	if err != nil {
		err := fmt.Errorf("Error processing bundle upload command: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Say("Uploading the bundle...")
	cmd := &packer.RemoteCmd{Command: config.BundleUploadCommand}

	if s.Debug {
		ui.Say(fmt.Sprintf("Running: %s", config.BundleUploadCommand))
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		state.Put("error", fmt.Errorf("Error uploading volume: %s", err))
		ui.Error(state.Get("error").(error).Error())
		return multistep.ActionHalt
	}

	if cmd.ExitStatus != 0 {
		state.Put("error", fmt.Errorf(
			"Bundle upload failed. Please see the output above for more\n"+
				"details on what went wrong."))
		ui.Error(state.Get("error").(error).Error())
		return multistep.ActionHalt
	}

	state.Put("remote_manifest_path", fmt.Sprintf(
		"%s/%s", config.S3Bucket, manifestName))

	return multistep.ActionContinue
}

func (s *StepUploadBundle) Cleanup(state multistep.StateBag) {}
<commit_msg>Populate access and secret key for bundle_upload_command.<commit_after>package instance

import (
	"fmt"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

type uploadCmdData struct {
	AccessKey       string
	BucketName      string
	BundleDirectory string
	ManifestPath    string
	Region          string
	SecretKey       string
}

type StepUploadBundle struct {
	Debug bool
}

func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction {
	comm := state.Get("communicator").(packer.Communicator)
	config := state.Get("config").(*Config)
	manifestName := state.Get("manifest_name").(string)
	manifestPath := state.Get("manifest_path").(string)
	ui := state.Get("ui").(packer.Ui)

	region, err := config.Region()
	if err != nil {
		err := fmt.Errorf("Error retrieving region: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	accessKey := config.AccessKey
	secretKey := config.SecretKey
	accessConfig, err := config.AccessConfig.Config()
	if err == nil && accessKey == "" && secretKey == "" {
		credentials, err := accessConfig.Credentials.Get()
		if err == nil {
			accessKey = credentials.AccessKeyID
			secretKey = credentials.SecretAccessKey
		}
	}

	config.ctx.Data = uploadCmdData{
		AccessKey:       accessKey,
		BucketName:      config.S3Bucket,
		BundleDirectory: config.BundleDestination,
		ManifestPath:    manifestPath,
		Region:          region,
		SecretKey:       secretKey,
	}
	config.BundleUploadCommand, err = interpolate.Render(config.BundleUploadCommand, &config.ctx)
	if err != nil {
		err := fmt.Errorf("Error processing bundle upload command: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Say("Uploading the bundle...")
	cmd := &packer.RemoteCmd{Command: config.BundleUploadCommand}

	if s.Debug {
		ui.Say(fmt.Sprintf("Running: %s", config.BundleUploadCommand))
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		state.Put("error", fmt.Errorf("Error uploading volume: %s", err))
		ui.Error(state.Get("error").(error).Error())
		return multistep.ActionHalt
	}

	if cmd.ExitStatus != 0 {
		state.Put("error", fmt.Errorf(
			"Bundle upload failed. Please see the output above for more\n"+
				"details on what went wrong."))
		ui.Error(state.Get("error").(error).Error())
		return multistep.ActionHalt
	}

	state.Put("remote_manifest_path", fmt.Sprintf(
		"%s/%s", config.S3Bucket, manifestName))

	return multistep.ActionContinue
}

func (s *StepUploadBundle) Cleanup(state multistep.StateBag) {}
<|endoftext|>


<commit_before>// Copyright 2016 The Upspin 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 context creates a client context from various sources.
package context

import "upspin.io/upspin"

// User returns an upspin.User record for the user in the given context.
func User(ctx upspin.Context) *upspin.User {
	var key upspin.PublicKey
	if f := ctx.Factotum(); f != nil {
		key = f.PublicKey()
	}
	return &upspin.User{
		Name:      ctx.UserName(),
		Dirs:      []upspin.Endpoint{ctx.DirEndpoint()},
		Stores:    []upspin.Endpoint{ctx.StoreEndpoint()},
		PublicKey: key,
	}
}
<commit_msg>context: remove superfluous comment<commit_after>// Copyright 2016 The Upspin 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 context

import "upspin.io/upspin"

// User returns an upspin.User record for the user in the given context.
func User(ctx upspin.Context) *upspin.User {
	var key upspin.PublicKey
	if f := ctx.Factotum(); f != nil {
		key = f.PublicKey()
	}
	return &upspin.User{
		Name:      ctx.UserName(),
		Dirs:      []upspin.Endpoint{ctx.DirEndpoint()},
		Stores:    []upspin.Endpoint{ctx.StoreEndpoint()},
		PublicKey: key,
	}
}
<|endoftext|>


<commit_before>package fire

import (
	"testing"

	"github.com/256dpi/fire/coal"

	"github.com/stretchr/testify/assert"
)

func TestOperation(t *testing.T) {
	table := []struct {
		op Operation
		r  bool
		w  bool
	}{
		{List, true, false},
		{Find, true, false},
		{Create, false, true},
		{Update, false, true},
		{Delete, false, true},
	}

	for _, entry := range table {
		assert.Equal(t, entry.r, entry.op.Read())
		assert.Equal(t, entry.w, entry.op.Write())
	}
}

func TestContextOriginal(t *testing.T) {
	tester.Clean()

	savedPost := coal.Init(&postModel{
		Title: "foo",
	}).(*postModel)

	tester.Save(savedPost)

	post := coal.Init(&postModel{
		Title: "bar",
	}).(*postModel)

	post.DocID = savedPost.DocID

	tester.WithContext(&Context{Operation: Update, Model: post}, func(ctx *Context) {
		m, err := ctx.Original()
		assert.NoError(t, err)
		assert.Equal(t, savedPost.ID(), m.ID())
		assert.Equal(t, savedPost.MustGet("Title"), m.MustGet("Title"))

		m2, err := ctx.Original()
		assert.NoError(t, err)
		assert.Equal(t, m, m2)
	})
}

func TestContextOriginalWrongOperation(t *testing.T) {
	tester.WithContext(nil, func(ctx *Context) {
		assert.Panics(t, func() {
			ctx.Original()
		})
	})
}

func TestContextOriginalNonExisting(t *testing.T) {
	tester.Clean()

	post := coal.Init(&postModel{
		Title: "foo",
	}).(*postModel)

	tester.WithContext(&Context{Operation: Update, Model: post}, func(ctx *Context) {
		m, err := ctx.Original()
		assert.Error(t, err)
		assert.Nil(t, m)
	})
}
<commit_msg>added missing tests<commit_after>package fire

import (
	"testing"

	"github.com/256dpi/fire/coal"

	"github.com/stretchr/testify/assert"
)

func TestOperation(t *testing.T) {
	table := []struct {
		o Operation
		r bool
		w bool
		a bool
		s string
	}{
		{List, true, false, false, "List"},
		{Find, true, false, false, "Find"},
		{Create, false, true, false, "Create"},
		{Update, false, true, false, "Update"},
		{Delete, false, true, false, "Delete"},
		{CollectionAction, false, false, true, "CollectionAction"},
		{ResourceAction, false, false, true, "ResourceAction"},
		{Operation(0), false, false, false, ""},
	}

	for _, entry := range table {
		assert.Equal(t, entry.r, entry.o.Read())
		assert.Equal(t, entry.w, entry.o.Write())
		assert.Equal(t, entry.a, entry.o.Action())
		assert.Equal(t, entry.s, entry.o.String())
	}
}

func TestContextOriginal(t *testing.T) {
	tester.Clean()

	savedPost := coal.Init(&postModel{
		Title: "foo",
	}).(*postModel)

	tester.Save(savedPost)

	post := coal.Init(&postModel{
		Title: "bar",
	}).(*postModel)

	post.DocID = savedPost.DocID

	tester.WithContext(&Context{Operation: Update, Model: post}, func(ctx *Context) {
		m, err := ctx.Original()
		assert.NoError(t, err)
		assert.Equal(t, savedPost.ID(), m.ID())
		assert.Equal(t, savedPost.MustGet("Title"), m.MustGet("Title"))

		m2, err := ctx.Original()
		assert.NoError(t, err)
		assert.Equal(t, m, m2)
	})
}

func TestContextOriginalWrongOperation(t *testing.T) {
	tester.WithContext(nil, func(ctx *Context) {
		assert.Panics(t, func() {
			ctx.Original()
		})
	})
}

func TestContextOriginalNonExisting(t *testing.T) {
	tester.Clean()

	post := coal.Init(&postModel{
		Title: "foo",
	}).(*postModel)

	tester.WithContext(&Context{Operation: Update, Model: post}, func(ctx *Context) {
		m, err := ctx.Original()
		assert.Error(t, err)
		assert.Nil(t, m)
	})
}
<|endoftext|>


<commit_before>package Golf

import (
	"io"
	"fmt"
	"bufio"
	"strings"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"
)

func makeTestHTTPRequest(body io.Reader, method, url string) *http.Request {
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return nil
	}
	return req
}

func makeTestContext(method, url string) *Context {
	r := makeTestHTTPRequest(nil, method, url)
	w := httptest.NewRecorder()
	app := New()
	return NewContext(r, w, app)
}

func TestContextCreate(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/foo/bar/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	if ctx == nil {
		t.Errorf("Can not create context.")
	}
}

func TestCookieSet(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/foo/bar/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.SetCookie("foo", "bar", 0)
	ctx.Send()
	if w.HeaderMap.Get("Set-Cookie") != `foo=bar; Path=/` {
		t.Errorf("Cookie test failed: %q != %q", w.HeaderMap.Get("Set-Cookie"), `foo=bar; Path=/`)
	}
}

func TestCookieSetWithExpire(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/foo/bar/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.SetCookie("foo", "bar", 3600)
	ctx.Send()
	rawCookie := w.HeaderMap.Get("Set-Cookie")
	rawRequest := fmt.Sprintf("GET / HTTP/1.0\r\nCookie: %s\r\n\r\n", rawCookie)
	req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(rawRequest)))
	if err == nil {
		cookies := req.Cookies()
		cookie := cookies[3]
		if cookie.Value != "3600" {
			t.Errorf("Can not set cookie with expiration correctly.")
		}
  }
}

func TestTemplateLoader(t *testing.T) {
	ctx := makeTestContext("GET", "/")
	ctx.Loader("admin")
	if ctx.templateLoader != "admin" {
		t.Errorf("Can not set templateLoader for Context.")
	}
}

func TestQuery(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/search?q=foo&p=bar")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	q, err := ctx.Query("q")
	if err != nil {
		t.Errorf("Can not retrieve a query.")
	} else {
		if q != "foo" {
			t.Errorf("Can not retrieve the correct query `q`.")
		}
	}
	p, err := ctx.Query("p")
	if err != nil {
		t.Errorf("Can not retrieve a query.")
	} else {
		if p != "bar" {
			t.Errorf("Can not retrieve the correct query `p`.")
		}
	}
}

func TestQueries(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/search?myarray=value1&myarray=value2&myarray=value3")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	q, err := ctx.Query("myarray", 2)
	if err != nil {
		t.Errorf("Can not retrieve a query.")
	}
	if q != "value3" {
		t.Errorf("Can not correctly retrive a query.")
	}
}

func TestQueryNotFound(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/search?myarray=value1&myarray=value2&myarray=value3")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	q, err := ctx.Query("query")
	if err == nil || q != "" {
		t.Errorf("Can not raise error when query not found.")
	}
}

func makeNewContext(method, url string) *Context {
	r := makeTestHTTPRequest(nil, method, url)
	w := httptest.NewRecorder()
	app := New()
	return NewContext(r, w, app)
}

func TestRedirection(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.Redirect("/foo")
	ctx.Send()
	if w.HeaderMap.Get("Location") != `/foo` {
		t.Errorf("Can not perform a 301 redirection.")
	}
}

func TestWrite(t *testing.T) {
	ctx := makeNewContext("GET", "/foo")
	ctx.Write("hello world")
	if !reflect.DeepEqual(ctx.Body, []byte("hello world")) {
		t.Errorf("Context.Write failed.")
	}
}

func TestAbort(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.Abort(500)
	if w.Code != 500 || !ctx.IsSent {
		t.Errorf("Can not abort a context.")
	}
}

func TestRenderFromString(t *testing.T) {
	cases := []struct {
		src    string
		args   map[string]interface{}
		output string
	}{
		{
			"foo {{.Title}} bar",
			map[string]interface{}{"Title": "Hello World"},
			"foo Hello World bar",
		},
	}

	for _, c := range cases {
		r := makeTestHTTPRequest(nil, "GET", "/")
		w := httptest.NewRecorder()
		app := New()
		ctx := NewContext(r, w, app)
		ctx.RenderFromString(c.src, c.args)
		ctx.Send()
		if w.Body.String() != c.output {
			t.Errorf("Can not render from string correctly: %v != %v", w.Body.String(), c.output)
		}
	}
}

func TestJSON(t *testing.T) {
	cases := []struct {
		input  map[string]interface{}
		output string
	}{
		{
			map[string]interface{}{"status": "success", "code": 200},
			`{"code":200,"status":"success"}`,
		},
	}

	for _, c := range cases {
		r := makeTestHTTPRequest(nil, "GET", "/")
		w := httptest.NewRecorder()
		app := New()
		ctx := NewContext(r, w, app)
		ctx.JSON(c.input)
		ctx.Send()
		if w.Body.String() != c.output {
			t.Errorf("Can not return JSON correctly: %v != %v", w.Body.String(), c.output)
		}
		if w.HeaderMap.Get("Content-Type") != `application/json` {
			t.Errorf("Content-Type didn't set properly when calling Context.JSON.")
		}
	}
}
<commit_msg>[style] Improved coding style.<commit_after>package Golf

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"reflect"
	"strings"
	"testing"
)

func makeTestHTTPRequest(body io.Reader, method, url string) *http.Request {
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return nil
	}
	return req
}

func makeTestContext(method, url string) *Context {
	r := makeTestHTTPRequest(nil, method, url)
	w := httptest.NewRecorder()
	app := New()
	return NewContext(r, w, app)
}

func TestContextCreate(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/foo/bar/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	if ctx == nil {
		t.Errorf("Can not create context.")
	}
}

func TestCookieSet(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/foo/bar/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.SetCookie("foo", "bar", 0)
	ctx.Send()
	if w.HeaderMap.Get("Set-Cookie") != `foo=bar; Path=/` {
		t.Errorf("Cookie test failed: %q != %q", w.HeaderMap.Get("Set-Cookie"), `foo=bar; Path=/`)
	}
}

func TestCookieSetWithExpire(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/foo/bar/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.SetCookie("foo", "bar", 3600)
	ctx.Send()
	rawCookie := w.HeaderMap.Get("Set-Cookie")
	rawRequest := fmt.Sprintf("GET / HTTP/1.0\r\nCookie: %s\r\n\r\n", rawCookie)
	req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(rawRequest)))
	if err == nil {
		cookies := req.Cookies()
		cookie := cookies[3]
		if cookie.Value != "3600" {
			t.Errorf("Can not set cookie with expiration correctly.")
		}
	}
}

func TestTemplateLoader(t *testing.T) {
	ctx := makeTestContext("GET", "/")
	ctx.Loader("admin")
	if ctx.templateLoader != "admin" {
		t.Errorf("Can not set templateLoader for Context.")
	}
}

func TestQuery(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/search?q=foo&p=bar")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	q, err := ctx.Query("q")
	if err != nil {
		t.Errorf("Can not retrieve a query.")
	} else {
		if q != "foo" {
			t.Errorf("Can not retrieve the correct query `q`.")
		}
	}
	p, err := ctx.Query("p")
	if err != nil {
		t.Errorf("Can not retrieve a query.")
	} else {
		if p != "bar" {
			t.Errorf("Can not retrieve the correct query `p`.")
		}
	}
}

func TestQueries(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/search?myarray=value1&myarray=value2&myarray=value3")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	q, err := ctx.Query("myarray", 2)
	if err != nil {
		t.Errorf("Can not retrieve a query.")
	}
	if q != "value3" {
		t.Errorf("Can not correctly retrive a query.")
	}
}

func TestQueryNotFound(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/search?myarray=value1&myarray=value2&myarray=value3")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	q, err := ctx.Query("query")
	if err == nil || q != "" {
		t.Errorf("Can not raise error when query not found.")
	}
}

func makeNewContext(method, url string) *Context {
	r := makeTestHTTPRequest(nil, method, url)
	w := httptest.NewRecorder()
	app := New()
	return NewContext(r, w, app)
}

func TestRedirection(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.Redirect("/foo")
	ctx.Send()
	if w.HeaderMap.Get("Location") != `/foo` {
		t.Errorf("Can not perform a 301 redirection.")
	}
}

func TestWrite(t *testing.T) {
	ctx := makeNewContext("GET", "/foo")
	ctx.Write("hello world")
	if !reflect.DeepEqual(ctx.Body, []byte("hello world")) {
		t.Errorf("Context.Write failed.")
	}
}

func TestAbort(t *testing.T) {
	r := makeTestHTTPRequest(nil, "GET", "/")
	w := httptest.NewRecorder()
	app := New()
	ctx := NewContext(r, w, app)
	ctx.Abort(500)
	if w.Code != 500 || !ctx.IsSent {
		t.Errorf("Can not abort a context.")
	}
}

func TestRenderFromString(t *testing.T) {
	cases := []struct {
		src    string
		args   map[string]interface{}
		output string
	}{
		{
			"foo {{.Title}} bar",
			map[string]interface{}{"Title": "Hello World"},
			"foo Hello World bar",
		},
	}

	for _, c := range cases {
		r := makeTestHTTPRequest(nil, "GET", "/")
		w := httptest.NewRecorder()
		app := New()
		ctx := NewContext(r, w, app)
		ctx.RenderFromString(c.src, c.args)
		ctx.Send()
		if w.Body.String() != c.output {
			t.Errorf("Can not render from string correctly: %v != %v", w.Body.String(), c.output)
		}
	}
}

func TestJSON(t *testing.T) {
	cases := []struct {
		input  map[string]interface{}
		output string
	}{
		{
			map[string]interface{}{"status": "success", "code": 200},
			`{"code":200,"status":"success"}`,
		},
	}

	for _, c := range cases {
		r := makeTestHTTPRequest(nil, "GET", "/")
		w := httptest.NewRecorder()
		app := New()
		ctx := NewContext(r, w, app)
		ctx.JSON(c.input)
		ctx.Send()
		if w.Body.String() != c.output {
			t.Errorf("Can not return JSON correctly: %v != %v", w.Body.String(), c.output)
		}
		if w.HeaderMap.Get("Content-Type") != `application/json` {
			t.Errorf("Content-Type didn't set properly when calling Context.JSON.")
		}
	}
}
<|endoftext|>


<commit_before>package dockergen

import (
	"testing"
)

func TestGetCurrentContainerID(t *testing.T) {
	currentContainerID := GetCurrentContainerID()

	if len(currentContainerID) != 0 && len(currentContainerID) != 64 {
		t.Fail()
	}
}

func TestGetCurrentContainerID_ECS(t *testing.T) {
	cgroup :=
		`9:perf_event:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
8:memory:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
7:hugetlb:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
6:freezer:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
5:devices:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
4:cpuset:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
3:cpuacct:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
2:cpu:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f
1:blkio:/ecs/628967a1-46b4-4a8a-84ff-605128f4679e/3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f`

	if got, exp := matchECSCurrentContainerID(cgroup), "3c94e08259a6235781bb65f3dec91150c92e9d414ecc410d6245687392d3900f"; got != exp {
		t.Fatalf("id mismatch: got %v, exp %v", got, exp)
	}
}

func TestGetCurrentContainerID_DockerCE(t *testing.T) {
	cgroup :=
		`13:name=systemd:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
12:pids:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
11:hugetlb:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
10:net_prio:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
9:perf_event:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
8:net_cls:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
7:freezer:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
6:devices:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
5:memory:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
4:blkio:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
3:cpuacct:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
2:cpu:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb
1:cpuset:/docker-ce/docker/18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb`

	if got, exp := matchDockerCurrentContainerID(cgroup), "18862cabc2e0d24142cf93c46ccb6e070c2ea7b996c81c0311ec0309abcbcdfb"; got != exp {
		t.Fatalf("id mismatch: got %v, exp %v", got, exp)
	}

}
<commit_msg>fix(test): fix GetCurrentContainerID() tests<commit_after>package dockergen

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"testing"
)

func TestGetCurrentContainerID(t *testing.T) {
	hostname := os.Getenv("HOSTNAME")
	defer os.Setenv("HOSTNAME", hostname)

	ids := []string{
		"0fa939e22e6938e7517f663de83e79a5087a18b1b997a36e0c933a917cddb295",
		"e881f8c51a72db7da515e9d5cab8ed105b869579eb9923fdcf4ee80933160802",
		"eede6bd9e72f5d783a4bfb845bd71f310e974cb26987328a5d15704e23a8d6cb",
	}

	contents := map[string]string{
		"cpuset": fmt.Sprintf("/docker/%v", ids[0]),
		"cgroup": fmt.Sprintf(`13:name=systemd:/docker-ce/docker/%[1]v
12:pids:/docker-ce/docker/%[1]v
11:hugetlb:/docker-ce/docker/%[1]v
10:net_prio:/docker-ce/docker/%[1]v
9:perf_event:/docker-ce/docker/%[1]v
8:net_cls:/docker-ce/docker/%[1]v
7:freezer:/docker-ce/docker/%[1]v
6:devices:/docker-ce/docker/%[1]v
5:memory:/docker-ce/docker/%[1]v
4:blkio:/docker-ce/docker/%[1]v
3:cpuacct:/docker-ce/docker/%[1]v
2:cpu:/docker-ce/docker/%[1]v
1:cpuset:/docker-ce/docker/%[1]v`, ids[1]),
		"mountinfo": fmt.Sprintf(`705 661 0:96 / / rw,relatime master:192 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/CVAK3VWZFQCUGTLHRJHPEKJ4UL:/var/lib/docker/overlay2/l/XMJZ73SKVWVECU7TJCOY62F3H2:/var/lib/docker/overlay2/l/AVNBXO52GHDY3MZU3R4RCSNMCE:/var/lib/docker/overlay2/l/L4IJZ33E6NAMXJ5W3SKJSVX5TS:/var/lib/docker/overlay2/l/JXAUAD5TDJCXA34FGS6NYGUZKT:/var/lib/docker/overlay2/l/TBQDSAFKBSTFMUS3QCFWN5NRLB:/var/lib/docker/overlay2/l/MXIUXRGB7MU4Y4NUNZE2VXTXIN:/var/lib/docker/overlay2/l/HN7E4YWJG7TMG7BXLZTGICTBOA:/var/lib/docker/overlay2/l/65XQPC72Z5VRY4THGASZIQXS57:/var/lib/docker/overlay2/l/BVQKC7LU6D7MOSLBDKFHY7YSO3:/var/lib/docker/overlay2/l/R4GGX3SFPMLXTNM3WKMVOKDTOY:/var/lib/docker/overlay2/l/VHGYTU73JLTRCGX45ZF2VGW4FK,upperdir=/var/lib/docker/overlay2/e1fab975d5ffd51474b11a964c82c3bfda1c0e82aec6845a1f12c8150bf61419/diff,workdir=/var/lib/docker/overlay2/e1fab975d5ffd51474b11a964c82c3bfda1c0e82aec6845a1f12c8150bf61419/work,index=off
706 705 0:105 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
707 705 0:106 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
708 707 0:107 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
709 705 0:108 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro
710 709 0:25 / /sys/fs/cgroup ro,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw,nsdelegate,memory_recursiveprot
711 707 0:104 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw
712 707 0:109 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k,inode64
713 705 8:3 /var/lib/docker/containers/%[1]v/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/sda3 rw
714 705 8:3 /var/lib/docker/containers/%[1]v/hostname /etc/hostname rw,relatime - ext4 /dev/sda3 rw
715 705 8:3 /var/lib/docker/containers/%[1]v/hosts /etc/hosts rw,relatime - ext4 /dev/sda3 rw
716 705 8:3 /var/lib/docker/volumes/ca8074e1a2eb12edc86c59c5108bb48c31bb7ace4b90beb0da8137a9baa45812/_data /etc/nginx/certs rw,relatime master:1 - ext4 /dev/sda3 rw
717 705 8:3 /var/lib/docker/volumes/2cf8a52c907469a56f6e2cc7d1959d74a4dd04131e7edcd53eaf909db28f770f/_data /etc/nginx/dhparam rw,relatime master:1 - ext4 /dev/sda3 rw
662 707 0:107 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
663 706 0:105 /bus /proc/bus ro,relatime - proc proc rw
664 706 0:105 /fs /proc/fs ro,relatime - proc proc rw
665 706 0:105 /irq /proc/irq ro,relatime - proc proc rw
666 706 0:105 /sys /proc/sys ro,relatime - proc proc rw
667 706 0:105 /sysrq-trigger /proc/sysrq-trigger ro,relatime - proc proc rw
668 706 0:110 / /proc/acpi ro,relatime - tmpfs tmpfs ro,inode64
669 706 0:106 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
670 706 0:106 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
671 706 0:106 /null /proc/latency_stats rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
672 706 0:106 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
673 706 0:106 /null /proc/sched_debug rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
674 706 0:111 / /proc/scsi ro,relatime - tmpfs tmpfs ro,inode64
675 709 0:112 / /sys/firmware ro,relatime - tmpfs tmpfs ro,inode64`, ids[2]),
	}

	keys := []string{
		"cpuset",
		"cgroup",
		"mountinfo",
	}

	var filepaths []string
	// Create temporary files with test content
	for _, key := range keys {
		file, err := ioutil.TempFile("", key)
		if err != nil {
			log.Fatal(err)
		}
		defer os.Remove(file.Name())
		if _, err = file.WriteString(contents[key]); err != nil {
			log.Fatal(err)
		}
		filepaths = append(filepaths, file.Name())
	}

	// Each time the HOSTNAME is set to a short form ID, GetCurrentContainerID() should match and return the corresponding full ID
	for _, id := range ids {
		os.Setenv("HOSTNAME", id[0:12])
		if got, exp := GetCurrentContainerID(filepaths...), id; got != exp {
			t.Fatalf("id mismatch with HOSTNAME %v: got %v, exp %v", id[0:12], got, exp)
		}
	}

	// If the Hostname isn't a short form ID, we should match the first valid ID (64 character hex string) instead
	os.Setenv("HOSTNAME", "customhostname")
	if got, exp := GetCurrentContainerID(filepaths...), ids[0]; got != exp {
		t.Fatalf("id mismatch with custom HOSTNAME: got %v, exp %v", got, exp)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	"os"
	"path"

	"github.com/MJKWoolnough/byteio"
	"github.com/MJKWoolnough/minecraft"
	"github.com/MJKWoolnough/minecraft/nbt"
	"github.com/MJKWoolnough/ora"
)

func (t Transfer) generate(name string, _ *byteio.StickyReader, w *byteio.StickyWriter, f *os.File, size int64) error {
	o, err := ora.Open(f, size)
	if err != nil {
		return err
	}
	terrain := o.Layer("terrain")
	if terrain == nil {
		return layerError{"terrain"}
	}
	height := o.Layer("height")
	if height == nil {
		return layerError{"height"}
	}
	mp := t.c.NewMap()
	if mp == nil {
		return errors.New("failed to create map")
	}

	done := false
	defer func() {
		if !done {
			t.c.RemoveMap(mp.ID)
		}
		go t.c.Save()
	}()

	mp.Lock()
	mp.Name = name
	mapPath := mp.Path
	mp.Server = -2
	mp.Unlock()

	ms := DefaultMapSettings()
	ms["level-type"] = minecraft.FlatGenerator
	ms["generator-settings"] = "0"
	ms["motd"] = name

	pf, err := os.Create(path.Join(mapPath, "properties.map"))
	if err != nil {
		return err
	}

	if err = ms.WriteTo(pf); err != nil {
		return err
	}
	pf.Close()

	b := o.Bounds()
	w.WriteUint8(2)
	w.WriteInt32(int32(b.Max.X) >> 4)
	w.WriteInt32(int32(b.Max.Y) >> 4)
	c := make(chan paint, 1024)
	m := make(chan string, 4)
	e := make(chan struct{}, 0)
	defer close(e)
	go func() {
		defer close(c)
		defer close(m)
		for {
			select {
			case message := <-m:
				w.WriteUint8(3)
				writeString(w, message)
			case p := <-c:
				w.WriteUint8(4)
				w.WriteInt32(p.X)
				w.WriteInt32(p.Y)
				r, g, b, a := p.RGBA()
				w.WriteUint8(uint8(r >> 8))
				w.WriteUint8(uint8(g >> 8))
				w.WriteUint8(uint8(b >> 8))
				w.WriteUint8(uint8(a >> 8))
			case <-e:
				return
			}
		}
	}()

	sTerrain := image.NewPaletted(o.Bounds(), terrainColours)
	terrainI, err := terrain.Image()
	if err != nil {
		return err
	}
	draw.Draw(sTerrain, image.Rect(terrain.X, terrain.Y, sTerrain.Bounds().Max.X, sTerrain.Bounds().Max.Y), terrainI, image.Point{}, draw.Src)
	terrainI = nil
	sHeight := image.NewGray(o.Bounds())
	heightI, err := height.Image()
	if err != nil {
		return err
	}
	draw.Draw(sHeight, image.Rect(height.X, height.Y, sTerrain.Bounds().Max.X, sTerrain.Bounds().Max.Y), heightI, image.Point{}, draw.Src)
	heightI = nil

	var sBiomes *image.Paletted
	if biomes := o.Layer("biomes"); biomes != nil {
		sBiomes = image.NewPaletted(o.Bounds(), biomePalette)
		biomesI, err := biomes.Image()
		if err != nil {
			return err
		}
		draw.Draw(sBiomes, image.Rect(height.X, height.Y, sBiomes.Bounds().Max.X, sBiomes.Bounds().Max.Y), biomesI, image.Point{}, draw.Src)
	}

	var sWater *image.Gray
	if water := o.Layer("biomes"); water != nil {
		sWater = image.NewGray(o.Bounds())
		waterI, err := water.Image()
		if err != nil {
			return err
		}
		draw.Draw(sWater, image.Rect(height.X, height.Y, sWater.Bounds().Max.X, sWater.Bounds().Max.Y), waterI, image.Point{}, draw.Src)
	}

	p, err := minecraft.NewFilePath(mapPath)
	if err != nil {
		return err
	}

	level, err := minecraft.NewLevel(p)
	if err != nil {
		return err
	}

	level.LevelName(name)

	m <- "Building Terrain"
	if err := buildTerrain(p, level, sTerrain, sBiomes, sHeight, sWater, c); err != nil {
		return err
	}

	level.LevelName(name)
	level.MobSpawning(false)
	level.KeepInventory(true)
	level.FireTick(false)
	level.DayLightCycle(false)
	level.MobGriefing(false)
	level.Spawn(10, 250, 10)
	level.Generator(minecraft.FlatGenerator)
	level.GeneratorOptions("0")
	level.GameMode(minecraft.Creative)
	level.AllowCommands(true)

	m <- "Exporting"
	level.Save()
	level.Close()
	done = true
	mp.Lock()
	mp.Server = -1
	mp.Unlock()

	return nil
}

type paint struct {
	color.Color
	X, Y int32
}

type layerError struct {
	name string
}

func (l layerError) Error() string {
	return "missing layer: " + l.name
}

type terrain struct {
	Base, Top minecraft.Block
	TopLevel  uint8
}

var (
	terrainColours = color.Palette{
		color.RGBA{},
		color.RGBA{255, 255, 0, 255},   // Yellow - Sand
		color.RGBA{0, 255, 0, 255},     // Green - Grass
		color.RGBA{87, 59, 12, 255},    // Brown - Dirt
		color.RGBA{255, 128, 0, 255},   // Orange - Farm
		color.RGBA{128, 128, 128, 255}, // Grey - Stone
		color.RGBA{255, 255, 255, 255}, // White - Snow
	}
	terrainBlocks = []terrain{
		{},
		{minecraft.Block{ID: 24, Data: 2}, minecraft.Block{ID: 12}, 5}, // Sandstone - Sand
		{minecraft.Block{ID: 3}, minecraft.Block{ID: 2}, 1},            // Dirt - Grass
		{minecraft.Block{ID: 3}, minecraft.Block{ID: 3}, 0},            // Dirt - Dirt
		{minecraft.Block{ID: 3}, minecraft.Block{ID: 60, Data: 7}, 1},  // Dirt - Farmland
		{minecraft.Block{ID: 1}, minecraft.Block{ID: 1}, 0},            // Stone - Stone
		{minecraft.Block{ID: 1}, minecraft.Block{ID: 80}, 3},           // Stone - Snow
		{minecraft.Block{ID: 9}, minecraft.Block{ID: 9}, 0},
	}
	biomePalette = color.Palette{}
	biomeList    = []minecraft.Biome{}
)

func modeTerrain(p *image.Paletted) uint8 {
	b := p.Bounds()
	modeMap := make([]uint16, len(terrainColours))
	most := uint16(0)
	mode := uint8(0)
	for i := b.Min.X; i < b.Max.X; i++ {
		for j := b.Min.Y; j < b.Max.Y; j++ {
			pos := p.ColorIndexAt(i, j)
			modeMap[pos]++
			if m := modeMap[pos]; m > most {
				most = m
				mode = pos
			}
		}
	}
	return mode
}

func meanHeight(g *image.Gray) uint8 {
	b := g.Bounds()
	var total int64
	for i := b.Min.X; i < b.Max.X; i++ {
		for j := b.Min.Y; j < b.Max.Y; j++ {
			total += int64(g.GrayAt(i, j).Y)
		}
	}
	return uint8(total / int64((b.Dx() * b.Dy())))
}

type chunkCache struct {
	mem   *minecraft.MemPath
	level *minecraft.Level
	clear nbt.Tag
	cache map[uint16]nbt.Tag
}

func newCache() *chunkCache {
	mem := minecraft.NewMemPath()
	l, _ := minecraft.NewLevel(mem)

	bedrock := minecraft.Block{ID: 7}

	l.SetBlock(0, 0, 0, minecraft.Block{})
	l.Save()
	l.Close()
	clearChunk, _ := mem.GetChunk(0, 0)

	for i := int32(-16); i < 16; i++ {
		for j := int32(0); j < 255; j++ {
			for k := int32(-16); j < 16; j++ {
				l.SetBlock(i, j, k, bedrock)
			}
		}
	}
	l.Save()
	l.Close()
	mem.SetChunk(clearChunk)
	return &chunkCache{
		mem,
		l,
		clearChunk,
		make(map[uint16]nbt.Tag),
	}
}

func (c *chunkCache) getFromCache(x, z int32, terrain uint8, height int32) nbt.Tag {
	cacheID := uint16(terrain)<<8 | uint16(height)
	chunk, ok := c.cache[cacheID]
	if !ok {
		b := terrainBlocks[terrain].Base
		for j := int32(0); j < height; j++ {
			for i := int32(0); i < 16; i++ {
				for k := int32(0); k < 16; k++ {
					c.level.SetBlock(i, j, k, b)
				}
			}
		}
		c.level.Save()
		c.level.Close()
		chunk, _ = c.mem.GetChunk(0, 0)
		c.mem.SetChunk(c.clear)
		c.cache[cacheID] = chunk
	}
	ld := chunk.Data().(nbt.Compound).Get("Level").Data().(nbt.Compound)
	ld.Set(nbt.NewTag("xPos", nbt.Int(x)))
	ld.Set(nbt.NewTag("zPos", nbt.Int(z)))
	return chunk
}

func buildTerrain(mpath minecraft.Path, level *minecraft.Level, terrain, biomes *image.Paletted, height, water *image.Gray, c chan paint) error {
	b := terrain.Bounds()
	proceed := make(chan struct{}, 10)
	errChan := make(chan error, 1)
	go func() {
		defer close(proceed)
		cc := newCache()
		for j := 0; j < b.Max.Y; j += 16 {
			chunkZ := int32(j >> 4)
			for i := 0; i < b.Max.X; i += 16 {
				chunkX := int32(i >> 4)
				p := terrain.SubImage(image.Rect(i, j, i+16, j+16)).(*image.Paletted)
				g := height.SubImage(image.Rect(i, j, i+16, j+16)).(*image.Gray)
				w := water.SubImage(image.Rect(i, j, i+16, j+16)).(*image.Gray)
				h := int32(meanHeight(g))
				wh := int32(meanHeight(w))
				var t uint8
				if wh >= h<<1 { // more water than land...
					c <- paint{
						color.RGBA{0, 0, 255, 255},
						chunkX, chunkZ,
					}
					t = uint8(len(terrainBlocks) - 1)
				} else {
					t = modeTerrain(p)
					c <- paint{
						terrainColours[t],
						chunkX, chunkZ,
					}
				}
				if err := mpath.SetChunk(cc.getFromCache(chunkX, chunkZ, t, h)); err != nil {
					errChan <- err
					return
				}
				proceed <- struct{}{}
			}
		}
	}()
	ts := make([]uint8, 0, 1024)
	for i := 0; i < (b.Max.X>>4)+2; i++ {
		ts = append(ts, <-proceed) // get far enough ahead so all chunks are surrounded before shaping, to get correct lighting
	}
	select {
	case err := <-errChan:
		return err
	default:
	}
	for j := int32(0); j < int32(b.Max.Y); j += 16 {
		chunkZ := j >> 4
		for i := int32(0); i < int32(b.Max.X); i += 16 {
			chunkX := i >> 4
			var totalHeight int32
			ot := ts[0]
			ts = ts[1:]
			for x := i; x < i+16; x++ {
				for z := j; z < j+16; z++ {
					if biomes != nil {
						level.SetBiome(x, z, biomeList[biomePalette.ColorIndexAt(int(x), int(z))])
					}
					h := int32(height.GrayAt(int(x), int(z)).Y)
					totalHeight += h
					y, _ := level.GetHeight(x, z)
					wl := int32(water.GrayAt(int(x), int(z)).Y)
					for ; y > h && y > wl; y-- {
						level.SetBlock(x, y, z, minecraft.Block{})
					}
					for ; y > h; y-- {
						level.SetBlock(x, y, z, minecraft.Block{ID: 9})
					}
					t := terrainBlocks[terrain.ColorIndexAt(int(x), int(z))]
					for ; y > h-int32(t.TopLevel); y-- {
						level.SetBlock(x, y, z, t.Top)
					}
					if t != ot {
						for ; y >= 0; y-- {
							level.SetBlock(x, y, z, t.Base)
						}
					}
				}
			}
			c <- paint{
				color.Alpha{uint8(totalHeight >> 8)},
				chunkX, chunkZ,
			}
			select {
			case p, ok := <-proceed:
				if ok {
					ts = append(ts, p)
				}
			case err := <-errChan:
				return err
			}
		}
	}
	return nil
}
<commit_msg>Corrected compile errors<commit_after>package main

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	"os"
	"path"

	"github.com/MJKWoolnough/byteio"
	"github.com/MJKWoolnough/minecraft"
	"github.com/MJKWoolnough/minecraft/nbt"
	"github.com/MJKWoolnough/ora"
)

func (t Transfer) generate(name string, _ *byteio.StickyReader, w *byteio.StickyWriter, f *os.File, size int64) error {
	o, err := ora.Open(f, size)
	if err != nil {
		return err
	}
	terrain := o.Layer("terrain")
	if terrain == nil {
		return layerError{"terrain"}
	}
	height := o.Layer("height")
	if height == nil {
		return layerError{"height"}
	}
	mp := t.c.NewMap()
	if mp == nil {
		return errors.New("failed to create map")
	}

	done := false
	defer func() {
		if !done {
			t.c.RemoveMap(mp.ID)
		}
		go t.c.Save()
	}()

	mp.Lock()
	mp.Name = name
	mapPath := mp.Path
	mp.Server = -2
	mp.Unlock()

	ms := DefaultMapSettings()
	ms["level-type"] = minecraft.FlatGenerator
	ms["generator-settings"] = "0"
	ms["motd"] = name

	pf, err := os.Create(path.Join(mapPath, "properties.map"))
	if err != nil {
		return err
	}

	if err = ms.WriteTo(pf); err != nil {
		return err
	}
	pf.Close()

	b := o.Bounds()
	w.WriteUint8(2)
	w.WriteInt32(int32(b.Max.X) >> 4)
	w.WriteInt32(int32(b.Max.Y) >> 4)
	c := make(chan paint, 1024)
	m := make(chan string, 4)
	e := make(chan struct{}, 0)
	defer close(e)
	go func() {
		defer close(c)
		defer close(m)
		for {
			select {
			case message := <-m:
				w.WriteUint8(3)
				writeString(w, message)
			case p := <-c:
				w.WriteUint8(4)
				w.WriteInt32(p.X)
				w.WriteInt32(p.Y)
				r, g, b, a := p.RGBA()
				w.WriteUint8(uint8(r >> 8))
				w.WriteUint8(uint8(g >> 8))
				w.WriteUint8(uint8(b >> 8))
				w.WriteUint8(uint8(a >> 8))
			case <-e:
				return
			}
		}
	}()

	sTerrain := image.NewPaletted(o.Bounds(), terrainColours)
	terrainI, err := terrain.Image()
	if err != nil {
		return err
	}
	draw.Draw(sTerrain, image.Rect(terrain.X, terrain.Y, sTerrain.Bounds().Max.X, sTerrain.Bounds().Max.Y), terrainI, image.Point{}, draw.Src)
	terrainI = nil
	sHeight := image.NewGray(o.Bounds())
	heightI, err := height.Image()
	if err != nil {
		return err
	}
	draw.Draw(sHeight, image.Rect(height.X, height.Y, sTerrain.Bounds().Max.X, sTerrain.Bounds().Max.Y), heightI, image.Point{}, draw.Src)
	heightI = nil

	var sBiomes *image.Paletted
	if biomes := o.Layer("biomes"); biomes != nil {
		sBiomes = image.NewPaletted(o.Bounds(), biomePalette)
		biomesI, err := biomes.Image()
		if err != nil {
			return err
		}
		draw.Draw(sBiomes, image.Rect(height.X, height.Y, sBiomes.Bounds().Max.X, sBiomes.Bounds().Max.Y), biomesI, image.Point{}, draw.Src)
	}

	var sWater *image.Gray
	if water := o.Layer("biomes"); water != nil {
		sWater = image.NewGray(o.Bounds())
		waterI, err := water.Image()
		if err != nil {
			return err
		}
		draw.Draw(sWater, image.Rect(height.X, height.Y, sWater.Bounds().Max.X, sWater.Bounds().Max.Y), waterI, image.Point{}, draw.Src)
	}

	p, err := minecraft.NewFilePath(mapPath)
	if err != nil {
		return err
	}

	level, err := minecraft.NewLevel(p)
	if err != nil {
		return err
	}

	level.LevelName(name)

	m <- "Building Terrain"
	if err := buildTerrain(p, level, sTerrain, sBiomes, sHeight, sWater, c); err != nil {
		return err
	}

	level.LevelName(name)
	level.MobSpawning(false)
	level.KeepInventory(true)
	level.FireTick(false)
	level.DayLightCycle(false)
	level.MobGriefing(false)
	level.Spawn(10, 250, 10)
	level.Generator(minecraft.FlatGenerator)
	level.GeneratorOptions("0")
	level.GameMode(minecraft.Creative)
	level.AllowCommands(true)

	m <- "Exporting"
	level.Save()
	level.Close()
	done = true
	mp.Lock()
	mp.Server = -1
	mp.Unlock()

	return nil
}

type paint struct {
	color.Color
	X, Y int32
}

type layerError struct {
	name string
}

func (l layerError) Error() string {
	return "missing layer: " + l.name
}

type terrain struct {
	Base, Top minecraft.Block
	TopLevel  uint8
}

var (
	terrainColours = color.Palette{
		color.RGBA{},
		color.RGBA{255, 255, 0, 255},   // Yellow - Sand
		color.RGBA{0, 255, 0, 255},     // Green - Grass
		color.RGBA{87, 59, 12, 255},    // Brown - Dirt
		color.RGBA{255, 128, 0, 255},   // Orange - Farm
		color.RGBA{128, 128, 128, 255}, // Grey - Stone
		color.RGBA{255, 255, 255, 255}, // White - Snow
	}
	terrainBlocks = []terrain{
		{},
		{minecraft.Block{ID: 24, Data: 2}, minecraft.Block{ID: 12}, 5}, // Sandstone - Sand
		{minecraft.Block{ID: 3}, minecraft.Block{ID: 2}, 1},            // Dirt - Grass
		{minecraft.Block{ID: 3}, minecraft.Block{ID: 3}, 0},            // Dirt - Dirt
		{minecraft.Block{ID: 3}, minecraft.Block{ID: 60, Data: 7}, 1},  // Dirt - Farmland
		{minecraft.Block{ID: 1}, minecraft.Block{ID: 1}, 0},            // Stone - Stone
		{minecraft.Block{ID: 1}, minecraft.Block{ID: 80}, 3},           // Stone - Snow
		{minecraft.Block{ID: 9}, minecraft.Block{ID: 9}, 0},
	}
	biomePalette = color.Palette{}
	biomeList    = []minecraft.Biome{}
)

func modeTerrain(p *image.Paletted) uint8 {
	b := p.Bounds()
	modeMap := make([]uint16, len(terrainColours))
	most := uint16(0)
	mode := uint8(0)
	for i := b.Min.X; i < b.Max.X; i++ {
		for j := b.Min.Y; j < b.Max.Y; j++ {
			pos := p.ColorIndexAt(i, j)
			modeMap[pos]++
			if m := modeMap[pos]; m > most {
				most = m
				mode = pos
			}
		}
	}
	return mode
}

func meanHeight(g *image.Gray) uint8 {
	b := g.Bounds()
	var total int64
	for i := b.Min.X; i < b.Max.X; i++ {
		for j := b.Min.Y; j < b.Max.Y; j++ {
			total += int64(g.GrayAt(i, j).Y)
		}
	}
	return uint8(total / int64((b.Dx() * b.Dy())))
}

type chunkCache struct {
	mem   *minecraft.MemPath
	level *minecraft.Level
	clear nbt.Tag
	cache map[uint16]nbt.Tag
}

func newCache() *chunkCache {
	mem := minecraft.NewMemPath()
	l, _ := minecraft.NewLevel(mem)

	bedrock := minecraft.Block{ID: 7}

	l.SetBlock(0, 0, 0, minecraft.Block{})
	l.Save()
	l.Close()
	clearChunk, _ := mem.GetChunk(0, 0)

	for i := int32(-16); i < 16; i++ {
		for j := int32(0); j < 255; j++ {
			for k := int32(-16); j < 16; j++ {
				l.SetBlock(i, j, k, bedrock)
			}
		}
	}
	l.Save()
	l.Close()
	mem.SetChunk(clearChunk)
	return &chunkCache{
		mem,
		l,
		clearChunk,
		make(map[uint16]nbt.Tag),
	}
}

func (c *chunkCache) getFromCache(x, z int32, terrain uint8, height int32) nbt.Tag {
	cacheID := uint16(terrain)<<8 | uint16(height)
	chunk, ok := c.cache[cacheID]
	if !ok {
		b := terrainBlocks[terrain].Base
		for j := int32(0); j < height; j++ {
			for i := int32(0); i < 16; i++ {
				for k := int32(0); k < 16; k++ {
					c.level.SetBlock(i, j, k, b)
				}
			}
		}
		c.level.Save()
		c.level.Close()
		chunk, _ = c.mem.GetChunk(0, 0)
		c.mem.SetChunk(c.clear)
		c.cache[cacheID] = chunk
	}
	ld := chunk.Data().(nbt.Compound).Get("Level").Data().(nbt.Compound)
	ld.Set(nbt.NewTag("xPos", nbt.Int(x)))
	ld.Set(nbt.NewTag("zPos", nbt.Int(z)))
	return chunk
}

func buildTerrain(mpath minecraft.Path, level *minecraft.Level, terrain, biomes *image.Paletted, height, water *image.Gray, c chan paint) error {
	b := terrain.Bounds()
	proceed := make(chan uint8, 10)
	errChan := make(chan error, 1)
	go func() {
		defer close(proceed)
		cc := newCache()
		for j := 0; j < b.Max.Y; j += 16 {
			chunkZ := int32(j >> 4)
			for i := 0; i < b.Max.X; i += 16 {
				chunkX := int32(i >> 4)
				p := terrain.SubImage(image.Rect(i, j, i+16, j+16)).(*image.Paletted)
				g := height.SubImage(image.Rect(i, j, i+16, j+16)).(*image.Gray)
				w := water.SubImage(image.Rect(i, j, i+16, j+16)).(*image.Gray)
				h := int32(meanHeight(g))
				wh := int32(meanHeight(w))
				var t uint8
				if wh >= h<<1 { // more water than land...
					c <- paint{
						color.RGBA{0, 0, 255, 255},
						chunkX, chunkZ,
					}
					t = uint8(len(terrainBlocks) - 1)
				} else {
					t = modeTerrain(p)
					c <- paint{
						terrainColours[t],
						chunkX, chunkZ,
					}
				}
				if err := mpath.SetChunk(cc.getFromCache(chunkX, chunkZ, t, h)); err != nil {
					errChan <- err
					return
				}
				proceed <- t
			}
		}
	}()
	ts := make([]uint8, 0, 1024)
	for i := 0; i < (b.Max.X>>4)+2; i++ {
		ts = append(ts, <-proceed) // get far enough ahead so all chunks are surrounded before shaping, to get correct lighting
	}
	select {
	case err := <-errChan:
		return err
	default:
	}
	for j := int32(0); j < int32(b.Max.Y); j += 16 {
		chunkZ := j >> 4
		for i := int32(0); i < int32(b.Max.X); i += 16 {
			chunkX := i >> 4
			var totalHeight int32
			ot := ts[0]
			ts = ts[1:]
			for x := i; x < i+16; x++ {
				for z := j; z < j+16; z++ {
					if biomes != nil {
						level.SetBiome(x, z, biomeList[biomes.ColorIndexAt(int(x), int(z))])
					}
					h := int32(height.GrayAt(int(x), int(z)).Y)
					totalHeight += h
					y, _ := level.GetHeight(x, z)
					wl := int32(water.GrayAt(int(x), int(z)).Y)
					for ; y > h && y > wl; y-- {
						level.SetBlock(x, y, z, minecraft.Block{})
					}
					for ; y > h; y-- {
						level.SetBlock(x, y, z, minecraft.Block{ID: 9})
					}
					t := terrain.ColorIndexAt(int(x), int(z))
					tb := terrainBlocks[t]
					for ; y > h-int32(tb.TopLevel); y-- {
						level.SetBlock(x, y, z, tb.Top)
					}
					if t != ot {
						for ; y >= 0; y-- {
							level.SetBlock(x, y, z, tb.Base)
						}
					}
				}
			}
			c <- paint{
				color.Alpha{uint8(totalHeight >> 8)},
				chunkX, chunkZ,
			}
			select {
			case p, ok := <-proceed:
				if ok {
					ts = append(ts, p)
				}
			case err := <-errChan:
				return err
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package transport

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/LUSHDigital/microservice-core-golang/transport/config"
	"github.com/LUSHDigital/microservice-core-golang/transport/domain"
)

// Resource - Useful for defining a remote resource without an attached transport.
type Resource struct {
	Branch      string // VCS branch the service is built from.
	Environment string // CI environment the service operates in.
	Namespace   string // Namespace of the service.
	Name        string // Name of the service.
	Version     int    // Major API version of the service.
}

// DNSPath returns internal dns path for the resource
func (r *Resource) DNSPath() string {
	// Make any alterations based upon the namespace.
	switch r.Namespace {
	case "aggregators":
		if !strings.HasPrefix(r.Name, config.AggregatorDomainPrefix) {
			r.Name = strings.Join([]string{config.AggregatorDomainPrefix, r.Name}, "-")
		}
	}
	// Determine the service namespace to use based on the service version.
	serviceNamespace := r.Name
	if r.Version != 0 {
		serviceNamespace = fmt.Sprintf("%s-%d", serviceNamespace, r.Version)
	}
	return serviceNamespace
}

// Service - Responsible for communication with a service.
type Service struct {
	Resource
	CurrentRequest *http.Request // Current HTTP request being actioned.
	Client         *http.Client  // http client implementation
}

// NewService - prepares a new service with the provided parameters and client.
func NewService(client *http.Client, branch, env, namespace, name string) *Service {
	return &Service{
		Resource: Resource{
			Branch:      branch,
			Name:        name,
			Environment: env,
			Namespace:   namespace,
		},
		Client: client,
	}
}

// Call - Do the current service request.
func (s *Service) Call() (*http.Response, error) {
	return s.Client.Do(s.CurrentRequest)
}

// Dial - Create a request to a service resource.
func (s *Service) Dial(request *Request) error {
	var err error

	serviceNamespace := s.DNSPath()
	// Get the name of the service.
	dnsName := domain.BuildServiceDNSName(s.Name, s.Branch, s.Environment, serviceNamespace)

	// Build the resource URL.
	resourceURL := fmt.Sprintf("%s://%s/%s", request.getProtocol(), dnsName, request.Resource)

	// Append the query string if we have any.
	if len(request.Query) > 0 {
		resourceURL = fmt.Sprintf("%s?%s", resourceURL, request.Query.Encode())
	}

	// Create the request.
	s.CurrentRequest, err = http.NewRequest(request.Method, resourceURL, request.Body)

	// Add the headers.
	for key, value := range request.Headers {
		s.CurrentRequest.Header.Set(key, value)
	}

	return err
}

// GetName - Get the name of the service
func (s *Service) GetName() string {
	return s.Name
}
<commit_msg>feat: add a complete domain name function to resource<commit_after>package transport

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/LUSHDigital/microservice-core-golang/transport/config"
)

// NewResource returns a new service
func NewResource(branch, env, namespace, name string) *Resource {
	// Make any alterations based upon the namespace
	switch namespace {
	case "aggregators":
		if !strings.HasPrefix(name, config.AggregatorDomainPrefix) {
			name = strings.Join([]string{config.AggregatorDomainPrefix, name}, "-")
		}
	}
	return &Resource{
		Branch:      branch,
		Name:        name,
		Environment: env,
		Namespace:   namespace,
	}
}

// Resource defines a remote service
type Resource struct {
	Branch      string // VCS branch the service is built from.
	Environment string // CI environment the service operates in.
	Namespace   string // Namespace of the service.
	Name        string // Name of the service.
	Version     int    // Major API version of the service.
}

// DomainName returns the resource domain name for the internal DNS
func (s *Service) DomainName() string {
	name := s.Name
	// Determine the service namespace to use based on the service version
	if s.Version != 0 {
		name = fmt.Sprintf("%s-%d", name, s.Version)
	}
	return fmt.Sprintf("%s-%s-%s.%s", s.Name, s.Branch, s.Environment, name)
}

// Service - Responsible for communication with a service.
type Service struct {
	Resource
	CurrentRequest *http.Request // Current HTTP request being actioned.
	Client         *http.Client  // http client implementation
}

// NewService - prepares a new service with the provided parameters and client.
func NewService(client *http.Client, branch, env, namespace, name string) *Service {
	return &Service{
		Resource: *NewResource(branch, env, namespace, name),
		Client:   client,
	}
}

// Call - Do the current service request.
func (s *Service) Call() (*http.Response, error) {
	return s.Client.Do(s.CurrentRequest)
}

// Dial - Create a request to a service resource.
func (s *Service) Dial(request *Request) error {
	var err error

	// Build the resource URL.
	resourceURL := fmt.Sprintf("%s://%s/%s", request.getProtocol(), s.DomainName(), request.Resource)

	// Append the query string if we have any.
	if len(request.Query) > 0 {
		resourceURL = fmt.Sprintf("%s?%s", resourceURL, request.Query.Encode())
	}

	// Create the request.
	s.CurrentRequest, err = http.NewRequest(request.Method, resourceURL, request.Body)

	// Add the headers.
	for key, value := range request.Headers {
		s.CurrentRequest.Header.Set(key, value)
	}

	return err
}

// GetName - Get the name of the service
func (s *Service) GetName() string {
	return s.Name
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/russross/blackfriday"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"time"
)

func setup(cacheDir string, src string, srcF os.FileInfo, err error) error {
	if strings.HasPrefix(srcF.Name(), ".") {
		return nil
	}

	dst := cacheDir + src
	if strings.HasSuffix(dst, ".md") {
		dst = strings.TrimSuffix(dst, ".md") + ".html"
	}
	dstF, dstE := os.Stat(dst)

	// if up to date, skip
	if !os.IsNotExist(dstE) &&
		(srcF.IsDir() || dstF.ModTime().After(srcF.ModTime())) {
		return nil
	}

	// copy to cache
	if os.IsNotExist(dstE) {
		log.Println("Copying", srcF.Name())
	} else {
		log.Println("Updating", srcF.Name())
	}

	if srcF.IsDir() {
		if err := os.MkdirAll(dst, srcF.Mode()); err != nil {
			return err
		}
		return nil
	}

	sbuf, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}
	dbuf := sbuf
	if strings.HasSuffix(src, ".md") {
		dbuf = blackfriday.MarkdownCommon(sbuf)
	}
	if err := ioutil.WriteFile(dst, dbuf, srcF.Mode()); err != nil {
		return err
	}

	return nil
}

func main() {
	tempDir, _ := ioutil.TempDir("", "tut")
	tempDir += string(os.PathSeparator)
	defer os.RemoveAll(tempDir)
	log.Println("Workdir", tempDir)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		os.RemoveAll(tempDir)
		log.Fatalln("Stopped")
	}()

	walker := func(src string, f os.FileInfo, err error) error {
		return setup(tempDir, src, f, err)
	}

	if err := filepath.Walk("./content/", walker); err != nil {
		log.Fatalln("Filewalk", err)
	}

	log.Println("Running at http:///localhost:8000/")

	go func() {
		for {
			filepath.Walk("./content/", walker)
			time.Sleep(2 * time.Second)
		}
	}()

	http.Handle("/", http.RedirectHandler("/tutorial/tutorial.html", 302))

	url, _ := url.Parse("http://localhost:8093")
	rp := httputil.NewSingleHostReverseProxy(url)
	http.Handle("/query", rp)

	fs := http.FileServer(http.Dir(tempDir + "/content/"))
	http.Handle("/tutorial/", http.StripPrefix("/tutorial/", fs))

	if err := http.ListenAndServe(":8000", nil); err != nil {
		log.Fatalln("ListenAndServe", err)
	}
}
<commit_msg>Navigate to first page on redirect<commit_after>package main

import (
	"github.com/russross/blackfriday"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"time"
)

func setup(cacheDir string, src string, srcF os.FileInfo, err error) error {
	if strings.HasPrefix(srcF.Name(), ".") {
		return nil
	}

	dst := cacheDir + src
	if strings.HasSuffix(dst, ".md") {
		dst = strings.TrimSuffix(dst, ".md") + ".html"
	}
	dstF, dstE := os.Stat(dst)

	// if up to date, skip
	if !os.IsNotExist(dstE) &&
		(srcF.IsDir() || dstF.ModTime().After(srcF.ModTime())) {
		return nil
	}

	// copy to cache
	if os.IsNotExist(dstE) {
		log.Println("Copying", srcF.Name())
	} else {
		log.Println("Updating", srcF.Name())
	}

	if srcF.IsDir() {
		if err := os.MkdirAll(dst, srcF.Mode()); err != nil {
			return err
		}
		return nil
	}

	sbuf, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}
	dbuf := sbuf
	if strings.HasSuffix(src, ".md") {
		dbuf = blackfriday.MarkdownCommon(sbuf)
	}
	if err := ioutil.WriteFile(dst, dbuf, srcF.Mode()); err != nil {
		return err
	}

	return nil
}

func main() {
	tempDir, _ := ioutil.TempDir("", "tut")
	tempDir += string(os.PathSeparator)
	defer os.RemoveAll(tempDir)
	log.Println("Workdir", tempDir)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		os.RemoveAll(tempDir)
		log.Fatalln("Stopped")
	}()

	walker := func(src string, f os.FileInfo, err error) error {
		return setup(tempDir, src, f, err)
	}

	if err := filepath.Walk("./content/", walker); err != nil {
		log.Fatalln("Filewalk", err)
	}

	log.Println("Running at http:///localhost:8000/")

	go func() {
		for {
			filepath.Walk("./content/", walker)
			time.Sleep(2 * time.Second)
		}
	}()

	http.Handle("/", http.RedirectHandler("/tutorial/tutorial.html#1", 302))

	url, _ := url.Parse("http://localhost:8093")
	rp := httputil.NewSingleHostReverseProxy(url)
	http.Handle("/query", rp)

	fs := http.FileServer(http.Dir(tempDir + "/content/"))
	http.Handle("/tutorial/", http.StripPrefix("/tutorial/", fs))

	if err := http.ListenAndServe(":8000", nil); err != nil {
		log.Fatalln("ListenAndServe", err)
	}
}
<|endoftext|>


<commit_before>package convey

import (
	"fmt"
	"strings"

	"github.com/smartystreets/goconvey/convey/reporting"
)

type scope struct {
	name       string
	title      string
	action     *action
	children   map[string]*scope
	birthOrder []*scope
	child      int
	resets     map[string]*action
	panicked   bool
	reporter   reporting.Reporter
	report     *reporting.ScopeReport
}

func (parent *scope) adopt(child *scope) {
	if parent.hasChild(child) {
		return
	}
	parent.birthOrder = append(parent.birthOrder, child)
	parent.children[child.name] = child
}
func (parent *scope) hasChild(child *scope) bool {
	for _, ordered := range parent.birthOrder {
		if ordered.name == child.name && ordered.title == child.title {
			return true
		}
	}
	return false
}

func (self *scope) registerReset(action *action) {
	self.resets[action.name] = action
}

func (self *scope) visited() bool {
	return self.panicked || self.child >= len(self.birthOrder)
}

func (parent *scope) visit() {
	defer parent.exit()
	parent.enter()
	parent.action.Invoke()
	parent.visitChildren()
}
func (parent *scope) enter() {
	parent.reporter.Enter(parent.report)
}
func (parent *scope) visitChildren() {
	if len(parent.birthOrder) == 0 {
		parent.cleanup()
	} else {
		parent.visitChild()
	}
}
func (parent *scope) visitChild() {
	child := parent.birthOrder[parent.child]
	child.visit()
	if child.visited() {
		parent.cleanup()
		parent.child++
	}
}
func (parent *scope) cleanup() {
	for _, reset := range parent.resets {
		reset.Invoke()
	}
}
func (parent *scope) exit() {
	if problem := recover(); problem != nil {
		if strings.HasPrefix(fmt.Sprintf("%v", problem), extraGoTest) {
			panic(problem)
		}
		if problem != failureHalt {
			parent.panicked = true
			parent.reporter.Report(reporting.NewErrorReport(problem))
		}
	}
	parent.reporter.Exit()
}

func newScope(entry *registration, reporter reporting.Reporter) *scope {
	self := new(scope)
	self.reporter = reporter
	self.name = entry.action.name
	self.title = entry.Situation
	self.action = entry.action
	self.children = make(map[string]*scope)
	self.birthOrder = []*scope{}
	self.resets = make(map[string]*action)
	self.report = reporting.NewScopeReport(self.title, self.name)
	return self
}
<commit_msg>fix #197<commit_after>package convey

import (
	"fmt"
	"strings"

	"github.com/smartystreets/goconvey/convey/reporting"
)

type scope struct {
	name       string
	title      string
	action     *action
	children   map[string]*scope
	birthOrder []*scope
	child      int
	resets     map[string]*action
	panicked   bool
	reporter   reporting.Reporter
	report     *reporting.ScopeReport
}

func (parent *scope) adopt(child *scope) {
	if parent.hasChild(child) {
		return
	}
	parent.birthOrder = append(parent.birthOrder, child)
	parent.children[child.name] = child
}
func (parent *scope) hasChild(child *scope) bool {
	for _, ordered := range parent.birthOrder {
		if ordered.name == child.name && ordered.title == child.title {
			return true
		}
	}
	return false
}

func (self *scope) registerReset(action *action) {
	self.resets[action.name] = action
}

func (self *scope) visited() bool {
	return self.panicked || self.child >= len(self.birthOrder)
}

func (parent *scope) visit() {
	defer parent.exit()
	parent.enter()
	parent.action.Invoke()
	parent.visitChildren()
}
func (parent *scope) enter() {
	parent.reporter.Enter(parent.report)
}
func (parent *scope) visitChildren() {
	if len(parent.birthOrder) == 0 {
		parent.cleanup()
	} else {
		parent.visitChild()
	}
}
func (parent *scope) visitChild() {
	child := parent.birthOrder[parent.child]
	child.visit()
	if child.visited() {
		parent.cleanup()
		parent.child++
	}
}
func (parent *scope) cleanup() {
	for _, reset := range parent.resets {
		reset.Invoke()
	}
}
func (parent *scope) exit() {
	if problem := recover(); problem != nil {
		if strings.HasPrefix(fmt.Sprintf("%v", problem), extraGoTest) {
			panic(problem)
		}
		if problem != failureHalt {
			parent.reporter.Report(reporting.NewErrorReport(problem))
		}
		parent.panicked = true
	}
	parent.reporter.Exit()
}

func newScope(entry *registration, reporter reporting.Reporter) *scope {
	self := new(scope)
	self.reporter = reporter
	self.name = entry.action.name
	self.title = entry.Situation
	self.action = entry.action
	self.children = make(map[string]*scope)
	self.birthOrder = []*scope{}
	self.resets = make(map[string]*action)
	self.report = reporting.NewScopeReport(self.title, self.name)
	return self
}
<|endoftext|>