github.com/opentofu/opentofu@v1.7.1/internal/lang/funcs/datetime_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package funcs
     7  
     8  import (
     9  	"fmt"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/zclconf/go-cty/cty"
    14  )
    15  
    16  func TestTimestamp(t *testing.T) {
    17  	currentTime := time.Now().UTC()
    18  	result, err := Timestamp()
    19  	if err != nil {
    20  		t.Fatalf("err: %s", err)
    21  	}
    22  	resultTime, err := time.Parse(time.RFC3339, result.AsString())
    23  	if err != nil {
    24  		t.Fatalf("Error parsing timestamp: %s", err)
    25  	}
    26  
    27  	if resultTime.Sub(currentTime).Seconds() > 10.0 {
    28  		t.Fatalf("Timestamp Diff too large. Expected: %s\nReceived: %s", currentTime.Format(time.RFC3339), result.AsString())
    29  	}
    30  
    31  }
    32  
    33  func TestTimeadd(t *testing.T) {
    34  	tests := []struct {
    35  		Time     cty.Value
    36  		Duration cty.Value
    37  		Want     cty.Value
    38  		Err      bool
    39  	}{
    40  		{
    41  			cty.StringVal("2017-11-22T00:00:00Z"),
    42  			cty.StringVal("1s"),
    43  			cty.StringVal("2017-11-22T00:00:01Z"),
    44  			false,
    45  		},
    46  		{
    47  			cty.StringVal("2017-11-22T00:00:00Z"),
    48  			cty.StringVal("10m1s"),
    49  			cty.StringVal("2017-11-22T00:10:01Z"),
    50  			false,
    51  		},
    52  		{ // also support subtraction
    53  			cty.StringVal("2017-11-22T00:00:00Z"),
    54  			cty.StringVal("-1h"),
    55  			cty.StringVal("2017-11-21T23:00:00Z"),
    56  			false,
    57  		},
    58  		{ // Invalid format timestamp
    59  			cty.StringVal("2017-11-22"),
    60  			cty.StringVal("-1h"),
    61  			cty.UnknownVal(cty.String).RefineNotNull(),
    62  			true,
    63  		},
    64  		{ // Invalid format duration (day is not supported by ParseDuration)
    65  			cty.StringVal("2017-11-22T00:00:00Z"),
    66  			cty.StringVal("1d"),
    67  			cty.UnknownVal(cty.String).RefineNotNull(),
    68  			true,
    69  		},
    70  	}
    71  
    72  	for _, test := range tests {
    73  		t.Run(fmt.Sprintf("TimeAdd(%#v, %#v)", test.Time, test.Duration), func(t *testing.T) {
    74  			got, err := TimeAdd(test.Time, test.Duration)
    75  
    76  			if test.Err {
    77  				if err == nil {
    78  					t.Fatal("succeeded; want error")
    79  				}
    80  				return
    81  			} else if err != nil {
    82  				t.Fatalf("unexpected error: %s", err)
    83  			}
    84  
    85  			if !got.RawEquals(test.Want) {
    86  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
    87  			}
    88  		})
    89  	}
    90  }
    91  
    92  func TestTimeCmp(t *testing.T) {
    93  	tests := []struct {
    94  		TimeA, TimeB cty.Value
    95  		Want         cty.Value
    96  		Err          string
    97  	}{
    98  		{
    99  			cty.StringVal("2017-11-22T00:00:00Z"),
   100  			cty.StringVal("2017-11-22T00:00:00Z"),
   101  			cty.Zero,
   102  			``,
   103  		},
   104  		{
   105  			cty.StringVal("2017-11-22T00:00:00Z"),
   106  			cty.StringVal("2017-11-22T01:00:00+01:00"),
   107  			cty.Zero,
   108  			``,
   109  		},
   110  		{
   111  			cty.StringVal("2017-11-22T00:00:01Z"),
   112  			cty.StringVal("2017-11-22T01:00:00+01:00"),
   113  			cty.NumberIntVal(1),
   114  			``,
   115  		},
   116  		{
   117  			cty.StringVal("2017-11-22T01:00:00Z"),
   118  			cty.StringVal("2017-11-22T00:59:00-01:00"),
   119  			cty.NumberIntVal(-1),
   120  			``,
   121  		},
   122  		{
   123  			cty.StringVal("2017-11-22T01:00:00+01:00"),
   124  			cty.StringVal("2017-11-22T01:00:00-01:00"),
   125  			cty.NumberIntVal(-1),
   126  			``,
   127  		},
   128  		{
   129  			cty.StringVal("2017-11-22T01:00:00-01:00"),
   130  			cty.StringVal("2017-11-22T01:00:00+01:00"),
   131  			cty.NumberIntVal(1),
   132  			``,
   133  		},
   134  		{
   135  			cty.StringVal("2017-11-22T00:00:00Z"),
   136  			cty.StringVal("bloop"),
   137  			cty.UnknownVal(cty.String).RefineNotNull(),
   138  			`not a valid RFC3339 timestamp: cannot use "bloop" as year`,
   139  		},
   140  		{
   141  			cty.StringVal("2017-11-22 00:00:00Z"),
   142  			cty.StringVal("2017-11-22T00:00:00Z"),
   143  			cty.UnknownVal(cty.String).RefineNotNull(),
   144  			`not a valid RFC3339 timestamp: missing required time introducer 'T'`,
   145  		},
   146  		{
   147  			cty.StringVal("2017-11-22T00:00:00Z"),
   148  			cty.UnknownVal(cty.String),
   149  			cty.UnknownVal(cty.Number).RefineNotNull(),
   150  			``,
   151  		},
   152  		{
   153  			cty.UnknownVal(cty.String),
   154  			cty.StringVal("2017-11-22T00:00:00Z"),
   155  			cty.UnknownVal(cty.Number).RefineNotNull(),
   156  			``,
   157  		},
   158  		{
   159  			cty.UnknownVal(cty.String),
   160  			cty.UnknownVal(cty.String),
   161  			cty.UnknownVal(cty.Number).RefineNotNull(),
   162  			``,
   163  		},
   164  	}
   165  
   166  	for _, test := range tests {
   167  		t.Run(fmt.Sprintf("TimeCmp(%#v, %#v)", test.TimeA, test.TimeB), func(t *testing.T) {
   168  			got, err := TimeCmp(test.TimeA, test.TimeB)
   169  
   170  			if test.Err != "" {
   171  				if err == nil {
   172  					t.Fatal("succeeded; want error")
   173  				}
   174  				if got := err.Error(); got != test.Err {
   175  					t.Errorf("wrong error message\ngot:  %s\nwant: %s", got, test.Err)
   176  				}
   177  				return
   178  			} else if err != nil {
   179  				t.Fatalf("unexpected error: %s", err)
   180  			}
   181  
   182  			if !got.RawEquals(test.Want) {
   183  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   184  			}
   185  		})
   186  	}
   187  }