<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pubsub

import (
	"io"
	"sync"
	"time"

	"golang.org/x/net/context"
)

// TODO(mcgreevy): make this more dynamic.
const batchPullSize = 100

type Iterator struct {
	// The name of the subscription that the Iterator is pulling messages from.
	sub string
	// The context to use for acking messages and extending message deadlines.
	ctx context.Context

	c *Client

	// Controls how often we send an ack deadline extension request.
	kaTicker *time.Ticker
	// Controls how often we acknowledge a batch of messages.
	ackTicker *time.Ticker

	ka     keepAlive
	acker  acker
	puller puller

	mu     sync.Mutex
	closed bool
}

// newIterator starts a new Iterator.  Close must be called on the Iterator
// when it is no longer needed.
// subName is the full name of the subscription to pull messages from.
// ackDeadline is the default ack deadline for the subscription
// maxExtension is the maximum period for which the iterator should automatically extend
// the ack deadline for each message.
func (c *Client) newIterator(ctx context.Context, subName string, ackDeadline, maxExtension time.Duration) *Iterator {
	it := &Iterator{
		sub: subName,
		ctx: ctx,
		c:   c,
	}

	// TODO: make kaTicker frequency more configurable.
	// (ackDeadline - 5s) is a reasonable default for now, because the minimum ack period is 10s.  This gives us 5s grace.
	keepAlivePeriod := ackDeadline - 5*time.Second
	it.kaTicker = time.NewTicker(keepAlivePeriod) // Stopped in it.Close
	it.ka = keepAlive{
		Client:        it.c,
		Ctx:           it.ctx,
		Sub:           it.sub,
		ExtensionTick: it.kaTicker.C,
		Deadline:      ackDeadline,
		MaxExtension:  maxExtension,
	}

	// TODO: make ackTicker more configurable.  Something less than
	// kaTicker is a reasonable default (there's no point extending
	// messages when they could be acked instead).
	it.ackTicker = time.NewTicker(keepAlivePeriod / 2) // Stopped in it.Close
	it.acker = acker{
		Client:  it.c,
		Ctx:     it.ctx,
		Sub:     it.sub,
		AckTick: it.ackTicker.C,
		Notify:  it.ka.Remove,
	}

	it.puller = puller{
		Client:    it.c,
		Sub:       it.sub,
		BatchSize: batchPullSize,
		Notify:    it.ka.Add,
	}

	it.ka.Start()
	it.acker.Start()
	return it
}

// Next returns the next Message to be processed.  The caller must call Done on
// the returned Message once it is finished with it.
// Once Close has been called, subsequent calls to Next will return io.EOF.
func (it *Iterator) Next(ctx context.Context) (*Message, error) {
	// TODO: decide whether to use it.ctx instead of ctx.
	it.mu.Lock()
	defer it.mu.Unlock()
	if it.closed {
		return nil, io.EOF
	}

	// Note: this is the only place where messages are added to keepAlive,
	// and this code is protected by mu. This means once an iterator starts
	// being closed down, no more messages will be added to keepalive.
	m, err := it.puller.Next(ctx)
	if err != nil {
		return nil, err
	}
	m.it = it
	return m, nil
}

// Client code must call Close on an Iterator when finished with it.
// Close will block until Done has been called on all Messages that have been
// returned by Next.
// Close need only be called once, but may be called multiple times from multiple goroutines.
func (it *Iterator) Close() error {
	// TODO: test calling from multiple goroutines.
	it.mu.Lock()
	defer it.mu.Unlock()
	if it.closed {
		return nil
	}
	it.closed = true

	// Remove messages that are being kept alive, but have not been
	// supplied to the caller yet.  Then the only messages being kept alive
	// will be those that have been supplied to the caller but have not yet
	// had their Done method called.
	for _, m := range it.puller.Pending() {
		it.ka.Remove(m.AckID)
	}

	// This will block until all messages have been removed from keepAlive.
	// This will happen once all outstanding messages have been either
	// ACKed or NACKed.
	it.ka.Stop()

	it.acker.Stop()

	it.kaTicker.Stop()
	it.ackTicker.Stop()
	return nil
}

func (it *Iterator) done(ackID string, ack bool) {
	// NOTE: this method does not lock mu, because it's fine for done to be
	// called while the iterator is in the process of being closed.  In
	// fact, this is the only way to drain oustanding messages.
	if ack {
		it.acker.Ack(ackID)
		// There's no need to call it.ka.Remove here, as acker will
		// call it via its Notify function.
	} else {
		it.ka.Remove(ackID)
	}
}
<commit_msg>pubsub: check for context cancellation in Iterator.Next.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pubsub

import (
	"io"
	"sync"
	"time"

	"golang.org/x/net/context"
)

// TODO(mcgreevy): make this more dynamic.
const batchPullSize = 100

type Iterator struct {
	// The name of the subscription that the Iterator is pulling messages from.
	sub string
	// The context to use for acking messages and extending message deadlines.
	ctx context.Context

	c *Client

	// Controls how often we send an ack deadline extension request.
	kaTicker *time.Ticker
	// Controls how often we acknowledge a batch of messages.
	ackTicker *time.Ticker

	ka     keepAlive
	acker  acker
	puller puller

	mu     sync.Mutex
	closed bool
}

// newIterator starts a new Iterator.  Close must be called on the Iterator
// when it is no longer needed.
// subName is the full name of the subscription to pull messages from.
// ackDeadline is the default ack deadline for the subscription
// maxExtension is the maximum period for which the iterator should automatically extend
// the ack deadline for each message.
func (c *Client) newIterator(ctx context.Context, subName string, ackDeadline, maxExtension time.Duration) *Iterator {
	it := &Iterator{
		sub: subName,
		ctx: ctx,
		c:   c,
	}

	// TODO: make kaTicker frequency more configurable.
	// (ackDeadline - 5s) is a reasonable default for now, because the minimum ack period is 10s.  This gives us 5s grace.
	keepAlivePeriod := ackDeadline - 5*time.Second
	it.kaTicker = time.NewTicker(keepAlivePeriod) // Stopped in it.Close
	it.ka = keepAlive{
		Client:        it.c,
		Ctx:           it.ctx,
		Sub:           it.sub,
		ExtensionTick: it.kaTicker.C,
		Deadline:      ackDeadline,
		MaxExtension:  maxExtension,
	}

	// TODO: make ackTicker more configurable.  Something less than
	// kaTicker is a reasonable default (there's no point extending
	// messages when they could be acked instead).
	it.ackTicker = time.NewTicker(keepAlivePeriod / 2) // Stopped in it.Close
	it.acker = acker{
		Client:  it.c,
		Ctx:     it.ctx,
		Sub:     it.sub,
		AckTick: it.ackTicker.C,
		Notify:  it.ka.Remove,
	}

	it.puller = puller{
		Client:    it.c,
		Sub:       it.sub,
		BatchSize: batchPullSize,
		Notify:    it.ka.Add,
	}

	it.ka.Start()
	it.acker.Start()
	return it
}

// Next returns the next Message to be processed.  The caller must call Done on
// the returned Message once it is finished with it.
// Once Close has been called, subsequent calls to Next will return io.EOF.
func (it *Iterator) Next(ctx context.Context) (*Message, error) {
	// TODO: decide whether to use it.ctx instead of ctx.
	it.mu.Lock()
	defer it.mu.Unlock()
	if it.closed {
		return nil, io.EOF
	}

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	// Note: this is the only place where messages are added to keepAlive,
	// and this code is protected by mu. This means once an iterator starts
	// being closed down, no more messages will be added to keepalive.
	m, err := it.puller.Next(ctx)
	if err != nil {
		return nil, err
	}
	m.it = it
	return m, nil
}

// Client code must call Close on an Iterator when finished with it.
// Close will block until Done has been called on all Messages that have been
// returned by Next.
// Close need only be called once, but may be called multiple times from multiple goroutines.
func (it *Iterator) Close() error {
	// TODO: test calling from multiple goroutines.
	it.mu.Lock()
	defer it.mu.Unlock()
	if it.closed {
		return nil
	}
	it.closed = true

	// Remove messages that are being kept alive, but have not been
	// supplied to the caller yet.  Then the only messages being kept alive
	// will be those that have been supplied to the caller but have not yet
	// had their Done method called.
	for _, m := range it.puller.Pending() {
		it.ka.Remove(m.AckID)
	}

	// This will block until all messages have been removed from keepAlive.
	// This will happen once all outstanding messages have been either
	// ACKed or NACKed.
	it.ka.Stop()

	it.acker.Stop()

	it.kaTicker.Stop()
	it.ackTicker.Stop()
	return nil
}

func (it *Iterator) done(ackID string, ack bool) {
	// NOTE: this method does not lock mu, because it's fine for done to be
	// called while the iterator is in the process of being closed.  In
	// fact, this is the only way to drain oustanding messages.
	if ack {
		it.acker.Ack(ackID)
		// There's no need to call it.ka.Remove here, as acker will
		// call it via its Notify function.
	} else {
		it.ka.Remove(ackID)
	}
}
<|endoftext|>


<commit_before>package db_test

import (
	"time"

	"github.com/deiwin/luncher-api/db/model"
	. "github.com/onsi/gomega"
	"gopkg.in/mgo.v2/bson"
)

type Mocks struct {
	offers       []*model.Offer
	tags         []*model.Tag
	regions      []*model.Region
	restaurants  []*model.Restaurant
	restaurantID bson.ObjectId
	users        []*model.User
}

func createMocks() *Mocks {
	restaurantID := bson.NewObjectId()
	return &Mocks{
		restaurantID: restaurantID,
		offers: []*model.Offer{&model.Offer{
			Restaurant: model.OfferRestaurant{
				Name:   "Asian Chef",
				Region: "Tartu",
			},
			Title:       "Sweet & Sour Chicken",
			Ingredients: []string{"Kana", "aedviljad", "tsillikaste"},
			FromTime:    parseTime("2014-11-10T09:00:00.000Z"),
			ToTime:      parseTime("2014-11-10T11:00:00.000Z"),
			Price:       3.4,
			Tags:        []string{"lind"},
			Image:       "08446744073709551615",
		},
			&model.Offer{
				Restaurant: model.OfferRestaurant{
					Name:   "Bulgarian Dude",
					Region: "Tallinn",
				},
				Title:       "Sweet & Sour Pork",
				Ingredients: []string{"Seafilee", "aedviljad", "mahushapu kaste"},
				FromTime:    parseTime("2014-11-10T09:00:00.000Z"),
				ToTime:      parseTime("2014-11-10T12:00:00.000Z"),
				Price:       3.3,
				Tags:        []string{"lind"},
				Image:       "07446744073709551615",
			},
			&model.Offer{
				Restaurant: model.OfferRestaurant{
					Name:   "Caesarian Kitchen",
					Region: "Tartu",
				},
				Title:       "Sweet & Sour Duck",
				Ingredients: []string{"Pardifilee", "aedviljad", "magushapu kaste"},
				FromTime:    parseTime("2014-11-12T09:00:00.000Z"),
				ToTime:      parseTime("2014-11-12T11:00:00.000Z"),
				Price:       3.6,
				Tags:        []string{"lind"},
				Image:       "06446744073709551615",
			},
		},
		tags: []*model.Tag{
			&model.Tag{
				Name:        "kala",
				DisplayName: "Kalast",
			},
			&model.Tag{
				Name:        "lind",
				DisplayName: "Linnust",
			},
			&model.Tag{
				Name:        "siga",
				DisplayName: "Seast",
			},
			&model.Tag{
				Name:        "veis",
				DisplayName: "Veisest",
			},
			&model.Tag{
				Name:        "lammas",
				DisplayName: "Lambast",
			},
		},
		regions: []*model.Region{
			&model.Region{
				Name:     "Tartu",
				Location: "Europe/Tallinn",
			},
			&model.Region{
				Name:     "Tallinn",
				Location: "Europe/Tallinn",
			},
			&model.Region{
				Name:     "London",
				Location: "Europe/London",
			},
		},
		restaurants: []*model.Restaurant{
			&model.Restaurant{
				Name:    "Bulgarian Dude",
				Address: "Võru 23, Tartu",
				Region:  "Tallinn",
			},
			&model.Restaurant{
				ID:      restaurantID,
				Name:    "Asian Chef",
				Address: "Võru 24, Tartu",
				Region:  "Tartu",
			},
			&model.Restaurant{
				Name:    "Caesarian Kitchen",
				Address: "Võru 25, Tartu",
				Region:  "Tartu",
			},
		},
		users: []*model.User{
			&model.User{
				RestaurantID:   restaurantID,
				FacebookUserID: facebookUserID,
				FacebookPageID: facebookPageID,
			},
			&model.User{
				RestaurantID:   restaurantID,
				FacebookUserID: "another user",
				FacebookPageID: facebookPageID,
			},
		},
	}
}

func parseTime(timeString string) time.Time {
	parsedTime, err := time.Parse(time.RFC3339, timeString)
	Expect(err).NotTo(HaveOccurred())
	return parsedTime
}
<commit_msg>update DB mocks to include new, missing data<commit_after>package db_test

import (
	"time"

	"github.com/deiwin/luncher-api/db/model"
	"github.com/deiwin/luncher-api/geo"
	. "github.com/onsi/gomega"
	"gopkg.in/mgo.v2/bson"
)

type Mocks struct {
	offers       []*model.Offer
	tags         []*model.Tag
	regions      []*model.Region
	restaurants  []*model.Restaurant
	restaurantID bson.ObjectId
	users        []*model.User
}

func createMocks() *Mocks {
	restaurantID := bson.NewObjectId()
	return &Mocks{
		restaurantID: restaurantID,
		offers: []*model.Offer{&model.Offer{
			Restaurant: model.OfferRestaurant{
				Name:   "Asian Chef",
				Region: "Tartu",
				Location: geo.Location{
					Lat: 58.37,
					Lng: 26.72,
				},
			},
			Title:       "Sweet & Sour Chicken",
			Ingredients: []string{"Kana", "aedviljad", "tsillikaste"},
			FromTime:    parseTime("2014-11-10T09:00:00.000Z"),
			ToTime:      parseTime("2014-11-10T11:00:00.000Z"),
			Price:       3.4,
			Tags:        []string{"lind"},
			Image:       "08446744073709551615",
		},
			&model.Offer{
				Restaurant: model.OfferRestaurant{
					Name:   "Bulgarian Dude",
					Region: "Tallinn",
					Location: geo.Location{
						Lat: 59.42,
						Lng: 24.74,
					},
				},
				Title:       "Sweet & Sour Pork",
				Ingredients: []string{"Seafilee", "aedviljad", "mahushapu kaste"},
				FromTime:    parseTime("2014-11-10T09:00:00.000Z"),
				ToTime:      parseTime("2014-11-10T12:00:00.000Z"),
				Price:       3.3,
				Tags:        []string{"lind"},
				Image:       "07446744073709551615",
			},
			&model.Offer{
				Restaurant: model.OfferRestaurant{
					Name:   "Caesarian Kitchen",
					Region: "Tartu",
					Location: geo.Location{
						Lat: 58.36,
						Lng: 26.73,
					},
				},
				Title:       "Sweet & Sour Duck",
				Ingredients: []string{"Pardifilee", "aedviljad", "magushapu kaste"},
				FromTime:    parseTime("2014-11-12T09:00:00.000Z"),
				ToTime:      parseTime("2014-11-12T11:00:00.000Z"),
				Price:       3.6,
				Tags:        []string{"lind"},
				Image:       "06446744073709551615",
			},
		},
		tags: []*model.Tag{
			&model.Tag{
				Name:        "kala",
				DisplayName: "Kalast",
			},
			&model.Tag{
				Name:        "lind",
				DisplayName: "Linnust",
			},
			&model.Tag{
				Name:        "siga",
				DisplayName: "Seast",
			},
			&model.Tag{
				Name:        "veis",
				DisplayName: "Veisest",
			},
			&model.Tag{
				Name:        "lammas",
				DisplayName: "Lambast",
			},
		},
		regions: []*model.Region{
			&model.Region{
				Name:     "Tartu",
				Location: "Europe/Tallinn",
				CCTLD:    "ee",
			},
			&model.Region{
				Name:     "Tallinn",
				Location: "Europe/Tallinn",
				CCTLD:    "ee",
			},
			&model.Region{
				Name:     "London",
				Location: "Europe/London",
				CCTLD:    "uk",
			},
		},
		restaurants: []*model.Restaurant{
			&model.Restaurant{
				Name:    "Bulgarian Dude",
				Address: "Võru 23, Tallinn",
				Region:  "Tallinn",
				Location: geo.Location{
					Lat: 59.42,
					Lng: 24.74,
				},
			},
			&model.Restaurant{
				ID:      restaurantID,
				Name:    "Asian Chef",
				Address: "Võru 24, Tartu",
				Region:  "Tartu",
				Location: geo.Location{
					Lat: 58.37,
					Lng: 26.72,
				},
			},
			&model.Restaurant{
				Name:    "Caesarian Kitchen",
				Address: "Võru 25, Tartu",
				Region:  "Tartu",
				Location: geo.Location{
					Lat: 58.36,
					Lng: 26.73,
				},
			},
		},
		users: []*model.User{
			&model.User{
				RestaurantID:   restaurantID,
				FacebookUserID: facebookUserID,
				FacebookPageID: facebookPageID,
			},
			&model.User{
				RestaurantID:   restaurantID,
				FacebookUserID: "another user",
				FacebookPageID: facebookPageID,
			},
		},
	}
}

func parseTime(timeString string) time.Time {
	parsedTime, err := time.Parse(time.RFC3339, timeString)
	Expect(err).NotTo(HaveOccurred())
	return parsedTime
}
<|endoftext|>


<commit_before>package irchuubase

import (
	"database/sql"
	"encoding/json"
	"github.com/26000/irchuu/relay"
	_ "github.com/lib/pq"
	"log"
	"os"
	"strings"
	"time"
)

// Log inserts a message into the DB.
func Log(msg relay.Message, db *sql.DB, logger *log.Logger) {
	extraString, err := json.Marshal(msg.Extra)
	if err != nil {
		logger.Printf("An error occurred while marshalling the extra data: %v.",
			err)
	}

	// If message text contains null, pg will crash
	if strings.Contains(msg.Text, "\xd0") {
		logger.Printf("Will not log %v from %v: malformed data", msg.Text, msg.FromID)
		return
	}

	if msg.Source {
		// Telegram
		rows1, err := db.Query("INSERT INTO"+
			" messages(date, source, \"text\", from_id, msg_id, extra)"+
			" VALUES($1, $2, $3, $4, $5, $6);",
			msg.Date, 1, msg.Text, msg.FromID, msg.ID,
			extraString)
		defer rows1.Close()
		handleErrors(err, logger)

		rows2, err := db.Query("INSERT INTO"+
			" tg_users(id, nick, first_name, last_name, last_active)"+
			" VALUES($1, NULLIF($2, ''), $3, $4, $5) ON CONFLICT (id) DO UPDATE"+
			" SET id = $1, nick = NULLIF($2, ''), first_name = $3,"+
			" last_name = $4, last_active = $5;",
			msg.FromID, msg.Nick, msg.FirstName, msg.LastName, msg.Date)
		defer rows2.Close()
		handleErrors(err, logger)
	} else {
		// IRC
		rows, err := db.Query("INSERT INTO"+
			" messages(date, source, nick, \"text\", extra)"+
			" VALUES($1, $2, $3, $4, $5);",
			msg.Date, 0, msg.Nick, msg.Text,
			extraString)
		defer rows.Close()
		handleErrors(err, logger)
	}
}

// Init creates tables needed for IRChuu and returns true on success.
func Init(dbURI string) *sql.DB {
	logger := log.New(os.Stdout, " DB ", log.LstdFlags)

	db, err := sql.Open("postgres", dbURI)
	if !handleErrors(err, logger) {
		return nil
	}
	rows1, err := db.Query("CREATE TABLE IF NOT EXISTS tg_users" +
		" (id INT PRIMARY KEY NOT NULL, nick VARCHAR(32)," +
		" first_name TEXT, last_name TEXT, last_active TIMESTAMP" +
		" WITH TIME ZONE);")
	if !handleErrors(err, logger) {
		return nil
	}
	defer rows1.Close()
	rows2, err := db.Query("CREATE TABLE IF NOT EXISTS messages" +
		" (id BIGSERIAL, date TIMESTAMP WITH TIME ZONE NOT NULL," +
		" source BOOLEAN, nick TEXT, \"text\" TEXT, from_id INT," +
		" msg_id INT, extra JSONB);")
	if !handleErrors(err, logger) {
		return nil
	}
	defer rows2.Close()
	logger.Println("Successfully initialized")
	return db
}

// GetMessages gets n last messages and returns them in a slice of relay.Message.
func GetMessages(db *sql.DB, n int) ([]relay.Message, error) {
	msgs := make([]relay.Message, 0, n)
	rows, err := db.Query(`SELECT date, source, coalesce(messages.nick,
tg_users.nick, ''), text, coalesce(msg_id, 0), coalesce(from_id, 0),
coalesce(first_name, ' '), coalesce(last_name, ' '), extra FROM messages
LEFT JOIN tg_users
ON tg_users.id = messages.from_id ORDER BY date DESC LIMIT $1;`, n)
	defer rows.Close()

	if err != nil {
		return msgs, err
	}
	for rows.Next() {
		var (
			date      time.Time
			source    bool
			nick      string
			text      string
			ID        int
			fromID    int
			firstName string
			lastName  string
			extras    []byte
			extra     map[string]string
		)
		err = rows.Scan(&date, &source, &nick, &text, &ID, &fromID, &firstName,
			&lastName, &extras)
		if err != nil {
			log.Println(err)
		}
		err = json.Unmarshal(extras, &extra)
		if err != nil {
			log.Println(err)
		}
		msgs = append(msgs, relay.Message{date, source, nick, text, ID,
			fromID, firstName, lastName, extra})
	}
	return msgs, nil
}

// handleErrors logs the error and returns false if it is not nil. Otherwise
// returns true.
func handleErrors(err error, logger *log.Logger) bool {
	if err != nil {
		logger.Printf("Error: %v\n", err)
		return false
	}
	return true
}

func FindUser(name string, db *sql.DB) (id int, foundName string, err error) {
	err = db.QueryRow("SELECT id, coalesce(nick, first_name || ' ' || last_name)"+
		"  FROM tg_users WHERE nick LIKE $1 || '%'"+
		" OR first_name || ' ' || last_name LIKE $1 || '%' "+
		" ORDER BY last_active DESC LIMIT 1", name).Scan(&id, &foundName)
	return
}
<commit_msg>Revert "Protect pg from malformed data", breaks logging<commit_after>package irchuubase

import (
	"database/sql"
	"encoding/json"
	"github.com/26000/irchuu/relay"
	_ "github.com/lib/pq"
	"log"
	"os"
	"time"
)

// Log inserts a message into the DB.
func Log(msg relay.Message, db *sql.DB, logger *log.Logger) {
	extraString, err := json.Marshal(msg.Extra)
	if err != nil {
		logger.Printf("An error occurred while marshalling the extra data: %v.",
			err)
	}
	if msg.Source {
		// Telegram
		rows1, err := db.Query("INSERT INTO"+
			" messages(date, source, \"text\", from_id, msg_id, extra)"+
			" VALUES($1, $2, $3, $4, $5, $6);",
			msg.Date, 1, msg.Text, msg.FromID, msg.ID,
			extraString)
		defer rows1.Close()
		handleErrors(err, logger)

		rows2, err := db.Query("INSERT INTO"+
			" tg_users(id, nick, first_name, last_name, last_active)"+
			" VALUES($1, NULLIF($2, ''), $3, $4, $5) ON CONFLICT (id) DO UPDATE"+
			" SET id = $1, nick = NULLIF($2, ''), first_name = $3,"+
			" last_name = $4, last_active = $5;",
			msg.FromID, msg.Nick, msg.FirstName, msg.LastName, msg.Date)
		defer rows2.Close()
		handleErrors(err, logger)
	} else {
		// IRC
		rows, err := db.Query("INSERT INTO"+
			" messages(date, source, nick, \"text\", extra)"+
			" VALUES($1, $2, $3, $4, $5);",
			msg.Date, 0, msg.Nick, msg.Text,
			extraString)
		defer rows.Close()
		handleErrors(err, logger)
	}
}

// Init creates tables needed for IRChuu and returns true on success.
func Init(dbURI string) *sql.DB {
	logger := log.New(os.Stdout, " DB ", log.LstdFlags)

	db, err := sql.Open("postgres", dbURI)
	if !handleErrors(err, logger) {
		return nil
	}
	rows1, err := db.Query("CREATE TABLE IF NOT EXISTS tg_users" +
		" (id INT PRIMARY KEY NOT NULL, nick VARCHAR(32)," +
		" first_name TEXT, last_name TEXT, last_active TIMESTAMP" +
		" WITH TIME ZONE);")
	if !handleErrors(err, logger) {
		return nil
	}
	defer rows1.Close()
	rows2, err := db.Query("CREATE TABLE IF NOT EXISTS messages" +
		" (id BIGSERIAL, date TIMESTAMP WITH TIME ZONE NOT NULL," +
		" source BOOLEAN, nick TEXT, \"text\" TEXT, from_id INT," +
		" msg_id INT, extra JSONB);")
	if !handleErrors(err, logger) {
		return nil
	}
	defer rows2.Close()
	logger.Println("Successfully initialized")
	return db
}

// GetMessages gets n last messages and returns them in a slice of relay.Message.
func GetMessages(db *sql.DB, n int) ([]relay.Message, error) {
	msgs := make([]relay.Message, 0, n)
	rows, err := db.Query(`SELECT date, source, coalesce(messages.nick,
tg_users.nick, ''), text, coalesce(msg_id, 0), coalesce(from_id, 0),
coalesce(first_name, ' '), coalesce(last_name, ' '), extra FROM messages
LEFT JOIN tg_users
ON tg_users.id = messages.from_id ORDER BY date DESC LIMIT $1;`, n)
	defer rows.Close()

	if err != nil {
		return msgs, err
	}
	for rows.Next() {
		var (
			date      time.Time
			source    bool
			nick      string
			text      string
			ID        int
			fromID    int
			firstName string
			lastName  string
			extras    []byte
			extra     map[string]string
		)
		err = rows.Scan(&date, &source, &nick, &text, &ID, &fromID, &firstName,
			&lastName, &extras)
		if err != nil {
			log.Println(err)
		}
		err = json.Unmarshal(extras, &extra)
		if err != nil {
			log.Println(err)
		}
		msgs = append(msgs, relay.Message{date, source, nick, text, ID,
			fromID, firstName, lastName, extra})
	}
	return msgs, nil
}

// handleErrors logs the error and returns false if it is not nil. Otherwise
// returns true.
func handleErrors(err error, logger *log.Logger) bool {
	if err != nil {
		logger.Printf("Error: %v\n", err)
		return false
	}
	return true
}

func FindUser(name string, db *sql.DB) (id int, foundName string, err error) {
	err = db.QueryRow("SELECT id, coalesce(nick, first_name || ' ' || last_name)"+
		"  FROM tg_users WHERE nick LIKE $1 || '%'"+
		" OR first_name || ' ' || last_name LIKE $1 || '%' "+
		" ORDER BY last_active DESC LIMIT 1", name).Scan(&id, &foundName)
	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package oci

import (
	"testing"

	"github.com/terraform-providers/terraform-provider-oci/httpreplay"

	"fmt"

	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/terraform"
	"github.com/stretchr/testify/suite"
)

type ResourcePrivateIPTestSuite struct {
	suite.Suite
	Providers        map[string]terraform.ResourceProvider
	Config           string
	ResourceName     string
	VlanConfig       string
	VlanResourceName string
}

func (s *ResourcePrivateIPTestSuite) SetupTest() {
	s.Providers = testAccProviders
	testAccPreCheck(s.T())
	s.Config = legacyTestProviderConfig() + testADs() + testVCN1() + testSubnet1() + testImage1() + testInstance1() + DefinedTagsDependencies + `
	data "oci_core_vnic_attachments" "t" {
		availability_domain = "${data.oci_identity_availability_domains.t.availability_domains.0.name}"
		compartment_id = "${var.compartment_id}"
		instance_id = "${oci_core_instance.t.id}"
	}`
	s.VlanConfig = legacyTestProviderConfig() +
		generateResourceFromRepresentationMap("oci_core_vlan", "test_vlan", Required, Create, vlanRepresentation) +
		generateResourceFromRepresentationMap("oci_core_vcn", "test_vcn", Required, Create, vcnRepresentation) +
		AvailabilityDomainConfig + DefinedTagsDependencies

	s.ResourceName = "oci_core_private_ip.t"
	s.VlanResourceName = "oci_core_private_ip.tpvlan"
}

func (s *ResourcePrivateIPTestSuite) TestAccCoreResourcePrivateIP_basic() {
	var resId string
	resource.Test(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			// test create
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "value"
									)}"
                    freeform_tags = { "Department" = "Finance"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttrSet(s.ResourceName, "id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "ip_address"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					// hostname_label should not be set unless explicitly set
					resource.TestCheckNoResourceAttr(s.ResourceName, "hostname_label"),
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip"),
					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, "oci_core_private_ip.t", "id")
						return
					},
					resource.TestCheckResourceAttr(s.ResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.ResourceName, "freeform_tags.%", "1"),
				),
			},
			// test update
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip2"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "updatedValue"
									)}"
                    freeform_tags = { "Department" = "Accounting"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "ip_address"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					// hostname_label should not be set unless explicitly set
					resource.TestCheckNoResourceAttr(s.ResourceName, "hostname_label"),
					resource.TestCheckResourceAttr(s.ResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.ResourceName, "freeform_tags.%", "1"),
				),
			},
			// test add host name label
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip2"
					hostname_label = "ahostname"
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "ip_address"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.ResourceName, "hostname_label", "ahostname"),
				),
			},
			// test destructive ip address change
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip2"
					hostname_label = "ahostname"
					ip_address = "10.0.1.22"
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttr(s.ResourceName, "ip_address", "10.0.1.22"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.ResourceName, "hostname_label", "ahostname"),
					func(s *terraform.State) (err error) {
						resId2, err := fromInstanceState(s, "oci_core_private_ip.t", "id")
						if resId == resId2 {
							return fmt.Errorf("Expected new private_ip ocid, got the same")
						}
						return err
					},
				),
			},
		},
	})
}

func (s *ResourcePrivateIPTestSuite) TestAccCoreResourcePrivateIPVlan_basic() {
	resource.Test(s.T(), resource.TestCase{
		Providers:    s.Providers,
		CheckDestroy: testAccCheckCorePrivateIpDestroy,
		Steps: []resource.TestStep{
			// test create
			{
				Config: s.VlanConfig + `
				resource "oci_core_private_ip" "tpvlan" {
					vlan_id		 = "${oci_core_vlan.test_vlan.id}"
					ip_address	 = "10.0.0.5"
					display_name = "-private-ip"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "value"
									)}"
                    freeform_tags = { "Department" = "Finance"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "id"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "ip_address", "10.0.0.5"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "vlan_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "display_name", "-private-ip"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "freeform_tags.%", "1"),
				),
			},
			// test update
			{
				Config: s.VlanConfig + `
				resource "oci_core_private_ip" "tpvlan" {
					vlan_id		 = "${oci_core_vlan.test_vlan.id}"
					ip_address	 = "10.0.0.10"
					display_name = "-private-ip2"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "updatedValue"
									)}"
                    freeform_tags = { "Department" = "Accounting"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.VlanResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "ip_address", "10.0.0.10"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "vlan_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "freeform_tags.%", "1"),
				),
			},
		},
	})
}

func TestResourceCorePrivateIPTestSuite(t *testing.T) {
	httpreplay.SetScenario("TestResourceCorePrivateIPTestSuite")
	defer httpreplay.SaveScenario()
	suite.Run(t, new(ResourcePrivateIPTestSuite))
}
<commit_msg>Core Private IP test fix<commit_after>// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package oci

import (
	"testing"

	"github.com/terraform-providers/terraform-provider-oci/httpreplay"

	"fmt"

	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/terraform"
	"github.com/stretchr/testify/suite"
)

type ResourcePrivateIPTestSuite struct {
	suite.Suite
	Providers        map[string]terraform.ResourceProvider
	Config           string
	ResourceName     string
	VlanConfig       string
	VlanResourceName string
}

func (s *ResourcePrivateIPTestSuite) SetupTest() {
	s.Providers = testAccProviders
	testAccPreCheck(s.T())
	s.Config = legacyTestProviderConfig() + testADs() + testVCN1() + testSubnet1() + testImage1() + testInstance1() + DefinedTagsDependencies + `
	data "oci_core_vnic_attachments" "t" {
		availability_domain = "${data.oci_identity_availability_domains.t.availability_domains.0.name}"
		compartment_id = "${var.compartment_id}"
		instance_id = "${oci_core_instance.t.id}"
	}`
	s.VlanConfig = legacyTestProviderConfig() +
		generateResourceFromRepresentationMap("oci_core_vlan", "test_vlan", Required, Create, vlanRepresentation) +
		generateResourceFromRepresentationMap("oci_core_vcn", "test_vcn", Required, Create, vcnRepresentation) +
		AvailabilityDomainConfig + DefinedTagsDependencies

	s.ResourceName = "oci_core_private_ip.t"
	s.VlanResourceName = "oci_core_private_ip.tpvlan"
}

func (s *ResourcePrivateIPTestSuite) TestAccCoreResourcePrivateIP_basic() {
	var resId string
	resource.Test(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			// test create
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "value"
									)}"
                    freeform_tags = { "Department" = "Finance"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttrSet(s.ResourceName, "id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "ip_address"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					// hostname_label should not be set unless explicitly set
					resource.TestCheckNoResourceAttr(s.ResourceName, "hostname_label"),
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip"),
					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, "oci_core_private_ip.t", "id")
						return
					},
					resource.TestCheckResourceAttr(s.ResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.ResourceName, "freeform_tags.%", "1"),
				),
			},
			// test update
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip2"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "updatedValue"
									)}"
                    freeform_tags = { "Department" = "Accounting"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "ip_address"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					// hostname_label should not be set unless explicitly set
					resource.TestCheckNoResourceAttr(s.ResourceName, "hostname_label"),
					resource.TestCheckResourceAttr(s.ResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.ResourceName, "freeform_tags.%", "1"),
				),
			},
			// test add host name label
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip2"
					hostname_label = "ahostname"
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "ip_address"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.ResourceName, "hostname_label", "ahostname"),
				),
			},
			// test destructive ip address change
			{
				Config: s.Config + `
				resource "oci_core_private_ip" "t" {
					vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0], "vnic_id")}"
					display_name = "-private-ip2"
					hostname_label = "ahostname"
					ip_address = "10.0.1.22"
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "vnic_id"),
					resource.TestCheckResourceAttr(s.ResourceName, "ip_address", "10.0.1.22"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(s.ResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.ResourceName, "hostname_label", "ahostname"),
					func(s *terraform.State) (err error) {
						resId2, err := fromInstanceState(s, "oci_core_private_ip.t", "id")
						if resId == resId2 {
							return fmt.Errorf("Expected new private_ip ocid, got the same")
						}
						return err
					},
				),
			},
		},
	})
}

func (s *ResourcePrivateIPTestSuite) TestAccCoreResourcePrivateIPVlan_basic() {
	resource.Test(s.T(), resource.TestCase{
		Providers:    s.Providers,
		CheckDestroy: testAccCheckCorePrivateIpDestroy,
		Steps: []resource.TestStep{
			// test create
			{
				Config: s.VlanConfig + `
				resource "oci_core_private_ip" "tpvlan" {
					vlan_id		 = "${oci_core_vlan.test_vlan.id}"
					ip_address	 = "10.0.0.5"
					display_name = "-private-ip"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "value"
									)}"
                    freeform_tags = { "Department" = "Finance"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "id"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "ip_address", "10.0.0.5"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "vlan_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "display_name", "-private-ip"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "freeform_tags.%", "1"),
				),
			},
			// test update
			{
				Config: s.VlanConfig + `
				resource "oci_core_private_ip" "tpvlan" {
					vlan_id		 = "${oci_core_vlan.test_vlan.id}"
					ip_address	 = "10.0.0.10"
					display_name = "-private-ip2"
					defined_tags = "${map(
									"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "updatedValue"
									)}"
                    freeform_tags = { "Department" = "Accounting"}
				}`,
				Check: ComposeAggregateTestCheckFuncWrapper(
					resource.TestCheckResourceAttr(s.VlanResourceName, "display_name", "-private-ip2"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "ip_address", "10.0.0.10"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "is_primary"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "vlan_id"),
					resource.TestCheckResourceAttrSet(s.VlanResourceName, "time_created"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(s.VlanResourceName, "freeform_tags.%", "1"),
				),
			},
		},
	})
}

func TestResourceCorePrivateIPTestSuite(t *testing.T) {
	httpreplay.SetScenario("TestResourceCorePrivateIPTestSuite")
	defer httpreplay.SaveScenario()
	suite.Run(t, new(ResourcePrivateIPTestSuite))
}
<|endoftext|>


<commit_before>package irchuubase

import (
	"database/sql"
	"encoding/json"
	"github.com/26000/irchuu/relay"
	"github.com/lib/pq"
	"log"
	"os"
	"time"
)

// Log inserts a message into the DB.
func Log(msg relay.Message, db *sql.DB, logger *log.Logger) {
	extraString, err := json.Marshal(msg.Extra)
	if err != nil {
		logger.Printf("An error occurred while marshalling the extra data: %v.",
			err)
	}
	if msg.Source {
		// Telegram
		rows1, err := db.Query("INSERT INTO"+
			" messages(date, source, \"text\", from_id, msg_id, extra)"+
			" VALUES($1, $2, $3, $4, $5, $6);",
			msg.Date, 1, msg.Text, msg.FromID, msg.ID,
			extraString)
		defer rows1.Close()
		handleErrors(err, logger)

		rows2, err := db.Query("INSERT INTO"+
			" tg_users(id, nick, first_name, last_name, last_active)"+
			" VALUES($1, NULLIF($2, ''), $3, $4, $5) ON CONFLICT (id) DO UPDATE"+
			" SET id = $1, nick = NULLIF($2, ''), first_name = $3,"+
			" last_name = $4, last_active = $5;",
			msg.FromID, msg.Nick, msg.FirstName, msg.LastName, msg.Date)
		defer rows2.Close()
		handleErrors(err, logger)
	} else {
		// IRC
		rows, err := db.Query("INSERT INTO"+
			" messages(date, source, nick, \"text\", extra)"+
			" VALUES($1, $2, $3, $4, $5);",
			msg.Date, 0, msg.Nick, msg.Text,
			extraString)
		defer rows.Close()
		handleErrors(err, logger)
	}
}

// Init creates tables needed for IRChuu and returns true on success.
func Init(dbURI string) *sql.DB {
	logger := log.New(os.Stdout, " DB ", log.LstdFlags)

	db, err := sql.Open("postgres", dbURI)
	if !handleErrors(err, logger) {
		return nil
	}
	rows1, err := db.Query("CREATE TABLE IF NOT EXISTS tg_users" +
		" (id INT PRIMARY KEY NOT NULL, nick VARCHAR(32)," +
		" first_name TEXT, last_name TEXT, last_active TIMESTAMP" +
		" WITH TIME ZONE);")
	defer rows1.Close()
	if !handleErrors(err, logger) {
		return nil
	}
	rows2, err := db.Query("CREATE TABLE IF NOT EXISTS messages" +
		" (id BIGSERIAL, date TIMESTAMP WITH TIME ZONE NOT NULL," +
		" source BOOLEAN, nick TEXT, \"text\" TEXT, from_id INT," +
		" msg_id INT, extra JSONB);")
	defer rows2.Close()
	if !handleErrors(err, logger) {
		return nil
	}
	log.Println("Successfully initialized DB")
	return db
}

// GetMessages gets n last messages and returns them in a slice of relay.Message.
func GetMessages(db *sql.DB, n int) ([]relay.Message, error) {
	msgs := make([]relay.Message, 0, n)
	rows, err := db.Query(`SELECT date, source, coalesce(messages.nick,
tg_users.nick), text, msg_id, from_id, first_name, last_name, extra FROM messages
LEFT JOIN tg_users
ON tg_users.id = messages.from_id ORDER BY date DESC LIMIT $1;`, n)
	defer rows.Close()

	if err != nil {
		return msgs, err
	}
	for rows.Next() {
		var (
			date      time.Time
			source    bool
			nick      string
			text      string
			ID        int
			fromID    int
			firstName string
			lastName  string
			extras    []byte
			extra     map[string]string
		)
		rows.Scan(&date, &source, &nick, &text, &ID, &fromID, &firstName,
			&lastName, &extras)
		err = json.Unmarshal(extras, &extra)
		msgs = append(msgs, relay.Message{date, source, nick, text, ID,
			fromID, firstName, lastName, extra})
	}
	return msgs, nil
}

// handleErrors logs the error and returns false if it is not nil. Otherwise
// returns true.
func handleErrors(err error, logger *log.Logger) bool {
	if err, ok := err.(*pq.Error); ok {
		logger.Printf("Database error: %v\n %v\n", err.Code.Name(), err)
		return false
	}
	return true
}

func FindUser(name string, db *sql.DB) (id int, foundName string, err error) {
	err = db.QueryRow("SELECT id, coalesce(nick, first_name || ' ' || last_name)"+
		"  FROM tg_users WHERE nick LIKE $1 || '%'"+
		" OR first_name || ' ' || last_name LIKE $1 || '%' "+
		" ORDER BY last_active DESC LIMIT 1", name).Scan(&id, &foundName)
	return
}
<commit_msg>Fix the IRC service messages history<commit_after>package irchuubase

import (
	"database/sql"
	"encoding/json"
	"github.com/26000/irchuu/relay"
	"github.com/lib/pq"
	"log"
	"os"
	"time"
)

// Log inserts a message into the DB.
func Log(msg relay.Message, db *sql.DB, logger *log.Logger) {
	extraString, err := json.Marshal(msg.Extra)
	if err != nil {
		logger.Printf("An error occurred while marshalling the extra data: %v.",
			err)
	}
	if msg.Source {
		// Telegram
		rows1, err := db.Query("INSERT INTO"+
			" messages(date, source, \"text\", from_id, msg_id, extra)"+
			" VALUES($1, $2, $3, $4, $5, $6);",
			msg.Date, 1, msg.Text, msg.FromID, msg.ID,
			extraString)
		defer rows1.Close()
		handleErrors(err, logger)

		rows2, err := db.Query("INSERT INTO"+
			" tg_users(id, nick, first_name, last_name, last_active)"+
			" VALUES($1, NULLIF($2, ''), $3, $4, $5) ON CONFLICT (id) DO UPDATE"+
			" SET id = $1, nick = NULLIF($2, ''), first_name = $3,"+
			" last_name = $4, last_active = $5;",
			msg.FromID, msg.Nick, msg.FirstName, msg.LastName, msg.Date)
		defer rows2.Close()
		handleErrors(err, logger)
	} else {
		// IRC
		rows, err := db.Query("INSERT INTO"+
			" messages(date, source, nick, \"text\", extra)"+
			" VALUES($1, $2, $3, $4, $5);",
			msg.Date, 0, msg.Nick, msg.Text,
			extraString)
		defer rows.Close()
		handleErrors(err, logger)
	}
}

// Init creates tables needed for IRChuu and returns true on success.
func Init(dbURI string) *sql.DB {
	logger := log.New(os.Stdout, " DB ", log.LstdFlags)

	db, err := sql.Open("postgres", dbURI)
	if !handleErrors(err, logger) {
		return nil
	}
	rows1, err := db.Query("CREATE TABLE IF NOT EXISTS tg_users" +
		" (id INT PRIMARY KEY NOT NULL, nick VARCHAR(32)," +
		" first_name TEXT, last_name TEXT, last_active TIMESTAMP" +
		" WITH TIME ZONE);")
	defer rows1.Close()
	if !handleErrors(err, logger) {
		return nil
	}
	rows2, err := db.Query("CREATE TABLE IF NOT EXISTS messages" +
		" (id BIGSERIAL, date TIMESTAMP WITH TIME ZONE NOT NULL," +
		" source BOOLEAN, nick TEXT, \"text\" TEXT, from_id INT," +
		" msg_id INT, extra JSONB);")
	defer rows2.Close()
	if !handleErrors(err, logger) {
		return nil
	}
	log.Println("Successfully initialized DB")
	return db
}

// GetMessages gets n last messages and returns them in a slice of relay.Message.
func GetMessages(db *sql.DB, n int) ([]relay.Message, error) {
	msgs := make([]relay.Message, 0, n)
	rows, err := db.Query(`SELECT date, source, coalesce(messages.nick,
tg_users.nick), text, coalesce(msg_id, 0), coalesce(from_id, 0),
coalesce(first_name, ' '), coalesce(last_name, ' '), extra FROM messages
LEFT JOIN tg_users
ON tg_users.id = messages.from_id ORDER BY date DESC LIMIT $1;`, n)
	defer rows.Close()

	if err != nil {
		return msgs, err
	}
	for rows.Next() {
		var (
			date      time.Time
			source    bool
			nick      string
			text      string
			ID        int
			fromID    int
			firstName string
			lastName  string
			extras    []byte
			extra     map[string]string
		)
		err = rows.Scan(&date, &source, &nick, &text, &ID, &fromID, &firstName,
			&lastName, &extras)
		if err != nil {
			log.Println(err)
		}
		err = json.Unmarshal(extras, &extra)
		if err != nil {
			log.Println(err)
		}
		msgs = append(msgs, relay.Message{date, source, nick, text, ID,
			fromID, firstName, lastName, extra})
	}
	return msgs, nil
}

// handleErrors logs the error and returns false if it is not nil. Otherwise
// returns true.
func handleErrors(err error, logger *log.Logger) bool {
	if err, ok := err.(*pq.Error); ok {
		logger.Printf("Database error: %v\n %v\n", err.Code.Name(), err)
		return false
	}
	return true
}

func FindUser(name string, db *sql.DB) (id int, foundName string, err error) {
	err = db.QueryRow("SELECT id, coalesce(nick, first_name || ' ' || last_name)"+
		"  FROM tg_users WHERE nick LIKE $1 || '%'"+
		" OR first_name || ' ' || last_name LIKE $1 || '%' "+
		" ORDER BY last_active DESC LIMIT 1", name).Scan(&id, &foundName)
	return
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func TestAccAzureRMContainerGroup_linuxBasic(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_linuxBasic(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Linux"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_linuxBasicUpdate(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_linuxBasic(ri, testLocation())
	updatedConfig := testAccAzureRMContainerGroup_linuxBasicUpdated(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
				),
			},
			{
				Config: updatedConfig,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "2"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_linuxComplete(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_linuxComplete(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.command", "/bin/bash -c ls"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo", "bar"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo1", "bar1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.0.mount_path", "/aci/logs"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.0.name", "logs"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.0.read_only", "false"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Linux"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_windowsBasic(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_windowsBasic(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Windows"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_windowsComplete(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_windowsComplete(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.command", "cmd.exe echo hi"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo", "bar"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo1", "bar1"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Windows"),
				),
			},
		},
	})
}

func testAccAzureRMContainerGroup_linuxBasic(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "linux"

  container {
    name   = "hw"
    image  = "microsoft/aci-helloworld:latest"
    cpu    = "0.5"
    memory = "0.5"
	port   = "80"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_linuxBasicUpdated(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "linux"

  container {
    name   = "hw"
    image  = "microsoft/aci-helloworld:latest"
    cpu    = "0.5"
    memory = "0.5"
	port   = "80"
  }

  container {
    name   = "sidecar"
    image  = "microsoft/aci-tutorial-sidecar"
    cpu    = "0.5"
    memory = "0.5"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_windowsBasic(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "windows"

  container {
    name   = "winapp"
    image  = "winappimage:latest"
    cpu    = "2.0"
    memory = "3.5"
    port   = "80"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_windowsComplete(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "windows"

  container {
    name   = "winapp"
    image  = "winappimage:latest"
    cpu    = "2.0"
    memory = "3.5"
    port   = "80"
	environment_variables {
		"foo" = "bar"
		"foo1" = "bar1"
	}
	command = "cmd.exe echo hi"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_linuxComplete(ri int, location string) string {
	return fmt.Sprintf(`
		resource "azurerm_resource_group" "test" {
			name     = "acctestRG-%d"
			location = "%s"
	}

	resource "azurerm_storage_account" "test" {
			name                = "accsa%d"
			resource_group_name = "${azurerm_resource_group.test.name}"
			location            = "${azurerm_resource_group.test.location}"
			account_type        = "Standard_LRS"
	}

	resource "azurerm_storage_share" "test" {
			name = "acctestss-%d"

			resource_group_name  = "${azurerm_resource_group.test.name}"
			storage_account_name = "${azurerm_storage_account.test.name}"

			quota = 50
	}

	resource "azurerm_container_group" "test" {
			name                = "acctestcontainergroup-%d"
			location            = "${azurerm_resource_group.test.location}"
			resource_group_name = "${azurerm_resource_group.test.name}"
			ip_address_type     = "public"
			os_type             = "linux"

			container {
					name   = "hf"
					image  = "seanmckenna/aci-hellofiles"
					cpu    = "1"
					memory = "1.5"
					port   = "80"
					protocol = "TCP"

			volume {
							name = "logs"
							mount_path = "/aci/logs"
							read_only = false
							share_name = "${azurerm_storage_share.test.name}"
							storage_account_name = "${azurerm_storage_account.test.name}"
							storage_account_key = "${azurerm_storage_account.test.primary_access_key}"
			}

			environment_variables {
				"foo" = "bar"
				"foo1" = "bar1"
			}

			command = "/bin/bash -c ls"
			}

			tags {
				environment = "Testing"
			}
	}
`, ri, location, ri, ri, ri)
}

func testCheckAzureRMContainerGroupExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Ensure we have enough information in state to look up in API
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
		if !hasResourceGroup {
			return fmt.Errorf("Bad: no resource group found in state for Container Registry: %s", name)
		}

		conn := testAccProvider.Meta().(*ArmClient).containerGroupsClient

		resp, err := conn.Get(resourceGroup, name)
		if err != nil {
			if utils.ResponseWasNotFound(resp.Response) {
				return fmt.Errorf("Bad: Container Group %q (resource group: %q) does not exist", name, resourceGroup)
			}
			return fmt.Errorf("Bad: Get on containerGroupsClient: %+v", err)
		}

		return nil
	}
}

func testCheckAzureRMContainerGroupDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*ArmClient).containerGroupsClient

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "azurerm_container_group" {
			continue
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup := rs.Primary.Attributes["resource_group_name"]

		resp, err := conn.Get(resourceGroup, name)

		if err != nil {
			if resp.StatusCode != http.StatusNotFound {
				return fmt.Errorf("Container Group still exists:\n%#v", resp)
			}

			return nil
		}

	}

	return nil
}
<commit_msg>Upgrading the new container service test<commit_after>package azurerm

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func TestAccAzureRMContainerGroup_linuxBasic(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_linuxBasic(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Linux"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_linuxBasicUpdate(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_linuxBasic(ri, testLocation())
	updatedConfig := testAccAzureRMContainerGroup_linuxBasicUpdated(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
				),
			},
			{
				Config: updatedConfig,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "2"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_linuxComplete(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_linuxComplete(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.command", "/bin/bash -c ls"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo", "bar"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo1", "bar1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.0.mount_path", "/aci/logs"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.0.name", "logs"),
					resource.TestCheckResourceAttr(resourceName, "container.0.volume.0.read_only", "false"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Linux"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_windowsBasic(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_windowsBasic(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Windows"),
				),
			},
		},
	})
}

func TestAccAzureRMContainerGroup_windowsComplete(t *testing.T) {
	resourceName := "azurerm_container_group.test"
	ri := acctest.RandInt()

	config := testAccAzureRMContainerGroup_windowsComplete(ri, testLocation())

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMContainerGroupDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMContainerGroupExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "container.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "container.0.command", "cmd.exe echo hi"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo", "bar"),
					resource.TestCheckResourceAttr(resourceName, "container.0.environment_variables.foo1", "bar1"),
					resource.TestCheckResourceAttr(resourceName, "os_type", "Windows"),
				),
			},
		},
	})
}

func testAccAzureRMContainerGroup_linuxBasic(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "linux"

  container {
    name   = "hw"
    image  = "microsoft/aci-helloworld:latest"
    cpu    = "0.5"
    memory = "0.5"
	port   = "80"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_linuxBasicUpdated(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "linux"

  container {
    name   = "hw"
    image  = "microsoft/aci-helloworld:latest"
    cpu    = "0.5"
    memory = "0.5"
	port   = "80"
  }

  container {
    name   = "sidecar"
    image  = "microsoft/aci-tutorial-sidecar"
    cpu    = "0.5"
    memory = "0.5"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_windowsBasic(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "windows"

  container {
    name   = "winapp"
    image  = "winappimage:latest"
    cpu    = "2.0"
    memory = "3.5"
    port   = "80"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_windowsComplete(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_container_group" "test" {
  name                = "acctestcontainergroup-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  ip_address_type     = "public"
  os_type             = "windows"

  container {
    name   = "winapp"
    image  = "winappimage:latest"
    cpu    = "2.0"
    memory = "3.5"
    port   = "80"
	environment_variables {
		"foo" = "bar"
		"foo1" = "bar1"
	}
	command = "cmd.exe echo hi"
  }

  tags {
    environment = "Testing"
  }
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_linuxComplete(ri int, location string) string {
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
	name     = "acctestRG-%d"
	location = "%s"
}

resource "azurerm_storage_account" "test" {
	name                     = "accsa%d"
	resource_group_name      = "${azurerm_resource_group.test.name}"
	location                 = "${azurerm_resource_group.test.location}"
	account_tier             = "Standard"
	account_replication_type = "LRS"
}

resource "azurerm_storage_share" "test" {
	name = "acctestss-%d"

	resource_group_name  = "${azurerm_resource_group.test.name}"
	storage_account_name = "${azurerm_storage_account.test.name}"

	quota = 50
}

resource "azurerm_container_group" "test" {
	name                = "acctestcontainergroup-%d"
	location            = "${azurerm_resource_group.test.location}"
	resource_group_name = "${azurerm_resource_group.test.name}"
	ip_address_type     = "public"
	os_type             = "linux"

	container {
		name   = "hf"
		image  = "seanmckenna/aci-hellofiles"
		cpu    = "1"
		memory = "1.5"
		port   = "80"
		protocol = "TCP"

		volume {
			name = "logs"
			mount_path = "/aci/logs"
			read_only = false
			share_name = "${azurerm_storage_share.test.name}"
			storage_account_name = "${azurerm_storage_account.test.name}"
			storage_account_key = "${azurerm_storage_account.test.primary_access_key}"
		}

		environment_variables {
			"foo" = "bar"
			"foo1" = "bar1"
		}

		command = "/bin/bash -c ls"
	}

	tags {
		environment = "Testing"
	}
}
`, ri, location, ri, ri, ri)
}

func testCheckAzureRMContainerGroupExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Ensure we have enough information in state to look up in API
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
		if !hasResourceGroup {
			return fmt.Errorf("Bad: no resource group found in state for Container Registry: %s", name)
		}

		conn := testAccProvider.Meta().(*ArmClient).containerGroupsClient

		resp, err := conn.Get(resourceGroup, name)
		if err != nil {
			if utils.ResponseWasNotFound(resp.Response) {
				return fmt.Errorf("Bad: Container Group %q (resource group: %q) does not exist", name, resourceGroup)
			}
			return fmt.Errorf("Bad: Get on containerGroupsClient: %+v", err)
		}

		return nil
	}
}

func testCheckAzureRMContainerGroupDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*ArmClient).containerGroupsClient

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "azurerm_container_group" {
			continue
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup := rs.Primary.Attributes["resource_group_name"]

		resp, err := conn.Get(resourceGroup, name)

		if err != nil {
			if resp.StatusCode != http.StatusNotFound {
				return fmt.Errorf("Container Group still exists:\n%#v", resp)
			}

			return nil
		}

	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"container/list"
	"fmt"
	"os"
	"strconv"

	"github.com/jyggen/advent-of-go/internal/solver"
	"github.com/jyggen/advent-of-go/internal/utils"
)

func main() {
	p1, p2, err := solver.SolveFromFile(os.Stdin, SolvePart1, SolvePart2)
	if err != nil {
		panic(err)
	}

	fmt.Println(p1)
	fmt.Println(p2)
}

type grid struct {
	colLength int
	grid      []int
	rowLength int
}

func (g *grid) simulate() int {
	queue := list.New()
	flashes := 0

	for j := 0; j < len(g.grid); j++ {
		queue.PushBack(j)
	}

	for queue.Len() > 0 {
		e := queue.Front()
		j := e.Value.(int)

		g.grid[j]++

		if g.grid[j] == 10 {
			flashes++

			x, y := utils.ToCoordinates(j, g.colLength)

			for _, k := range []int{
				utils.Neighbour(x, y, utils.North, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.NorthEast, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.East, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.SouthEast, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.South, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.SouthWest, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.West, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.NorthWest, g.rowLength, g.colLength),
			} {
				if k != -1 {
					queue.PushBack(k)
				}
			}
		}

		queue.Remove(e)
	}

	return flashes
}

func makeGrid(input string) (*grid, error) {
	stringSlice := utils.ToStringSlice(input, "\n")
	colLength := len(stringSlice[0])
	rowLength := len(stringSlice)
	g := &grid{
		colLength: colLength,
		grid:      make([]int, len(stringSlice)*colLength),
		rowLength: rowLength,
	}

	for i, s := range stringSlice {
		ints, err := utils.ToIntegerSlice(s, "")

		if err != nil {
			return g, err
		}

		for j, digit := range ints {
			g.grid[(i*colLength)+j] = digit
		}
	}

	return g, nil
}

func SolvePart1(input string) (string, error) {
	g, err := makeGrid(input)

	if err != nil {
		return "", err
	}

	flashes := 0

	for i := 0; i < 100; i++ {
		flashes += g.simulate()

		for k, v := range g.grid {
			if v > 9 {
				g.grid[k] = 0
			}
		}
	}

	return strconv.Itoa(flashes), nil
}

func SolvePart2(input string) (string, error) {
	g, err := makeGrid(input)

	if err != nil {
		return "", err
	}

	for i := 0; ; i++ {
		g.simulate()

		flashed := true

		for k, v := range g.grid {
			if v > 9 {
				g.grid[k] = 0
			} else {
				flashed = false
			}
		}

		if flashed {
			return strconv.Itoa(i + 1), nil
		}
	}

	return strconv.Itoa(0), nil
}
<commit_msg>Optimize 2021.11<commit_after>package main

import (
	"container/list"
	"fmt"
	"os"
	"strconv"

	"github.com/jyggen/advent-of-go/internal/solver"
	"github.com/jyggen/advent-of-go/internal/utils"
)

func main() {
	p1, p2, err := solver.SolveFromFile(os.Stdin, SolvePart1, SolvePart2)
	if err != nil {
		panic(err)
	}

	fmt.Println(p1)
	fmt.Println(p2)
}

type grid struct {
	colLength int
	grid      []int
	rowLength int
}

func (g *grid) simulate() int {
	queue := list.New()
	flashes := 0

	for j := 0; j < len(g.grid); j++ {
		g.grid[j]++

		if g.grid[j] > 9 {
			queue.PushBack(j)
		}
	}

	for queue.Len() > 0 {
		e := queue.Front()
		j := e.Value.(int)

		if g.grid[j] != 0 {
			g.grid[j]++
		}

		if g.grid[j] > 9 {
			flashes++

			g.grid[j] = 0
			x, y := utils.ToCoordinates(j, g.colLength)

			for _, k := range []int{
				utils.Neighbour(x, y, utils.North, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.NorthEast, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.East, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.SouthEast, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.South, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.SouthWest, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.West, g.rowLength, g.colLength),
				utils.Neighbour(x, y, utils.NorthWest, g.rowLength, g.colLength),
			} {
				if k != -1 {
					queue.PushBack(k)
				}
			}
		}

		queue.Remove(e)
	}

	return flashes
}

func makeGrid(input string) (*grid, error) {
	stringSlice := utils.ToStringSlice(input, "\n")
	colLength := len(stringSlice[0])
	rowLength := len(stringSlice)
	g := &grid{
		colLength: colLength,
		grid:      make([]int, len(stringSlice)*colLength),
		rowLength: rowLength,
	}

	for i, s := range stringSlice {
		ints, err := utils.ToIntegerSlice(s, "")

		if err != nil {
			return g, err
		}

		for j, digit := range ints {
			g.grid[(i*colLength)+j] = digit
		}
	}

	return g, nil
}

func SolvePart1(input string) (string, error) {
	g, err := makeGrid(input)

	if err != nil {
		return "", err
	}

	flashes := 0

	for i := 0; i < 100; i++ {
		flashes += g.simulate()
	}

	return strconv.Itoa(flashes), nil
}

func SolvePart2(input string) (string, error) {
	g, err := makeGrid(input)

	if err != nil {
		return "", err
	}

	for i := 0; ; i++ {
		g.simulate()

		allFlashed := true

		for _, v := range g.grid {
			if v != 0 {
				allFlashed = false
				break
			}
		}

		if allFlashed {
			return strconv.Itoa(i + 1), nil
		}
	}

	return strconv.Itoa(0), nil
}
<|endoftext|>


<commit_before>package main

import (
    "bytes"
    "crypto/rand"
    "crypto/sha1"
    "database/sql"
    "encoding/base64"
    "encoding/json"
    "flag"
    "fmt"
    "io"
    "io/ioutil"
    "net/mail"
    "os"
    "path/filepath"
    "strings"
    "time"

    _ "github.com/mattn/go-sqlite3"
)

func usage() {
    fmt.Fprintf(os.Stderr, "usage: %s [params]\n", filepath.Base(os.Args[0]))
    flag.PrintDefaults()
    os.Exit(2)
}

func encrypt(passwd string) (salt, hash string) {
    b := make([]byte, 16)
    n, err := io.ReadFull(rand.Reader, b)
    if n != len(b) || err != nil {
        fmt.Println("error:", err)
        return
    }
    salt = base64.URLEncoding.EncodeToString(b)
    sha := sha1.New()
    sha.Write([]byte(salt + passwd))
    hash = base64.URLEncoding.EncodeToString(sha.Sum(nil))
    return
}

func init_db(fileName, uname, passwd, fullname, email, www string) {
    createTables := []string{
        `create table tag (
            id integer not null primary key,
            name text,
            url text
        )`,
        `create table author (
            id integer not null primary key,
            disp_name text,
            salt text,
            passwd text,
            full_name text,
            email text,
            www text
        )`,
        `create table post (
            id integer not null primary key,
            author_id integer not null references author(id) on delete cascade on update cascade,
            title text,
            date long,
            url text,
            body text
        )`,
        `create table tagmap (
            id integer not null primary key,
            tag_id integer not null references tag(id) on delete cascade on update cascade,
            post_id integer not null references post(id) on delete cascade on update cascade
        )`,
        `create table commenter (
            id integer not null primary key,
            name text,
            email text,
            www text,
            ip text
        )`,
        `create table comment (
            id integer not null primary key,
            commenter_id integer not null references commenter(id) on delete cascade on update cascade,
            post_id integer not null references post(id) on delete cascade on update cascade,
            timestamp long,
            body text
        )`,
    }
    err := os.Remove(fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    db, err := sql.Open("sqlite3", fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer db.Close()
    for _, sql := range createTables {
        _, err := db.Exec(sql)
        if err != nil {
            fmt.Printf("%q: %s\n", err, sql)
            return
        }
    }
    stmt, _ := db.Prepare(`insert into author(id, disp_name, salt, passwd, full_name, email, www)
                           values(?, ?, ?, ?, ?, ?, ?)`)
    defer stmt.Close()
    salt, passwdHash := encrypt(passwd)
    stmt.Exec(1, uname, salt, passwdHash, fullname, email, www)
}

func populate(fileName string) {
    db, err := sql.Open("sqlite3", fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer db.Close()
    xaction, err := db.Begin()
    if err != nil {
        fmt.Println(err)
        return
    }
    stmt, _ := xaction.Prepare("insert into post(id, author_id, title, date, url, body) values(?, ?, ?, ?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, 1, "Labadėna", 123456, "labadena", "Nieko aš čia nerašysiu.")
    imgpost := `This is a post with a figure.

halfimage:

![hi][halfimg]

([Full size][fullimg])

[fullimg]: /no-dox.png
[halfimg]: /no-dox-halfsize.png`
    stmt.Exec(2, 1, "Iliustruotas", 1359308741, "iliustruotas", imgpost)
    stmt, _ = xaction.Prepare("insert into tag(id, name, url) values(?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, "Testas", "testas")
    stmt.Exec(2, "Žąsyčiai", "geese")
    stmt, _ = xaction.Prepare("insert into tagmap(id, tag_id, post_id) values(?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, 1, 1)
    stmt.Exec(2, 2, 1)
    stmt, _ = xaction.Prepare("insert into commenter(id, name, email, www, ip) values(?, ?, ?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, "Vytautas Šaltenis", "Vytautas.Shaltenis@gmail.com", "http://rtfb.lt", "127.0.0.1")
    stmt.Exec(2, "Vardenis Pavardenis", "niekas@niekur.com", "http://delfi.lt", "127.0.0.1")
    stmt, _ = xaction.Prepare("insert into comment(id, commenter_id, post_id, timestamp, body) values(?, ?, ?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, 2, 1, 1356872181, "Nu ir nerašyk, _niekam_ čia neįdomu tavo pisulkos.")
    stmt.Exec(2, 1, 1, 1356879181, "O tu čia tada **nekomentuok** ten kur neparašyta nieko. Eik [ten](http://google.com/)")
    xaction.Commit()
}

func populate2(fileName string, data []*Entry) {
    db, err := sql.Open("sqlite3", fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer db.Close()
    xaction, err := db.Begin()
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, e := range data {
        stmt, _ := xaction.Prepare("insert into post(author_id, title, date, url, body) values(?, ?, ?, ?, ?)")
        defer stmt.Close()
        date, _ := time.Parse("2006-01-02", e.Date)
        result, _ := stmt.Exec(1, e.Title, date.Unix(), e.Url, e.Body)
        postId, _ := result.LastInsertId()
        for _, t := range e.Tags {
            stmt, _ = xaction.Prepare("insert into tag(name, url) values(?, ?)")
            defer stmt.Close()
            result, _ = stmt.Exec(t.TagName, t.TagUrl)
            tagId, _ := result.LastInsertId()
            stmt, _ = xaction.Prepare("insert into tagmap(tag_id, post_id) values(?, ?)")
            defer stmt.Close()
            stmt.Exec(tagId, postId)
        }
    }
    xaction.Commit()
}

type Tag struct {
    TagUrl  string
    TagName string
}

type Entry struct {
    Author string
    Title  string
    Date   string
    Body   string
    Url    string
    Tags   []*Tag
}

func parseTags(tagList string) (tags []*Tag) {
    for _, t := range strings.Split(tagList, ", ") {
        if t == "" {
            continue
        }
        tag := new(Tag)
        tag.TagUrl = strings.ToLower(t)
        tag.TagName = t
        tags = append(tags, tag)
    }
    return
}

func readTextEntry(filename string) (entry *Entry, err error) {
    f, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    msg, err := mail.ReadMessage(f)
    if err != nil {
        return nil, err
    }
    entry = new(Entry)
    entry.Title = msg.Header.Get("subject")
    entry.Author = msg.Header.Get("author")
    entry.Date = msg.Header.Get("isodate")
    entry.Tags = parseTags(msg.Header.Get("tags"))
    base := filepath.Base(filename)
    entry.Url = base[:strings.LastIndex(base, filepath.Ext(filename))]
    buf := new(bytes.Buffer)
    buf.ReadFrom(msg.Body)
    entry.Body = buf.String()
    return
}

func readTextEntries(root string) (entries []*Entry, err error) {
    filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if strings.ToLower(filepath.Ext(path)) != ".txt" {
            return nil
        }
        entry, _ := readTextEntry(path)
        if entry == nil {
            return nil
        }
        entries = append(entries, entry)
        return nil
    })
    return
}

func readDbConf(path string) (db, uname, passwd, fullname, email, www string) {
    b, err := ioutil.ReadFile(path)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    var config DbConfig
    err = json.Unmarshal(b, &config)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    return config["db_file"], config["uname"], config["passwd"],
        config["fullname"], config["email"], config["www"]
}

func main() {
    dbconf := flag.String("db", "", "Database configuration file (required)")
    srcData := flag.String("src", "", "Can be either a directory, or a path to DB dump configuration file (required)")
    migrateOnly := flag.Bool("notest", false, "Don't populate DB with test data, only migrate what's in -src. (optional)")
    flag.Usage = usage
    flag.Parse()
    if *dbconf == "" || *srcData == "" {
        usage()
        return
    }
    db, uname, passwd, fullname, email, www := readDbConf(*dbconf)
    if !strings.HasSuffix(db, ".db") {
        fmt.Printf("File name is supposed to have a .db extension, but was %q\n", db)
        usage()
        return
    }
    dbFile, _ := filepath.Abs(db)
    init_db(dbFile, uname, passwd, fullname, email, www)
    srcFile, err := os.Open(*srcData)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer srcFile.Close()
    fi, err := srcFile.Stat()
    if err != nil {
        fmt.Println(err)
        return
    }
    if fi.IsDir() {
        populate(dbFile)
        data, err := readTextEntries(*srcData)
        if err != nil {
            println(err.Error())
            return
        }
        populate2(dbFile, data)
    } else {
        if !*migrateOnly {
            populate(dbFile)
        }
        importLegacyDb(db, *srcData)
    }
}
<commit_msg>dbtool: fix path to db<commit_after>package main

import (
    "bytes"
    "crypto/rand"
    "crypto/sha1"
    "database/sql"
    "encoding/base64"
    "encoding/json"
    "flag"
    "fmt"
    "io"
    "io/ioutil"
    "net/mail"
    "os"
    "path/filepath"
    "strings"
    "time"

    _ "github.com/mattn/go-sqlite3"
)

func usage() {
    fmt.Fprintf(os.Stderr, "usage: %s [params]\n", filepath.Base(os.Args[0]))
    flag.PrintDefaults()
    os.Exit(2)
}

func encrypt(passwd string) (salt, hash string) {
    b := make([]byte, 16)
    n, err := io.ReadFull(rand.Reader, b)
    if n != len(b) || err != nil {
        fmt.Println("error:", err)
        return
    }
    salt = base64.URLEncoding.EncodeToString(b)
    sha := sha1.New()
    sha.Write([]byte(salt + passwd))
    hash = base64.URLEncoding.EncodeToString(sha.Sum(nil))
    return
}

func init_db(fileName, uname, passwd, fullname, email, www string) {
    createTables := []string{
        `create table tag (
            id integer not null primary key,
            name text,
            url text
        )`,
        `create table author (
            id integer not null primary key,
            disp_name text,
            salt text,
            passwd text,
            full_name text,
            email text,
            www text
        )`,
        `create table post (
            id integer not null primary key,
            author_id integer not null references author(id) on delete cascade on update cascade,
            title text,
            date long,
            url text,
            body text
        )`,
        `create table tagmap (
            id integer not null primary key,
            tag_id integer not null references tag(id) on delete cascade on update cascade,
            post_id integer not null references post(id) on delete cascade on update cascade
        )`,
        `create table commenter (
            id integer not null primary key,
            name text,
            email text,
            www text,
            ip text
        )`,
        `create table comment (
            id integer not null primary key,
            commenter_id integer not null references commenter(id) on delete cascade on update cascade,
            post_id integer not null references post(id) on delete cascade on update cascade,
            timestamp long,
            body text
        )`,
    }
    err := os.Remove(fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    db, err := sql.Open("sqlite3", fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer db.Close()
    for _, sql := range createTables {
        _, err := db.Exec(sql)
        if err != nil {
            fmt.Printf("%q: %s\n", err, sql)
            return
        }
    }
    stmt, _ := db.Prepare(`insert into author(id, disp_name, salt, passwd, full_name, email, www)
                           values(?, ?, ?, ?, ?, ?, ?)`)
    defer stmt.Close()
    salt, passwdHash := encrypt(passwd)
    stmt.Exec(1, uname, salt, passwdHash, fullname, email, www)
}

func populate(fileName string) {
    db, err := sql.Open("sqlite3", fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer db.Close()
    xaction, err := db.Begin()
    if err != nil {
        fmt.Println(err)
        return
    }
    stmt, _ := xaction.Prepare("insert into post(id, author_id, title, date, url, body) values(?, ?, ?, ?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, 1, "Labadėna", 123456, "labadena", "Nieko aš čia nerašysiu.")
    imgpost := `This is a post with a figure.

halfimage:

![hi][halfimg]

([Full size][fullimg])

[fullimg]: /no-dox.png
[halfimg]: /no-dox-halfsize.png`
    stmt.Exec(2, 1, "Iliustruotas", 1359308741, "iliustruotas", imgpost)
    stmt, _ = xaction.Prepare("insert into tag(id, name, url) values(?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, "Testas", "testas")
    stmt.Exec(2, "Žąsyčiai", "geese")
    stmt, _ = xaction.Prepare("insert into tagmap(id, tag_id, post_id) values(?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, 1, 1)
    stmt.Exec(2, 2, 1)
    stmt, _ = xaction.Prepare("insert into commenter(id, name, email, www, ip) values(?, ?, ?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, "Vytautas Šaltenis", "Vytautas.Shaltenis@gmail.com", "http://rtfb.lt", "127.0.0.1")
    stmt.Exec(2, "Vardenis Pavardenis", "niekas@niekur.com", "http://delfi.lt", "127.0.0.1")
    stmt, _ = xaction.Prepare("insert into comment(id, commenter_id, post_id, timestamp, body) values(?, ?, ?, ?, ?)")
    defer stmt.Close()
    stmt.Exec(1, 2, 1, 1356872181, "Nu ir nerašyk, _niekam_ čia neįdomu tavo pisulkos.")
    stmt.Exec(2, 1, 1, 1356879181, "O tu čia tada **nekomentuok** ten kur neparašyta nieko. Eik [ten](http://google.com/)")
    xaction.Commit()
}

func populate2(fileName string, data []*Entry) {
    db, err := sql.Open("sqlite3", fileName)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer db.Close()
    xaction, err := db.Begin()
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, e := range data {
        stmt, _ := xaction.Prepare("insert into post(author_id, title, date, url, body) values(?, ?, ?, ?, ?)")
        defer stmt.Close()
        date, _ := time.Parse("2006-01-02", e.Date)
        result, _ := stmt.Exec(1, e.Title, date.Unix(), e.Url, e.Body)
        postId, _ := result.LastInsertId()
        for _, t := range e.Tags {
            stmt, _ = xaction.Prepare("insert into tag(name, url) values(?, ?)")
            defer stmt.Close()
            result, _ = stmt.Exec(t.TagName, t.TagUrl)
            tagId, _ := result.LastInsertId()
            stmt, _ = xaction.Prepare("insert into tagmap(tag_id, post_id) values(?, ?)")
            defer stmt.Close()
            stmt.Exec(tagId, postId)
        }
    }
    xaction.Commit()
}

type Tag struct {
    TagUrl  string
    TagName string
}

type Entry struct {
    Author string
    Title  string
    Date   string
    Body   string
    Url    string
    Tags   []*Tag
}

func parseTags(tagList string) (tags []*Tag) {
    for _, t := range strings.Split(tagList, ", ") {
        if t == "" {
            continue
        }
        tag := new(Tag)
        tag.TagUrl = strings.ToLower(t)
        tag.TagName = t
        tags = append(tags, tag)
    }
    return
}

func readTextEntry(filename string) (entry *Entry, err error) {
    f, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    msg, err := mail.ReadMessage(f)
    if err != nil {
        return nil, err
    }
    entry = new(Entry)
    entry.Title = msg.Header.Get("subject")
    entry.Author = msg.Header.Get("author")
    entry.Date = msg.Header.Get("isodate")
    entry.Tags = parseTags(msg.Header.Get("tags"))
    base := filepath.Base(filename)
    entry.Url = base[:strings.LastIndex(base, filepath.Ext(filename))]
    buf := new(bytes.Buffer)
    buf.ReadFrom(msg.Body)
    entry.Body = buf.String()
    return
}

func readTextEntries(root string) (entries []*Entry, err error) {
    filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if strings.ToLower(filepath.Ext(path)) != ".txt" {
            return nil
        }
        entry, _ := readTextEntry(path)
        if entry == nil {
            return nil
        }
        entries = append(entries, entry)
        return nil
    })
    return
}

func readDbConf(path string) (db, uname, passwd, fullname, email, www string) {
    b, err := ioutil.ReadFile(path)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    var config DbConfig
    err = json.Unmarshal(b, &config)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    return config["db_file"], config["uname"], config["passwd"],
        config["fullname"], config["email"], config["www"]
}

func main() {
    dbconf := flag.String("db", "", "Database configuration file (required)")
    srcData := flag.String("src", "", "Can be either a directory, or a path to DB dump configuration file (required)")
    migrateOnly := flag.Bool("notest", false, "Don't populate DB with test data, only migrate what's in -src. (optional)")
    flag.Usage = usage
    flag.Parse()
    if *dbconf == "" || *srcData == "" {
        usage()
        return
    }
    root, _ := filepath.Split(filepath.Clean(*dbconf))
    db, uname, passwd, fullname, email, www := readDbConf(*dbconf)
    if !strings.HasSuffix(db, ".db") {
        fmt.Printf("File name is supposed to have a .db extension, but was %q\n", db)
        usage()
        return
    }
    dbFile := filepath.Join(root, db)
    init_db(dbFile, uname, passwd, fullname, email, www)
    srcFile, err := os.Open(*srcData)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer srcFile.Close()
    fi, err := srcFile.Stat()
    if err != nil {
        fmt.Println(err)
        return
    }
    if fi.IsDir() {
        populate(dbFile)
        data, err := readTextEntries(*srcData)
        if err != nil {
            println(err.Error())
            return
        }
        populate2(dbFile, data)
    } else {
        if !*migrateOnly {
            populate(dbFile)
        }
        importLegacyDb(dbFile, *srcData)
    }
}
<|endoftext|>


<commit_before>package dbus

import (
	"testing"
)

// TestBasicSetActions asserts that Add & Remove behavior is correct
func TestBasicSetActions(t *testing.T) {
	s := set{}

	if s.Contains("foo") {
		t.Fatal("set should not contain 'foo'")
	}

	s.Add("foo")

	if !s.Contains("foo") {
		t.Fatal("set should contain 'foo'")
	}

	s.Remove("foo")

	if s.Contains("foo") {
		t.Fatal("set should not contain 'foo'")
	}
}
<commit_msg>Fix TestBasicSetActions.<commit_after>package dbus

import (
	"testing"
)

// TestBasicSetActions asserts that Add & Remove behavior is correct
func TestBasicSetActions(t *testing.T) {
	s := newSet()

	if s.Contains("foo") {
		t.Fatal("set should not contain 'foo'")
	}

	s.Add("foo")

	if !s.Contains("foo") {
		t.Fatal("set should contain 'foo'")
	}

	s.Remove("foo")

	if s.Contains("foo") {
		t.Fatal("set should not contain 'foo'")
	}
}
<|endoftext|>