<commit_before>package mig

import (
	"os/exec"
	"strings"
	"sync"
	"testing"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
)

/*mysql:
  requires mysqladmin
  create user 'testuser'@'localhost' identified by '<PASSWORD>password';
	grant all privileges on testdb . * to 'testuser'@'localhost';
*/

/*postgres:
  create user testuser;
	alter user testuser password '<PASSWORD>'
	alter user testuser createdb;
*/

func Test(t *testing.T) {
	//create the postgres table
	_ = exec.Command("dropdb", "-U", "testuser", "testdb").Run()
	output, err := exec.Command("createdb", "-U", "testuser", "testdb").CombinedOutput()
	defer exec.Command("dropdb", "-U", "testuser", "testdb").Run()
	if err != nil {
		t.Fatalf("couldn't create postgres db: %v, %s\n", err, output)
	}

	//create the mysql database
	mysqlTestDB := func(command string, input ...string) ([]byte, error) {
		cmd := exec.Command("mysqladmin", "-u", "testuser", command, "testdb")
		//passing passwords as command-line args in mysqladmin is broken: A space makes it prompt.
		cmd.Env = []string{"MYSQL_PWD=<PASSWORD>"}
		cmd.Stdin = strings.NewReader(strings.Join(input, " "))
		return cmd.CombinedOutput()
	}
	_, _ = mysqlTestDB("drop", "yes")
	output, err = mysqlTestDB("create")
	if err != nil {
		t.Fatalf("couldn't create mysql db: %v, %s\n", err, string(output))
	}
	defer mysqlTestDB("drop", "yes")

	pg, err := sqlx.Connect("postgres", "postgres://testuser:testpassword@localhost/testdb?sslmode=disable")
	if err != nil {
		t.Fatalf("couldn't connect to postgres test db: %v\n", err)
	}

	mysql, err := sqlx.Connect("mysql", "testuser:testpassword@/testdb")
	if err != nil {
		t.Fatalf("couldn't connect to mysql test db: %v\n", err)
	}

	pg.SetMaxOpenConns(30)
	mysql.SetMaxOpenConns(30)

	t.Run("database lock", func(t *testing.T) {
		testDatabaseLock(t, pg)
		testDatabaseLock(t, mysql)
	})

	// t.Run("re-run", func(t *testing.T) {
	// 	testReRun(t, pg)
	// 	testReRun(t, mysql)
	// })

	t.Run("prereq", func(t *testing.T) {
		testPrereq(t, pg)
		testPrereq(t, mysql)
	})

	t.Run("whitespace", func(t *testing.T) {
		testWhitespace(t, pg)
		testWhitespace(t, mysql)
	})
}

func testReRun(t *testing.T, db *sqlx.DB) {
	Register([]Step{
		{
			Migrate: `create table rerun(id int)`,
		},
	})

	_, err := db.Exec(`insert into rerun(id) values (42)`)
	if err != nil {
		t.Fatalf("inserting placeholder value: %v\n", err)
	}

}

func testPrereq(t *testing.T, db *sqlx.DB) {
	registered = nil
	Register([]Step{
		{
			Prereq: `
			  select 1 from test_prereq
			`,
			Migrate: `
			  alter table test_prereq add column food varchar(20)
			`,
		},
	})
<commit_msg>Add a test to ensure normal additions preserve values<commit_after>package mig

import (
	"os/exec"
	"strings"
	"sync"
	"testing"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
)

/*mysql:
  requires mysqladmin
  create user 'testuser'@'localhost' identified by 'testpassword';
	grant all privileges on testdb . * to 'testuser'@'localhost';
*/

/*postgres:
  create user testuser;
	alter user testuser password '<PASSWORD>'
	alter user testuser createdb;
*/

func Test(t *testing.T) {
	//create the postgres table
	_ = exec.Command("dropdb", "-U", "testuser", "testdb").Run()
	output, err := exec.Command("createdb", "-U", "testuser", "testdb").CombinedOutput()
	defer exec.Command("dropdb", "-U", "testuser", "testdb").Run()
	if err != nil {
		t.Fatalf("couldn't create postgres db: %v, %s\n", err, output)
	}

	//create the mysql database
	mysqlTestDB := func(command string, input ...string) ([]byte, error) {
		cmd := exec.Command("mysqladmin", "-u", "testuser", command, "testdb")
		//passing passwords as command-line args in mysqladmin is broken: A space makes it prompt.
		cmd.Env = []string{"MYSQL_PWD=<PASSWORD>"}
		cmd.Stdin = strings.NewReader(strings.Join(input, " "))
		return cmd.CombinedOutput()
	}
	_, _ = mysqlTestDB("drop", "yes")
	output, err = mysqlTestDB("create")
	if err != nil {
		t.Fatalf("couldn't create mysql db: %v, %s\n", err, string(output))
	}
	defer mysqlTestDB("drop", "yes")

	pg, err := sqlx.Connect("postgres", "postgres://testuser:testpassword@localhost/testdb?sslmode=disable")
	if err != nil {
		t.Fatalf("couldn't connect to postgres test db: %v\n", err)
	}

	mysql, err := sqlx.Connect("mysql", "testuser:testpassword@/testdb")
	if err != nil {
		t.Fatalf("couldn't connect to mysql test db: %v\n", err)
	}

	pg.SetMaxOpenConns(30)
	mysql.SetMaxOpenConns(30)

	t.Run("database lock", func(t *testing.T) {
		testDatabaseLock(t, pg)
		testDatabaseLock(t, mysql)
	})

	t.Run("values-preserved", func(t *testing.T) {
		testValuesPreserved(t, pg)
		testValuesPreserved(t, mysql)
	})

	t.Run("prereq", func(t *testing.T) {
		testPrereq(t, pg)
		testPrereq(t, mysql)
	})

	t.Run("whitespace", func(t *testing.T) {
		testWhitespace(t, pg)
		testWhitespace(t, mysql)
	})
}

func testValuesPreserved(t *testing.T, db *sqlx.DB) {
	registered = nil
	Register([]Step{
		{
			Migrate: `create table rerun(id int)`,
		},
	})

	err := Run(db)
	if err != nil {
		t.Fatalf("running migrations: %v\n", err)
	}

	_, err = db.Exec(`insert into rerun(id) values (42)`)
	if err != nil {
		t.Fatalf("inserting placeholder value: %v\n", err)
	}

	Register([]Step{
		{
			Migrate: `create table rerun(id int)`,
		},
		{
			Migrate: `alter table rerun add column name text`,
		},
	})

	var val int
	err = db.Get(&val, `select id from rerun limit 1`)
	if err != nil {
		t.Fatalf("getting placeholder value: %v\n", err)
	}

	if val != 42 {
		t.Fatalf(`val != 42, val == "%v"`, val)
	}

}

func testPrereq(t *testing.T, db *sqlx.DB) {
	registered = nil
	Register([]Step{
		{
			Prereq: `
			  select 1 from test_prereq
			`,
			Migrate: `
			  alter table test_prereq add column food varchar(20)
			`,
		},
	})

{'fraction_non_alphanumeric': 0.17612859097127223, 'fraction_numerical': 0.00393296853625171, 'mean_word_length': 3.9821124361158433, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1293824', 'n_tokens_mistral': 2382, 'n_tokens_neox': 2229, 'n_words': 532}