📄 skel-test.c
字号:
/* skel-test.c --- tests for the skeleton functions * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <stdio.h>#include <apr.h>#include "svn_pools.h"#include "svn_string.h"#include "../svn_test.h"#include "../svn_test_fs.h"#include "../../libsvn_fs_base/fs.h"#include "../../libsvn_fs_base/util/skel.h"/* Some utility functions. *//* A quick way to create error messages. */static svn_error_t *fail(apr_pool_t *pool, const char *fmt, ...){ va_list ap; char *msg; va_start(ap, fmt); msg = apr_pvsprintf(pool, fmt, ap); va_end(ap); return svn_error_create(SVN_ERR_TEST_FAILED, 0, msg);}/* Free everything from pool, and return an empty Subversion string. */static svn_stringbuf_t *get_empty_string(apr_pool_t *pool){ svn_pool_clear(pool); return svn_stringbuf_ncreate(0, 0, pool);}/* Parse a skeleton from a Subversion string. */static skel_t *parse_str(svn_stringbuf_t *str, apr_pool_t *pool){ return svn_fs_base__parse_skel(str->data, str->len, pool);}/* Parse a skeleton from a C string. */static skel_t *parse_cstr(const char *str, apr_pool_t *pool){ return svn_fs_base__parse_skel(str, strlen(str), pool);}enum char_type { type_nothing = 0, type_space = 1, type_digit = 2, type_paren = 3, type_name = 4};static int skel_char_map_initialized;static enum char_type skel_char_map[256];static voidinit_char_types(void){ int i; const char *c; if (skel_char_map_initialized) return; for (i = 0; i < 256; i++) skel_char_map[i] = type_nothing; for (i = '0'; i <= '9'; i++) skel_char_map[i] = type_digit; for (c = "\t\n\f\r "; *c; c++) skel_char_map[(unsigned char) *c] = type_space; for (c = "()[]"; *c; c++) skel_char_map[(unsigned char) *c] = type_paren; for (i = 'A'; i <= 'Z'; i++) skel_char_map[i] = type_name; for (i = 'a'; i <= 'z'; i++) skel_char_map[i] = type_name; skel_char_map_initialized = 1;}/* Return true iff BYTE is a whitespace byte. */static intskel_is_space(char byte){ init_char_types(); return skel_char_map[(unsigned char) byte] == type_space;}#if 0/* Return true iff BYTE is a digit byte. */static intskel_is_digit(char byte){ init_char_types(); return skel_char_map[(unsigned char) byte] == type_digit;}#endif/* Return true iff BYTE is a paren byte. */static intskel_is_paren(char byte){ init_char_types(); return skel_char_map[(unsigned char) byte] == type_paren;}/* Return true iff BYTE is a name byte. */static intskel_is_name(char byte){ init_char_types(); return skel_char_map[(unsigned char) byte] == type_name;}/* Check that SKEL is an atom, and its contents match LEN bytes of DATA. */static intcheck_atom(skel_t *skel, const char *data, apr_size_t len){ return (skel && skel->is_atom && skel->len == len && ! memcmp(skel->data, data, len));}/* Functions that generate/check interesting implicit-length atoms. *//* Append to STR an implicit-length atom consisting of the byte BYTE, terminated by the character TERM. BYTE must be a name byte, and TERM must be a valid skel separator, or NULL. */static voidput_implicit_length_byte(svn_stringbuf_t *str, char byte, char term){ if (! skel_is_name(byte)) abort(); if (term != '\0' && ! skel_is_space(term) && ! skel_is_paren(term)) abort(); svn_stringbuf_appendbytes(str, &byte, 1); if (term != '\0') svn_stringbuf_appendbytes(str, &term, 1);}/* Return true iff SKEL is the parsed form of the atom produced by calling put_implicit_length with BYTE. */static intcheck_implicit_length_byte(skel_t *skel, char byte){ if (! skel_is_name(byte)) abort(); return check_atom(skel, &byte, 1);}/* Subroutine for the *_implicit_length_all_chars functions. */static char *gen_implicit_length_all_chars(apr_size_t *len_p){ apr_size_t pos; int i; static char name[256]; /* Gotta start with a valid name character. */ pos = 0; name[pos++] = 'x'; for (i = 0; i < 256; i++) if (! skel_is_space( (apr_byte_t)i) && ! skel_is_paren( (apr_byte_t)i)) name[pos++] = i; *len_p = pos; return name;}/* Append to STR an implicit-length atom containing every character that's legal in such atoms, terminated by the valid atom terminator TERM. */static voidput_implicit_length_all_chars(svn_stringbuf_t *str, char term){ apr_size_t len; char *name = gen_implicit_length_all_chars(&len); if (term != '\0' && ! skel_is_space(term) && ! skel_is_paren(term)) abort(); svn_stringbuf_appendbytes(str, name, len); if (term != '\0') svn_stringbuf_appendbytes(str, &term, 1);}/* Return true iff SKEL is the parsed form of the atom produced by calling put_implicit_length_all_chars. */static intcheck_implicit_length_all_chars(skel_t *skel){ apr_size_t len; char *name = gen_implicit_length_all_chars(&len); return check_atom(skel, name, len);}/* Test parsing of implicit-length atoms. */static svn_error_t *parse_implicit_length(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ svn_stringbuf_t *str = get_empty_string(pool); skel_t *skel; *msg = "parse implicit-length atoms"; if (msg_only) return SVN_NO_ERROR; /* Try all valid single-byte atoms. */ { const char *c; int i; for (c = "\t\n\f\r ()[]"; *c; c++) for (i = 0; i < 256; i++) if (skel_is_name((apr_byte_t)i)) { svn_stringbuf_setempty(str); put_implicit_length_byte(str, (apr_byte_t)i, *c); skel = parse_str(str, pool); if (! check_implicit_length_byte(skel, (apr_byte_t)i)) return fail(pool, "single-byte implicit-length skel 0x%02x" " with terminator 0x%02x", i, c); } } /* Try an atom that contains every character that's legal in an implicit-length atom. */ svn_stringbuf_setempty(str); put_implicit_length_all_chars(str, '\0'); skel = parse_str(str, pool); if (! check_implicit_length_all_chars(skel)) return fail(pool, "implicit-length skel containing all legal chars"); return SVN_NO_ERROR;}/* Functions that generate/check interesting explicit-length atoms. *//* Append to STR the representation of the atom containing the LEN bytes at DATA, in explicit-length form, using SEP as the separator between the length and the data. */static voidput_explicit_length(svn_stringbuf_t *str, const char *data, apr_size_t len, char sep){ char *buf = malloc(len + 100); apr_size_t length_len; if (! skel_is_space(sep)) abort(); /* Generate the length and separator character. */ sprintf(buf, "%"APR_SIZE_T_FMT"%c", len, sep); length_len = strlen(buf); /* Copy in the real data (which may contain nulls). */ memcpy(buf + length_len, data, len); svn_stringbuf_appendbytes(str, buf, length_len + len); free(buf);}/* Return true iff SKEL is the parsed form of an atom generated by put_explicit_length. */static intcheck_explicit_length(skel_t *skel, const char *data, apr_size_t len){ return check_atom(skel, data, len);}/* Test parsing of explicit-length atoms. */static svn_error_t *try_explicit_length(const char *data, apr_size_t len, apr_size_t check_len, apr_pool_t *pool){ int i; svn_stringbuf_t *str = get_empty_string(pool); skel_t *skel; /* Try it with every possible separator character. */ for (i = 0; i < 256; i++) if (skel_is_space( (apr_byte_t)i)) { svn_stringbuf_setempty(str); put_explicit_length(str, data, len, (apr_byte_t)i); skel = parse_str(str, pool); if (! check_explicit_length(skel, data, check_len)) return fail(pool, "failed to reparse explicit-length atom"); } return SVN_NO_ERROR;}static svn_error_t *parse_explicit_length(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ *msg = "parse explicit-length atoms"; if (msg_only) return SVN_NO_ERROR; /* Try to parse the empty atom. */ SVN_ERR(try_explicit_length("", 0, 0, pool)); /* Try to parse every one-character atom. */ { int i; for (i = 0; i < 256; i++) { char buf[1]; buf[0] = i; SVN_ERR(try_explicit_length(buf, 1, 1, pool)); } } /* Try to parse an atom containing every character. */ { int i; char data[256]; for (i = 0; i < 256; i++) data[i] = i; SVN_ERR(try_explicit_length(data, 256, 256, pool)); } return SVN_NO_ERROR;}/* Test parsing of invalid atoms. */static struct invalid_atoms{ int type; apr_size_t len; const char *data;} invalid_atoms[] = { { 1, 1, "(" }, { 1, 1, ")" }, { 1, 1, "[" }, { 1, 1, "]" }, { 1, 1, " " }, { 1, 13, "Hello, World!" }, { 1, 8, "1mplicit" }, { 2, 2, "1" }, { 2, 1, "12" }, { 7, 0, NULL } };static svn_error_t *parse_invalid_atoms(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ struct invalid_atoms *ia = invalid_atoms; *msg = "parse invalid atoms"; if (msg_only) return SVN_NO_ERROR; while (ia->type != 7) { if (ia->type == 1) { skel_t *skel = parse_cstr(ia->data, pool); if (check_atom(skel, ia->data, ia->len)) return fail(pool, "failed to detect parsing error in '%s'", ia->data); } else { svn_error_t *err = try_explicit_length(ia->data, ia->len, strlen(ia->data), pool); if (err == SVN_NO_ERROR) return fail(pool, "got wrong length in explicit-length atom"); svn_error_clear(err); } ia++; } return SVN_NO_ERROR;}/* Functions that generate/check interesting lists. *//* Append the start of a list to STR, using LEN bytes of the whitespace character SPACE. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -