/****************************************************************************** * rangeset.c * * Creation, maintenance and automatic destruction of per-domain sets of * numeric ranges. * * Copyright (c) 2005, K A Fraser */ #include #include #include #include /* An inclusive range [s,e] and pointer to next range in ascending order. */ struct range { struct list_head list; unsigned long s, e; }; struct rangeset { /* Owning domain and threaded list of rangesets. */ struct list_head rangeset_list; struct domain *domain; /* Ordered list of ranges contained in this set, and protecting lock. */ struct list_head range_list; spinlock_t lock; /* Pretty-printing name. */ char name[32]; /* RANGESETF flags. */ unsigned int flags; }; /***************************** * Private range functions hide the underlying linked-list implemnetation. */ /* Find highest range lower than or containing s. NULL if no such range. */ static struct range *find_range( struct rangeset *r, unsigned long s) { struct range *x = NULL, *y; list_for_each_entry ( y, &r->range_list, list ) { if ( y->s > s ) break; x = y; } return x; } /* Return the lowest range in the set r, or NULL if r is empty. */ static struct range *first_range( struct rangeset *r) { if ( list_empty(&r->range_list) ) return NULL; return list_entry(r->range_list.next, struct range, list); } /* Return range following x in ascending order, or NULL if x is the highest. */ static struct range *next_range( struct rangeset *r, struct range *x) { if ( x->list.next == &r->range_list ) return NULL; return list_entry(x->list.next, struct range, list); } /* Insert range y after range x in r. Insert as first range if x is NULL. */ static void insert_range( struct rangeset *r, struct range *x, struct range *y) { list_add(&y->list, (x != NULL) ? &x->list : &r->range_list); } /* Remove a range from its list and free it. */ static void destroy_range( struct range *x) { list_del(&x->list); xfree(x); } /***************************** * Core public functions */ int rangeset_add_range( struct rangeset *r, unsigned long s, unsigned long e) { struct range *x, *y; int rc = 0; rc = xsm_add_range(r->domain, r->name, s, e); if ( rc ) return rc; ASSERT(s <= e); spin_lock(&r->lock); x = find_range(r, s); y = find_range(r, e); if ( x == y ) { if ( (x == NULL) || ((x->e < s) && ((x->e + 1) != s)) ) { x = xmalloc(struct range); if ( x == NULL ) { rc = -ENOMEM; goto out; } x->s = s; x->e = e; insert_range(r, y, x); } else if ( x->e < e ) x->e = e; } else { if ( x == NULL ) { x = first_range(r); x->s = s; } else if ( (x->e < s) && ((x->e + 1) != s) ) { x = next_range(r, x); x->s = s; } x->e = (y->e > e) ? y->e : e; for ( ; ; ) { y = next_range(r, x); if ( (y == NULL) || (y->e > x->e) ) break; destroy_range(y); } } y = next_range(r, x); if ( (y != NULL) && ((x->e + 1) == y->s) ) { x->e = y->e; destroy_range(y); } out: spin_unlock(&r->lock); return rc; } int rangeset_remove_range( struct rangeset *r, unsigned long s, unsigned long e) { struct range *x, *y, *t; int rc = 0; rc = xsm_remove_range(r->domain, r->name, s, e); if ( rc ) return rc; ASSERT(s <= e); spin_lock(&r->lock); x = find_range(r, s); y = find_range(r, e); if ( x == y ) { if ( (x == NULL) || (x->e < s) ) goto out; if ( (x->s < s) && (x->e > e) ) { y = xmalloc(struct range); if ( y == NULL ) { rc = -ENOMEM; goto out; } y->s = e + 1; y->e = x->e; x->e = s - 1; insert_range(r, x, y); } else if ( (x->s == s) && (x->e <= e) ) destroy_range(x); else if ( x->s == s ) x->s = e + 1; else if ( x->e <= e ) x->e = s - 1; } else { if ( x == NULL ) x = first_range(r); if ( x->s < s ) { x->e = s - 1; x = next_range(r, x); } while ( x != y ) { t = x; x = next_range(r, x); destroy_range(t); } x->s = e + 1; if ( x->s > x->e ) destroy_range(x); } out: spin_unlock(&r->lock); return rc; } int rangeset_contains_range( struct rangeset *r, unsigned long s, unsigned long e) { struct range *x; int contains; ASSERT(s <= e); spin_lock(&r->lock); x = find_range(r, s); contains = (x && (x->e >= e)); spin_unlock(&r->lock); return contains; } int rangeset_add_singleton( struct rangeset *r, unsigned long s) { return rangeset_add_range(r, s, s); } int rangeset_remove_singleton( struct rangeset *r, unsigned long s) { return rangeset_remove_range(r, s, s); } int rangeset_contains_singleton( struct rangeset *r, unsigned long s) { return rangeset_contains_range(r, s, s); } int rangeset_is_empty( struct rangeset *r) { return ((r == NULL) || list_empty(&r->range_list)); } struct rangeset *rangeset_new( struct domain *d, char *name, unsigned int flags) { struct rangeset *r; r = xmalloc(struct rangeset); if ( r == NULL ) return NULL; spin_lock_init(&r->lock);
import * as utils from '../../flow/utils'

describe('MessageUtils', () => {
    it('should be possible to get first header', () => {
        let msg = { headers: [["foo", "bar"]]}
        expect(utils.MessageUtils.get_first_header(msg, "foo")).toEqual("bar")
        expect(utils.MessageUtils.get_first_header(msg, "123")).toEqual(undefined)
    })

    it('should be possible to get Content-Type', () => {
        let type = "text/html",
            msg = { headers: [["Content-Type", type]]}
        expect(utils.MessageUtils.getContentType(msg)).toEqual(type)
    })

    it('should be possible to match header', () => {
        let h1 = ["foo", "bar"],
            msg = {headers : [h1]}
        expect(utils.MessageUtils.match_header(msg, /foo/i)).toEqual(h1)
        expect(utils.MessageUtils.match_header(msg, /123/i)).toBeFalsy()
    })

    it('should be possible to get content URL', () => {
        // request
        let msg = "foo", view = "bar",
            flow = { request: msg, id: 1}
        expect(utils.MessageUtils.getContentURL(flow, msg, view)).toEqual(
            "./flows/1/request/content/bar.json"
        )
        expect(utils.MessageUtils.getContentURL(flow, msg, '')).toEqual(
            "./flows/1/request/content.data"
        )
        // response
        flow = {response: msg, id: 2}
        expect(utils.MessageUtils.getContentURL(flow, msg, view)).toEqual(
            "./flows/2/response/content/bar.json"
        )
    })
})

describe('RequestUtils', () => {
    it('should be possible prettify url', () => {
        let request = {port: 4444, scheme: "http", pretty_host: "foo", path: "/bar"}
        expect(utils.RequestUtils.pretty_url(request)).toEqual(
            "http://foo:4444/bar"
        )
    })
})

describe('parseUrl', () => {
    it('should be possible to parse url', () => {
        let url = "http://foo:4444/bar"
        expect(utils.parseUrl(url)).toEqual({
            port: 4444,
            scheme: 'http',
            host: 'foo',
            path: '/bar'
        })

        expect(utils.parseUrl("foo:foo")).toBeFalsy()
    })
})

describe('isValidHttpVersion', () => {
    it('should be possible to validate http version', () => {
        expect(utils.isValidHttpVersion("HTTP/1.1")).toBeTruthy()
        expect(utils.isValidHttpVersion("HTTP//1")).toBeFalsy()
    })
})