tests: Extend aspath_test.c with cases for invalid segments & attributes

* aspath_test.c: Add more test cases. In particular ones to cover the
  last invalid-segment problem. Also add ability to specify aspath attribute
  headers and test them somewhat.

  NB: It's obvious this test has not been run for a year by anyone, despite
  2 non-trivial commits to bgpd aspath code.
diff --git a/tests/aspath_test.c b/tests/aspath_test.c
index 9e51e8d..ade60c6 100644
--- a/tests/aspath_test.c
+++ b/tests/aspath_test.c
@@ -6,6 +6,7 @@
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_attr.h"
 
 #define VT100_RESET "\x1b[0m"
 #define VT100_RED "\x1b[31m"
@@ -420,7 +421,187 @@
     { "", "",
       0, 0, 0, 0, 0, 0 },
   },
-  { NULL, NULL, {0}, 0, { NULL, 0, 0 } }
+  { /* 27  */ 
+    "invalid segment type",
+    "type=8(4096 3456)",
+    { 0x8,0x2, 0x10,0x00, 0x0d,0x80 },
+    14
+    ,
+    { "", "",
+      0, 0, 0, 0, 0, 0 },
+  },  { NULL, NULL, {0}, 0, { NULL, 0, 0 } }
+};
+
+/* */
+static struct aspath_tests {
+  const char *desc;
+  const struct test_segment *segment;
+  const char *shouldbe;  /* String it should evaluate to */
+  const enum as4 { AS4_DATA, AS2_DATA }
+          as4; 	/* whether data should be as4 or not (ie as2) */
+  const int result;	/* expected result for bgp_attr_parse */
+  const int cap;	/* capabilities to set for peer */
+  const char attrheader [1024];
+  size_t len;
+} aspath_tests [] =
+{
+  /* 0 */
+  {
+    "basic test",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, 0,
+    0,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 1 */
+  {
+    "length too short",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      8,
+    },
+    3,
+  },
+  /* 2 */
+  {
+    "length too long",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      12,
+    },
+    3,
+  },
+  /* 3 */
+  {
+    "incorrect flag",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 4 */
+  {
+    "as4_path, with as2 format data",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS4_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 5 */
+  {
+    "as4, with incorrect attr length",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS4_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 6 */
+  {
+    "basic 4-byte as-path",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, 0,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      18,
+    },
+    3,
+  },
+  /* 7 */
+  {
+    "4b AS_PATH: too short",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      16,
+    },
+    3,
+  },
+  /* 8 */
+  {
+    "4b AS_PATH: too long",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      20,
+    },
+    3,
+  },
+  /* 9 */
+  {
+    "4b AS_PATH: too long2",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      22,
+    },
+    3,
+  },
+  /* 10 */
+  {
+    "4b AS_PATH: bad flags",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS_PATH, 
+      18,
+    },
+    3,
+  },
+  /* 11 */
+  {
+    "4b AS_PATH: confed",
+    &test_segments[6],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS4_PATH, 
+      14,
+    },
+    3,
+  },
+  { NULL, NULL, NULL, 0, 0, 0, { 0 }, 0 },
 };
 
 /* prepending tests */
@@ -430,21 +611,25 @@
   struct test_spec sp;
 } prepend_tests[] = 
 {
+  /* 0 */
   { &test_segments[0], &test_segments[1],
     { "8466 3 52737 4096 8722 4",
       "8466 3 52737 4096 8722 4",
       6, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 },
   },
+  /* 1 */
   { &test_segments[1], &test_segments[3],
     { "8722 4 8482 51457 {5204}",
       "8722 4 8482 51457 {5204}",
       5, 0, NOT_ALL_PRIVATE, 5204, 1, 8722 }
   },
+  /* 2 */
   { &test_segments[3], &test_segments[4],
     { "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}",
       "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}",
       7, 0, NOT_ALL_PRIVATE, 5204, 1, 8482 },
   },
+  /* 3 */
   { &test_segments[4], &test_segments[5],
     { "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665"
       " {2457,4369,61697} 1842 41590 51793",
@@ -452,11 +637,13 @@
       " {2457,4369,61697} 1842 41590 51793",
       11, 0, NOT_ALL_PRIVATE, 61697, 1, 8467 }
   },
+  /* 4 */
   { &test_segments[5], &test_segments[6],
-    { "6435 59408 21665 {2457,4369,61697} 1842 41590 51793 (123 456 789)",
-      "6435 59408 21665 {2457,4369,61697} 1842 41590 51793 (123 456 789)",
-      7, 3, NOT_ALL_PRIVATE, 123, 1, 6435 },
+    { "6435 59408 21665 {2457,4369,61697} 1842 41590 51793",
+      "6435 59408 21665 {2457,4369,61697} 1842 41590 51793",
+      7, 0, NOT_ALL_PRIVATE, 1842, 1, 6435 },
   },
+  /* 5 */
   { &test_segments[6], &test_segments[7],
     { "(123 456 789) (123 456 789) (111 222)",
       "",
@@ -649,7 +836,7 @@
       s = stream_new (len);
       stream_put (s, data, len);
     }
-  as = aspath_parse (s, len, use32bit, 0);
+  as = aspath_parse (s, len, use32bit);
   
   if (s)
     stream_free (s);
@@ -993,30 +1180,106 @@
       aspath_unintern (asp2);
     }
 }
-     
+
+static int
+handle_attr_test (struct aspath_tests *t)
+{
+  struct bgp bgp = { 0 }; 
+  struct peer peer = { 0 };
+  struct attr attr = { 0 };  
+  int ret;
+  int initfail = failed;
+  struct aspath *asp;
+  size_t datalen;
+  
+  asp = make_aspath (t->segment->asdata, t->segment->len, 0);
+    
+  peer.ibuf = stream_new (BGP_MAX_PACKET_SIZE);
+  peer.obuf = stream_fifo_new ();
+  peer.bgp = &bgp;
+  peer.host = (char *)"none";
+  peer.fd = -1;
+  peer.cap = t->cap;
+  
+  stream_write (peer.ibuf, t->attrheader, t->len);
+  datalen = aspath_put (peer.ibuf, asp, t->as4 == AS4_DATA);
+  
+  ret = bgp_attr_parse (&peer, &attr, t->len + datalen, NULL, NULL);
+  
+  if (ret != t->result)
+    {
+      printf ("bgp_attr_parse returned %d, expected %d\n", ret, t->result);
+      printf ("datalen %d\n", datalen);
+      failed++;
+    }
+  if (ret != 0)
+    goto out;
+  
+  if (attr.aspath == NULL)
+    {
+      printf ("aspath is NULL!\n");
+      failed++;
+    }
+  if (attr.aspath && strcmp (attr.aspath->str, t->shouldbe))
+    {
+      printf ("attr str and 'shouldbe' mismatched!\n"
+              "attr str:  %s\n"
+              "shouldbe:  %s\n",
+              attr.aspath->str, t->shouldbe);
+      failed++;
+    }
+
+out:
+  if (attr.aspath)
+    aspath_unintern (attr.aspath);
+  if (asp)
+    aspath_unintern (asp);
+  return failed - initfail;
+}
+
+static void
+attr_test (struct aspath_tests *t)
+{
+    printf ("%s\n", t->desc);
+    printf ("%s\n\n", handle_attr_test (t) ? FAILED : OK);  
+}
+
 int
 main (void)
 {
   int i = 0;
-  aspath_init();
+  bgp_master_init ();
+  master = bm->master;
+  bgp_attr_init ();
+  
   while (test_segments[i].name)
     {
+      printf ("test %u\n", i);
       parse_test (&test_segments[i]);
       empty_prepend_test (&test_segments[i++]);
     }
   
   i = 0;
   while (prepend_tests[i].test1)
-    prepend_test (&prepend_tests[i++]);
+    {
+      printf ("prepend test %u\n", i);
+      prepend_test (&prepend_tests[i++]);
+    }
   
   i = 0;
   while (aggregate_tests[i].test1)
-    aggregate_test (&aggregate_tests[i++]);
+    {
+      printf ("aggregate test %u\n", i);
+      aggregate_test (&aggregate_tests[i++]);
+    }
   
   i = 0;
   
   while (reconcile_tests[i].test1)
-    as4_reconcile_test (&reconcile_tests[i++]);
+    {
+      printf ("reconcile test %u\n", i);
+      as4_reconcile_test (&reconcile_tests[i++]);
+    }
   
   i = 0;
   
@@ -1026,6 +1289,14 @@
   
   empty_get_test();
   
+  i = 0;
+  
+  while (aspath_tests[i].desc)
+    {
+      printf ("aspath_attr test %d\n", i);
+      attr_test (&aspath_tests[i++]);
+    }
+  
   printf ("failures: %d\n", failed);
   printf ("aspath count: %ld\n", aspath_count());