1231984Sjilles/*- 2231984Sjilles * Copyright (c) 2012 Jilles Tjoelker 3231984Sjilles * All rights reserved. 4231984Sjilles * 5231984Sjilles * Redistribution and use in source and binary forms, with or without 6231984Sjilles * modification, are permitted provided that the following conditions 7231984Sjilles * are met: 8231984Sjilles * 1. Redistributions of source code must retain the above copyright 9231984Sjilles * notice, this list of conditions and the following disclaimer. 10231984Sjilles * 2. Redistributions in binary form must reproduce the above copyright 11231984Sjilles * notice, this list of conditions and the following disclaimer in the 12231984Sjilles * documentation and/or other materials provided with the distribution. 13231984Sjilles * 14231984Sjilles * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15231984Sjilles * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16231984Sjilles * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17231984Sjilles * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18231984Sjilles * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19231984Sjilles * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20231984Sjilles * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21231984Sjilles * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22231984Sjilles * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23231984Sjilles * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24231984Sjilles * SUCH DAMAGE. 25231984Sjilles */ 26231984Sjilles 27231984Sjilles#include <sys/cdefs.h> 28231984Sjilles__FBSDID("$FreeBSD$"); 29231984Sjilles 30231984Sjilles#include <sys/wait.h> 31231984Sjilles 32231984Sjilles#include <err.h> 33231984Sjilles#include <errno.h> 34231984Sjilles#include <fmtmsg.h> 35231984Sjilles#include <stdio.h> 36231984Sjilles#include <stdlib.h> 37231984Sjilles#include <string.h> 38231984Sjilles#include <unistd.h> 39231984Sjilles 40231984Sjillesstatic char *run_test(long classification, const char *label, int severity, 41231984Sjilles const char *text, const char *action, const char *tag); 42231984Sjilles 43231984Sjillesstruct testcase { 44231984Sjilles long classification; 45231984Sjilles const char *label; 46231984Sjilles int severity; 47231984Sjilles const char *text; 48231984Sjilles const char *action; 49231984Sjilles const char *tag; 50231984Sjilles const char *msgverb; 51231984Sjilles const char *result; 52231984Sjilles} testcases[] = { 53231984Sjilles { 54231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 55231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 56231984Sjilles NULL, 57231984Sjilles "BSD:ls: ERROR: illegal option -- z\n" 58231984Sjilles "TO FIX: refer to manual BSD:ls:001\n" 59231984Sjilles }, 60231984Sjilles { 61231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 62231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 63231984Sjilles "text:severity:action:tag", 64231984Sjilles "illegal option -- z: ERROR\n" 65231984Sjilles "TO FIX: refer to manual BSD:ls:001\n" 66231984Sjilles }, 67231984Sjilles { 68231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 69231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 70231984Sjilles "text", 71231984Sjilles "illegal option -- z\n" 72231984Sjilles }, 73231984Sjilles { 74231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 75231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 76231984Sjilles "severity:text", 77231984Sjilles "ERROR: illegal option -- z\n" 78231984Sjilles }, 79231984Sjilles { 80231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 81231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 82231984Sjilles "ignore me", 83231984Sjilles "BSD:ls: ERROR: illegal option -- z\n" 84231984Sjilles "TO FIX: refer to manual BSD:ls:001\n" 85231984Sjilles }, 86231984Sjilles { 87231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 88231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 89231984Sjilles "tag:severity:text:nothing:action", 90231984Sjilles "BSD:ls: ERROR: illegal option -- z\n" 91231984Sjilles "TO FIX: refer to manual BSD:ls:001\n" 92231984Sjilles }, 93231984Sjilles { 94231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 95231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 96231984Sjilles "", 97231984Sjilles "BSD:ls: ERROR: illegal option -- z\n" 98231984Sjilles "TO FIX: refer to manual BSD:ls:001\n" 99231984Sjilles }, 100231984Sjilles { 101231984Sjilles MM_UTIL | MM_PRINT, MM_NULLLBL, MM_ERROR, 102231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 103231984Sjilles NULL, 104231984Sjilles "ERROR: illegal option -- z\n" 105231984Sjilles "TO FIX: refer to manual BSD:ls:001\n" 106231984Sjilles }, 107231984Sjilles { 108231984Sjilles MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR, 109231984Sjilles "illegal option -- z", MM_NULLACT, MM_NULLTAG, 110231984Sjilles NULL, 111231984Sjilles "BSD:ls: ERROR: illegal option -- z\n" 112231984Sjilles }, 113231984Sjilles { 114231984Sjilles MM_UTIL | MM_NULLMC, "BSD:ls", MM_ERROR, 115231984Sjilles "illegal option -- z", "refer to manual", "BSD:ls:001", 116231984Sjilles NULL, 117231984Sjilles "" 118231984Sjilles }, 119231984Sjilles { 120231984Sjilles MM_APPL | MM_PRINT, "ABCDEFGHIJ:abcdefghijklmn", MM_INFO, 121231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 122231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 123231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 124231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 125231984Sjilles "refer to manual", "ABCDEFGHIJ:abcdefghijklmn:001", 126231984Sjilles NULL, 127231984Sjilles "ABCDEFGHIJ:abcdefghijklmn: INFO: " 128231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 129231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 130231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 131231984Sjilles "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" 132231984Sjilles "TO FIX: refer to manual ABCDEFGHIJ:abcdefghijklmn:001\n" 133231984Sjilles }, 134231984Sjilles { 135231984Sjilles MM_OPSYS | MM_PRINT, "TEST:test", MM_HALT, 136231984Sjilles "failed", "nothing can help me", "NOTHING", 137231984Sjilles NULL, 138231984Sjilles "TEST:test: HALT: failed\n" 139231984Sjilles "TO FIX: nothing can help me NOTHING\n" 140231984Sjilles }, 141231984Sjilles { 142231984Sjilles MM_OPSYS | MM_PRINT, "TEST:test", MM_WARNING, 143231984Sjilles "failed", "nothing can help me", "NOTHING", 144231984Sjilles NULL, 145231984Sjilles "TEST:test: WARNING: failed\n" 146231984Sjilles "TO FIX: nothing can help me NOTHING\n" 147231984Sjilles }, 148231984Sjilles { 149231984Sjilles MM_OPSYS | MM_PRINT, "TEST:test", MM_NOSEV, 150231984Sjilles "failed", "nothing can help me", "NOTHING", 151231984Sjilles NULL, 152231984Sjilles "TEST:test: failed\n" 153231984Sjilles "TO FIX: nothing can help me NOTHING\n" 154231984Sjilles } 155231984Sjilles}; 156231984Sjilles 157231984Sjillesstatic char * 158231984Sjillesrun_test(long classification, const char *label, int severity, 159231984Sjilles const char *text, const char *action, const char *tag) 160231984Sjilles{ 161231984Sjilles int pip[2]; 162231984Sjilles pid_t pid, wpid; 163231984Sjilles char *result, *p; 164231984Sjilles size_t resultsize; 165231984Sjilles ssize_t n; 166231984Sjilles int status; 167231984Sjilles 168231984Sjilles if (pipe(pip) == -1) 169231984Sjilles err(2, "pipe"); 170231984Sjilles pid = fork(); 171231984Sjilles if (pid == -1) 172231984Sjilles err(2, "fork"); 173231984Sjilles if (pid == 0) { 174231984Sjilles close(pip[0]); 175231984Sjilles if (pip[1] != STDERR_FILENO && 176231984Sjilles dup2(pip[1], STDERR_FILENO) == -1) 177231984Sjilles _exit(2); 178231984Sjilles if (fmtmsg(classification, label, severity, text, action, tag) 179231984Sjilles != MM_OK) 180231984Sjilles _exit(1); 181231984Sjilles else 182231984Sjilles _exit(0); 183231984Sjilles } 184231984Sjilles close(pip[1]); 185231984Sjilles resultsize = 1024; 186231984Sjilles result = malloc(resultsize); 187231984Sjilles p = result; 188231984Sjilles while ((n = read(pip[0], p, result + resultsize - p - 1)) != 0) { 189231984Sjilles if (n == -1) { 190231984Sjilles if (errno == EINTR) 191231984Sjilles continue; 192231984Sjilles else 193231984Sjilles err(2, "read"); 194231984Sjilles } 195231984Sjilles p += n; 196231984Sjilles if (result + resultsize == p - 1) { 197231984Sjilles resultsize *= 2; 198231984Sjilles result = realloc(result, resultsize); 199231984Sjilles if (result == NULL) 200231984Sjilles err(2, "realloc"); 201231984Sjilles } 202231984Sjilles } 203231984Sjilles if (memchr(result, '\0', p - result) != NULL) { 204231984Sjilles free(result); 205231984Sjilles return (NULL); 206231984Sjilles } 207231984Sjilles *p = '\0'; 208231984Sjilles close(pip[0]); 209231984Sjilles while ((wpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR) 210231984Sjilles ; 211231984Sjilles if (wpid == -1) 212231984Sjilles err(2, "waitpid"); 213231984Sjilles if (status != 0) { 214231984Sjilles free(result); 215231984Sjilles return (NULL); 216231984Sjilles } 217231984Sjilles return (result); 218231984Sjilles} 219231984Sjilles 220231984Sjillesint 221231984Sjillesmain(void) 222231984Sjilles{ 223231984Sjilles size_t i, n; 224231984Sjilles int errors; 225231984Sjilles char *result; 226231984Sjilles struct testcase *t; 227231984Sjilles 228231984Sjilles n = sizeof(testcases) / sizeof(testcases[0]); 229231984Sjilles errors = 0; 230231984Sjilles printf("1..%zu\n", n); 231231984Sjilles for (i = 0; i < n; i++) { 232231984Sjilles t = &testcases[i]; 233231984Sjilles if (t->msgverb != NULL) 234231984Sjilles setenv("MSGVERB", t->msgverb, 1); 235231984Sjilles else 236231984Sjilles unsetenv("MSGVERB"); 237231984Sjilles result = run_test(t->classification, t->label, t->severity, 238231984Sjilles t->text, t->action, t->tag); 239231984Sjilles if (result != NULL && strcmp(result, t->result) == 0) 240231984Sjilles printf("ok %zu - correct\n", 241231984Sjilles i + 1); 242231984Sjilles else { 243231984Sjilles printf("not ok %zu - %s\n", 244231984Sjilles i + 1, result != NULL ? "incorrect" : "failed"); 245231984Sjilles errors = 1; 246231984Sjilles } 247231984Sjilles free(result); 248231984Sjilles } 249231984Sjilles 250231984Sjilles return (errors); 251231984Sjilles} 252