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

View as plain text