Best Ginkgo code snippet using internal.CopyAppend
session_test.go
Source:session_test.go
...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) {...
tree.go
Source:tree.go
...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}...
CopyAppend
Using AI Code Generation
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}
CopyAppend
Using AI Code Generation
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}
CopyAppend
Using AI Code Generation
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}
CopyAppend
Using AI Code Generation
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
CopyAppend
Using AI Code Generation
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}
CopyAppend
Using AI Code Generation
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:"
CopyAppend
Using AI Code Generation
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
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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!