github.com/bigcommerce/nomad@v0.9.3-bc/nomad/plan_normalization_test.go (about)

     1  package nomad
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/hashicorp/nomad/nomad/mock"
     9  	"github.com/hashicorp/nomad/nomad/structs"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/ugorji/go/codec"
    12  )
    13  
    14  // This test compares the size of the normalized + OmitEmpty raft plan log entry
    15  // with the earlier denormalized log.
    16  //
    17  // Whenever this test is changed, care should be taken to ensure the older msgpack size
    18  // is recalculated when new fields are introduced in ApplyPlanResultsRequest
    19  func TestPlanNormalize(t *testing.T) {
    20  	// This size was calculated using the older ApplyPlanResultsRequest format, in which allocations
    21  	// didn't use OmitEmpty and only the job was normalized in the stopped and preempted allocs.
    22  	// The newer format uses OmitEmpty and uses a minimal set of fields for the diff of the
    23  	// stopped and preempted allocs. The file for the older format hasn't been checked in, because
    24  	// it's not a good idea to check-in a 20mb file to the git repo.
    25  	unoptimizedLogSize := 19460168
    26  
    27  	numUpdatedAllocs := 10000
    28  	numStoppedAllocs := 8000
    29  	numPreemptedAllocs := 2000
    30  	mockAlloc := mock.Alloc()
    31  	mockAlloc.Job = nil
    32  
    33  	mockUpdatedAllocSlice := make([]*structs.Allocation, numUpdatedAllocs)
    34  	for i := 0; i < numUpdatedAllocs; i++ {
    35  		mockUpdatedAllocSlice = append(mockUpdatedAllocSlice, mockAlloc)
    36  	}
    37  
    38  	now := time.Now().UTC().UnixNano()
    39  	mockStoppedAllocSlice := make([]*structs.AllocationDiff, numStoppedAllocs)
    40  	for i := 0; i < numStoppedAllocs; i++ {
    41  		mockStoppedAllocSlice = append(mockStoppedAllocSlice, normalizeStoppedAlloc(mockAlloc, now))
    42  	}
    43  
    44  	mockPreemptionAllocSlice := make([]*structs.AllocationDiff, numPreemptedAllocs)
    45  	for i := 0; i < numPreemptedAllocs; i++ {
    46  		mockPreemptionAllocSlice = append(mockPreemptionAllocSlice, normalizePreemptedAlloc(mockAlloc, now))
    47  	}
    48  
    49  	// Create a plan result
    50  	applyPlanLogEntry := structs.ApplyPlanResultsRequest{
    51  		AllocUpdateRequest: structs.AllocUpdateRequest{
    52  			AllocsUpdated: mockUpdatedAllocSlice,
    53  			AllocsStopped: mockStoppedAllocSlice,
    54  		},
    55  		AllocsPreempted: mockPreemptionAllocSlice,
    56  	}
    57  
    58  	handle := structs.MsgpackHandle
    59  	var buf bytes.Buffer
    60  	if err := codec.NewEncoder(&buf, handle).Encode(applyPlanLogEntry); err != nil {
    61  		t.Fatalf("Encoding failed: %v", err)
    62  	}
    63  
    64  	optimizedLogSize := buf.Len()
    65  	assert.True(t, float64(optimizedLogSize)/float64(unoptimizedLogSize) < 0.62)
    66  }