Source file src/cmd/compile/internal/ssa/poset_test.go

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  import (
     8  	"fmt"
     9  	"testing"
    10  )
    11  
    12  const (
    13  	SetOrder             = "SetOrder"
    14  	SetOrder_Fail        = "SetOrder_Fail"
    15  	SetOrderOrEqual      = "SetOrderOrEqual"
    16  	SetOrderOrEqual_Fail = "SetOrderOrEqual_Fail"
    17  	Ordered              = "Ordered"
    18  	Ordered_Fail         = "Ordered_Fail"
    19  	OrderedOrEqual       = "OrderedOrEqual"
    20  	OrderedOrEqual_Fail  = "OrderedOrEqual_Fail"
    21  	SetEqual             = "SetEqual"
    22  	SetEqual_Fail        = "SetEqual_Fail"
    23  	Equal                = "Equal"
    24  	Equal_Fail           = "Equal_Fail"
    25  	SetNonEqual          = "SetNonEqual"
    26  	SetNonEqual_Fail     = "SetNonEqual_Fail"
    27  	NonEqual             = "NonEqual"
    28  	NonEqual_Fail        = "NonEqual_Fail"
    29  	Checkpoint           = "Checkpoint"
    30  	Undo                 = "Undo"
    31  )
    32  
    33  type posetTestOp struct {
    34  	typ  string
    35  	a, b int
    36  }
    37  
    38  func vconst(i int) int {
    39  	if i < -128 || i >= 128 {
    40  		panic("invalid const")
    41  	}
    42  	return 1000 + 128 + i
    43  }
    44  
    45  func testPosetOps(t *testing.T, unsigned bool, ops []posetTestOp) {
    46  	var v [1512]*Value
    47  	for i := range v {
    48  		v[i] = new(Value)
    49  		v[i].ID = ID(i)
    50  		if i >= 1000 && i < 1256 {
    51  			v[i].Op = OpConst64
    52  			v[i].AuxInt = int64(i - 1000 - 128)
    53  		}
    54  	}
    55  
    56  	po := newPoset()
    57  	po.SetUnsigned(unsigned)
    58  	for idx, op := range ops {
    59  		t.Logf("op%d%v", idx, op)
    60  		switch op.typ {
    61  		case SetOrder:
    62  			if !po.SetOrder(v[op.a], v[op.b]) {
    63  				t.Errorf("FAILED: op%d%v failed", idx, op)
    64  			}
    65  		case SetOrder_Fail:
    66  			if po.SetOrder(v[op.a], v[op.b]) {
    67  				t.Errorf("FAILED: op%d%v passed", idx, op)
    68  			}
    69  		case SetOrderOrEqual:
    70  			if !po.SetOrderOrEqual(v[op.a], v[op.b]) {
    71  				t.Errorf("FAILED: op%d%v failed", idx, op)
    72  			}
    73  		case SetOrderOrEqual_Fail:
    74  			if po.SetOrderOrEqual(v[op.a], v[op.b]) {
    75  				t.Errorf("FAILED: op%d%v passed", idx, op)
    76  			}
    77  		case Ordered:
    78  			if !po.Ordered(v[op.a], v[op.b]) {
    79  				t.Errorf("FAILED: op%d%v failed", idx, op)
    80  			}
    81  		case Ordered_Fail:
    82  			if po.Ordered(v[op.a], v[op.b]) {
    83  				t.Errorf("FAILED: op%d%v passed", idx, op)
    84  			}
    85  		case OrderedOrEqual:
    86  			if !po.OrderedOrEqual(v[op.a], v[op.b]) {
    87  				t.Errorf("FAILED: op%d%v failed", idx, op)
    88  			}
    89  		case OrderedOrEqual_Fail:
    90  			if po.OrderedOrEqual(v[op.a], v[op.b]) {
    91  				t.Errorf("FAILED: op%d%v passed", idx, op)
    92  			}
    93  		case SetEqual:
    94  			if !po.SetEqual(v[op.a], v[op.b]) {
    95  				t.Errorf("FAILED: op%d%v failed", idx, op)
    96  			}
    97  		case SetEqual_Fail:
    98  			if po.SetEqual(v[op.a], v[op.b]) {
    99  				t.Errorf("FAILED: op%d%v passed", idx, op)
   100  			}
   101  		case Equal:
   102  			if !po.Equal(v[op.a], v[op.b]) {
   103  				t.Errorf("FAILED: op%d%v failed", idx, op)
   104  			}
   105  		case Equal_Fail:
   106  			if po.Equal(v[op.a], v[op.b]) {
   107  				t.Errorf("FAILED: op%d%v passed", idx, op)
   108  			}
   109  		case SetNonEqual:
   110  			if !po.SetNonEqual(v[op.a], v[op.b]) {
   111  				t.Errorf("FAILED: op%d%v failed", idx, op)
   112  			}
   113  		case SetNonEqual_Fail:
   114  			if po.SetNonEqual(v[op.a], v[op.b]) {
   115  				t.Errorf("FAILED: op%d%v passed", idx, op)
   116  			}
   117  		case NonEqual:
   118  			if !po.NonEqual(v[op.a], v[op.b]) {
   119  				t.Errorf("FAILED: op%d%v failed", idx, op)
   120  			}
   121  		case NonEqual_Fail:
   122  			if po.NonEqual(v[op.a], v[op.b]) {
   123  				t.Errorf("FAILED: op%d%v passed", idx, op)
   124  			}
   125  		case Checkpoint:
   126  			po.Checkpoint()
   127  		case Undo:
   128  			t.Log("Undo stack", po.undo)
   129  			po.Undo()
   130  		default:
   131  			panic("unimplemented")
   132  		}
   133  
   134  		if false {
   135  			po.DotDump(fmt.Sprintf("op%d.dot", idx), fmt.Sprintf("Last op: %v", op))
   136  		}
   137  
   138  		po.CheckIntegrity()
   139  	}
   140  
   141  	// Check that the poset is completely empty
   142  	if err := po.CheckEmpty(); err != nil {
   143  		t.Error(err)
   144  	}
   145  }
   146  
   147  func TestPoset(t *testing.T) {
   148  	testPosetOps(t, false, []posetTestOp{
   149  		{Ordered_Fail, 123, 124},
   150  
   151  		// Dag #0: 100<101
   152  		{Checkpoint, 0, 0},
   153  		{SetOrder, 100, 101},
   154  		{Ordered, 100, 101},
   155  		{Ordered_Fail, 101, 100},
   156  		{SetOrder_Fail, 101, 100},
   157  		{SetOrder, 100, 101}, // repeat
   158  		{NonEqual, 100, 101},
   159  		{NonEqual, 101, 100},
   160  		{SetEqual_Fail, 100, 101},
   161  
   162  		// Dag #1: 4<=7<12
   163  		{Checkpoint, 0, 0},
   164  		{SetOrderOrEqual, 4, 7},
   165  		{OrderedOrEqual, 4, 7},
   166  		{SetOrder, 7, 12},
   167  		{Ordered, 7, 12},
   168  		{Ordered, 4, 12},
   169  		{Ordered_Fail, 12, 4},
   170  		{NonEqual, 4, 12},
   171  		{NonEqual, 12, 4},
   172  		{NonEqual_Fail, 4, 100},
   173  		{OrderedOrEqual, 4, 12},
   174  		{OrderedOrEqual_Fail, 12, 4},
   175  		{OrderedOrEqual, 4, 7},
   176  		{OrderedOrEqual_Fail, 7, 4},
   177  
   178  		// Dag #1: 1<4<=7<12
   179  		{Checkpoint, 0, 0},
   180  		{SetOrder, 1, 4},
   181  		{Ordered, 1, 4},
   182  		{Ordered, 1, 12},
   183  		{Ordered_Fail, 12, 1},
   184  
   185  		// Dag #1: 1<4<=7<12, 6<7
   186  		{Checkpoint, 0, 0},
   187  		{SetOrder, 6, 7},
   188  		{Ordered, 6, 7},
   189  		{Ordered, 6, 12},
   190  		{SetOrder_Fail, 7, 4},
   191  		{SetOrder_Fail, 7, 6},
   192  		{SetOrder_Fail, 7, 1},
   193  
   194  		// Dag #1: 1<4<=7<12, 1<6<7
   195  		{Checkpoint, 0, 0},
   196  		{Ordered_Fail, 1, 6},
   197  		{SetOrder, 1, 6},
   198  		{Ordered, 1, 6},
   199  		{SetOrder_Fail, 6, 1},
   200  
   201  		// Dag #1: 1<4<=7<12, 1<4<6<7
   202  		{Checkpoint, 0, 0},
   203  		{Ordered_Fail, 4, 6},
   204  		{Ordered_Fail, 4, 7},
   205  		{SetOrder, 4, 6},
   206  		{Ordered, 4, 6},
   207  		{OrderedOrEqual, 4, 6},
   208  		{Ordered, 4, 7},
   209  		{OrderedOrEqual, 4, 7},
   210  		{SetOrder_Fail, 6, 4},
   211  		{Ordered_Fail, 7, 6},
   212  		{Ordered_Fail, 7, 4},
   213  		{OrderedOrEqual_Fail, 7, 6},
   214  		{OrderedOrEqual_Fail, 7, 4},
   215  
   216  		// Merge: 1<4<6, 4<=7<12, 6<101
   217  		{Checkpoint, 0, 0},
   218  		{Ordered_Fail, 6, 101},
   219  		{SetOrder, 6, 101},
   220  		{Ordered, 6, 101},
   221  		{Ordered, 1, 101},
   222  
   223  		// Merge: 1<4<6, 4<=7<12, 6<100<101
   224  		{Checkpoint, 0, 0},
   225  		{Ordered_Fail, 6, 100},
   226  		{SetOrder, 6, 100},
   227  		{Ordered, 1, 100},
   228  
   229  		// Undo: 1<4<6<7<12, 6<101
   230  		{Ordered, 100, 101},
   231  		{Undo, 0, 0},
   232  		{Ordered, 100, 101},
   233  		{Ordered_Fail, 6, 100},
   234  		{Ordered, 6, 101},
   235  		{Ordered, 1, 101},
   236  
   237  		// Undo: 1<4<6<7<12, 100<101
   238  		{Undo, 0, 0},
   239  		{Ordered_Fail, 1, 100},
   240  		{Ordered_Fail, 1, 101},
   241  		{Ordered_Fail, 6, 100},
   242  		{Ordered_Fail, 6, 101},
   243  
   244  		// Merge: 1<4<6<7<12, 6<100<101
   245  		{Checkpoint, 0, 0},
   246  		{Ordered, 100, 101},
   247  		{SetOrder, 6, 100},
   248  		{Ordered, 6, 100},
   249  		{Ordered, 6, 101},
   250  		{Ordered, 1, 101},
   251  
   252  		// Undo 2 times: 1<4<7<12, 1<6<7
   253  		{Undo, 0, 0},
   254  		{Undo, 0, 0},
   255  		{Ordered, 1, 6},
   256  		{Ordered, 4, 12},
   257  		{Ordered_Fail, 4, 6},
   258  		{SetOrder_Fail, 6, 1},
   259  
   260  		// Undo 2 times: 1<4<7<12
   261  		{Undo, 0, 0},
   262  		{Undo, 0, 0},
   263  		{Ordered, 1, 12},
   264  		{Ordered, 7, 12},
   265  		{Ordered_Fail, 1, 6},
   266  		{Ordered_Fail, 6, 7},
   267  		{Ordered, 100, 101},
   268  		{Ordered_Fail, 1, 101},
   269  
   270  		// Undo: 4<7<12
   271  		{Undo, 0, 0},
   272  		{Ordered_Fail, 1, 12},
   273  		{Ordered_Fail, 1, 4},
   274  		{Ordered, 4, 12},
   275  		{Ordered, 100, 101},
   276  
   277  		// Undo: 100<101
   278  		{Undo, 0, 0},
   279  		{Ordered_Fail, 4, 7},
   280  		{Ordered_Fail, 7, 12},
   281  		{Ordered, 100, 101},
   282  
   283  		// Recreated DAG #1 from scratch, reusing same nodes.
   284  		// This also stresses that Undo has done its job correctly.
   285  		// DAG: 1<2<(5|6), 101<102<(105|106<107)
   286  		{Checkpoint, 0, 0},
   287  		{SetOrder, 101, 102},
   288  		{SetOrder, 102, 105},
   289  		{SetOrder, 102, 106},
   290  		{SetOrder, 106, 107},
   291  		{SetOrder, 1, 2},
   292  		{SetOrder, 2, 5},
   293  		{SetOrder, 2, 6},
   294  		{SetEqual_Fail, 1, 6},
   295  		{SetEqual_Fail, 107, 102},
   296  
   297  		// Now Set 2 == 102
   298  		// New DAG: (1|101)<2==102<(5|6|105|106<107)
   299  		{Checkpoint, 0, 0},
   300  		{SetEqual, 2, 102},
   301  		{Equal, 2, 102},
   302  		{SetEqual, 2, 102},         // trivially pass
   303  		{SetNonEqual_Fail, 2, 102}, // trivially fail
   304  		{Ordered, 1, 107},
   305  		{Ordered, 101, 6},
   306  		{Ordered, 101, 105},
   307  		{Ordered, 2, 106},
   308  		{Ordered, 102, 6},
   309  
   310  		// Undo SetEqual
   311  		{Undo, 0, 0},
   312  		{Equal_Fail, 2, 102},
   313  		{Ordered_Fail, 2, 102},
   314  		{Ordered_Fail, 1, 107},
   315  		{Ordered_Fail, 101, 6},
   316  		{Checkpoint, 0, 0},
   317  		{SetEqual, 2, 100},
   318  		{Ordered, 1, 107},
   319  		{Ordered, 100, 6},
   320  
   321  		// SetEqual with new node
   322  		{Undo, 0, 0},
   323  		{Checkpoint, 0, 0},
   324  		{SetEqual, 2, 400},
   325  		{SetEqual, 401, 2},
   326  		{Equal, 400, 401},
   327  		{Ordered, 1, 400},
   328  		{Ordered, 400, 6},
   329  		{Ordered, 1, 401},
   330  		{Ordered, 401, 6},
   331  		{Ordered_Fail, 2, 401},
   332  
   333  		// SetEqual unseen nodes and then connect
   334  		{Checkpoint, 0, 0},
   335  		{SetEqual, 500, 501},
   336  		{SetEqual, 102, 501},
   337  		{Equal, 500, 102},
   338  		{Ordered, 501, 106},
   339  		{Ordered, 100, 500},
   340  		{SetEqual, 500, 501},
   341  		{Ordered_Fail, 500, 501},
   342  		{Ordered_Fail, 102, 501},
   343  
   344  		// SetNonEqual relations
   345  		{Undo, 0, 0},
   346  		{Checkpoint, 0, 0},
   347  		{SetNonEqual, 600, 601},
   348  		{NonEqual, 600, 601},
   349  		{SetNonEqual, 601, 602},
   350  		{NonEqual, 601, 602},
   351  		{NonEqual_Fail, 600, 602}, // non-transitive
   352  		{SetEqual_Fail, 601, 602},
   353  
   354  		// Undo back to beginning, leave the poset empty
   355  		{Undo, 0, 0},
   356  		{Undo, 0, 0},
   357  		{Undo, 0, 0},
   358  		{Undo, 0, 0},
   359  	})
   360  }
   361  
   362  func TestPosetStrict(t *testing.T) {
   363  
   364  	testPosetOps(t, false, []posetTestOp{
   365  		{Checkpoint, 0, 0},
   366  		// Build: 20!=30, 10<20<=30<40. The 20<=30 will become 20<30.
   367  		{SetNonEqual, 20, 30},
   368  		{SetOrder, 10, 20},
   369  		{SetOrderOrEqual, 20, 30}, // this is affected by 20!=30
   370  		{SetOrder, 30, 40},
   371  
   372  		{Ordered, 10, 30},
   373  		{Ordered, 20, 30},
   374  		{Ordered, 10, 40},
   375  		{OrderedOrEqual, 10, 30},
   376  		{OrderedOrEqual, 20, 30},
   377  		{OrderedOrEqual, 10, 40},
   378  
   379  		{Undo, 0, 0},
   380  
   381  		// Now do the opposite: first build the DAG and then learn non-equality
   382  		{Checkpoint, 0, 0},
   383  		{SetOrder, 10, 20},
   384  		{SetOrderOrEqual, 20, 30}, // this is affected by 20!=30
   385  		{SetOrder, 30, 40},
   386  
   387  		{Ordered, 10, 30},
   388  		{Ordered_Fail, 20, 30},
   389  		{Ordered, 10, 40},
   390  		{OrderedOrEqual, 10, 30},
   391  		{OrderedOrEqual, 20, 30},
   392  		{OrderedOrEqual, 10, 40},
   393  
   394  		{Checkpoint, 0, 0},
   395  		{SetNonEqual, 20, 30},
   396  		{Ordered, 10, 30},
   397  		{Ordered, 20, 30},
   398  		{Ordered, 10, 40},
   399  		{OrderedOrEqual, 10, 30},
   400  		{OrderedOrEqual, 20, 30},
   401  		{OrderedOrEqual, 10, 40},
   402  		{Undo, 0, 0},
   403  
   404  		{Checkpoint, 0, 0},
   405  		{SetOrderOrEqual, 30, 35},
   406  		{OrderedOrEqual, 20, 35},
   407  		{Ordered_Fail, 20, 35},
   408  		{SetNonEqual, 20, 35},
   409  		{Ordered, 20, 35},
   410  		{Undo, 0, 0},
   411  
   412  		// Learn <= and >=
   413  		{Checkpoint, 0, 0},
   414  		{SetOrderOrEqual, 50, 60},
   415  		{SetOrderOrEqual, 60, 50},
   416  		{OrderedOrEqual, 50, 60},
   417  		{OrderedOrEqual, 60, 50},
   418  		{Ordered_Fail, 50, 60},
   419  		{Ordered_Fail, 60, 50},
   420  		{Equal, 50, 60},
   421  		{Equal, 60, 50},
   422  		{NonEqual_Fail, 50, 60},
   423  		{NonEqual_Fail, 60, 50},
   424  		{Undo, 0, 0},
   425  
   426  		{Undo, 0, 0},
   427  	})
   428  }
   429  
   430  func TestPosetCollapse(t *testing.T) {
   431  	testPosetOps(t, false, []posetTestOp{
   432  		{Checkpoint, 0, 0},
   433  		// Create a complex graph of <= relations among nodes between 10 and 25.
   434  		{SetOrderOrEqual, 10, 15},
   435  		{SetOrderOrEqual, 15, 20},
   436  		{SetOrderOrEqual, 20, vconst(20)},
   437  		{SetOrderOrEqual, vconst(20), 25},
   438  		{SetOrderOrEqual, 10, 12},
   439  		{SetOrderOrEqual, 12, 16},
   440  		{SetOrderOrEqual, 16, vconst(20)},
   441  		{SetOrderOrEqual, 10, 17},
   442  		{SetOrderOrEqual, 17, 25},
   443  		{SetOrderOrEqual, 15, 18},
   444  		{SetOrderOrEqual, 18, vconst(20)},
   445  		{SetOrderOrEqual, 15, 19},
   446  		{SetOrderOrEqual, 19, 25},
   447  
   448  		// These are other paths not part of the main collapsing path
   449  		{SetOrderOrEqual, 10, 11},
   450  		{SetOrderOrEqual, 11, 26},
   451  		{SetOrderOrEqual, 13, 25},
   452  		{SetOrderOrEqual, 100, 25},
   453  		{SetOrderOrEqual, 101, 15},
   454  		{SetOrderOrEqual, 102, 10},
   455  		{SetOrderOrEqual, 25, 103},
   456  		{SetOrderOrEqual, 20, 104},
   457  
   458  		{Checkpoint, 0, 0},
   459  		// Collapse everything by setting 10 >= 25: this should make everything equal
   460  		{SetOrderOrEqual, 25, 10},
   461  
   462  		// Check that all nodes are pairwise equal now
   463  		{Equal, 10, 12},
   464  		{Equal, 10, 15},
   465  		{Equal, 10, 16},
   466  		{Equal, 10, 17},
   467  		{Equal, 10, 18},
   468  		{Equal, 10, 19},
   469  		{Equal, 10, vconst(20)},
   470  		{Equal, 10, 25},
   471  
   472  		{Equal, 12, 15},
   473  		{Equal, 12, 16},
   474  		{Equal, 12, 17},
   475  		{Equal, 12, 18},
   476  		{Equal, 12, 19},
   477  		{Equal, 12, vconst(20)},
   478  		{Equal, 12, 25},
   479  
   480  		{Equal, 15, 16},
   481  		{Equal, 15, 17},
   482  		{Equal, 15, 18},
   483  		{Equal, 15, 19},
   484  		{Equal, 15, vconst(20)},
   485  		{Equal, 15, 25},
   486  
   487  		{Equal, 16, 17},
   488  		{Equal, 16, 18},
   489  		{Equal, 16, 19},
   490  		{Equal, 16, vconst(20)},
   491  		{Equal, 16, 25},
   492  
   493  		{Equal, 17, 18},
   494  		{Equal, 17, 19},
   495  		{Equal, 17, vconst(20)},
   496  		{Equal, 17, 25},
   497  
   498  		{Equal, 18, 19},
   499  		{Equal, 18, vconst(20)},
   500  		{Equal, 18, 25},
   501  
   502  		{Equal, 19, vconst(20)},
   503  		{Equal, 19, 25},
   504  
   505  		{Equal, vconst(20), 25},
   506  
   507  		// ... but not 11/26/100/101/102, which were on a different path
   508  		{Equal_Fail, 10, 11},
   509  		{Equal_Fail, 10, 26},
   510  		{Equal_Fail, 10, 100},
   511  		{Equal_Fail, 10, 101},
   512  		{Equal_Fail, 10, 102},
   513  		{OrderedOrEqual, 10, 26},
   514  		{OrderedOrEqual, 25, 26},
   515  		{OrderedOrEqual, 13, 25},
   516  		{OrderedOrEqual, 13, 10},
   517  
   518  		{Undo, 0, 0},
   519  		{OrderedOrEqual, 10, 25},
   520  		{Equal_Fail, 10, 12},
   521  		{Equal_Fail, 10, 15},
   522  		{Equal_Fail, 10, 25},
   523  
   524  		{Undo, 0, 0},
   525  	})
   526  
   527  	testPosetOps(t, false, []posetTestOp{
   528  		{Checkpoint, 0, 0},
   529  		{SetOrderOrEqual, 10, 15},
   530  		{SetOrderOrEqual, 15, 20},
   531  		{SetOrderOrEqual, 20, 25},
   532  		{SetOrder, 10, 16},
   533  		{SetOrderOrEqual, 16, 20},
   534  		// Check that we cannot collapse here because of the strict relation 10<16
   535  		{SetOrderOrEqual_Fail, 20, 10},
   536  		{Undo, 0, 0},
   537  	})
   538  }
   539  
   540  func TestPosetSetEqual(t *testing.T) {
   541  	testPosetOps(t, false, []posetTestOp{
   542  		// 10<=20<=30<40,  20<=100<110
   543  		{Checkpoint, 0, 0},
   544  		{SetOrderOrEqual, 10, 20},
   545  		{SetOrderOrEqual, 20, 30},
   546  		{SetOrder, 30, 40},
   547  		{SetOrderOrEqual, 20, 100},
   548  		{SetOrder, 100, 110},
   549  		{OrderedOrEqual, 10, 30},
   550  		{OrderedOrEqual_Fail, 30, 10},
   551  		{Ordered_Fail, 10, 30},
   552  		{Ordered_Fail, 30, 10},
   553  		{Ordered, 10, 40},
   554  		{Ordered_Fail, 40, 10},
   555  
   556  		// Try learning 10==20.
   557  		{Checkpoint, 0, 0},
   558  		{SetEqual, 10, 20},
   559  		{OrderedOrEqual, 10, 20},
   560  		{Ordered_Fail, 10, 20},
   561  		{Equal, 10, 20},
   562  		{SetOrderOrEqual, 10, 20},
   563  		{SetOrderOrEqual, 20, 10},
   564  		{SetOrder_Fail, 10, 20},
   565  		{SetOrder_Fail, 20, 10},
   566  		{Undo, 0, 0},
   567  
   568  		// Try learning 20==10.
   569  		{Checkpoint, 0, 0},
   570  		{SetEqual, 20, 10},
   571  		{OrderedOrEqual, 10, 20},
   572  		{Ordered_Fail, 10, 20},
   573  		{Equal, 10, 20},
   574  		{Undo, 0, 0},
   575  
   576  		// Try learning 10==40 or 30==40 or 10==110.
   577  		{Checkpoint, 0, 0},
   578  		{SetEqual_Fail, 10, 40},
   579  		{SetEqual_Fail, 40, 10},
   580  		{SetEqual_Fail, 30, 40},
   581  		{SetEqual_Fail, 40, 30},
   582  		{SetEqual_Fail, 10, 110},
   583  		{SetEqual_Fail, 110, 10},
   584  		{Undo, 0, 0},
   585  
   586  		// Try learning 40==110, and then 10==40 or 10=110
   587  		{Checkpoint, 0, 0},
   588  		{SetEqual, 40, 110},
   589  		{SetEqual_Fail, 10, 40},
   590  		{SetEqual_Fail, 40, 10},
   591  		{SetEqual_Fail, 10, 110},
   592  		{SetEqual_Fail, 110, 10},
   593  		{Undo, 0, 0},
   594  
   595  		// Try learning 40<20 or 30<20 or 110<10
   596  		{Checkpoint, 0, 0},
   597  		{SetOrder_Fail, 40, 20},
   598  		{SetOrder_Fail, 30, 20},
   599  		{SetOrder_Fail, 110, 10},
   600  		{Undo, 0, 0},
   601  
   602  		// Try learning 30<=20
   603  		{Checkpoint, 0, 0},
   604  		{SetOrderOrEqual, 30, 20},
   605  		{Equal, 30, 20},
   606  		{OrderedOrEqual, 30, 100},
   607  		{Ordered, 30, 110},
   608  		{Undo, 0, 0},
   609  
   610  		{Undo, 0, 0},
   611  	})
   612  }
   613  
   614  func TestPosetNonEqual(t *testing.T) {
   615  	testPosetOps(t, false, []posetTestOp{
   616  		{Equal_Fail, 10, 20},
   617  		{NonEqual_Fail, 10, 20},
   618  
   619  		// Learn 10!=20
   620  		{Checkpoint, 0, 0},
   621  		{SetNonEqual, 10, 20},
   622  		{Equal_Fail, 10, 20},
   623  		{NonEqual, 10, 20},
   624  		{SetEqual_Fail, 10, 20},
   625  
   626  		// Learn again 10!=20
   627  		{Checkpoint, 0, 0},
   628  		{SetNonEqual, 10, 20},
   629  		{Equal_Fail, 10, 20},
   630  		{NonEqual, 10, 20},
   631  
   632  		// Undo. We still know 10!=20
   633  		{Undo, 0, 0},
   634  		{Equal_Fail, 10, 20},
   635  		{NonEqual, 10, 20},
   636  		{SetEqual_Fail, 10, 20},
   637  
   638  		// Undo again. Now we know nothing
   639  		{Undo, 0, 0},
   640  		{Equal_Fail, 10, 20},
   641  		{NonEqual_Fail, 10, 20},
   642  
   643  		// Learn 10==20
   644  		{Checkpoint, 0, 0},
   645  		{SetEqual, 10, 20},
   646  		{Equal, 10, 20},
   647  		{NonEqual_Fail, 10, 20},
   648  		{SetNonEqual_Fail, 10, 20},
   649  
   650  		// Learn again 10==20
   651  		{Checkpoint, 0, 0},
   652  		{SetEqual, 10, 20},
   653  		{Equal, 10, 20},
   654  		{NonEqual_Fail, 10, 20},
   655  		{SetNonEqual_Fail, 10, 20},
   656  
   657  		// Undo. We still know 10==20
   658  		{Undo, 0, 0},
   659  		{Equal, 10, 20},
   660  		{NonEqual_Fail, 10, 20},
   661  		{SetNonEqual_Fail, 10, 20},
   662  
   663  		// Undo. We know nothing
   664  		{Undo, 0, 0},
   665  		{Equal_Fail, 10, 20},
   666  		{NonEqual_Fail, 10, 20},
   667  	})
   668  }
   669  

View as plain text