ronantakizawa/codereview-bench huggingface dataset:
Repository: hashicorp/nomad
File: command/agent/command.go (Go)

Code before:
// handleSignals blocks until we get an exit-causing signal
func (c *Command) handleSignals() int {
	signalCh := make(chan os.Signal, 4)
	defer close(signalCh)

	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE)

	// Signal readiness only once signal handlers are setup
	sdSock, err := openNotify()
	if err != nil {
		c.agent.logger.Debug("notify socket could not be accessed", "error", err)
	}

	if sdSock != nil {
		defer sdSock.Close()
	}
	sdNotify(sdSock, sdReady)

	for {
		select {
		case sig := <-signalCh:
			c.Ui.Output(fmt.Sprintf("Caught signal: %v", sig))

			switch sig {
			case syscall.SIGPIPE:
				// Skip any SIGPIPE signal and don't try to log it (See issues #1798, #3554)
				continue
			case syscall.SIGHUP:
				sdNotifyReloading(sdSock)
				err := c.handleReload()
				if err != nil {
					c.Ui.Output("Terminal error found while reloading")
					return 1
				}

				sdNotify(sdSock, sdReady)
			case syscall.SIGTERM:
				if !c.agent.GetConfig().LeaveOnTerm {
					return 1
				}

				return c.terminateGracefully(signalCh, sdSock)
			case os.Interrupt:
				if !c.agent.GetConfig().LeaveOnInt {
					return 1
				}

				return c.terminateGracefully(signalCh, sdSock)
			}

		case <-winsvc.ShutdownChannel():

Review comment (suggestion):
Because we're not catching the SIGPIPE before we call `c.Ui.Output`, we'll end up logging it here whenever journald restarts. That's probably ok, but let's fix the comment:

```suggestion
				// Skip any SIGPIPE signal (see issues #1798, #3554)
```

Code after:
	// Wait for leave or another signal
	select {
	case <-signalCh:
		return 1
	case <-delay.C:
		return 1
	case <-gracefulCh:
	}

	return 0
}

// handleSignals blocks until we get an exit-causing signal
func (c *Command) handleSignals() int {
	signalCh := make(chan os.Signal, 4)
	defer signal.Stop(signalCh)

	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE)

	// Signal readiness only once signal handlers are setup
	sdSock, err := openNotify()
	if err != nil {
		c.agent.logger.Debug("notify socket could not be accessed", "error", err)
	}

	if sdSock != nil {
		defer sdSock.Close()
	}
	sdNotify(sdSock, sdReady)

	for {
		select {
		case sig := <-signalCh:
			c.Ui.Output(fmt.Sprintf("Caught signal: %v", sig))

			switch sig {
			case syscall.SIGPIPE:
				// Skip any SIGPIPE signal (see issues #1798, #3554)
				continue
			case syscall.SIGHUP:
				sdNotifyReloading(sdSock)
				err := c.handleReload()
				if err != nil {
					c.Ui.Error(fmt.Sprintf("Fatal error while reloading: %v", err))
					return 1
				}

				sdNotify(sdSock, sdReady)
			case syscall.SIGTERM:
				if !c.agent.GetConfig().LeaveOnTerm {
					return 1
Repository: hashicorp/nomad
File: command/agent/command.go (Go)

Code before:

	// Signal readiness only once signal handlers are setup
	sdSock, err := openNotify()
	if err != nil {
		c.agent.logger.Debug("notify socket could not be accessed", "error", err)
	}

	if sdSock != nil {
		defer sdSock.Close()
	}
	sdNotify(sdSock, sdReady)

	for {
		select {
		case sig := <-signalCh:
			c.Ui.Output(fmt.Sprintf("Caught signal: %v", sig))

			switch sig {
			case syscall.SIGPIPE:
				// Skip any SIGPIPE signal and don't try to log it (See issues #1798, #3554)
				continue
			case syscall.SIGHUP:
				sdNotifyReloading(sdSock)
				err := c.handleReload()
				if err != nil {
					c.Ui.Output("Terminal error found while reloading")
					return 1
				}

				sdNotify(sdSock, sdReady)
			case syscall.SIGTERM:
				if !c.agent.GetConfig().LeaveOnTerm {
					return 1
				}

				return c.terminateGracefully(signalCh, sdSock)
			case os.Interrupt:
				if !c.agent.GetConfig().LeaveOnInt {
					return 1
				}

				return c.terminateGracefully(signalCh, sdSock)
			}

		case <-winsvc.ShutdownChannel():
			if !c.agent.GetConfig().LeaveOnInt {
				return 1
			}

			return c.terminateGracefully(signalCh, sdSock)


Review comment (suggestion):
I think we usually use the term "fatal" for this. But also, should this report the error?

```suggestion
					c.Ui.Error(fmt.Sprintf("Fatal error while reloading: %v", err)
```

Code after:
	case <-gracefulCh:
	}

	return 0
}

// handleSignals blocks until we get an exit-causing signal
func (c *Command) handleSignals() int {
	signalCh := make(chan os.Signal, 4)
	defer signal.Stop(signalCh)

	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE)

	// Signal readiness only once signal handlers are setup
	sdSock, err := openNotify()
	if err != nil {
		c.agent.logger.Debug("notify socket could not be accessed", "error", err)
	}

	if sdSock != nil {
		defer sdSock.Close()
	}
	sdNotify(sdSock, sdReady)

	for {
		select {
		case sig := <-signalCh:
			c.Ui.Output(fmt.Sprintf("Caught signal: %v", sig))

			switch sig {
			case syscall.SIGPIPE:
				// Skip any SIGPIPE signal (see issues #1798, #3554)
				continue
			case syscall.SIGHUP:
				sdNotifyReloading(sdSock)
				err := c.handleReload()
				if err != nil {
					c.Ui.Error(fmt.Sprintf("Fatal error while reloading: %v", err))
					return 1
				}

				sdNotify(sdSock, sdReady)
			case syscall.SIGTERM:
				if !c.agent.GetConfig().LeaveOnTerm {
					return 1
				}

				return c.terminateGracefully(signalCh, sdSock)
			case os.Interrupt:
				if !c.agent.GetConfig().LeaveOnInt {
					return 1
Repository: hashicorp/nomad
File: command/agent/command.go (Go)

Code before:
	go func() {
		if err := c.agent.Leave(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error: %s", err))
			return
		}
		close(gracefulCh)
	}()

	delay := time.NewTimer(gracefulTimeout)

	// Wait for leave or another signal
	select {
	case <-signalCh:
		return 1
	case <-delay.C:
		return 1
	case <-gracefulCh:
	}

	return 0
}

// handleSignals blocks until we get an exit-causing signal
func (c *Command) handleSignals() int {
	signalCh := make(chan os.Signal, 4)
	defer close(signalCh)

	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE)

	// Signal readiness only once signal handlers are setup
	sdSock, err := openNotify()
	if err != nil {
		c.agent.logger.Debug("notify socket could not be accessed", "error", err)
	}

	if sdSock != nil {
		defer sdSock.Close()
	}
	sdNotify(sdSock, sdReady)

	for {
		select {
		case sig := <-signalCh:
			c.Ui.Output(fmt.Sprintf("Caught signal: %v", sig))

			switch sig {
			case syscall.SIGPIPE:
				// Skip any SIGPIPE signal and don't try to log it (See issues #1798, #3554)
				continue
			case syscall.SIGHUP:
				sdNotifyReloading(sdSock)

Review comment (suggestion):
I'm actually not sure what the behavior of closing the signal chan does. I think the preferred mechanism to cleanup signal handling is to call [`signal.Stop(...)`](https://pkg.go.dev/os/signal@go1.24.2#Stop)

```suggestion
	defer signal.Stop(signalCh)
```

Code after:
	timeout := gracefulTimeout

	config := c.agent.client.GetConfig()
	if config == nil {
		c.Ui.Output("Unable to read the agent configuration, using the default graceful timeout")
	}

	if config.Drain != nil && config.Drain.Deadline != 0 {
		timeout += config.Drain.Deadline
	}

	c.Ui.Output("Gracefully shutting down agent...")
	go func() {
		if err := c.agent.Leave(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error: %s", err))
			return
		}
		close(gracefulCh)
	}()

	delay := time.NewTimer(timeout)

	// Wait for leave or another signal
	select {
	case <-signalCh:
		return 1
	case <-delay.C:
		return 1
	case <-gracefulCh:
	}

	return 0
}

// handleSignals blocks until we get an exit-causing signal
func (c *Command) handleSignals() int {
	signalCh := make(chan os.Signal, 4)
	defer signal.Stop(signalCh)

	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE)

	// Signal readiness only once signal handlers are setup
	sdSock, err := openNotify()
	if err != nil {
		c.agent.logger.Debug("notify socket could not be accessed", "error", err)
	}

	if sdSock != nil {
		defer sdSock.Close()
	}
	sdNotify(sdSock, sdReady)
Repository: hashicorp/nomad
File: command/agent/command.go (Go)

Code before:
			errCh:        c.retryJoinErrCh,
			joinCfg:      config.Client.ServerJoin,
			joinFunc:     c.agent.client.SetServers,
			logger:       c.agent.logger.Named("joiner").With("agent_mode", "client"),
		}

		if err := joiner.Validate(config); err != nil {
			return err
		}

		go joiner.RetryJoin()
	}

	return nil
}

// terminateGracefully attempts a graceful leave
func (c *Command) terminateGracefully(signalCh chan os.Signal, sdSock io.Writer) int {
	sdNotify(sdSock, sdStopping)

	gracefulCh := make(chan struct{})
	defer close(gracefulCh)

	timeout := gracefulTimeout

	config := c.agent.config
	if config == nil {
		c.Ui.Output("Unable to read the agent configuration, using the default graceful timeout")
	}

	if config.Client != nil && config.Client.Drain != nil && config.Client.Drain.Deadline != nil {
		ddl, err := time.ParseDuration(*config.Client.Drain.Deadline)
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Unable to read the client's drain deadline, using the default graceful timeout: %s", err))
		}

		if ddl != 0 {
			timeout += ddl
		}
	}

	c.Ui.Output("Gracefully shutting down agent...")
	go func() {
		if err := c.agent.Leave(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error: %s", err))
			return
		}
		close(gracefulCh)
	}()

	delay := time.NewTimer(timeout)

Review comment (suggestion):
We should be using the `configLock` around the agent configuration here. And then we probably need to release it right away rather than waiting for the `defer`.


Code after:
			errCh:        c.retryJoinErrCh,
			joinCfg:      config.Client.ServerJoin,
			joinFunc:     c.agent.client.SetServers,
			logger:       c.agent.logger.Named("joiner").With("agent_mode", "client"),
		}

		if err := joiner.Validate(config); err != nil {
			return err
		}

		go joiner.RetryJoin()
	}

	return nil
}

// terminateGracefully attempts a graceful leave
func (c *Command) terminateGracefully(signalCh chan os.Signal, sdSock io.Writer) int {
	sdNotify(sdSock, sdStopping)

	gracefulCh := make(chan struct{})
	defer close(gracefulCh)

	timeout := gracefulTimeout

	config := c.agent.client.GetConfig()
	if config == nil {
		c.Ui.Output("Unable to read the agent configuration, using the default graceful timeout")
	}

	if config.Drain != nil && config.Drain.Deadline != 0 {
		timeout += config.Drain.Deadline
	}

	c.Ui.Output("Gracefully shutting down agent...")
	go func() {
		if err := c.agent.Leave(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error: %s", err))
			return
		}
		close(gracefulCh)
	}()

	delay := time.NewTimer(timeout)

	// Wait for leave or another signal
	select {
	case <-signalCh:
		return 1
	case <-delay.C:
		return 1
Repository: hashicorp/nomad
File: command/agent/command.go (Go)

Code before:

		go joiner.RetryJoin()
	}

	return nil
}

// terminateGracefully attempts a graceful leave
func (c *Command) terminateGracefully(signalCh chan os.Signal, sdSock io.Writer) int {
	sdNotify(sdSock, sdStopping)

	gracefulCh := make(chan struct{})
	defer close(gracefulCh)

	timeout := gracefulTimeout

	config := c.agent.config
	if config == nil {
		c.Ui.Output("Unable to read the agent configuration, using the default graceful timeout")
	}

	if config.Client != nil && config.Client.Drain != nil && config.Client.Drain.Deadline != nil {
		ddl, err := time.ParseDuration(*config.Client.Drain.Deadline)
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Unable to read the client's drain deadline, using the default graceful timeout: %s", err))
		}

		if ddl != 0 {
			timeout += ddl
		}
	}

	c.Ui.Output("Gracefully shutting down agent...")
	go func() {
		if err := c.agent.Leave(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error: %s", err))
			return
		}
		close(gracefulCh)
	}()

	delay := time.NewTimer(timeout)

	// Wait for leave or another signal
	select {
	case <-signalCh:
		return 1
	case <-delay.C:
		return 1
	case <-gracefulCh:
	}

Review comment (suggestion):
Another option would be to look at `c.agent.client.GetConfig().Drain.Deadline` to get the client's already-parsed configuration so we don't have to re-parse the HCL value and we can't ever hit an error.

Code after:

		go joiner.RetryJoin()
	}

	return nil
}

// terminateGracefully attempts a graceful leave
func (c *Command) terminateGracefully(signalCh chan os.Signal, sdSock io.Writer) int {
	sdNotify(sdSock, sdStopping)

	gracefulCh := make(chan struct{})
	defer close(gracefulCh)

	timeout := gracefulTimeout

	config := c.agent.client.GetConfig()
	if config == nil {
		c.Ui.Output("Unable to read the agent configuration, using the default graceful timeout")
	}

	if config.Drain != nil && config.Drain.Deadline != 0 {
		timeout += config.Drain.Deadline
	}

	c.Ui.Output("Gracefully shutting down agent...")
	go func() {
		if err := c.agent.Leave(); err != nil {
			c.Ui.Error(fmt.Sprintf("Error: %s", err))
			return
		}
		close(gracefulCh)
	}()

	delay := time.NewTimer(timeout)

	// Wait for leave or another signal
	select {
	case <-signalCh:
		return 1
	case <-delay.C:
		return 1
	case <-gracefulCh:
	}

	return 0
}

// handleSignals blocks until we get an exit-causing signal
func (c *Command) handleSignals() int {
	signalCh := make(chan os.Signal, 4)
Repository: hashicorp/nomad
File: command/node_status.go (Go)

Code before:

		out[0] += "Drain|Eligibility|Status"

		if c.list_allocs {
			out[0] += "|Running Allocs"
		}

		for i, node := range nodes {
			out[i+1] = fmt.Sprintf("%s|%s|%s|%s|%s",
				limit(node.ID, c.length),
				node.NodePool,
				node.Datacenter,
				node.Name,
				node.NodeClass)
			if c.os {
				out[i+1] += fmt.Sprintf("|%s", node.Attributes["os.name"])
			}
			if c.verbose {
				var nodeMaxAlloc string
				if node.NodeMaxAllocs == 0 {
					nodeMaxAlloc = "N/A"
				} else {
					nodeMaxAlloc = strconv.FormatUint(node.NodeMaxAllocs, 10)
				}
				out[i+1] += fmt.Sprintf("|%s|%s|%s",
					node.Address, node.Version, nodeMaxAlloc)
			}
			out[i+1] += fmt.Sprintf("|%v|%s|%s",
				node.Drain,
				node.SchedulingEligibility,
				node.Status)

			if c.list_allocs {
				numAllocs, err := getRunningAllocs(client, node.ID)
				if err != nil {
					c.Ui.Error(fmt.Sprintf("Error querying node allocations: %s", err))
					return 1
				}
				out[i+1] += fmt.Sprintf("|%v",
					len(numAllocs))
			}
		}

		// Dump the output
		c.Ui.Output(formatList(out))

		if qm.NextToken != "" {
			c.Ui.Output(fmt.Sprintf(`
Results have been paginated. To get the next page run:

%s -page-token %s`, argsWithoutPageToken(os.Args), qm.NextToken))

Review comment (suggestion):
There's a very small number of fields on this `nomad status` list. It doesn't seem like the max allocs allowed on a node rises to that level of importance? I'd leave it out of this output.

Code after:

		out[0] += "Drain|Eligibility|Status"

		if c.list_allocs {
			out[0] += "|Running Allocs"
		}

		for i, node := range nodes {
			out[i+1] = fmt.Sprintf("%s|%s|%s|%s|%s",
				limit(node.ID, c.length),
				node.NodePool,
				node.Datacenter,
				node.Name,
				node.NodeClass)
			if c.os {
				out[i+1] += fmt.Sprintf("|%s", node.Attributes["os.name"])
			}
			if c.verbose {
				out[i+1] += fmt.Sprintf("|%s|%s",
					node.Address, node.Version)
			}
			out[i+1] += fmt.Sprintf("|%v|%s|%s",
				node.Drain,
				node.SchedulingEligibility,
				node.Status)

			if c.list_allocs {
				numAllocs, err := getRunningAllocs(client, node.ID)
				if err != nil {
					c.Ui.Error(fmt.Sprintf("Error querying node allocations: %s", err))
					return 1
				}
				out[i+1] += fmt.Sprintf("|%v",
					len(numAllocs))
			}
		}

		// Dump the output
		c.Ui.Output(formatList(out))

		if qm.NextToken != "" {
			c.Ui.Output(fmt.Sprintf(`
Results have been paginated. To get the next page run:

%s -page-token %s`, argsWithoutPageToken(os.Args), qm.NextToken))
		}

		hint, _ := c.Meta.showUIPath(UIHintContext{
			Command: c.Name(),
			OpenURL: c.openURL,
		})
Repository: hashicorp/nomad
File: scheduler/rank_test.go (Go)

Code before:
		},
		{
			name:     "no_nodes",
			maxAlloc: 0,
			tasks: []*structs.Task{
				taskGen("web1"),
				taskGen("web2"),
				taskGen("web3")},
			nodesPlaced: 0,
			noNodes:     true,
		},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			if tc.noNodes {
				// Note: test case order matters here
				for _, v := range nodes {
					v.Node.NodeMaxAllocs = &structs.NodeMaxAllocs{
						MaxAllocs: tc.maxAlloc,
					}
				}
			}
			// only add allocation limit to first node except in noNodes
			nodes[0].Node.NodeMaxAllocs = &structs.NodeMaxAllocs{
				MaxAllocs: tc.maxAlloc,
			}
			static := NewStaticRankIterator(ctx, nodes)

			// Create task group with empty resource sets
			taskGroup := &structs.TaskGroup{
				EphemeralDisk: &structs.EphemeralDisk{},
				Tasks:         tc.tasks,
			}
			// Create BinPackIterator and evaluate tasks
			binp := NewBinPackIterator(ctx, static, false, 0)
			binp.SetTaskGroup(taskGroup)
			binp.SetSchedulerConfiguration(testSchedulerConfig)
			scoreNorm := NewScoreNormalizationIterator(ctx, binp)

			// Place tasks
			out := collectRanked(scoreNorm)
			must.Len(t, tc.nodesPlaced, out)
		})
	}
}
func TestJobAntiAffinity_PlannedAlloc(t *testing.T) {
	_, ctx := testContext(t)
	nodes := []*RankedNode{
		{
			Node: &structs.Node{
				ID: uuid.Generate(),

Review comment (suggestion):
This test is fine in terms of correctness. But from a test design standpoint it might be nice if you had explicit `maxAllocNode0` and `maxAllocNode1` fields in the test cases instead of having conditional test setup logic here. That way someone reading the test can look at a given test case and just see the inputs and outputs, and the test itself has no logic except calling the functions under test.

Code after:
		TaskGroup:          "web",
	}
	must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
	must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
	must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))

	testCases := []struct {
		name          string
		maxAllocNode1 int
		maxAllocNode2 int
		tasks         []*structs.Task
		tasksOn1      int
		nodesPlaced   int
		noNodes       bool
	}{
		{
			name:          "both_nodes",
			maxAllocNode1: 2,
			maxAllocNode2: 2,
			tasks: []*structs.Task{
				taskGen("web1"),
				taskGen("web2"),
				taskGen("web3")},
			nodesPlaced: 2,
		},
		{
			name:          "only_node2",
			maxAllocNode1: 1,
			maxAllocNode2: 2,
			tasks: []*structs.Task{
				taskGen("web1"),
				taskGen("web2"),
				taskGen("web3")},
			nodesPlaced: 1,
		},
		{
			name:          "no_nodes",
			maxAllocNode1: 1,
			maxAllocNode2: 1,
			tasks: []*structs.Task{
				taskGen("web1"),
				taskGen("web2"),
				taskGen("web3")},
			nodesPlaced: 0,
			noNodes:     true,
		},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			// add allocation limits
			nodes[0].Node.NodeMaxAllocs = tc.maxAllocNode1
Repository: hashicorp/nomad
File: nomad/structs/funcs_test.go (Go)

Code before:
			expectErr:   false,
			maxAllocs:   2,
		},
		{
			name:        "too many allocs",
			allocations: []*Allocation{baseAlloc, baseAlloc, baseAlloc},
			expectErr:   true,
			maxAllocs:   2,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			n := node2k()
			n.NodeMaxAllocs = &NodeMaxAllocs{tc.maxAllocs}
			fit, dim, used, err := AllocsFit(n, tc.allocations, nil, false)
			if !tc.expectErr {
				must.NoError(t, err)
				must.True(t, fit)
				must.Eq(t, 1000, used.Flattened.Cpu.CpuShares)
				must.Eq(t, 1024, used.Flattened.Memory.MemoryMB)
			} else {
				must.Error(t, err)
				must.False(t, fit)
				must.StrContains(t, dim, "max allocation exceeded")
				must.StrContains(t, err.Error(), "plan exceeds max allocation")
				must.Eq(t, 0, used.Flattened.Cpu.CpuShares)
				must.Eq(t, 0, used.Flattened.Memory.MemoryMB)
			}
		})
	}
}
func TestACLPolicyListHash(t *testing.T) {
	ci.Parallel(t)

	h1 := ACLPolicyListHash(nil)
	assert.NotEqual(t, "", h1)

	p1 := &ACLPolicy{
		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
		Description: "Super cool policy!",
		Rules: `
		namespace "default" {
			policy = "write"
		}
		node {
			policy = "read"
		}
		agent {
			policy = "read"
		}

Review comment (suggestion):
`ErrorContains` contains a nil-check for the error, so we can combine these:

```suggestion
				must.ErrorContains(t, err, "plan exceeded max allocation")
				must.False(t, fit)
				must.StrContains(t, dim, "max allocation exceeded")
```


Code after:
			expectErr:   false,
			maxAllocs:   2,
		},
		{
			name:        "too many allocs",
			allocations: []*Allocation{baseAlloc, baseAlloc, baseAlloc},
			expectErr:   true,
			maxAllocs:   2,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			n := node2k()
			n.NodeMaxAllocs = tc.maxAllocs
			fit, dim, used, err := AllocsFit(n, tc.allocations, nil, false)
			if !tc.expectErr {
				must.NoError(t, err)
				must.True(t, fit)
				must.Eq(t, 1000, used.Flattened.Cpu.CpuShares)
				must.Eq(t, 1024, used.Flattened.Memory.MemoryMB)
			} else {
				must.False(t, fit)
				must.StrContains(t, dim, "max allocation exceeded")
				must.ErrorContains(t, err, "plan exceeds max allocation")
				must.Eq(t, 0, used.Flattened.Cpu.CpuShares)
				must.Eq(t, 0, used.Flattened.Memory.MemoryMB)
			}
		})
	}
}
func TestACLPolicyListHash(t *testing.T) {
	ci.Parallel(t)

	h1 := ACLPolicyListHash(nil)
	assert.NotEqual(t, "", h1)

	p1 := &ACLPolicy{
		Name:        fmt.Sprintf("policy-%s", uuid.Generate()),
		Description: "Super cool policy!",
		Rules: `
		namespace "default" {
			policy = "write"
		}
		node {
			policy = "read"
		}
		agent {
			policy = "read"
		}
		`,