use std::cell::RefCell;
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
use std::str::FromStr;

#[cfg(test)]
mod test {
    use super::*;
    use ripcalc::*;

    #[test]
    fn test_broadcast_num() {
        assert_eq!(
            broadcast(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.255").unwrap())
        );

        assert_eq!(
            broadcast(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.255.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("192.168.255.255").unwrap())
        );

        assert_eq!(
            broadcast(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:8a2e:0370:7334").unwrap()
                ),
                cidr: 64,
            })
            .address,
            Addr::V6(Ipv6Addr::from_str("2001:0db8:85a3:0000:ffff:ffff:ffff:ffff").unwrap())
        );
    }

    #[test]
    fn test_network_num() {
        assert_eq!(
            network(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap())
        );

        assert_eq!(
            network(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.255.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("192.168.255.0").unwrap())
        );

        assert_eq!(
            network(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:8a2e:0370:7334").unwrap()
                ),
                cidr: 64,
            })
            .address,
            Addr::V6(Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap())
        );
    }

    #[test]
    fn test_subnet_num() {
        assert_eq!(
            subnet(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.0").unwrap())
        );

        assert_eq!(
            subnet(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.255.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.0").unwrap())
        );
    }

    #[test]
    fn test_wildcard_num() {
        assert_eq!(
            wildcard(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.255").unwrap())
        );

        assert_eq!(
            wildcard(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.255.1").unwrap()),
                cidr: 24,
            })
            .address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.255").unwrap())
        );
    }

    #[test]
    fn test_network_size() {
        assert_eq!(
            network_size(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 32,
            }),
            1
        );
        assert_eq!(
            network_size(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 31,
            }),
            2
        );
        assert_eq!(
            network_size(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 30,
            }),
            4
        );
        assert_eq!(
            network_size(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 29,
            }),
            8
        );
        assert_eq!(
            network_size(&Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 28,
            }),
            16
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 128,
            }),
            1
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 127,
            }),
            2
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 126,
            }),
            4
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 125,
            }),
            8
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 124,
            }),
            16
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 123,
            }),
            32
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 122,
            }),
            64
        );
        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 121,
            }),
            128
        );

        assert_eq!(
            network_size(&Ip {
                address: Addr::V6(
                    Ipv6Addr::from_str("2001:0db8:85a3:0000:0000:0000:0000:0000").unwrap()
                ),
                cidr: 120,
            }),
            256
        );
    }

    #[test]
    fn test_network_iter() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 30,
        };

        let mut i = addresses(&net, None, None);

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.2").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.3").unwrap())
        );
        assert_eq!(i.next(), None);
    }

    fn default_config() -> Config {
        Config::new()
    }

    #[test]
    fn test_format_ng_ip() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 30,
        };
        let config = RefCell::new(default_config());

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%a".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(f, Some("192.168.0.0".to_string()));
    }

    #[test]
    fn test_format_ng_percent() {
        let config = RefCell::new(default_config());
        let f = format_details(
            &FormatDetail {
                ip: Some(&Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 30,
                }),
                line: None,
            },
            "%".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(f, Some("%".to_string()));

        let f = format_details(
            &FormatDetail {
                ip: Some(&Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 30,
                }),
                line: None,
            },
            "%%".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(f, Some("%".to_string()));

        let f = format_details(
            &FormatDetail {
                ip: Some(&Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 30,
                }),
                line: None,
            },
            "%%%".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(f, Some("%%".to_string()));

        let f = format_details(
            &FormatDetail {
                ip: Some(&Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 30,
                }),
                line: None,
            },
            "%%%%".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(f, Some("%%".to_string()));
    }

    #[test]
    fn test_format_ng_boilerplate() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("2001:ba8:1f1:f1cb::4").unwrap()),
            cidr: 64,
        };

        let config = RefCell::new(default_config());
        let f = format_details(&FormatDetail { ip: Some(&net), line: None }, "select * from IP6 where (ip >= %ln and ip <= %lb) and active = 1;\nupdate IP6 set active = 0 where (ip >= %ln and ip <= %lb) and active = 1;".to_string(), &None, None, None, &config);

        assert_eq!(f, Some("select * from IP6 where (ip >= 42540724579414763292693624807812497408 and ip <= 42540724579414763311140368881522049023) and active = 1;
update IP6 set active = 0 where (ip >= 42540724579414763292693624807812497408 and ip <= 42540724579414763311140368881522049023) and active = 1;".to_string()));
    }

    #[test]
    fn test_format_ng_percent_marker() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("2001:ba8:1f1:f1cb::4").unwrap()),
            cidr: 64,
        };

        let config = RefCell::new(default_config());
        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%%b".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(f, Some("%b".to_string()));
    }

    #[test]
    fn test_format_ng_long_broadcast() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("2001:ba8:1f1:f1cb::4").unwrap()),
            cidr: 64,
        };

        let config = RefCell::new(default_config());
        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%lb".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(
            f,
            Some("42540724579414763311140368881522049023".to_string())
        );
    }

    #[test]
    fn test_format_ng_long_broadcast_backslash() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("2001:ba8:1f1:f1cb::4").unwrap()),
            cidr: 64,
        };

        let config = RefCell::new(default_config());
        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%lb\n\n\n%%".to_string(),
            &None,
            None,
            None,
            &config,
        );

        assert_eq!(
            f,
            Some("42540724579414763311140368881522049023\n\n\n%".to_string())
        );
    }

    #[test]
    fn test_format_ng_backslash() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("2001:ba8:1f1:f1cb::4").unwrap()),
            cidr: 64,
        };
        let config = RefCell::new(default_config());

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "\n".to_string(),
            &None,
            None,
            None,
            &config,
        );
        assert_eq!(f, Some("\n".to_string()));

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "\\".to_string(),
            &None,
            None,
            None,
            &config,
        );
        assert_eq!(f, Some('\\'.to_string()));

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "\\i".to_string(),
            &None,
            None,
            None,
            &config,
        );
        assert_eq!(f, Some("i".to_string()));

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "\\t".to_string(),
            &None,
            None,
            None,
            &config,
        );
        assert_eq!(f, Some("\t".to_string()));
    }

    #[test]
    fn test_address_space_use() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 30,
        };

        let mut hm: HashMap<Addr, bool> = HashMap::new();

        hm.insert(Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()), true);
        hm.insert(Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap()), true);
        hm.insert(Addr::V4(Ipv4Addr::from_str("192.168.0.2").unwrap()), true);

        let mut i = addresses(&net, Some(&hm), None);

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.3").unwrap())
        );
        assert_eq!(i.next(), None);

        let mut hm: HashMap<Addr, bool> = HashMap::new();

        hm.insert(Addr::V4(Ipv4Addr::from_str("192.168.1.0").unwrap()), true);
        hm.insert(Addr::V4(Ipv4Addr::from_str("192.168.1.1").unwrap()), true);
        hm.insert(Addr::V4(Ipv4Addr::from_str("192.168.1.2").unwrap()), true);

        let mut i = addresses(&net, Some(&hm), None);

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap())
        );
    }

    #[test]
    fn test_smallest_network() {
        let mut hm: HashMap<Ip, bool> = HashMap::new();

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 30,
        };
        hm.insert(net, true);

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.1.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.2.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.3.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.4.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.5.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.2.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        assert_eq!(
            smallest_group_network(&hm),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 21,
            })
        );

        let mut hm: HashMap<Ip, bool> = HashMap::new();

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.1.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.20.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.40.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.70.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.90.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.200.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.255.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.220.0").unwrap()),
            cidr: 24,
        };
        hm.insert(net, true);

        assert_eq!(
            smallest_group_network(&hm),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 16,
            })
        );

        let mut hm: HashMap<Ip, bool> = HashMap::new();
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 30,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.1").unwrap()),
            cidr: 30,
        };
        hm.insert(net, true);
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.2").unwrap()),
            cidr: 30,
        };
        hm.insert(net, true);

        assert_eq!(
            smallest_group_network(&hm),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                cidr: 30,
            })
        );
    }

    #[test]
    fn test_base_hex() {
        let config = RefCell::new(default_config());
        assert_eq!(
            parse_address_mask("192.168.1.1", None, None, Some(10), false, &config),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.1.1").unwrap()),
                cidr: 32,
            })
        );

        assert_eq!(
            parse_address_mask("192.168.1.1", None, None, None, false, &config),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.1.1").unwrap()),
                cidr: 32,
            })
        );
        assert_eq!(
            parse_address_mask("D4166001", None, None, Some(16), false, &config),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("212.22.96.1").unwrap()),
                cidr: 32,
            })
        );
        assert_eq!(
            parse_address_mask("177.0.0.1", None, None, Some(8), false, &config),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("127.0.0.1").unwrap()),
                cidr: 32,
            })
        );
    }

    #[test]
    fn test_reverse() {
        let config = RefCell::new(default_config());

        assert_eq!(
            parse_address_mask("0101A8C0", None, None, Some(16), true, &config),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.1.1").unwrap()),
                cidr: 32,
            })
        );
    }

    #[test]
    fn test_signed_ints() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("147.147.137.206").unwrap()),
            cidr: 30,
        };

        let mut config = RefCell::new(default_config());

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%La".to_string(),
            &None,
            None,
            None,
            &mut config,
        );
        assert_eq!(f, Some("-1819047474".to_string()));
        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%la".to_string(),
            &None,
            None,
            None,
            &mut config,
        );
        assert_eq!(f, Some("2475919822".to_string()));

        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("ffff::ffff").unwrap()),
            cidr: 30,
        };

        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%La".to_string(),
            &None,
            None,
            None,
            &mut config,
        );
        assert_eq!(f, Some("-5192296858534827628530496329154561".to_string()));
        let f = format_details(
            &FormatDetail {
                ip: Some(&net),
                line: None,
            },
            "%la".to_string(),
            &None,
            None,
            None,
            &mut config,
        );
        assert_eq!(
            f,
            Some("340277174624079928635746076935439056895".to_string())
        );
    }

    #[test]
    fn test_within_ipv4() {
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("127.0.0.1").unwrap()),
                    cidr: 8
                },
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("10.0.0.0").unwrap()),
                    cidr: 8
                },
            ),
            false
        );
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 24
                },
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 16
                },
            ),
            false
        );
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("127.0.0.1").unwrap()),
                    cidr: 8
                },
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
                    cidr: 16
                },
            ),
            false
        );
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("127.0.0.1").unwrap()),
                    cidr: 8
                },
                &Ip {
                    address: Addr::V4(Ipv4Addr::from_str("127.1.1.1").unwrap()),
                    cidr: 16
                },
            ),
            true
        );
    }
    #[test]
    fn test_within_ipv6() {
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V6(Ipv6Addr::from_str("::1").unwrap()),
                    cidr: 48
                },
                &Ip {
                    address: Addr::V6(Ipv6Addr::from_str("f::1").unwrap()),
                    cidr: 48
                },
            ),
            false
        );
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V6(Ipv6Addr::from_str("::1").unwrap()),
                    cidr: 48
                },
                &Ip {
                    address: Addr::V6(Ipv6Addr::from_str("dead:beef::cafe").unwrap()),
                    cidr: 48
                },
            ),
            false
        );
        assert_eq!(
            within(
                &Ip {
                    address: Addr::V6(Ipv6Addr::from_str("1::1").unwrap()),
                    cidr: 48
                },
                &Ip {
                    address: Addr::V6(Ipv6Addr::from_str("::f:f:f:f:f").unwrap()),
                    cidr: 48
                },
            ),
            false
        );
    }

    #[test]
    fn test_network_divide_iter() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap()),
            cidr: 24,
        };

        let mut i = addresses(&net, None, Some(25));
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.128").unwrap())
        );
        assert_eq!(i.next(), None,);

        let mut i = addresses(&net, None, Some(26));
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.64").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.128").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.168.0.192").unwrap())
        );
        assert_eq!(i.next(), None,);
    }

    #[test]
    fn test_network_divide_iter_v6() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("::1").unwrap()),
            cidr: 48,
        };

        let mut i = addresses(&net, None, Some(64));
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V6(Ipv6Addr::from_str("::").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V6(Ipv6Addr::from_str("0:0:0:1::").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V6(Ipv6Addr::from_str("0:0:0:2::").unwrap())
        );

        let i = addresses(&net, None, Some(64));
        let v: Vec<Ip> = i.collect();
        assert_eq!(v.len(), 65536);
    }

    #[test]
    fn test_networks_sizing_v6() {
        let net = Ip {
            address: Addr::V6(Ipv6Addr::from_str("::1").unwrap()),
            cidr: 48,
        };

        assert_eq!(subnets_in_network(64, &net), 65536);
        assert_eq!(subnets_in_network(48, &net), 1);
        assert_eq!(subnets_in_network(49, &net), 2);
    }

    #[test]
    fn test_networks_sizing_v4() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("127.0.0.1").unwrap()),
            cidr: 16,
        };

        assert_eq!(subnets_in_network(24, &net), 256);
        assert_eq!(subnets_in_network(25, &net), 512);
        assert_eq!(subnets_in_network(26, &net), 1024);
        assert_eq!(subnets_in_network(27, &net), 2048);
        assert_eq!(subnets_in_network(28, &net), 4096);
    }

    #[test]
    fn test_smallest_network_limited() {
        let empty: HashMap<Ip, bool> = HashMap::new();
        assert_eq!(smallest_group_network_limited(&empty, 32, 64), None);
    }

    #[test]
    fn test_smallest_network_limited_22_24() {
        let mut net_list: HashMap<Ip, bool> = HashMap::new();
        for i in 0..4 {
            for j in 0..4 {
                net_list.insert(
                    Ip {
                        address: Addr::V4(
                            Ipv4Addr::from_str(&format!("192.168.{i}.{j}")).expect("bad ipv4"),
                        ),
                        cidr: 24,
                    },
                    true,
                );
            }
        }

        let mut resp = smallest_group_network_limited(&net_list, 22, 48).unwrap();
        resp.sort_by(|a, b| a.partial_cmp(b).unwrap());
        assert_eq!(
            resp,
            [Ip {
                address: Addr::V4(Ipv4Addr::from_str(&format!("192.168.0.0")).expect("bad ipv4")),
                cidr: 22
            }]
        );
    }

    #[test]
    fn test_smallest_network_limited_22_8() {
        let mut net_list: HashMap<Ip, bool> = HashMap::new();
        for i in 0..4 {
            for j in 0..4 {
                net_list.insert(
                    Ip {
                        address: Addr::V4(
                            Ipv4Addr::from_str(&format!("192.{i}.{j}.0")).expect("bad ipv4"),
                        ),
                        cidr: 8,
                    },
                    true,
                );
            }
        }

        let mut resp = smallest_group_network_limited(&net_list, 22, 32).unwrap();
        resp.sort_by(|a, b| a.partial_cmp(b).unwrap());
        assert_eq!(
            resp,
            [
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.0.0")).expect("bad ipv4")),
                    cidr: 22
                },
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.1.0.0")).expect("bad ipv4")),
                    cidr: 22
                },
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.2.0.0")).expect("bad ipv4")),
                    cidr: 22
                },
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.3.0.0")).expect("bad ipv4")),
                    cidr: 22
                },
            ]
        );
    }

    #[test]
    fn test_smallest_network_limited_24_8() {
        let mut net_list: HashMap<Ip, bool> = HashMap::new();
        for i in 0..4 {
            for j in 0..4 {
                net_list.insert(
                    Ip {
                        address: Addr::V4(
                            Ipv4Addr::from_str(&format!("192.0.{i}.{j}")).expect("bad ipv4"),
                        ),
                        cidr: 8,
                    },
                    true,
                );
            }
        }

        let mut resp = smallest_group_network_limited(&net_list, 24, 48).unwrap();
        resp.sort_by(|a, b| a.partial_cmp(b).unwrap());
        assert_eq!(
            resp,
            [
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.0.0")).expect("bad ipv4")),
                    cidr: 24
                },
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.1.0")).expect("bad ipv4")),
                    cidr: 24
                },
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.2.0")).expect("bad ipv4")),
                    cidr: 24
                },
                Ip {
                    address: Addr::V4(Ipv4Addr::from_str(&format!("192.0.3.0")).expect("bad ipv4")),
                    cidr: 24
                },
            ]
        );
    }

    #[test]
    fn test_is_like_hostname() {
        assert_eq!(is_like_hostname("www.usenix.org.uk"), true);
        assert_eq!(is_like_hostname("www.usenix.org.uk:80"), false);
        assert_eq!(is_like_hostname("org.uk"), true);
        assert_eq!(is_like_hostname("bbc.co.uk"), true);
        assert_eq!(is_like_hostname("org"), false);
        assert_eq!(is_like_hostname("n"), false);
        assert_eq!(is_like_hostname("n!"), false);
        assert_eq!(is_like_hostname("http://www.bbc.co.uk/"), false);
    }

    #[test]
    fn test_inside_filter() {
        let config = RefCell::new(default_config());

        let mut net_list = vec![];

        net_list
            .push(parse_address_mask("192.168.0.0/24", None, None, None, false, &config).unwrap());

        let ip = parse_address_mask("192.168.0.0/24", None, None, None, false, &config).unwrap();
        assert_eq!(inside_filter(Some(true), net_list.as_slice(), &ip), true);
        assert_eq!(inside_filter(Some(false), net_list.as_slice(), &ip), false);

        let ip = parse_address_mask("192.168.1.0/24", None, None, None, false, &config).unwrap();
        assert_eq!(inside_filter(Some(false), net_list.as_slice(), &ip), true);
        assert_eq!(inside_filter(Some(true), net_list.as_slice(), &ip), false);

        net_list
            .push(parse_address_mask("192.168.1.0/24", None, None, None, false, &config).unwrap());

        let ip = parse_address_mask("192.168.0.0/24", None, None, None, false, &config).unwrap();
        assert_eq!(inside_filter(Some(true), net_list.as_slice(), &ip), true);
        assert_eq!(inside_filter(Some(false), net_list.as_slice(), &ip), false);

        let ip = parse_address_mask("192.168.1.0/24", None, None, None, false, &config).unwrap();
        assert_eq!(inside_filter(Some(true), net_list.as_slice(), &ip), true);
        assert_eq!(inside_filter(Some(false), net_list.as_slice(), &ip), false);
    }

    #[test]
    fn test_network_match_iter() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("255.255.255.255").unwrap()),
            cidr: 32,
        };

        let mut i = network_iter(&net);

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.254").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.252").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.248").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.240").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.224").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.192").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.128").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.0").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.254.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.252.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.248.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.240.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.224.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.192.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.128.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.0.0").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.254.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.252.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.248.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.240.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.224.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.192.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.128.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.0.0.0").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("254.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("252.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("248.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("240.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("224.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("128.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap())
        );
        assert_eq!(i.next().as_ref(), None,);
    }

    #[test]
    fn test_network_match_broadcast_iter() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap()),
            cidr: 32,
        };

        let mut i = broadcast_iter(&net);

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.1").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.3").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.7").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.15").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.31").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.63").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.127").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.255").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.1.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.3.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.7.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.15.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.31.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.63.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.127.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.255.255").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.1.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.3.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.7.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.15.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.31.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.63.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.127.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.255.255.255").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("1.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("3.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("7.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("15.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("31.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("63.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("127.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.255").unwrap())
        );

        assert_eq!(i.next().as_ref(), None,);
    }

    #[test]
    fn test_network_match_subnet_iter() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap()),
            cidr: 32,
        };

        let mut i = subnet_iter(&net);
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.254").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.252").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.248").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.240").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.224").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.192").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.128").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.0").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.254.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.252.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.248.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.240.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.224.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.192.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.128.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.0.0").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.254.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.252.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.248.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.240.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.224.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.192.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.128.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.0.0.0").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("254.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("252.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("248.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("240.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("224.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("192.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("128.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap())
        );
        assert_eq!(i.next().as_ref(), None,);
    }

    #[test]
    fn test_network_match_wildcard_iter() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap()),
            cidr: 32,
        };

        let mut i = wildcard_iter(&net);

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.0").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.1").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.3").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.7").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.15").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.31").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.63").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.127").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.0.255").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.1.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.3.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.7.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.15.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.31.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.63.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.127.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.0.255.255").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.1.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.3.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.7.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.15.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.31.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.63.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.127.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("0.255.255.255").unwrap())
        );

        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("1.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("3.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("7.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("15.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("31.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("63.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("127.255.255.255").unwrap())
        );
        assert_eq!(
            i.next().as_ref().unwrap().address,
            Addr::V4(Ipv4Addr::from_str("255.255.255.255").unwrap())
        );

        assert_eq!(i.next().as_ref(), None,);
    }

    #[test]
    fn test_network_reservation() {
        let net = Ip {
            address: Addr::V4(Ipv4Addr::from_str("255.255.255.255").unwrap()),
            cidr: 32,
        };

        assert_eq!(
            network_reservation(&net),
            Some("Reserved for limited broadcast destination address.".to_string())
        );
    }

    #[test]
    fn test_line_filter_filternum() {
        let config = RefCell::new(default_config());

        assert_eq!(
            line_filter(&config, Some(1), "foo 192.168.1.1", None),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.1.1").unwrap()),
                cidr: 32
            }),
        );

        let config = RefCell::new(default_config());

        assert_eq!(line_filter(&config, Some(0), "foo 192.168.1.1", None), None,);
    }

    #[test]
    fn test_line_filter_filterany() {
        let config = RefCell::new(default_config());
        config
            .borrow_mut()
            .options
            .insert("filterany".to_string(), "".to_string());

        assert_eq!(
            line_filter(&config, None, "foo 192.168.1.1", None),
            Some(Ip {
                address: Addr::V4(Ipv4Addr::from_str("192.168.1.1").unwrap()),
                cidr: 32
            }),
        );
    }
}
