How to use CopyAppend method of internal Package

Best Ginkgo code snippet using internal.CopyAppend

session_test.go

Source:session_test.go Github

copy

Full Screen

...84var emptypath = []string{}85var invalidpath = []string{"foo", "bar", "baz"}86var rootpath = []string{""}87var testcontainerpath = []string{testcontainer}88var testemptypath = pathutil.CopyAppend(testcontainerpath, testempty)89var testbooleanpath = pathutil.CopyAppend(testcontainerpath, testboolean)90var testleafpath = pathutil.CopyAppend(testcontainerpath, testleaf)91var testleaflistuserpath = pathutil.CopyAppend(testcontainerpath, testleaflistuser)92var testlistpath = pathutil.CopyAppend(testcontainerpath, testlist)93var testlist1path = pathutil.CopyAppend(testlistpath, "list1")94var teststringpath = pathutil.CopyAppend(testcontainerpath, teststring)95// Tests run in the order they are defined96type validateExistsTbl struct {97	path      []string98	expexists bool99}100const existsSchema = `101container testcontainer {102	leaf testempty {103		type empty;104	}105	leaf testboolean {106		type boolean;107		default false;108	}109}110`111func TestExists(t *testing.T) {112	const config = `113testcontainer {114	testempty115}116`117	tbl := []validateExistsTbl{118		{emptypath, true},119		{invalidpath, false},120		{rootpath, false},121		{testemptypath, true},122		{testbooleanpath, true},123	}124	srv, sess := TstStartup(t, existsSchema, config)125	for key, _ := range tbl {126		ValidateExists(t, sess, srv.Ctx, tbl[key].path, tbl[key].expexists)127	}128	sess.Kill()129}130// Check GetTree handles defaults correctly131func TestDefaultExistsGetTree(t *testing.T) {132	srv, sess := TstStartup(t, existsSchema, "")133	opts := &TreeOpts{Defaults: false, Secrets: true}134	if _, err := sess.GetTree(srv.Ctx, testbooleanpath, opts); err == nil {135		t.Fatalf("testboolean should not be found.")136		return137	}138	opts.Defaults = true139	if _, err := sess.GetTree(srv.Ctx, testbooleanpath, opts); err != nil {140		t.Fatalf("testboolean should be found.")141		return142	}143}144// Check GetFullTree handles defaults correctly145func TestDefaultExistsGetFullTree(t *testing.T) {146	// Skip this test until VRVDR-32367 is fixed.147	t.Skip("Skipping until VRVDR-32367 is fixed")148	srv, sess := TstStartup(t, existsSchema, "")149	opts := &TreeOpts{Defaults: false, Secrets: true}150	// TODO - this is returning the default and should not be.151	if _, err, _ := sess.GetFullTree(152		srv.Ctx, testbooleanpath, opts); err == nil {153		t.Fatalf("testboolean should not be found.")154		return155	}156	opts.Defaults = true157	// TODO - this is returning the default even without the fix.  It should158	//        only return the default once the fix is in!159	if _, err, _ := sess.GetFullTree(160		srv.Ctx, testbooleanpath, opts); err != nil {161		t.Fatalf("testboolean should be found.")162		return163	}164}165type validateTypeTbl struct {166	path []string167	exp  rpc.NodeType168}169func validateType(t *testing.T, sess *Session, ctx *configd.Context, tst validateTypeTbl) {170	nt, err := sess.GetType(ctx, tst.path)171	if err != nil {172		t.Errorf("Unable to get type for path [%s]; %s",173			pathutil.Pathstr(tst.path), err)174		testutils.LogStack(t)175	} else if nt != tst.exp {176		t.Errorf("Invalid type %d for path [%s]; expected %d",177			nt, pathutil.Pathstr(tst.path), tst.exp)178		testutils.LogStack(t)179	}180}181func TestGetType(t *testing.T) {182	const schema = `183container testcontainer {184	leaf testempty {185		type empty;186	}187	leaf testboolean {188		type boolean;189		default false;190	}191	list testlist {192		key nodetag;193		leaf nodetag {194			type string;195		}196	}197	leaf-list testleaflistuser {198		type string;199		ordered-by user;200	}201}202`203	const config = `204testcontainer {205	testleaflistuser foo206}207`208	var testbooleanpath_false = pathutil.CopyAppend(testbooleanpath, "false")209	var testleaflistuserpath_foo = pathutil.CopyAppend(testleaflistuserpath, "foo")210	tbl := []validateTypeTbl{211		{emptypath, rpc.CONTAINER},212		{invalidpath, rpc.CONTAINER},213		{rootpath, rpc.CONTAINER},214		{testcontainerpath, rpc.CONTAINER},215		{testemptypath, rpc.LEAF},216		{testbooleanpath_false, rpc.LEAF},217		{testlistpath, rpc.LIST},218		{testlist1path, rpc.CONTAINER},219		{testleaflistuserpath, rpc.LEAF_LIST},220		{testleaflistuserpath_foo, rpc.LEAF},221	}222	srv, sess := TstStartup(t, schema, emptyconfig)223	for key, _ := range tbl {224		validateType(t, sess, srv.Ctx, tbl[key])225	}226	sess.Kill()227}228type validateDefaultTbl struct {229	path []string230	exp  bool231}232func validateDefault(t *testing.T, sess *Session, ctx *configd.Context, tst validateDefaultTbl) {233	def, err := sess.IsDefault(ctx, tst.path)234	if err != nil {235		t.Errorf("Unable to determine default for path [%s] : %s", pathutil.Pathstr(tst.path), err)236		testutils.LogStack(t)237	} else if def != tst.exp {238		t.Errorf("Incorrect default for path [%s]", pathutil.Pathstr(tst.path))239		testutils.LogStack(t)240	}241}242func TestIsDefault(t *testing.T) {243	const schema = `244typedef testdefaulttype {245	type uint32;246	default 42;247}248container testcontainer {249	leaf testboolean {250		type boolean;251		default false;252	}253	leaf testempty {254		type empty;255	}256	leaf testdefaulttype {257		type testdefaulttype;258	}259}260`261	const config = `262testcontainer {263	testboolean true;264}265`266	var testbooleanpath_true = pathutil.CopyAppend(testbooleanpath, "true")267	var testdefaulttypepath = pathutil.CopyAppend(testcontainerpath, "testdefaulttype")268	tbl := []validateDefaultTbl{269		{emptypath, false},270		{invalidpath, false},271		{rootpath, false},272		{testbooleanpath_true, false},273		{testemptypath, false},274		{testdefaulttypepath, true},275	}276	srv, sess := TstStartup(t, schema, config)277	for key, _ := range tbl {278		validateDefault(t, sess, srv.Ctx, tbl[key])279	}280	sess.Kill()281}282type validateGetTbl struct {283	path []string284	exp  []string285}286func validateGet(t *testing.T, sess *Session, ctx *configd.Context, tst validateGetTbl) {287	val, err := sess.Get(ctx, tst.path)288	if err != nil {289		t.Errorf("Unable to get path [%s] : %s", pathutil.Pathstr(tst.path), err)290		testutils.LogStack(t)291	} else if strings.Join(val, " ") != strings.Join(tst.exp, " ") {292		t.Errorf("Unexpected result from path [%s]",293			pathutil.Pathstr(tst.path))294		t.Logf("Received: %s", val)295		t.Logf("Expected: %s", tst.exp)296		testutils.LogStack(t)297	}298}299func TestGet(t *testing.T) {300	const schema = `301container testcontainer {302    presence "allow config of empty container";303	leaf testboolean {304		type boolean;305		default false;306	}307}308`309	const config = `310testcontainer {311}312`313	tbl := []validateGetTbl{314		{emptypath, []string{testcontainer}},315		{invalidpath, emptypath},316		{rootpath, emptypath},317		{testcontainerpath, []string{testboolean}},318		{testbooleanpath, []string{"false"}},319	}320	srv, sess := TstStartup(t, schema, config)321	for key, _ := range tbl {322		validateGet(t, sess, srv.Ctx, tbl[key])323	}324	sess.Kill()325}326func getLockedState(t *testing.T, sess *Session, ctx *configd.Context) int32 {327	lock, err := sess.Locked(ctx)328	if err != nil {329		t.Fatalf("Unable to get locked state; %s", err)330	}331	return lock332}333func TestLocked(t *testing.T) {334	srv, sess := TstStartup(t, emptyschema, emptyconfig)335	lock := getLockedState(t, sess, srv.Ctx)336	if lock != 0 {337		t.Fatalf("Session incorrectly locked; %d", lock)338	}339	sess.Kill()340}341func TestLock(t *testing.T) {342	srv, sess := TstStartup(t, emptyschema, emptyconfig)343	lock, err := sess.Lock(srv.Ctx)344	if err != nil {345		t.Fatalf("Unable to lock session; %s", err)346	}347	lockpid := getLockedState(t, sess, srv.Ctx)348	if lock != lockpid {349		t.Fatalf("Session incorrectly locked; locked by %d, reported as %d",350			lock, lockpid)351	}352	lock, err = sess.Lock(srv.Ctx)353	if err == nil {354		t.Fatal("Incorrectly locked already locked session")355	}356	ctx := &configd.Context{357		Pid:  int32(5),358		Auth: srv.Auth,359		Dlog: srv.Dlog,360		Elog: srv.Elog,361	}362	lock, err = sess.Lock(ctx)363	if err == nil {364		t.Fatal("Incorrectly locked session locked by different context")365	}366	sess.Kill()367}368func TestUnlock(t *testing.T) {369	srv, sess := TstStartup(t, emptyschema, emptyconfig)370	_, err := sess.Unlock(srv.Ctx)371	if err == nil {372		t.Fatalf("Session incorrectly locked; %s", err)373	}374	var lockpid, unlockpid int32375	lockpid, err = sess.Lock(srv.Ctx)376	if err != nil {377		t.Fatalf("Unable to lock session; %s", err)378	}379	ctx := &configd.Context{380		Pid:  int32(5),381		Auth: srv.Auth,382		Dlog: srv.Dlog,383		Elog: srv.Elog,384	}385	unlockpid, err = sess.Unlock(ctx)386	if err == nil {387		t.Fatalf("Incorrectly unlocked session from different context")388	}389	unlockpid, err = sess.Unlock(srv.Ctx)390	if err != nil {391		t.Fatalf("Unable to unlock session; %s", err)392	}393	if lockpid != unlockpid {394		t.Fatalf("Session was incorrectly locked; locked by %d, unlocked by %d",395			lockpid, unlockpid)396	}397	sess.Kill()398}399func validateSaved(t *testing.T, sess *Session, ctx *configd.Context, exp bool) {400	if sess.Saved(ctx) != exp {401		t.Errorf("Session marked with incorrect saved state; expected %v", exp)402	}403}404func TestSaved(t *testing.T) {405	srv, sess := TstStartup(t, emptyschema, emptyconfig)406	validateSaved(t, sess, srv.Ctx, false)407	sess.MarkSaved(srv.Ctx, true)408	validateSaved(t, sess, srv.Ctx, true)409	sess.MarkSaved(srv.Ctx, false)410	validateSaved(t, sess, srv.Ctx, false)411	sess.Kill()412}413// TODO: move to separate test functions414// validateSetPath(t, sess, srv.ctx, testlistpath, true)415// validateSetPath(t, sess, srv.ctx, testlist1path, false)416func TestValidateSetPath(t *testing.T) {417	const schema = `418container testcontainer {419}420`421	tbl := []ValidateOpTbl{422		NewValOpTblEntry("Validate set without a path", emptypath, "", false),423		NewValOpTblEntry("Validate set invalid path", invalidpath, "", true),424		NewValOpTblEntry("Validate set root path", rootpath, "", true),425		NewValOpTblEntry("Validate set container", testcontainerpath, "", true),426	}427	srv, sess := TstStartup(t, schema, emptyconfig)428	ValidateSetPathTable(t, sess, srv.Ctx, tbl)429	sess.Kill()430}431func TestValidateSetLeafList(t *testing.T) {432	const schema = `433container testcontainer {434	leaf-list testleaflistuser {435		type string;436		ordered-by user;437	}438}439`440	var testleaflistuserpath_bam = pathutil.CopyAppend(testleaflistuserpath, "bam")441	testleaflistuserpath_bam = pathutil.CopyAppend(testleaflistuserpath_bam, "")442	tbl := []ValidateOpTbl{443		NewValOpTblEntry(validatesetnovalue, testleaflistuserpath, "", true),444		NewValOpTblEntry("Validate set list-leaf item 1", testleaflistuserpath, "foo", false),445		NewValOpTblEntry("Validate set list-leaf item 2", testleaflistuserpath, "bar", false),446		NewValOpTblEntry("Validate set list-leaf item 3", testleaflistuserpath, "baz", false),447		NewValOpTblEntry("Validate set list-leaf item with trailing /", testleaflistuserpath_bam, "", true),448	}449	srv, sess := TstStartup(t, schema, emptyconfig)450	ValidateSetPathTable(t, sess, srv.Ctx, tbl)451	sess.Kill()452}453func TestValidateSetList(t *testing.T) {454	const schema = `455container testcontainer {456	list testlist {457		key nodetag;458		leaf nodetag {459			type string;460		}461	}462}463`464	tbl := []ValidateOpTbl{465		NewValOpTblEntry(validatesetnovalue, testlistpath, "", true),466		NewValOpTblEntry("Validate set list item 1", testlistpath, "foo", false),467		NewValOpTblEntry("Validate set list item 2", testlistpath, "bar", false),468		NewValOpTblEntry("Validate set list item 3", testlistpath, "baz", false),469	}470	srv, sess := TstStartup(t, schema, emptyconfig)471	ValidateSetPathTable(t, sess, srv.Ctx, tbl)472	sess.Kill()473}474func TestValidateSetUnion(t *testing.T) {475	const schema = `476container testcontainer {477	leaf testunion {478		type union {479			type uint32;480			type string;481		}482	}483}484`485	var testunionpath = pathutil.CopyAppend(testcontainerpath, "testunion")486	tbl := []ValidateOpTbl{487		NewValOpTblEntry("Validate set union uint", testunionpath, "10", false),488		NewValOpTblEntry("Validate set union string", testunionpath, "foo", false),489	}490	srv, sess := TstStartup(t, schema, emptyconfig)491	ValidateSetPathTable(t, sess, srv.Ctx, tbl)492	sess.Kill()493}494func TestSet(t *testing.T) {495	const schema = `496container testcontainer {497	leaf testempty {498		type empty;499	}500	leaf testboolean {501		type boolean;502		default false;503	}504	leaf teststring {505		type string;506	}507}508`509	var teststringpath_bam = pathutil.CopyAppend(teststringpath, "bam")510	teststringpath_bam = pathutil.CopyAppend(teststringpath_bam, "")511	tbl := []ValidateOpTbl{512		NewValOpTblEntry("Set empty path", emptypath, "", true),513		NewValOpTblEntry("Set invalid path", invalidpath, "", true),514		NewValOpTblEntry("Set root path", rootpath, "", true),515		NewValOpTblEntry("Set empty leaf", testemptypath, "", false),516		NewValOpTblEntry("Set boolean node true", testbooleanpath, "true", false),517		NewValOpTblEntry("Set boolean node false", testbooleanpath, "false", false),518		NewValOpTblEntry("Set string value", teststringpath, "foo", false),519		NewValOpTblEntry("Set string value with trailing /", teststringpath_bam, "", true),520	}521	srv, sess := TstStartup(t, schema, emptyconfig)522	ValidateSetTable(t, sess, srv.Ctx, tbl)523	sess.Kill()524}525func TestChoiceSet(t *testing.T) {526	var targetpath = []string{"testcontainer", "target", "a-target-value"}527	var abstargetpath = []string{"testcontainer", "abs-target", "a-target-value"}528	var relativetargetpath = []string{"testcontainer", "relative-target", "a-target-value"}529	const schema = `530container testcontainer {531	list target {532		key value;533		leaf value {534			type string;535		}536	}537	choice achoice {538		case one {539			leaf testempty {540				type empty;541			}542			choice alpha {543				leaf alpha-one {544					type string;545				}546				case alpha-case {547					leaf alpha-two {548						type string;549					}550					leaf alpha-three {551						type string;552					}553					leaf abs-target {554						type leafref {555							path "/testcontainer/target/value";556						}557					}558					leaf relative-target {559						type leafref {560							path "../target/value";561						}562					}563				}564			}565			leaf one-one {566				type string;567			}568			leaf one-two {569				type string;570			}571		}572		case two {573			leaf testboolean {574				type boolean;575				default false;576			}577			choice beta {578				leaf beta-one {579					type string;580				}581				case beta-case {582					leaf beta-two {583						type string;584					}585					leaf beta-three {586						type string;587					}588				}589			}590			leaf two-one {591				type string;592			}593			leaf two-two {594				type string;595			}596		}597		leaf teststring {598			type string;599		}600	}601}602`603	var teststringpath_bam = pathutil.CopyAppend(teststringpath, "bam")604	teststringpath_bam = pathutil.CopyAppend(teststringpath_bam, "")605	tbl := []ValidateOpTbl{606		NewValOpTblEntry("Set empty path", emptypath, "", true),607		NewValOpTblEntry("Set empty path", targetpath, "", false),608		NewValOpTblEntry("Set empty path", abstargetpath, "", false),609		NewValOpTblEntry("Set empty path", relativetargetpath, "", false),610		NewValOpTblEntry("Set invalid path", invalidpath, "", true),611		NewValOpTblEntry("Set root path", rootpath, "", true),612		NewValOpTblEntry("Set empty leaf", testemptypath, "", false),613		NewValOpTblEntry("Set boolean node true", testbooleanpath, "true", false),614		NewValOpTblEntry("Set boolean node false", testbooleanpath, "false", false),615		NewValOpTblEntry("Set string value", teststringpath, "foo", false),616		NewValOpTblEntry("Set string value with trailing /", teststringpath_bam, "", true),617	}618	srv, sess := TstStartup(t, schema, emptyconfig)619	ValidateSetTable(t, sess, srv.Ctx, tbl)620	sess.Kill()621}622// Tests that work through a series of set operations623// do verify that other cases in a choice are deleted624func TestChoiceAutoDelete(t *testing.T) {625	const schema = `626	container testcontainer {627	choice achoice {628		case one {629			leaf one-one {630				type string;631			}632		}633		case two {634			leaf one-two {635				type string;636			}637			leaf mand-node {638				mandatory true;639				type string;640			}641		}642		case three {643			container one-three {644				leaf one-three-leaf {645					type string;646				}647			}648			choice anotherchoice {649				container two-one {650					leaf two-one-leaf {651						type string;652					}653				}654				case a {655					container two-two {656						leaf two-two-a {657							type string;658						}659						leaf two-two-b {660							type string;661						}662					}663				}664			}665		}666	}667}668`669	var cOneOne = []string{"testcontainer", "one-one", "11"}670	var cOneTwo = []string{"testcontainer", "one-two", "12"}671	var cMandNode = []string{"testcontainer", "mand-node", "foo"}672	var cOneThreeLeaf = []string{"testcontainer", "one-three", "one-three-leaf", "13"}673	var cTwoOneLeaf = []string{"testcontainer", "two-one", "two-one-leaf", "21"}674	var cTwoTwoA = []string{"testcontainer", "two-two", "two-two-a", "22A"}675	var cTwoTwoB = []string{"testcontainer", "two-two", "two-two-b", "22B"}676	srv, sess := TstStartup(t, schema, emptyconfig)677	defer sess.Kill()678	ValidateSet(t, sess, srv.Ctx, cOneOne, false)679	const sOneOne = `testcontainer {680	one-one 11681}682`683	ValidateShow(t, sess, srv.Ctx, emptypath, false, sOneOne, true)684	// Applying this config should remove the one-one config applied earlier685	ValidateSet(t, sess, srv.Ctx, cOneTwo, false)686	const sOneTwo = `testcontainer {687	mand-node foo688	one-two 12689}690`691	// Fails as mand-node is missing692	ValidateCommit(t, sess, srv.Ctx, false, sOneTwo)693	ValidateSet(t, sess, srv.Ctx, cMandNode, false)694	// Success again as mandatory (mand-node) present695	ValidateCommit(t, sess, srv.Ctx, true, sOneTwo)696	ValidateShow(t, sess, srv.Ctx, emptypath, false, sOneTwo, true)697	// this will result in previous config being removed698	ValidateSet(t, sess, srv.Ctx, cOneThreeLeaf, false)699	const sOneThreeLeaf = `testcontainer {700	one-three {701		one-three-leaf 13702	}703}704`705	ValidateShow(t, sess, srv.Ctx, emptypath, false, sOneThreeLeaf, true)706	// Check config in a hierarchical choice behaves correctly707	ValidateSet(t, sess, srv.Ctx, cTwoTwoA, false)708	ValidateSet(t, sess, srv.Ctx, cTwoTwoB, false)709	const sTwoTwo = `testcontainer {710	one-three {711		one-three-leaf 13712	}713	two-two {714		two-two-a 22A715		two-two-b 22B716	}717}718`719	ValidateShow(t, sess, srv.Ctx, emptypath, false, sTwoTwo, true)720	ValidateSet(t, sess, srv.Ctx, cTwoOneLeaf, false)721	const sTwoOneLeaf = `testcontainer {722	one-three {723		one-three-leaf 13724	}725	two-one {726		two-one-leaf 21727	}728}729`730	ValidateShow(t, sess, srv.Ctx, emptypath, false, sTwoOneLeaf, true)731}732// Tests to verify a choice default733// Verify that initial defaults appear in show output734// instantiate values in other cases, and verify the correct735// defaults are shown736func TestChoiceDefaults(t *testing.T) {737	const schema = `738	choice top-level {739		default top-default-seen;740		leaf top-default-seen {741			type string;742			default "seen";743		}744		leaf top-default-hidden {745			type string;746			default "hidden";747		}748	}749	container testcontainer {750	choice achoice {751		default three-four;752		case one {753			leaf one {754				type string;755			}756			leaf default-one {757				type string;758				default "1";759			}760		}761		case two {762			leaf two {763				type string;764			}765			leaf default-two {766				type string;767				default "2";768			}769		}770		case three-four {771			container three {772				leaf three {773					type string;774				}775				leaf default-three {776					type string;777					default "3";778				}779				choice sub-three {780					default sub-three-a;781					case sub-three-a {782						container defaults-seen {783							leaf def-one {784								type string;785								default "1";786							}787							leaf def-two {788								type string;789								default "2";790							}791						}792						container defaults-hidden {793							presence "";794							leaf def-three {795								type string;796								default "3";797							}798							leaf def-four {799								type string;800								default "4";801							}802						}803					}804				}805			}806			container four {807				presence "guard default-four";808				leaf four {809					type string;810				}811				leaf default-four {812					type string;813					default four;814				}815			}816		}817	}818}819`820	srv, sess := TstStartup(t, schema, emptyconfig)821	defer sess.Kill()822	//ValidateSet(t, sess, srv.Ctx, cOneOne, false)823	const initConfig = `testcontainer {824	three {825		default-three 3826		defaults-seen {827			def-one 1828			def-two 2829		}830	}831}832top-default-seen seen833`834	ValidateShowWithDefaults(t, sess, srv.Ctx, emptypath, false, initConfig, true)835	const finalConfig = `testcontainer {836	default-one 1837	one one838}839top-default-hidden override840`841	ValidateSet(t, sess, srv.Ctx, []string{"top-default-hidden", "override"}, false)842	ValidateSet(t, sess, srv.Ctx, []string{"testcontainer", "one", "one"}, false)843	ValidateShowWithDefaults(t, sess, srv.Ctx, emptypath, false, finalConfig, true)844}845func TestSetLeafList(t *testing.T) {846	const schema = `847container testcontainer {848	leaf-list testleaflistuser {849		type string;850		ordered-by user;851	}852	leaf-list testleaflistsystem {853		type string;854		ordered-by system;855	}856}857`858	// TODO: order-by system not supported yet859	// var testleaflistsystempath = pathutil.CopyAppend(testcontainerpath, "testleaflistsystem")860	tbl := []ValidateOpTbl{861		NewValOpTblEntry("Set list-leaf without value", testleaflistuserpath, "", true),862		NewValOpTblEntry("Set list-leaf item 1", testleaflistuserpath, "foo", false),863		NewValOpTblEntry("Set list-leaf item 2", testleaflistuserpath, "bar", false),864		NewValOpTblEntry("Set list-leaf item 3", testleaflistuserpath, "baz", false),865		NewValOpTblEntry("Set list-leaf item 4", testleaflistuserpath, "foo", true),866	}867	srv, sess := TstStartup(t, schema, emptyconfig)868	ValidateSetTable(t, sess, srv.Ctx, tbl)869	sess.Kill()870}871func TestSetList(t *testing.T) {872	const schema = `873container testcontainer {874	list testlist {875		key nodetag;876		leaf nodetag {877			type string;878		}879	}880}881`882	tbl := []ValidateOpTbl{883		NewValOpTblEntry("Set list without value", testlistpath, "", true),884		NewValOpTblEntry("Set list item 1", testlistpath, "foo", false),885		NewValOpTblEntry("Set list item 2", testlistpath, "bar", false),886		NewValOpTblEntry("Set list item 3", testlistpath, "baz", false),887		NewValOpTblEntry("Set list item 4", testlistpath, "foo", true),888	}889	srv, sess := TstStartup(t, schema, emptyconfig)890	ValidateSetTable(t, sess, srv.Ctx, tbl)891	sess.Kill()892}893// Checking aspects of leaves' behaviour with defaults and mandatory894// statements:895//896// (a) Non-presence container shows leaf with default897// (b) Presence container doesn't show leaf with default UNLESS898// (c) ... presence container is configured.899// (d) Mandatory leaf inheriting default is accepted and configurable.900func TestDefaultInNonPresenceContainer(t *testing.T) {901	const schema = `902	typedef uint_with_default {903		type uint8;904	    default 66;905	}906	container nonPresenceContainer {907		leaf testLeafInheritsDefault {908			type uint_with_default;909		}910	}`911	// Set up initial empty config.912	srv, sess := TstStartup(t, schema, "")913	// Non-presence showing leaf with default.  Should see '66' as dflt.914	const expNonPresenceConfig = `nonPresenceContainer {915	testLeafInheritsDefault 66916}917`918	ValidateShowWithDefaults(t, sess, srv.Ctx, []string{}, false,919		expNonPresenceConfig, true /* default visible */)920}921func TestDefaultNotShownInUnconfigPresenceContainer(t *testing.T) {922	const schema = `923	typedef uint_with_default {924		type uint8;925	    default 66;926	}927	container presenceContainerWithoutMandatory {928		presence "Present to show defaults hidden";929		leaf testLeafInheritsDefault {930			type uint_with_default;931		}932	}`933	// Set up initial empty config934	srv, sess := TstStartup(t, schema, "")935	// Presence container should not show leaf with default936	const expPresenceConfig = `presenceContainerWithoutMandatory {937	testLeafInheritsDefault 66938}939`940	ValidateShowWithDefaults(t, sess, srv.Ctx, []string{}, false,941		expPresenceConfig, false /* 66 not visible */)942	sess.Kill()943}944func TestDefaultShownInConfiguredPresenceContainer(t *testing.T) {945	const schema = `946	typedef uint_with_default {947		type uint8;948	    default 66;949	}950	container presenceContainerWithoutMandatory {951		presence "Present to show defaults hidden";952		leaf testLeafInheritsDefault {953			type uint_with_default;954		}955	}`956	// Set up initial empty config957	srv, sess := TstStartup(t, schema, "")958	// Now configure presence container and we should see default.959	const cfgPresence = `presenceContainerWithoutMandatory960`961	const expPresenceConfigWithoutMandatory = `presenceContainerWithoutMandatory {962	testLeafInheritsDefault 66963}964`965	tblSetPresenceWithoutMand := []ValidateOpTbl{966		NewValOpTblEntry("Verify set of non-mandatory presence container",967			[]string{"presenceContainerWithoutMandatory"}, "", false),968	}969	ValidateOperationTable(t, sess, srv.Ctx, tblSetPresenceWithoutMand,970		SET)971	ValidateCommit(t, sess, srv.Ctx, true /* expect pass */, cfgPresence)972	ValidateShowWithDefaults(t, sess, srv.Ctx, []string{}, false,973		expPresenceConfigWithoutMandatory, true)974	sess.Kill()975}976func TestMandatoryLeafInheritingDefaultIsConfigurable(t *testing.T) {977	const schema = `978	typedef uint_with_default {979		type uint8;980	    default 66;981	}982	container presenceContainer {983        presence "Show mandatory overrides inherited default.";984        description "Container to show mandatory can override default.";985		leaf testLeafInheritsDefault {986			type uint_with_default;987            mandatory "true";988		}989	}`990	// Set up initial config with mandatory node991	const mandatoryPresenceConfig = `presenceContainer {992	testLeafInheritsDefault 33993}994`995	srv, sess := TstStartup(t, schema, mandatoryPresenceConfig)996	// Non-presence showing leaf with default overridden997	const expPresenceConfig = `presenceContainer {998	testLeafInheritsDefault 33999}1000`1001	ValidateShowWithDefaults(t, sess, srv.Ctx, []string{}, false,1002		expPresenceConfig, true /* 33 visible */)1003	sess.Kill()1004}1005func validateCommitOrdering(t *testing.T, sess *Session, ctx *configd.Context, exp bool, expOut string) {1006	ValidateSessOpOutput(t, sess, ctx, exp, expOut, COMMIT)1007}1008func TestDelete(t *testing.T) {1009	const schema = `1010container testcontainer {1011	leaf testempty {1012		type empty;1013	}1014	list testlist {1015		key nodetag;1016		leaf nodetag {1017			type string;1018		}1019	}1020	leaf-list testleaflistuser {1021		type string;1022		ordered-by user;1023	}1024}1025`1026	const config = `1027testcontainer {1028	testempty1029	testlist foo1030	testlist bar1031	testlist baz1032	testleaflistuser foo1033	testleaflistuser bar1034	testleaflistuser baz1035}1036`1037	tbl := []ValidateOpTbl{1038		NewValOpTblEntry("", emptypath, "", true),1039		NewValOpTblEntry("", invalidpath, "", true),1040		NewValOpTblEntry("", rootpath, "", true),1041		NewValOpTblEntry("", testemptypath, "", false),1042		NewValOpTblEntry("", testlistpath, "foo", false),1043		NewValOpTblEntry("", testlistpath, "foo", true),1044		NewValOpTblEntry("", testlistpath, "baz", false),1045		NewValOpTblEntry("", testlistpath, "baz", true),1046		NewValOpTblEntry("", testleaflistuserpath, "foo", false),1047		NewValOpTblEntry("", testleaflistuserpath, "foo", true),1048		NewValOpTblEntry("", testleaflistuserpath, "baz", false),1049		NewValOpTblEntry("", testleaflistuserpath, "baz", true),1050	}1051	srv, sess := TstStartup(t, schema, config)1052	ValidateDeleteTable(t, sess, srv.Ctx, tbl)1053	sess.Kill()1054}1055func TestDeleteWithDefault(t *testing.T) {1056	const schema = `1057container testcontainer {1058    container cwp {1059        presence "Some presence container";1060        leaf bar {1061           type string;1062        }1063    }1064    container testcontainer2 {1065        leaf testdefault {1066            type string;1067            default hrw;1068        }1069    }1070}1071`1072	const config = `1073testcontainer {1074    cwp1075}1076`1077	srv, sess := TstStartup(t, schema, config)1078	ValidateDelete(t, sess, srv.Ctx, []string{"testcontainer"}, false)1079	ValidateExists(t, sess, srv.Ctx, []string{"testcontainer", "cwp"}, false)1080	sess.Kill()1081}1082func validateChanged(t *testing.T, sess *Session, ctx *configd.Context, exp bool) {1083	if sess.Changed(ctx) != exp {1084		t.Errorf("Session marked with incorrect changed state; expected %v", exp)1085	}1086}1087func TestChanged(t *testing.T) {1088	const schema = `1089container testcontainer {1090	leaf testboolean {1091		type boolean;1092		default false;1093	}1094	leaf teststring {1095		type string;1096	}1097}1098`1099	const config = `1100testcontainer {1101	teststring foo1102}1103`1104	srv, sess := TstStartup(t, schema, config)1105	validateChanged(t, sess, srv.Ctx, false)1106	var testbooleanpath_true = pathutil.CopyAppend(testbooleanpath, "true")1107	ValidateSet(t, sess, srv.Ctx, testbooleanpath_true, false)1108	validateChanged(t, sess, srv.Ctx, true)1109	ValidateDelete(t, sess, srv.Ctx, testbooleanpath, false)1110	validateChanged(t, sess, srv.Ctx, false)1111	var teststringpath_bar = pathutil.CopyAppend(teststringpath, "bar")1112	ValidateSet(t, sess, srv.Ctx, teststringpath_bar, false)1113	validateChanged(t, sess, srv.Ctx, true)1114	err := sess.Discard(srv.Ctx)1115	if err != nil {1116		t.Errorf("Discard failed; %s", err)1117	}1118	validateChanged(t, sess, srv.Ctx, false)1119	sess.Kill()1120}1121type validateStatusTbl struct {1122	path   []string1123	status rpc.NodeStatus1124	err    bool1125}1126func validateStatus(t *testing.T, sess *Session, ctx *configd.Context, exp validateStatusTbl) {1127	status, err := sess.GetStatus(ctx, exp.path)1128	if (err != nil) != exp.err {1129		if err == nil {1130			t.Errorf("Unexpected error from get status of  path [%s]",1131				pathutil.Pathstr(exp.path))1132		} else {1133			t.Errorf("Unexpeced error from to get status of path [%s]; %s",1134				pathutil.Pathstr(exp.path), err)1135		}1136		testutils.LogStack(t)1137		return1138	}1139	if status != exp.status {1140		statusStr := [...]string{"UNCHANGED", "CHANGED", "ADDED", "DELETED"}1141		t.Errorf("Unexpected status from path [%s]", pathutil.Pathstr(exp.path))1142		t.Logf("Received: %s(%d)", statusStr[status], status)1143		t.Logf("Expected: %s(%d)", statusStr[exp.status], exp.status)1144		testutils.LogStack(t)1145	}1146}1147func TestGetStatus(t *testing.T) {1148	const schema = `1149container testcontainer {1150	leaf testempty {1151		type empty;1152	}1153	leaf testboolean {1154		type boolean;1155		default false;1156	}1157	leaf teststring {1158		type string;1159	}1160	leaf-list testleaflistuser {1161		type string;1162		ordered-by user;1163	}1164	list testlist {1165		key name;1166		leaf name {1167			type string;1168		}1169		leaf bar {1170			type empty;1171		}1172	}1173}1174`1175	const config = `1176testcontainer {1177	teststring foo1178	testleaflistuser foo1179	testleaflistuser bar1180	testlist foo1181	testlist baz {1182		bar1183	}1184}1185`1186	var testbooleanpath_true = pathutil.CopyAppend(testbooleanpath, "true")1187	var testleaflistuserpath_foo = pathutil.CopyAppend(testleaflistuserpath, "foo")1188	var testleaflistuserpath_bar = pathutil.CopyAppend(testleaflistuserpath, "bar")1189	var testlistpath_foo = pathutil.CopyAppend(testlistpath, "foo")1190	var testlistpath_foo_bar = pathutil.CopyAppend(testlistpath_foo, "bar")1191	var testlistpath_baz = pathutil.CopyAppend(testlistpath, "baz")1192	var testlistpath_baz_bar = pathutil.CopyAppend(testlistpath_baz, "bar")1193	tbl := []ValidateStatusTbl{1194		NewValStatusTblEntry(emptypath, rpc.UNCHANGED, false),1195		NewValStatusTblEntry(invalidpath, rpc.UNCHANGED, true),1196		NewValStatusTblEntry(rootpath, rpc.UNCHANGED, true),1197		NewValStatusTblEntry(testcontainerpath, rpc.CHANGED, false),1198		NewValStatusTblEntry(testemptypath, rpc.UNCHANGED, true),1199		NewValStatusTblEntry(testbooleanpath_true, rpc.CHANGED, false),1200		NewValStatusTblEntry(teststringpath, rpc.DELETED, false),1201		NewValStatusTblEntry(testleaflistuserpath, rpc.CHANGED, false),1202		NewValStatusTblEntry(testleaflistuserpath_foo, rpc.DELETED, false),1203		NewValStatusTblEntry(testleaflistuserpath_bar, rpc.CHANGED, false),1204		NewValStatusTblEntry(testlistpath_foo, rpc.CHANGED, false),1205		NewValStatusTblEntry(testlistpath_foo_bar, rpc.ADDED, false),1206		NewValStatusTblEntry(testlistpath_baz_bar, rpc.DELETED, false),1207	}1208	srv, sess := TstStartup(t, schema, config)1209	ValidateSet(t, sess, srv.Ctx, testbooleanpath_true, false)1210	ValidateSet(t, sess, srv.Ctx, testlistpath_foo_bar, false)1211	ValidateDelete(t, sess, srv.Ctx, teststringpath, false)1212	ValidateDelete(t, sess, srv.Ctx, testleaflistuserpath_foo, false)1213	ValidateDelete(t, sess, srv.Ctx, testlistpath_baz, false)1214	for key, _ := range tbl {1215		ValidateStatus(t, sess, srv.Ctx, tbl[key])1216	}1217	sess.Kill()1218}1219func TestShow(t *testing.T) {1220	const schema = `1221container testcontainer {1222	leaf testboolean {1223		type boolean;1224		default false;1225	}1226	leaf teststring {1227		type string;1228		configd:secret true;1229	}1230	leaf-list testleaflistuser {1231		type string;1232		ordered-by user;1233	}1234	list testlist {1235		key name;1236		leaf name {1237			type string;1238		}1239		leaf bar {1240			type empty;1241		}1242	}1243}1244`1245	const config = `testcontainer {1246	testleaflistuser foo1247	testleaflistuser bar1248	testlist foo {1249		bar1250	}1251	teststring foo1252}1253`1254	srv, sess := TstStartup(t, schema, config)1255	ValidateShow(t, sess, srv.Ctx, emptypath, false, config, true)1256	hidcfg := strings.Replace(config, "teststring foo", "teststring \"********\"", 1)1257	ValidateShow(t, sess, srv.Ctx, emptypath, true, hidcfg, true)1258	expErrs := errtest.1259		NewNodeDoesntExistError(t, "/foo").1260		RawErrorStrings()1261	ValidateShowContains(t, sess, srv.Ctx, invalidpath, false, true, expErrs...)1262	sess.Kill()1263}1264func mkLoadFile(t *testing.T, config string) string {1265	f, err := ioutil.TempFile("/tmp", "tmpconfig")1266	if err != nil {1267		t.Fatal("Unable to create test config file")1268		testutils.LogStack(t)1269		return ""1270	}1271	name := f.Name()1272	f.WriteString(config)1273	f.Close()1274	return name1275}1276func validateLoad(t *testing.T, sess *Session, ctx *configd.Context, cfgfile string) {1277	err, invalidPaths := sess.Load(ctx, cfgfile, nil)1278	if err != nil {1279		t.Errorf("Error loading configuration file %s; %s", cfgfile, err)1280		testutils.LogStack(t)1281	}1282	if len(invalidPaths) > 0 {1283		t.Fatalf("Invalid paths when loading configuration file %s:\n%v\n",1284			cfgfile, invalidPaths)1285		return1286	}1287}1288func TestLoad(t *testing.T) {1289	const schema = `1290container testcontainer {1291	leaf testboolean {1292		type boolean;1293		default false;1294	}1295	leaf teststring {1296		type string;1297		configd:secret true;1298	}1299	leaf-list testleaflistuser {1300		type string;1301		ordered-by user;1302	}1303	list testlist {1304		key name;1305		leaf name {1306			type string;1307		}1308		leaf bar {1309			type empty;1310		}1311	}1312}1313`1314	const config = `1315testcontainer {1316	testleaflistuser foo1317	testleaflistuser bar1318	testlist foo {1319		bar1320	}1321	teststring foo1322}1323`1324	// config has a prepended '\n' so strip it1325	expcfg := config[1:]1326	srv, sess := TstStartup(t, schema, emptyconfig)1327	name := mkLoadFile(t, expcfg)1328	if len(name) == 0 {1329		return1330	}1331	validateLoad(t, sess, srv.Ctx, name)1332	os.Remove(name)1333	ValidateShow(t, sess, srv.Ctx, emptypath, false, expcfg, true)1334	sess.Kill()1335}1336type validateGetTreeTbl struct {1337	path     []string1338	encoding string1339	exptree  string1340	expfail  bool1341}1342func validateGetTree(t *testing.T, sess *Session, ctx *configd.Context, tst validateGetTreeTbl) {1343	ut, err := sess.GetTree(ctx, tst.path,1344		&TreeOpts{Defaults: false, Secrets: true})1345	var tree string1346	if err == nil {1347		tree, err = ut.Marshal("data", tst.encoding, union.Authorizer(sess.NewAuther(ctx)),1348			union.IncludeDefaults)1349	}1350	if (err != nil) != tst.expfail {1351		if err == nil {1352			t.Errorf("Unexpected get tree result for path [%s]; \n%s",1353				pathutil.Pathstr(tst.path), tree)1354		} else {1355			t.Errorf("Error getting tree for path loading %s; %s",1356				pathutil.Pathstr(tst.path), err)1357		}1358		testutils.LogStack(t)1359		return1360	}1361	if !tst.expfail && tst.exptree != tree {1362		t.Errorf("Unexpected tree returned for path %s", pathutil.Pathstr(tst.path))1363		t.Logf("Received:\n%s", tree)1364		t.Logf("Expected:\n%s", tst.exptree)1365	}1366}1367func TestGetTree(t *testing.T) {1368	const schema = `1369container testcontainer {1370	leaf testboolean {1371		type boolean;1372		default false;1373	}1374	leaf teststring {1375		type string;1376		configd:secret true;1377	}1378	leaf-list testleaflistuser {1379		type string;1380		ordered-by user;1381	}1382	list testlist {1383		key name;1384		leaf name {1385			type string;1386		}1387		leaf bar {1388			type empty;1389		}1390	}1391	list testlistuser {1392		ordered-by "user";1393		key name;1394		leaf name {1395			type string;1396		}1397		leaf bar {1398			type empty;1399		}1400	}1401}1402container state {1403	config false;1404	leaf status {1405		type string;1406		default "foo";1407		configd:get-state "echo {\"status\": \"Should not see this\"}";1408	}1409}1410`1411	const config = `1412testcontainer {1413	testleaflistuser foo1414	testleaflistuser bar1415	testlist foo {1416		bar1417	}1418	testlist baz {1419		bar1420	}1421	testlist bar {1422		bar1423	}1424	teststring foo1425	testlistuser foo {1426		bar1427	}1428	testlistuser baz {1429		bar1430	}1431	testlistuser bar {1432		bar1433	}1434}1435`1436	const cfg_internal = `{"testcontainer":{"testboolean":false,"testleaflistuser":["foo","bar"],"testlist":{"bar":{"bar":null},"baz":{"bar":null},"foo":{"bar":null}},"testlistuser":{"foo":{"bar":null},"baz":{"bar":null},"bar":{"bar":null}},"teststring":"foo"}}`1437	const cfg_json = `{"testcontainer":{"testboolean":false,"testleaflistuser":["foo","bar"],"testlist":[{"name":"bar","bar":null},{"name":"baz","bar":null},{"name":"foo","bar":null}],"testlistuser":[{"name":"foo","bar":null},{"name":"baz","bar":null},{"name":"bar","bar":null}],"teststring":"foo"}}`1438	const cfg_xml = `<data><testcontainer xmlns="urn:vyatta.com:test:configd-session"><testboolean xmlns="urn:vyatta.com:test:configd-session">false</testboolean><testleaflistuser xmlns="urn:vyatta.com:test:configd-session">foo</testleaflistuser><testleaflistuser xmlns="urn:vyatta.com:test:configd-session">bar</testleaflistuser><testlist xmlns="urn:vyatta.com:test:configd-session"><name xmlns="urn:vyatta.com:test:configd-session">bar</name><bar xmlns="urn:vyatta.com:test:configd-session"></bar></testlist><testlist xmlns="urn:vyatta.com:test:configd-session"><name xmlns="urn:vyatta.com:test:configd-session">baz</name><bar xmlns="urn:vyatta.com:test:configd-session"></bar></testlist><testlist xmlns="urn:vyatta.com:test:configd-session"><name xmlns="urn:vyatta.com:test:configd-session">foo</name><bar xmlns="urn:vyatta.com:test:configd-session"></bar></testlist><testlistuser xmlns="urn:vyatta.com:test:configd-session"><name xmlns="urn:vyatta.com:test:configd-session">foo</name><bar xmlns="urn:vyatta.com:test:configd-session"></bar></testlistuser><testlistuser xmlns="urn:vyatta.com:test:configd-session"><name xmlns="urn:vyatta.com:test:configd-session">baz</name><bar xmlns="urn:vyatta.com:test:configd-session"></bar></testlistuser><testlistuser xmlns="urn:vyatta.com:test:configd-session"><name xmlns="urn:vyatta.com:test:configd-session">bar</name><bar xmlns="urn:vyatta.com:test:configd-session"></bar></testlistuser><teststring xmlns="urn:vyatta.com:test:configd-session">foo</teststring></testcontainer></data>`1439	const enc_internal = "internal"1440	const enc_json = "json"1441	const enc_xml = "xml"1442	const enc_invalid = "invalidencoding"1443	tbl := []validateGetTreeTbl{1444		{emptypath, enc_invalid, "", true},1445		{emptypath, enc_internal, cfg_internal, false},1446		{invalidpath, enc_internal, cfg_internal, true},1447		{rootpath, enc_internal, cfg_internal, true},1448		{testcontainerpath, enc_internal, cfg_internal, false},1449		{testcontainerpath, enc_json, cfg_json, false},1450		{testcontainerpath, enc_xml, cfg_xml, false},1451	}1452	srv, sess := TstStartup(t, schema, config)1453	for key, _ := range tbl {1454		validateGetTree(t, sess, srv.Ctx, tbl[key])1455	}1456	sess.Kill()1457}1458func validateValidate(t *testing.T, sess *Session, ctx *configd.Context, exp bool, expOut string) {1459	ValidateSessOpOutput(t, sess, ctx, exp, expOut, VALIDATE)1460}1461// TODO: Since no xpath, need multiple schemas to test validation1462// failure and success. Once we have xpath support these can be1463// collapsed into a single test schema with xpath expression.1464func TestValidateFailure(t *testing.T) {1465	const schema = `1466container testcontainer {1467	leaf testempty {1468		type empty;1469		configd:validate "false";1470	}1471}1472`1473	const emptyout = ""1474	srv, sess := TstStartup(t, schema, emptyconfig)1475	// Validate locked session1476	altctx := &configd.Context{1477		Pid:  int32(1),1478		Auth: srv.Auth,1479		Dlog: srv.Dlog,1480		Elog: srv.Elog,1481	}1482	_, err := sess.Lock(altctx)1483	if err != nil {1484		t.Fatalf("Unable to lock session; %s", err)1485	}1486	validateValidate(t, sess, srv.Ctx, false, emptyout)1487	_, err = sess.Unlock(altctx)1488	if err != nil {1489		t.Fatalf("Unable to unlock session; %s", err)1490	}1491	// Validate no change doesn't generate error first ...1492	validateValidate(t, sess, srv.Ctx, true, emptyout)1493	// Validate with validation failure1494	ValidateSet(t, sess, srv.Ctx, testemptypath, false)1495	validateValidate(t, sess, srv.Ctx, false, emptyout)1496	sess.Kill()1497}1498func TestValidate(t *testing.T) {1499	const schema = `container testcontainer {1500	leaf testempty {1501		type empty;1502		configd:validate "echo testempty";1503	}1504	leaf testboolean {1505		type boolean;1506		default false;1507		configd:validate "echo testboolean";1508	}1509	leaf teststring {1510		type string;1511		configd:secret true;1512		configd:validate "echo teststring";1513	}1514	leaf-list testleaflistuser {1515		type string;1516		ordered-by user;1517		configd:validate "echo testleaflistuser";1518	}1519	list testlist {1520		key name;1521		leaf name {1522			type string;1523			configd:validate "echo testlist key name";1524		}1525		leaf bar {1526			type empty;1527			configd:validate "echo testlist leaf bar";1528		}1529		configd:validate "echo testlist";1530	}1531}1532`1533	const config = `testcontainer {1534	testempty1535	testlist foo {1536		bar1537	}1538}1539`1540	var expOutput = `[testcontainer testboolean false]1541testboolean1542[testcontainer testempty]1543testempty1544[testcontainer testleaflistuser bar]1545testleaflistuser1546[testcontainer testleaflistuser foo]1547testleaflistuser1548[testcontainer testlist baz]1549testlist1550[testcontainer testlist baz bar]1551testlist leaf bar1552[testcontainer testlist baz name baz]1553testlist key name1554[testcontainer teststring foo]1555teststring1556`1557	var testleaflistuserpath_foo = pathutil.CopyAppend(testleaflistuserpath, "foo")1558	var testleaflistuserpath_bar = pathutil.CopyAppend(testleaflistuserpath, "bar")1559	var testlistpath_foo = pathutil.CopyAppend(testlistpath, "foo")1560	var testlistpath_baz = pathutil.CopyAppend(testlistpath, "baz")1561	var testlistpath_baz_bar = pathutil.CopyAppend(testlistpath_baz, "bar")1562	var teststringpath_foo = pathutil.CopyAppend(teststringpath, "foo")1563	srv, sess := TstStartup(t, schema, config)1564	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_foo, false)1565	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_bar, false)1566	ValidateDelete(t, sess, srv.Ctx, testlistpath_foo, false)1567	ValidateSet(t, sess, srv.Ctx, testlistpath_baz_bar, false)1568	ValidateSet(t, sess, srv.Ctx, teststringpath_foo, false)1569	validateValidate(t, sess, srv.Ctx, true, expOutput)1570	sess.Kill()1571}1572func TestExtensionIfFeatureEnabled(t *testing.T) {1573	const schema = `1574	feature testfeature {1575		description "testfeature";1576	}1577	augment /testcontainer {1578		if-feature testfeature;1579		configd:validate "echo testcontainer if-feature";1580	}1581container testcontainer {1582	leaf testempty {1583		type empty;1584		configd:validate "echo testempty";1585	}1586	leaf testboolean {1587		type boolean;1588		default false;1589		configd:validate "echo testboolean";1590	}1591	leaf teststring {1592		type string;1593		configd:secret true;1594		configd:validate "echo teststring";1595	}1596	leaf-list testleaflistuser {1597		type string;1598		ordered-by user;1599		configd:validate "echo testleaflistuser";1600	}1601	list testlist {1602		key name;1603		leaf name {1604			type string;1605			configd:validate "echo testlist key name";1606		}1607		leaf bar {1608			type empty;1609			configd:validate "echo testlist leaf bar";1610		}1611		configd:validate "echo testlist";1612	}1613}1614`1615	const config = `testcontainer {1616	testempty1617	testlist foo {1618		bar1619	}1620}1621`1622	var expOutput = `[testcontainer]1623testcontainer if-feature1624[testcontainer testboolean false]1625testboolean1626[testcontainer testempty]1627testempty1628[testcontainer testleaflistuser bar]1629testleaflistuser1630[testcontainer testleaflistuser foo]1631testleaflistuser1632[testcontainer testlist baz]1633testlist1634[testcontainer testlist baz bar]1635testlist leaf bar1636[testcontainer testlist baz name baz]1637testlist key name1638[testcontainer teststring foo]1639teststring1640`1641	var testleaflistuserpath_foo = pathutil.CopyAppend(testleaflistuserpath, "foo")1642	var testleaflistuserpath_bar = pathutil.CopyAppend(testleaflistuserpath, "bar")1643	var testlistpath_foo = pathutil.CopyAppend(testlistpath, "foo")1644	var testlistpath_baz = pathutil.CopyAppend(testlistpath, "baz")1645	var testlistpath_baz_bar = pathutil.CopyAppend(testlistpath_baz, "bar")1646	var teststringpath_foo = pathutil.CopyAppend(teststringpath, "foo")1647	srv, sess := TstStartupWithCapabilities(t, schema, config,1648		"testdata/extensionFeatures/capsAll")1649	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_foo, false)1650	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_bar, false)1651	ValidateDelete(t, sess, srv.Ctx, testlistpath_foo, false)1652	ValidateSet(t, sess, srv.Ctx, testlistpath_baz_bar, false)1653	ValidateSet(t, sess, srv.Ctx, teststringpath_foo, false)1654	validateValidate(t, sess, srv.Ctx, true, expOutput)1655	sess.Kill()1656}1657func TestExtensionIfFeatureDisabled(t *testing.T) {1658	const schema = `1659	feature testfeature {1660		description "testfeature";1661	}1662	augment /testcontainer {1663		if-feature testfeature;1664		configd:validate "echo testcontainer if-feature";1665	}1666container testcontainer {1667	leaf testempty {1668		type empty;1669		configd:validate "echo testempty";1670	}1671	leaf testboolean {1672		type boolean;1673		default false;1674		configd:validate "echo testboolean";1675	}1676	leaf teststring {1677		type string;1678		configd:secret true;1679		configd:validate "echo teststring";1680	}1681	leaf-list testleaflistuser {1682		type string;1683		ordered-by user;1684		configd:validate "echo testleaflistuser";1685	}1686	list testlist {1687		key name;1688		leaf name {1689			type string;1690			configd:validate "echo testlist key name";1691		}1692		leaf bar {1693			type empty;1694			configd:validate "echo testlist leaf bar";1695		}1696		configd:validate "echo testlist";1697	}1698}1699`1700	const config = `testcontainer {1701	testempty1702	testlist foo {1703		bar1704	}1705}1706`1707	var expOutput = `[testcontainer testboolean false]1708testboolean1709[testcontainer testempty]1710testempty1711[testcontainer testleaflistuser bar]1712testleaflistuser1713[testcontainer testleaflistuser foo]1714testleaflistuser1715[testcontainer testlist baz]1716testlist1717[testcontainer testlist baz bar]1718testlist leaf bar1719[testcontainer testlist baz name baz]1720testlist key name1721[testcontainer teststring foo]1722teststring1723`1724	var testleaflistuserpath_foo = pathutil.CopyAppend(testleaflistuserpath, "foo")1725	var testleaflistuserpath_bar = pathutil.CopyAppend(testleaflistuserpath, "bar")1726	var testlistpath_foo = pathutil.CopyAppend(testlistpath, "foo")1727	var testlistpath_baz = pathutil.CopyAppend(testlistpath, "baz")1728	var testlistpath_baz_bar = pathutil.CopyAppend(testlistpath_baz, "bar")1729	var teststringpath_foo = pathutil.CopyAppend(teststringpath, "foo")1730	srv, sess := TstStartup(t, schema, config)1731	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_foo, false)1732	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_bar, false)1733	ValidateDelete(t, sess, srv.Ctx, testlistpath_foo, false)1734	ValidateSet(t, sess, srv.Ctx, testlistpath_baz_bar, false)1735	ValidateSet(t, sess, srv.Ctx, teststringpath_foo, false)1736	validateValidate(t, sess, srv.Ctx, true, expOutput)1737	sess.Kill()1738}1739func TestCommit(t *testing.T) {1740	const schema = `1741container testcontainer {1742	leaf testboolean {1743		type boolean;1744		default false;1745	}1746	leaf teststring {1747		type string;1748		configd:secret true;1749	}1750	leaf-list testleaflistuser {1751		type string;1752		ordered-by user;1753	}1754	list testlist {1755		key name;1756		leaf name {1757			type string;1758		}1759		leaf bar {1760			type empty;1761		}1762	}1763}1764`1765	const config = `testcontainer {1766	testboolean true1767	testleaflistuser foo1768	testleaflistuser bar1769	testlist foo {1770		bar1771	}1772	teststring foo1773}1774`1775	srv, sess := TstStartup(t, schema, emptyconfig)1776	// Commit nothing1777	ValidateCommit(t, sess, srv.Ctx, false, emptyconfig)1778	// Commit locked session1779	altctx := &configd.Context{1780		Pid:  int32(1),1781		Auth: srv.Auth,1782		Dlog: srv.Dlog,1783		Elog: srv.Elog,1784	}1785	_, err := sess.Lock(altctx)1786	if err != nil {1787		t.Fatalf("Unable to lock session; %s", err)1788	}1789	ValidateCommit(t, sess, srv.Ctx, false, emptyconfig)1790	_, err = sess.Unlock(altctx)1791	if err != nil {1792		t.Fatalf("Unable to unlock session; %s", err)1793	}1794	// Commit changes1795	var testbooleanpath_true = pathutil.CopyAppend(testbooleanpath, "true")1796	var teststringpath_foo = pathutil.CopyAppend(teststringpath, "foo")1797	var testleaflistuserpath_foo = pathutil.CopyAppend(testleaflistuserpath, "foo")1798	var testleaflistuserpath_bar = pathutil.CopyAppend(testleaflistuserpath, "bar")1799	var testlistpath_foo = pathutil.CopyAppend(testlistpath, "foo")1800	var testlistpath_foo_bar = pathutil.CopyAppend(testlistpath_foo, "bar")1801	ValidateSet(t, sess, srv.Ctx, testbooleanpath_true, false)1802	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_foo, false)1803	ValidateSet(t, sess, srv.Ctx, testleaflistuserpath_bar, false)1804	ValidateSet(t, sess, srv.Ctx, testlistpath_foo_bar, false)1805	ValidateSet(t, sess, srv.Ctx, teststringpath_foo, false)1806	ValidateCommit(t, sess, srv.Ctx, true, config)1807	sess.Kill()1808}1809/*1810 * TestUnique1811 *1812 * T1: same port, no IP1813 * T2: same port, S1 has IP1814 * T3: same port, different IP1815 * T4: same IP, no port1816 * T5: same IP, S1 has port1817 * T6: same IP, different port1818 * T7: same IP and port (expect FAIL)1819 */1820func TestUnique(t *testing.T) {1821	type validateUniqueTbl struct {1822		path []string1823		exp  bool1824	}1825	type uniqueTestTbl struct {1826		add_cmds []ValidateOpTbl1827		exp      bool1828	}1829	const schema = `1830	container testuniq {1831		list server {1832			key "name";1833			unique "port ip";1834			leaf name {1835				type string;1836			}1837			leaf ip {1838				type uint32;1839			}1840			leaf port {1841				type uint32 {1842					range 1000..9999;1843				}1844			}1845		}1846	}1847	`1848	const config = `testuniq {1849	server dummy1850}1851`1852	const server = "server"1853	const testuniq = "testuniq"1854	var testuniqpath = []string{testuniq}1855	var server_path = pathutil.CopyAppend(testuniqpath, server)1856	var s1p1 = []string{"testuniq", "server", "s1", "port", "1111"}1857	var s1i1 = []string{"testuniq", "server", "s1", "ip", "111"}1858	var s2p1 = []string{"testuniq", "server", "s2", "port", "1111"}1859	var s2p2 = []string{"testuniq", "server", "s2", "port", "2222"}1860	var s2i1 = []string{"testuniq", "server", "s2", "ip", "111"}1861	var s2i2 = []string{"testuniq", "server", "s2", "ip", "222"}1862	// Always use S1 and S2, so common delete table.1863	test_del_tbl := []ValidateOpTbl{1864		NewValOpTblEntry("", server_path, "s1", true /* commit should pass */),1865		NewValOpTblEntry("", server_path, "s2", true /* commit should pass */),1866	}1867	// T1: same port, no IP1868	test1_tbl := []ValidateOpTbl{1869		NewValOpTblEntry("", s1p1, "", false /* set should PASS */),1870		NewValOpTblEntry("", s2p1, "", false),1871	}1872	// T2: same port, S1 has IP1873	test2_tbl := []ValidateOpTbl{1874		NewValOpTblEntry("", s1p1, "", false),1875		NewValOpTblEntry("", s1i1, "", false),1876		NewValOpTblEntry("", s2p1, "", false),1877	}1878	// T3: same port, different IP1879	test3_tbl := []ValidateOpTbl{1880		NewValOpTblEntry("", s1p1, "", false),1881		NewValOpTblEntry("", s1i1, "", false),1882		NewValOpTblEntry("", s2p1, "", false),1883		NewValOpTblEntry("", s2i2, "", false),1884	}1885	// T4: same IP, no port1886	test4_tbl := []ValidateOpTbl{1887		NewValOpTblEntry("", s1i1, "", false),1888		NewValOpTblEntry("", s2i1, "", false),1889	}1890	// T5: same IP, S1 has port1891	test5_tbl := []ValidateOpTbl{1892		NewValOpTblEntry("", s1p1, "", false),1893		NewValOpTblEntry("", s1i1, "", false),1894		NewValOpTblEntry("", s2i1, "", false),1895	}1896	// T6: same IP, different port1897	test6_tbl := []ValidateOpTbl{1898		NewValOpTblEntry("", s1p1, "", false),1899		NewValOpTblEntry("", s1i1, "", false),1900		NewValOpTblEntry("", s2p2, "", false),1901		NewValOpTblEntry("", s2i1, "", false),1902	}1903	// T7: same IP and port (expect FAIL)1904	test7_tbl_fail := []ValidateOpTbl{1905		NewValOpTblEntry("", s1p1, "", false),1906		NewValOpTblEntry("", s1i1, "", false),1907		NewValOpTblEntry("", s2p1, "", false),1908		NewValOpTblEntry("", s2i1, "", false),1909	}1910	// List of tests + results.  Ideally we'd have the test definitions1911	// above including their result, but for now this will do.  Note use1912	// of _fail as suffix for tests expected to fail to try to ensure1913	// correct results listed below.1914	uniq_tests := []uniqueTestTbl{1915		{test1_tbl, true /* commit should pass */},1916		{test2_tbl, true},1917		{test3_tbl, true},1918		{test4_tbl, true},1919		{test5_tbl, true},1920		{test6_tbl, true},1921		{test7_tbl_fail, false /* commit should fail */},1922	}1923	srv, sess := TstStartup(t, schema, config)1924	// For each test case, set all commands, then commit, then delete1925	// and (un)commit to leave a clean config for next test.1926	for _, test := range uniq_tests {1927		ValidateOperationTable(t, sess, srv.Ctx, test.add_cmds, SET)1928		ValidateCommit(t, sess, srv.Ctx, test.exp)1929		ValidateOperationTable(t, sess, srv.Ctx, test_del_tbl,1930			DELETE_AND_COMMIT)1931	}1932	sess.Kill()1933}1934type leaflistpath []string1935func (p leaflistpath) Generate(rand *rand.Rand, size int) reflect.Value {1936	p = pathutil.CopyAppend([]string{testleaflist},1937		fmt.Sprintf("%d", rand.Uint32()))1938	return reflect.ValueOf(p)1939}1940func (p leaflistpath) String() string {1941	var b bytes.Buffer1942	for i, s := range p {1943		if i > 0 {1944			b.WriteByte(' ')1945		}1946		b.WriteString(s)1947	}1948	return b.String()1949}1950func TestLeafListUserOrder(t *testing.T) {1951	if testing.Short() {1952		// Ironically, 'quick' test takes 1.75s!1953		t.Skipf("Skip LeafListUser Order test for 'short' tests")1954	}1955	const schema = `1956	leaf-list testleaflist {1957		type string;1958		ordered-by user;1959	}1960`1961	srv, sess := TstStartup(t, schema, emptyconfig)1962	defer sess.Kill()1963	check := func(paths []leaflistpath) bool {1964		defer sess.Discard(srv.Ctx)1965		var exp bytes.Buffer1966		for _, p := range paths {1967			if err := sess.Set(srv.Ctx, p); err != nil {1968				t.Fatal(err)1969			}1970			exp.WriteString(p.String())1971			exp.WriteByte('\n')1972		}1973		cfg, err := sess.Show(srv.Ctx, emptypath, true, false)1974		if err != nil {1975			t.Fatal(err)1976		}1977		return cfg == exp.String()1978	}1979	seed := time.Now().UnixNano()1980	qcfg := quick.Config{1981		Rand: rand.New(rand.NewSource(seed)),1982	}1983	if err := quick.Check(check, &qcfg); err != nil {1984		t.Logf("Seed %v", seed)1985		t.Error(err)1986	}1987}1988func TestLeafListSystemOrder(t *testing.T) {1989	if testing.Short() {1990		// Ironically, 'quick' test takes 1.75s!1991		t.Skipf("Skip LeafListSystem Order test for 'short' tests")1992	}1993	const schema = `1994	leaf-list testleaflist {1995		type string;1996		ordered-by system;1997	}1998`1999	srv, sess := TstStartup(t, schema, emptyconfig)2000	defer sess.Kill()2001	check := func(paths []leaflistpath) bool {2002		defer sess.Discard(srv.Ctx)2003		cfgPaths := make([]string, len(paths))2004		for i, p := range paths {2005			if err := sess.Set(srv.Ctx, p); err != nil {2006				t.Fatal(err)2007			}2008			cfgPaths[i] = p.String()2009		}2010		cfg, err := sess.Show(srv.Ctx, emptypath, true, false)2011		if err != nil {2012			t.Fatal(err)2013		}2014		natsort.Sort(cfgPaths)2015		var exp bytes.Buffer2016		for _, p := range cfgPaths {2017			exp.WriteString(p)2018			exp.WriteByte('\n')2019		}2020		return cfg == exp.String()2021	}2022	seed := time.Now().UnixNano()2023	qcfg := quick.Config{2024		Rand: rand.New(rand.NewSource(seed)),2025	}2026	if err := quick.Check(check, &qcfg); err != nil {2027		t.Logf("Seed %v", seed)2028		t.Error(err)2029	}2030}2031func TestLeafListOrder_VRVDR2911(t *testing.T) {2032	const schema = `2033container testcontainer {2034	list testlist {2035		key id;2036		leaf id {2037			type uint32;2038		}2039		leaf-list testleaflistuser {2040			type string;2041			ordered-by user;2042		}2043	}2044}2045`2046	const config = `testcontainer {2047	testlist 0 {2048		testleaflistuser foo2049		testleaflistuser bar2050	}2051}2052`2053	const expconfig = `testcontainer {2054	testlist 0 {2055		testleaflistuser baz2056		testleaflistuser bar2057	}2058}2059`2060	var testlistpath_0 = pathutil.CopyAppend(testlistpath, "0")2061	var testleaflistpath = pathutil.CopyAppend(testlistpath_0, testleaflistuser)2062	var testleaflistpath_bar = pathutil.CopyAppend(testleaflistpath, "bar")2063	var testleaflistpath_baz = pathutil.CopyAppend(testleaflistpath, "baz")2064	srv, sess := TstStartup(t, schema, config)2065	ValidateDelete(t, sess, srv.Ctx, testlistpath, false)2066	ValidateSet(t, sess, srv.Ctx, testleaflistpath_baz, false)2067	ValidateSet(t, sess, srv.Ctx, testleaflistpath_bar, false)2068	ValidateCommit(t, sess, srv.Ctx, true, expconfig)2069	ValidateDelete(t, sess, srv.Ctx, testlistpath, false)2070	ValidateSet(t, sess, srv.Ctx, testleaflistpath_baz, false)2071	ValidateSet(t, sess, srv.Ctx, testleaflistpath_bar, false)2072	ValidateCommit(t, sess, srv.Ctx, false, expconfig)2073	sess.Kill()2074}2075type listpath []string2076func (p listpath) Generate(rand *rand.Rand, size int) reflect.Value {2077	p = pathutil.CopyAppend([]string{testlist},2078		fmt.Sprintf("%d", rand.Uint32()))2079	return reflect.ValueOf(p)2080}2081func (p listpath) String() string {2082	var b bytes.Buffer2083	for i, s := range p {2084		if i > 0 {2085			b.WriteByte(' ')2086		}2087		b.WriteString(s)2088	}2089	return b.String()2090}2091func TestListUserOrder(t *testing.T) {2092	if testing.Short() {2093		// Ironically, 'quick' test takes 1.75s!2094		t.Skipf("Skip ListUser Order test for 'short' tests")2095	}2096	const schema = `2097	list testlist {2098		ordered-by user;2099		key name;2100		leaf name {2101			type string;2102		}2103	}2104`2105	srv, sess := TstStartup(t, schema, emptyconfig)2106	defer sess.Kill()2107	check := func(paths []listpath) bool {2108		defer sess.Discard(srv.Ctx)2109		var exp bytes.Buffer2110		for _, p := range paths {2111			if err := sess.Set(srv.Ctx, p); err != nil {2112				t.Fatal(err)2113			}2114			exp.WriteString(p.String())2115			exp.WriteByte('\n')2116		}2117		cfg, err := sess.Show(srv.Ctx, emptypath, true, false)2118		if err != nil {2119			t.Fatal(err)2120		}2121		return cfg == exp.String()2122	}2123	seed := time.Now().UnixNano()2124	qcfg := quick.Config{2125		Rand: rand.New(rand.NewSource(seed)),2126	}2127	if err := quick.Check(check, &qcfg); err != nil {2128		t.Logf("Seed %v", seed)2129		t.Error(err)2130	}2131}2132func TestListSystemOrder(t *testing.T) {2133	if testing.Short() {2134		// Ironically, 'quick' test takes 1.75s!2135		t.Skipf("Skip ListSystem Order test for 'short' tests")2136	}2137	const schema = `2138	list testlist {2139		ordered-by system;2140		key name;2141		leaf name {2142			type string;2143		}2144	}2145`2146	srv, sess := TstStartup(t, schema, emptyconfig)2147	defer sess.Kill()2148	check := func(paths []listpath) bool {2149		defer sess.Discard(srv.Ctx)2150		cfgPaths := make([]string, len(paths))2151		for i, p := range paths {2152			if err := sess.Set(srv.Ctx, p); err != nil {2153				t.Fatal(err)2154			}2155			cfgPaths[i] = p.String()2156		}2157		cfg, err := sess.Show(srv.Ctx, emptypath, true, false)2158		if err != nil {2159			t.Fatal(err)2160		}2161		natsort.Sort(cfgPaths)2162		var exp bytes.Buffer2163		for _, p := range cfgPaths {2164			exp.WriteString(p)2165			exp.WriteByte('\n')2166		}2167		return cfg == exp.String()2168	}2169	seed := time.Now().UnixNano()2170	qcfg := quick.Config{2171		Rand: rand.New(rand.NewSource(seed)),2172	}2173	if err := quick.Check(check, &qcfg); err != nil {2174		t.Logf("Seed %v", seed)2175		t.Error(err)2176	}2177}2178func TestGuessSecrets_VRVDR3934(t *testing.T) {2179	const schema = `2180container testcontainer {2181	list testlist {2182		key name;2183		leaf name {2184			type string;2185		}2186		leaf secret {2187			type string;2188			configd:secret true;2189		}2190	}2191}2192`2193	const config = `testcontainer {2194	testlist foo {2195		secret bar2196	}2197}2198`2199	const expconfig = `testcontainer {2200	testlist foo {2201		secret "********"2202	}2203}2204`2205	var testlistpath_foo = pathutil.CopyAppend(testlistpath, "foo")2206	var secretpath = pathutil.CopyAppend(testlistpath_foo, "secret")2207	var secretpath_bar = pathutil.CopyAppend(secretpath, "bar")2208	var secretpath_baz = pathutil.CopyAppend(secretpath, "baz")2209	srv, sess := TstStartup(t, schema, config)2210	altctx := srv.Ctx2211	altctx.Configd = false2212	ValidateSet(t, sess, altctx, secretpath_bar, false)2213	ValidateCommit(t, sess, altctx, false, emptyconfig)2214	ValidateSet(t, sess, altctx, secretpath_baz, false)2215	ValidateCommit(t, sess, altctx, true, expconfig)2216	ValidateSet(t, sess, srv.Ctx, secretpath_baz, false)2217	ValidateCommit(t, sess, srv.Ctx, false, emptyconfig)2218	ValidateSet(t, sess, srv.Ctx, secretpath_bar, false)2219	ValidateCommit(t, sess, srv.Ctx, true, expconfig)2220	sess.Kill()2221}2222// configd scripts can be invoked in one of 2 ways - via execfn, or via2223// execCmd.  Environment variables for each are now sourced from the same2224// location; previously they were sourced differently.2225//2226// This test ensures they are accessible via execfn() calls.  If I could2227// work out how to get a configd:syntax call to echo the environment variables2228// (well, simply to run w/o failing in a UT environment) then I'd add a test2229// for that as well.  Suggestions on a postcard to the author ...2230func TestConfigdExecFnEnvVars(t *testing.T) {2231	t.Log("Verify env vars are set correctly for scripts using execfn().")2232	const schema = `2233container testcontainer {2234	leaf testleaf {2235		type string;2236		configd:begin "env";2237	}2238}2239`2240	const expconfig = `testcontainer {2241	testleaf foo2242}2243`2244	const expout = `[]2245[testcontainer testleaf foo]2246vyatta_htmldir=/opt/vyatta/share/html2247vyatta_datadir=/opt/vyatta/share2248vyatta_op_templates=/opt/vyatta/share/vyatta-op/templates2249vyatta_sysconfdir=/opt/vyatta/etc2250vyatta_sharedstatedir=/opt/vyatta/com2251vyatta_sbindir=/opt/vyatta/sbin2252vyatta_cfg_templates=/opt/vyatta/share/vyatta-cfg/templates2253vyatta_bindir=/opt/vyatta/bin2254vyatta_libdir=/opt/vyatta/lib2255vyatta_localstatedir=/opt/vyatta/var2256vyatta_libexecdir=/opt/vyatta/libexec2257vyatta_prefix=/opt/vyatta2258vyatta_datarootdir=/opt/vyatta/share2259vyatta_configdir=/opt/vyatta/config2260vyatta_infodir=/opt/vyatta/share/info2261vyatta_localedir=/opt/vyatta/share/locale2262PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/vyatta/bin:/opt/vyatta/bin/sudo-users:/opt/vyatta/sbin2263PERL5LIB=/opt/vyatta/share/perl52264VYATTA_CONFIG_SID=TEST2265COMMIT_ACTION=SET2266CONFIGD_PATH=/testcontainer/testleaf/foo2267CONFIGD_EXT=begin2268[]2269`2270	var testleafpath_foo = pathutil.CopyAppend(testleafpath, "foo")2271	srv, sess := TstStartup(t, schema, emptyconfig)2272	ValidateSet(t, sess, srv.Ctx, testleafpath_foo, false)2273	ValidateCommit(t, sess, srv.Ctx, true, expconfig, expout)2274	sess.Kill()2275}2276// TODO: test authorization access in APIs2277// TODO: test order of action execution2278//        - create commit dry-run that returns called scripts2279//        - or action scripts that just echo a string that we can compare with expected output2280// TODO: test node priority2281// TODO2282// func TestComment(t *testing.T) {...

Full Screen

Full Screen

tree.go

Source:tree.go Github

copy

Full Screen

...46			}47			leftNodes, rightNodes := nodes.SplitAround(nodes[i])48			leftNodes = leftNodes.WithoutType(types.NodeTypesForContainerAndIt)49			rightNodes = rightNodes.WithoutType(types.NodeTypesForContainerAndIt)50			leftNodes = lNodes.CopyAppend(leftNodes...)51			rightNodes = rightNodes.CopyAppend(rNodes...)52			if nodes[i].NodeType.Is(types.NodeTypeIt) {53				tests = append(tests, Spec{Nodes: leftNodes.CopyAppend(nodes[i]).CopyAppend(rightNodes...)})54			} else {55				treeNode := trees.WithID(nodes[i].ID)56				tests = append(tests, walkTree(nestingLevel+1, leftNodes.CopyAppend(nodes[i]), rightNodes, treeNode.Children)...)57			}58		}59		return tests60	}61	return walkTree(0, Nodes{}, Nodes{}, tree.Children)62}...

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1func main() {2    a := []int{1, 2, 3}3    b := []int{4, 5, 6}4    c := internal.CopyAppend(a, b)5    fmt.Println(c)6}7func CopyAppend(a, b []int) []int {8    c := make([]int, len(a)+len(b))9    copy(c, a)10    copy(c[len(a):], b)11}

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1func main() {2	s1 = append(s1, 1)3	s1 = append(s1, 2)4	s1 = append(s1, 3)5	s1 = append(s1, 4)6	s1 = append(s1, 5)7	fmt.Println(s1)8	s1 = CopyAppend(s1, 6)9	fmt.Println(s1)10	s1 = CopyAppend(s1, 7)11	fmt.Println(s1)12}13func main() {14	s1 = append(s1, 1)15	s1 = append(s1, 2)16	s1 = append(s1, 3)17	s1 = append(s1, 4)18	s1 = append(s1, 5)19	fmt.Println(s1)20	s1 = CopyAppend(s1, 6)21	fmt.Println(s1)22	s1 = CopyAppend(s1, 7)23	fmt.Println(s1)24}

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1import (2func main() {3	a = internal.CopyAppend(a, 1, 2, 3, 4, 5)4	fmt.Println(a)5}6func CopyAppend(a []int, args ...int) []int {7	b := make([]int, len(a))8	copy(b, a)9	b = append(b, args...)10}

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1import (2func main() {3	a := []int{1, 2, 3}4	b := []int{4, 5, 6}5	fmt.Println(append.CopyAppend(a, b))6}7func CopyAppend(a, b []int) []int {8	c := make([]int, len(a), len(a)+len(b))9	copy(c, a)10	return append(c, b...)11}12$ go list -f '{{.Dir}}' internal/append13$ go list -f '{{.Dir}}' internal14$ go list -f '{{.Dir}}' internal/append15$ go list -f '{{.Dir}}' internal16$ go list -f '{{.Dir}}' fmt17$ go list -f '{{.Dir}}' fmt/internal18$ go list -f '{{.Dir}}' fmt/internal19$ go list -f '{{.Dir}}' fmt20$ go list -f '{{.Dir}}' internal

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3    c.CopyAppend()4    fmt.Println(c)5}6import "fmt"7func main() {8    c.CopyAppend()9    fmt.Println(c)10}11import "fmt"12func main() {13    c.CopyAppend()14    fmt.Println(c)15}16import "fmt"17func main() {18    c.CopyAppend()19    fmt.Println(c)20}21import "fmt"22func main() {23    c.CopyAppend()24    fmt.Println(c)25}26import "fmt"27func main() {28    c.CopyAppend()29    fmt.Println(c)30}31import "fmt"32func main() {33    c.CopyAppend()34    fmt.Println(c)35}36import "fmt"37func main() {38    c.CopyAppend()39    fmt.Println(c)40}41import "fmt"42func main() {43    c.CopyAppend()44    fmt.Println(c)45}46import "fmt"47func main() {48    c.CopyAppend()49    fmt.Println(c)50}51import "fmt"52func main() {53    c.CopyAppend()54    fmt.Println(c)55}

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1import (2func main() {3    fmt.Println(internal.CopyAppend("Hello", "World"))4}5        /usr/local/go/src/main/internal (from $GOROOT)6        /home/username/go/src/main/internal (from $GOPATH)7In the above program, we are trying to import the package "main/internal" which is not available in the GOROOT. So, we get the error "cannot find package "main/internal" in any of:"8        /usr/local/go/src/main/internal (from $GOROOT)9        /home/username/go/src/main/internal (from $GOPATH)10In the above program, we are trying to import the package "main/internal" which is not available in the GOROOT. So, we get the error "cannot find package "main/internal" in any of:"

Full Screen

Full Screen

CopyAppend

Using AI Code Generation

copy

Full Screen

1import "fmt"2import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"3func main() {4    fmt.Println(stringutil.CopyAppend("Hello", " World!"))5}6import "fmt"7import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"8func main() {9    fmt.Println(stringutil.CopyAppend("Hello", " World!"))10}11import "fmt"12import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"13func main() {14    fmt.Println(stringutil.CopyAppend("Hello", " World!"))15}16import "fmt"17import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"18func main() {19    fmt.Println(stringutil.CopyAppend("Hello", " World!"))20}21import "fmt"22import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"23func main() {24    fmt.Println(stringutil.CopyAppend("Hello", " World!"))25}26import "fmt"27import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"28func main() {29    fmt.Println(stringutil.CopyAppend("Hello", " World!"))30}31import "fmt"32import "github.com/krishna-ramaswamy/GoLang/GoLangTraining/02_package/stringutil"33func main() {34    fmt.Println(stringutil.CopyAppend("Hello", " World!"))35}36import "fmt"37import

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Ginkgo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful