<commit_before>package main

import (
	"encoding/json"
	"syscall"
	"time"

	ct "github.com/flynn/flynn/controller/types"
	"github.com/flynn/flynn/host/types"
	logaggc "github.com/flynn/flynn/logaggregator/client"
	logagg "github.com/flynn/flynn/logaggregator/types"
	"github.com/flynn/flynn/pkg/exec"
	c "github.com/flynn/go-check"
)

type HostUpdateSuite struct {
	Helper
}

var _ = c.ConcurrentSuite(&HostUpdateSuite{})

func (s *HostUpdateSuite) TestUpdateLogs(t *c.C) {
	x := s.bootCluster(t, 1)
	defer x.Destroy()

	hosts, err := x.cluster.Hosts()
	t.Assert(err, c.IsNil)
	t.Assert(hosts, c.HasLen, 1)

	app := &ct.App{Name: "partial-logger"}
	t.Assert(x.controller.CreateApp(app), c.IsNil)

	// start partial logger job
	cmd := exec.JobUsingHost(
		hosts[0],
		s.createArtifactWithClient(t, "test-apps", x.controller),
		&host.Job{
			Config: host.ContainerConfig{Args: []string{"/bin/partial-logger"}},
			Metadata: map[string]string{
				"flynn-controller.app": app.ID,
			},
		},
	)
	t.Assert(cmd.Start(), c.IsNil)
	defer cmd.Kill()

	// wait for partial line
	_, err = x.discoverd.Instances("partial-logger", 10*time.Second)
	t.Assert(err, c.IsNil)

	// update flynn-host using the same flags
	status, err := hosts[0].GetStatus()
	t.Assert(err, c.IsNil)
	_, err = hosts[0].UpdateWithShutdownDelay(
		"/usr/local/bin/flynn-host",
		10*time.Second,
		append([]string{"daemon"}, status.Flags...)...,
	)
	t.Assert(err, c.IsNil)

	// stream the log
	log, err := x.controller.GetAppLog(app.ID, &logagg.LogOpts{Follow: true})
	t.Assert(err, c.IsNil)
	defer log.Close()

	msgs := make(chan *logaggc.Message)
	go func() {
		defer close(msgs)
		dec := json.NewDecoder(log)
		for {
			var msg logaggc.Message
			if err := dec.Decode(&msg); err != nil {
				debugf(t, "error decoding message: %s", err)
				return
			}
			msgs <- &msg
		}
	}()

	// finish logging
	t.Assert(hosts[0].SignalJob(cmd.Job.ID, int(syscall.SIGUSR1)), c.IsNil)

	// check we get a single log line
	for {
		select {
		case msg, ok := <-msgs:
			if !ok {
				t.Fatal("error getting log")
			}
			if msg.Stream == "stdout" {
				t.Assert(msg.Msg, c.Equals, "hello world")
				return
			}
		case <-time.After(10 * time.Second):
			t.Fatal("timed out waiting for log")
		}
	}
}<commit_msg>test: Use a new TCP connection after host update<commit_after>package main

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

	ct "github.com/flynn/flynn/controller/types"
	"github.com/flynn/flynn/host/types"
	logaggc "github.com/flynn/flynn/logaggregator/client"
	logagg "github.com/flynn/flynn/logaggregator/types"
	"github.com/flynn/flynn/pkg/cluster"
	"github.com/flynn/flynn/pkg/dialer"
	"github.com/flynn/flynn/pkg/exec"
	c "github.com/flynn/go-check"
)

type HostUpdateSuite struct {
	Helper
}

var _ = c.ConcurrentSuite(&HostUpdateSuite{})

func (s *HostUpdateSuite) TestUpdateLogs(t *c.C) {
	x := s.bootCluster(t, 1)
	defer x.Destroy()

	hosts, err := x.cluster.Hosts()
	t.Assert(err, c.IsNil)
	t.Assert(hosts, c.HasLen, 1)
	hostClient := hosts[0]

	app := &ct.App{Name: "partial-logger"}
	t.Assert(x.controller.CreateApp(app), c.IsNil)

	// start partial logger job
	cmd := exec.JobUsingHost(
		hostClient,
		s.createArtifactWithClient(t, "test-apps", x.controller),
		&host.Job{
			Config: host.ContainerConfig{Args: []string{"/bin/partial-logger"}},
			Metadata: map[string]string{
				"flynn-controller.app": app.ID,
			},
		},
	)
	t.Assert(cmd.Start(), c.IsNil)
	defer cmd.Kill()

	// wait for partial line
	_, err = x.discoverd.Instances("partial-logger", 10*time.Second)
	t.Assert(err, c.IsNil)

	// update flynn-host using the same flags
	status, err := hostClient.GetStatus()
	t.Assert(err, c.IsNil)
	_, err = hostClient.UpdateWithShutdownDelay(
		"/usr/local/bin/flynn-host",
		10*time.Second,
		append([]string{"daemon"}, status.Flags...)...,
	)
	t.Assert(err, c.IsNil)

	// stream the log
	log, err := x.controller.GetAppLog(app.ID, &logagg.LogOpts{Follow: true})
	t.Assert(err, c.IsNil)
	defer log.Close()

	msgs := make(chan *logaggc.Message)
	go func() {
		defer close(msgs)
		dec := json.NewDecoder(log)
		for {
			var msg logaggc.Message
			if err := dec.Decode(&msg); err != nil {
				debugf(t, "error decoding message: %s", err)
				return
			}
			msgs <- &msg
		}
	}()

	// finish logging using a new cluster client to avoid reusing the TCP
	// connection to the host which has shut down
	hostClient = cluster.NewHost(
		hostClient.ID(),
		hostClient.Addr(),
		&http.Client{Transport: &http.Transport{Dial: dialer.Retry.Dial}},
		hostClient.Tags(),
	)
	t.Assert(hostClient.SignalJob(cmd.Job.ID, int(syscall.SIGUSR1)), c.IsNil)

	// check we get a single log line
	for {
		select {
		case msg, ok := <-msgs:
			if !ok {
				t.Fatal("error getting log")
			}
			if msg.Stream == "stdout" {
				t.Assert(msg.Msg, c.Equals, "hello world")
				return
			}
		case <-time.After(10 * time.Second):
			t.Fatal("timed out waiting for log")
		}
	}
}
{'fraction_non_alphanumeric': 0.16764646259882424, 'fraction_numerical': 0.004662477194405028, 'mean_word_length': 3.5940409683426444, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 3, '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': '1427964', 'n_tokens_mistral': 2089, 'n_tokens_neox': 1907, 'n_words': 385}