text:
package org.onosproject.provider.host.impl;

import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.ARP;
import org.onlab.packet.BasePacket;
import org.onlab.packet.DHCP;
import org.onlab.packet.DHCP6;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPacket;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
import org.onlab.packet.dhcp.Dhcp6IaNaOption;
import org.onlab.packet.dhcp.Dhcp6IaTaOption;
import org.onlab.packet.dhcp.Dhcp6RelayOption;
import org.onlab.packet.ipv6.IExtensionHeader;
import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.packet.ndp.RouterAdvertisement;
import org.onlab.packet.ndp.RouterSolicitation;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.host.HostLocationProbingService;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.nio.ByteBuffer;
import java.util.Dictionary;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import java.util.Set;

import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provider which uses an OpenFlow controller to detect network end-station
 * hosts.
 */
@Component(immediate = true)
@Service
public class HostLocationProvider extends AbstractProvider implements HostProvider, HostLocationProbingService {
    private final Logger log = getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostProviderRegistry providerRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PacketService packetService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TopologyService topologyService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService cfgService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected InterfaceService interfaceService;

    private HostProviderService providerService;

    private final InternalHostProvider processor = new InternalHostProvider();
    private final DeviceListener deviceListener = new InternalDeviceListener();

    private ApplicationId appId;

    @Property(name = "hostRemovalEnabled", boolValue = true,
            label = "Enable host removal on port/device down events")
    private boolean hostRemovalEnabled = true;

    @Property(name = "requestArp", boolValue = true,
            label = "Request ARP packets for neighbor discovery by the " +
                    "Host Location Provider; default is true")
    private boolean requestArp = true;

    @Property(name = "requestIpv6ND", boolValue = false,
            label = "Requests IPv6 Neighbor Discovery by the " +
                    "Host Location Provider; default is false")
    private boolean requestIpv6ND = false;

    @Property(name = "useDhcp", boolValue = false,
            label = "Use DHCP to update IP address of the host; default is false")
    private boolean useDhcp = false;

    @Property(name = "useDhcp6", boolValue = false,
            label = "Use DHCPv6 to update IP address of the host; default is false")
    private boolean useDhcp6 = false;

    @Property(name = "requestInterceptsEnabled", boolValue = true,
            label = "Enable requesting packet intercepts")
    private boolean requestInterceptsEnabled = true;

    @Property(name = "multihomingEnabled", boolValue = false,
            label = "Allow hosts to be multihomed")
    private boolean multihomingEnabled = false;

    private int probeInitDelayMs = 1000;

    protected ExecutorService eventHandler;

    private int probeDelayMs = 1000;

    /**
     * Creates an OpenFlow host provider.
     */
    public HostLocationProvider() {
        super(new ProviderId("of", "org.onosproject.provider.host"));
    }

    @Activate
    public void activate(ComponentContext context) {
        cfgService.registerProperties(getClass());
        appId = coreService.registerApplication("org.onosproject.provider.host");
        eventHandler = newSingleThreadScheduledExecutor(
                groupedThreads("onos/host-loc-provider", "event-handler", log));
        providerService = providerRegistry.register(this);
        packetService.addProcessor(processor, PacketProcessor.advisor(1));
        deviceService.addListener(deviceListener);

        modified(context);

        log.info("Started with Application ID {}", appId.id());
    }

    @Deactivate
    public void deactivate() {
        cfgService.unregisterProperties(getClass(), false);

        withdrawIntercepts();

        providerRegistry.unregister(this);
        packetService.removeProcessor(processor);
        deviceService.removeListener(deviceListener);
        eventHandler.shutdown();
        providerService = null;
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        readComponentConfiguration(context);

        if (requestInterceptsEnabled) {
            requestIntercepts();
        } else {
            withdrawIntercepts();
        }
    }

    /**
     * Request packet intercepts.
     */
    private void requestIntercepts() {
        // Use ARP
        TrafficSelector arpSelector = DefaultTrafficSelector.builder()
                .matchEthType(Ethernet.TYPE_ARP)
                .build();
        if (requestArp) {
            packetService.requestPackets(arpSelector, PacketPriority.CONTROL, appId);
        } else {
            packetService.cancelPackets(arpSelector, PacketPriority.CONTROL, appId);
        }

        // Use IPv6 Neighbor Discovery
        TrafficSelector ipv6NsSelector = DefaultTrafficSelector.builder()
                .matchEthType(Ethernet.TYPE_IPV6)
                .matchIPProtocol(IPv6.PROTOCOL_ICMP6)
                .matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION)
                .build();
        TrafficSelector ipv6NaSelector = DefaultTrafficSelector.builder()
                .matchEthType(Ethernet.TYPE_IPV6)
                .matchIPProtocol(IPv6.PROTOCOL_ICMP6)
                .matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT)
                .build();
        if (requestIpv6ND) {
            packetService.requestPackets(ipv6NsSelector, PacketPriority.CONTROL, appId);
            packetService.requestPackets(ipv6NaSelector, PacketPriority.CONTROL, appId);
        } else {
            packetService.cancelPackets(ipv6NsSelector, PacketPriority.CONTROL, appId);
            packetService.cancelPackets(ipv6NaSelector, PacketPriority.CONTROL, appId);
        }
    }

    /**
     * Withdraw packet intercepts.
     */
    private void withdrawIntercepts() {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(Ethernet.TYPE_ARP);
        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);

        // IPv6 Neighbor Solicitation packet.
        selector.matchEthType(Ethernet.TYPE_IPV6);
        selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
        selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);

        // IPv6 Neighbor Advertisement packet.
        selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
    }

    /**
     * Extracts properties from the component configuration context.
     *
     * @param context the component context
     */
    private void readComponentConfiguration(ComponentContext context) {
        Dictionary<?, ?> properties = context.getProperties();
        Boolean flag;

        flag = Tools.isPropertyEnabled(properties, "hostRemovalEnabled");
        if (flag == null) {
            log.info("Host removal on port/device down events is not configured, " +
                     "using current value of {}", hostRemovalEnabled);
        } else {
            hostRemovalEnabled = flag;
            log.info("Configured. Host removal on port/device down events is {}",
                     hostRemovalEnabled ? "enabled" : "disabled");
        }

        flag = Tools.isPropertyEnabled(properties, "requestArp");
        if (flag == null) {
            log.info("Using ARP is not configured, " +
                     "using current value of {}", requestArp);
        } else {
            requestArp = flag;
            log.info("Configured. Using ARP is {}",
                     requestArp ? "enabled" : "disabled");
        }

        flag = Tools.isPropertyEnabled(properties, "requestIpv6ND");
        if (flag == null) {
            log.info("Using IPv6 Neighbor Discovery is not configured, " +
                             "using current value of {}", requestIpv6ND);
        } else {
            requestIpv6ND = flag;
            log.info("Configured. Using IPv6 Neighbor Discovery is {}",
                     requestIpv6ND ? "enabled" : "disabled");
        }

        flag = Tools.isPropertyEnabled(properties, "useDhcp");
        if (flag == null) {
            log.info("Using DHCP is not configured, " +
                     "using current value of {}", useDhcp);
        } else {
            useDhcp = flag;
            log.info("Configured. Using DHCP is {}",
                     useDhcp ? "enabled" : "disabled");
        }

        flag = Tools.isPropertyEnabled(properties, "requestInterceptsEnabled");
        if (flag == null) {
            log.info("Request intercepts is not configured, " +
                     "using current value of {}", requestInterceptsEnabled);
        } else {
            requestInterceptsEnabled = flag;
            log.info("Configured. Request intercepts is {}",
                     requestInterceptsEnabled ? "enabled" : "disabled");
        }

        flag = Tools.isPropertyEnabled(properties, "multihomingEnabled");
        if (flag == null) {
            log.info("Multihoming is not configured, " +
                    "using current value of {}", multihomingEnabled);
        } else {
            multihomingEnabled = flag;
            log.info("Configured. Multihoming is {}",
                    multihomingEnabled ? "enabled" : "disabled");
        }
    }

    @Override
    public void probeHostLocation(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
        host.ipAddresses().stream().findFirst().ifPresent(ip -> {
            MacAddress probeMac = providerService.addPendingHostLocation(host.id(), connectPoint, probeMode);
            log.debug("Constructing {} probe for host {} with {}", probeMode, host.id(), ip);
            Ethernet probe;
            if (ip.isIp4()) {
                probe = ARP.buildArpRequest(probeMac.toBytes(), Ip4Address.ZERO.toOctets(),
                        host.id().mac().toBytes(), ip.toOctets(),
                        host.id().mac().toBytes(), host.id().vlanId().toShort());
            } else {
                probe = NeighborSolicitation.buildNdpSolicit(
                        ip.getIp6Address(),
                        Ip6Address.valueOf(IPv6.getLinkLocalAddress(probeMac.toBytes())),
                        ip.getIp6Address(),
                        probeMac,
                        host.id().mac(),
                        host.id().vlanId());
            }

            // NOTE: delay the probe a little bit to wait for the store synchronization is done
            ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
            executorService.schedule(() ->
                    sendLocationProbe(probe, connectPoint), probeInitDelayMs, TimeUnit.MILLISECONDS);
        });
    }

    /**
     * Send the probe packet on given port.
     *
     * @param probe the probe packet
     * @param connectPoint the port we want to probe
     */
    private void sendLocationProbe(Ethernet probe, ConnectPoint connectPoint) {
        log.info("Sending probe for host {} on location {} with probeMac {}",
                probe.getDestinationMAC(), connectPoint, probe.getSourceMAC());
        TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
        OutboundPacket outboundPacket = new DefaultOutboundPacket(connectPoint.deviceId(),
                treatment, ByteBuffer.wrap(probe.serialize()));
        packetService.emit(outboundPacket);
    }

    @Override
    public void triggerProbe(Host host) {
        //log.info("Triggering probe on device {} ", host);

        // FIXME Disabling host probing for now, because sending packets from a
        // broadcast MAC address caused problems when two ONOS networks were
        // interconnected. Host probing should take into account the interface
        // configuration when determining which source address to use.

        //MastershipRole role = deviceService.getRole(host.location().deviceId());
        //if (role.equals(MastershipRole.MASTER)) {
        //    host.ipAddresses().forEach(ip -> {
        //        sendProbe(host, ip);
        //    });
        //} else {
        //    log.info("not the master, master will probe {}");
        //}
    }

    private void sendProbe(Host host, IpAddress targetIp) {
        Ethernet probePacket = null;
        if (targetIp.isIp4()) {
            // IPv4: Use ARP
            probePacket = buildArpRequest(targetIp, host);
        } else {
            // IPv6: Use Neighbor Discovery
            //TODO need to implement ndp probe
            log.info("Triggering probe on device {} ", host);
        }

        TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(host.location().port()).build();

        OutboundPacket outboundPacket = new DefaultOutboundPacket(host.location().deviceId(), treatment,
                ByteBuffer.wrap(probePacket.serialize()));

        packetService.emit(outboundPacket);
    }

    // This method is using source ip as 0.0.0.0 , to receive the reply even from the sub net hosts.
    private Ethernet buildArpRequest(IpAddress targetIp, Host host) {
        return ARP.buildArpRequest(MacAddress.BROADCAST.toBytes(), Ip4Address.ZERO.toOctets(),
                MacAddress.BROADCAST.toBytes(), targetIp.toOctets(),
                MacAddress.BROADCAST.toBytes(), VlanId.NONE.toShort());
    }

    private class InternalHostProvider implements PacketProcessor {
        /**
         * Create or update host information.
         * Will not update IP if IP is null, all zero or self-assigned.
         *
         * @param hid  host ID
         * @param mac  source Mac address
         * @param vlan VLAN ID
         * @param hloc host location
         * @param ip   source IP address or null if not updating
         */
        private void createOrUpdateHost(HostId hid, MacAddress mac,
                                        VlanId vlan, HostLocation hloc,
                                        IpAddress ip) {
            Set<HostLocation> newLocations = Sets.newHashSet(hloc);

            if (multihomingEnabled) {
                Host existingHost = hostService.getHost(hid);
                if (existingHost != null) {
                    Set<HostLocation> prevLocations = existingHost.locations();

                    if (prevLocations.stream().noneMatch(loc -> loc.deviceId().equals(hloc.deviceId()))) {
                        // New location is on a device that we haven't seen before
                        // Could be a dual-home host. Append new location and send out the probe
                        newLocations.addAll(prevLocations);
                        prevLocations.forEach(prevLocation ->
                                probeHostLocation(existingHost, prevLocation, ProbeMode.VERIFY));
                    } else {
                        // Move within the same switch
                        // Simply replace old location that is on the same device
                        prevLocations.stream().filter(loc -> !loc.deviceId().equals(hloc.deviceId()))
                                .forEach(newLocations::add);
                    }
                }
            }

            HostDescription desc = ip == null || ip.isZero() || ip.isSelfAssigned() ?
                    new DefaultHostDescription(mac, vlan, newLocations, Sets.newHashSet(), false) :
                    new DefaultHostDescription(mac, vlan, newLocations, Sets.newHashSet(ip), false);
            try {
                providerService.hostDetected(hid, desc, false);
            } catch (IllegalStateException e) {
                log.debug("Host {} suppressed", hid);
            }
        }

        /**
         * Updates IP address for an existing host.
         *
         * @param hid host ID
         * @param ip IP address
         */
        private void updateHostIp(HostId hid, IpAddress ip) {
            Host host = hostService.getHost(hid);
            if (host == null) {
                log.warn("Fail to update IP for {}. Host does not exist", hid);
                return;
            }

            HostDescription desc = new DefaultHostDescription(hid.mac(), hid.vlanId(),
                    host.locations(), Sets.newHashSet(ip), false);
            try {
                providerService.hostDetected(hid, desc, false);
            } catch (IllegalStateException e) {
                log.debug("Host {} suppressed", hid);
            }
        }

        @Override
        public void process(PacketContext context) {
            if (context == null) {
                return;
            }

            Ethernet eth = context.inPacket().parsed();
            if (eth == null) {
                return;
            }

            MacAddress srcMac = eth.getSourceMAC();
            if (srcMac.isBroadcast() || srcMac.isMulticast()) {
                return;
            }

            VlanId vlan = VlanId.vlanId(eth.getVlanID());
            ConnectPoint heardOn = context.inPacket().receivedFrom();

            // If this arrived on control port, bail out.
            if (heardOn.port().isLogical()) {
                return;
            }

            // If this is not an edge port, bail out.
            Topology topology = topologyService.currentTopology();
            if (topologyService.isInfrastructure(topology, heardOn)) {
                return;
            }

            HostLocation hloc = new HostLocation(heardOn, System.currentTimeMillis());
            HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
            MacAddress destMac = eth.getDestinationMAC();

            // Receives a location probe. Invalid entry from the cache
            if (multihomingEnabled && destMac.isOnos() && !MacAddress.NONE.equals(destMac)) {
                log.info("Receives probe for {}/{} on {}", srcMac, vlan, heardOn);
                providerService.removePendingHostLocation(destMac);
                return;
            }

            // ARP: possible new hosts, update both location and IP
            if (eth.getEtherType() == Ethernet.TYPE_ARP) {
                ARP arp = (ARP) eth.getPayload();
                IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
                                                 arp.getSenderProtocolAddress());
                createOrUpdateHost(hid, srcMac, vlan, hloc, ip);

            // IPv4: update location only
            } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
                // Update host location
                createOrUpdateHost(hid, srcMac, vlan, hloc, null);
                if (useDhcp) {
                    DHCP dhcp = findDhcp(eth).orElse(null);
                    // DHCP ACK: additionally update IP of DHCP client
                    if (dhcp != null  && dhcp.getPacketType().equals(DHCP.MsgType.DHCPACK)) {
                        MacAddress hostMac = MacAddress.valueOf(dhcp.getClientHardwareAddress());
                        VlanId hostVlan = VlanId.vlanId(eth.getVlanID());
                        HostId hostId = HostId.hostId(hostMac, hostVlan);
                        updateHostIp(hostId, IpAddress.valueOf(dhcp.getYourIPAddress()));
                    }
                }
            // NeighborAdvertisement and NeighborSolicitation: possible
            // new hosts, update both location and IP.
            //
            // IPv6: update location only
            } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
                IPv6 ipv6 = (IPv6) eth.getPayload();
                IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
                                                 ipv6.getSourceAddress());

                // skip extension headers
                IPacket pkt = ipv6;
                while (pkt.getPayload() != null &&
                        pkt.getPayload() instanceof IExtensionHeader) {
                    pkt = pkt.getPayload();
                }
                pkt = pkt.getPayload();

                // DHCPv6 protocol
                DHCP6 dhcp6 = findDhcp6(pkt).orElse(null);
                if (dhcp6 != null && useDhcp6) {
                    createOrUpdateHost(hid, srcMac, vlan, hloc, null);
                    handleDhcp6(dhcp6, vlan);
                    return;
                }

                if (pkt != null && pkt instanceof ICMP6) {
                    // Neighbor Discovery Protocol
                    pkt = pkt.getPayload();
                    if (pkt != null) {
                        // RouterSolicitation, RouterAdvertisement
                        if (pkt instanceof RouterAdvertisement || pkt instanceof RouterSolicitation) {
                            return;
                        }
                        if (pkt instanceof NeighborSolicitation || pkt instanceof NeighborAdvertisement) {
                            // Duplicate Address Detection
                            if (ip.isZero()) {
                                return;
                            }
                            // NeighborSolicitation, NeighborAdvertisement
                            createOrUpdateHost(hid, srcMac, vlan, hloc, ip);

                            // Also learn from the target address of NeighborAdvertisement
                            if (pkt instanceof NeighborAdvertisement) {
                                NeighborAdvertisement na = (NeighborAdvertisement) pkt;
                                Ip6Address targetAddr = Ip6Address.valueOf(na.getTargetAddress());
                                createOrUpdateHost(hid, srcMac, vlan, hloc, targetAddr);
                            }
                            return;
                        }
                    }
                }

                // multicast, exclude DHCPv6
                if (eth.isMulticast() && dhcp6 == null) {
                    return;
                }

                // normal IPv6 packets
                createOrUpdateHost(hid, srcMac, vlan, hloc, null);
            }
        }

        /**
         * Handles DHCPv6 packet, if message type is ACK, update IP address
         * according to DHCPv6 payload (IA Address option).
         *
         * @param dhcp6 the DHCPv6 payload
         * @param vlanId the vlan of this packet
         */
        private void handleDhcp6(DHCP6 dhcp6, VlanId vlanId) {
            // extract the relay message if exist
            while (dhcp6 != null && DHCP6.RELAY_MSG_TYPES.contains(dhcp6.getMsgType())) {
                dhcp6 = dhcp6.getOptions().stream()
                        .filter(opt -> opt instanceof Dhcp6RelayOption)
                        .map(BasePacket::getPayload)
                        .map(pld -> (DHCP6) pld)
                        .findFirst()
                        .orElse(null);
            }

            if (dhcp6 == null) {
                // Can't find dhcp payload
                log.warn("Can't find dhcp payload from relay message");
                return;
            }

            if (dhcp6.getMsgType() != DHCP6.MsgType.REPLY.value()) {
                // Update IP address only when we received REPLY message
                return;
            }
            Optional<Dhcp6ClientIdOption> clientIdOption = dhcp6.getOptions()
                    .stream()
                    .filter(opt -> opt instanceof Dhcp6ClientIdOption)
                    .map(opt -> (Dhcp6ClientIdOption) opt)
                    .findFirst();

            if (!clientIdOption.isPresent()) {
                // invalid DHCPv6 option
                log.warn("Can't find client ID from DHCPv6 {}", dhcp6);
                return;
            }

            byte[] linkLayerAddr = clientIdOption.get().getDuid().getLinkLayerAddress();
            if (linkLayerAddr == null || linkLayerAddr.length != 6) {
                // No any mac address found
                log.warn("Can't find client mac from option {}", clientIdOption);
                return;
            }
            MacAddress clientMac = MacAddress.valueOf(linkLayerAddr);

            // Extract IPv6 address from IA NA ot IA TA option
            Optional<Dhcp6IaNaOption> iaNaOption = dhcp6.getOptions()
                    .stream()
                    .filter(opt -> opt instanceof Dhcp6IaNaOption)
                    .map(opt -> (Dhcp6IaNaOption) opt)
                    .findFirst();
            Optional<Dhcp6IaTaOption> iaTaOption = dhcp6.getOptions()
                    .stream()
                    .filter(opt -> opt instanceof Dhcp6IaTaOption)
                    .map(opt -> (Dhcp6IaTaOption) opt)
                    .findFirst();
            Optional<Dhcp6IaAddressOption> iaAddressOption;
            if (iaNaOption.isPresent()) {
                iaAddressOption = iaNaOption.get().getOptions().stream()
                        .filter(opt -> opt instanceof Dhcp6IaAddressOption)
                        .map(opt -> (Dhcp6IaAddressOption) opt)
                        .findFirst();
            } else if (iaTaOption.isPresent()) {
                iaAddressOption = iaTaOption.get().getOptions().stream()
                        .filter(opt -> opt instanceof Dhcp6IaAddressOption)
                        .map(opt -> (Dhcp6IaAddressOption) opt)
                        .findFirst();
            } else {
                iaAddressOption = Optional.empty();
            }
            if (iaAddressOption.isPresent()) {
                Ip6Address ip = iaAddressOption.get().getIp6Address();
                HostId hostId = HostId.hostId(clientMac, vlanId);
                updateHostIp(hostId, ip);
            } else {
                log.warn("Can't find IPv6 address from DHCPv6 {}", dhcp6);
            }
        }

        private Optional<DHCP> findDhcp(Ethernet eth) {
            IPacket pkt = eth.getPayload();
            return Stream.of(pkt)
                    .filter(Objects::nonNull)
                    .filter(p -> p instanceof IPv4)
                    .map(IPacket::getPayload)
                    .filter(Objects::nonNull)
                    .filter(p -> p instanceof UDP)
                    .map(IPacket::getPayload)
                    .filter(Objects::nonNull)
                    .filter(p -> p instanceof DHCP)
                    .map(p -> (DHCP) p)
                    .findFirst();
        }

        private Optional<DHCP6> findDhcp6(IPacket pkt) {
            return Stream.of(pkt)
                    .filter(Objects::nonNull)
                    .filter(p -> p instanceof UDP)
                    .map(IPacket::getPayload)
                    .filter(Objects::nonNull)
                    .filter(p -> p instanceof DHCP6)
                    .map(p -> (DHCP6) p)
                    .findFirst();
        }
    }

    // Auxiliary listener to device events.
    private class InternalDeviceListener implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            eventHandler.execute(() -> handleEvent(event));
        }

        private void handleEvent(DeviceEvent event) {
            Device device = event.subject();
            switch (event.type()) {
                case DEVICE_ADDED:
                    break;
                case DEVICE_AVAILABILITY_CHANGED:
                    if (hostRemovalEnabled && !deviceService.isAvailable(device.id())) {
                        processDeviceDown(device.id());
                    }
                    break;
                case DEVICE_SUSPENDED:
                case DEVICE_UPDATED:
                    // Nothing to do?
                    break;
                case DEVICE_REMOVED:
                    if (hostRemovalEnabled) {
                        processDeviceDown(device.id());
                    }
                    break;
                case PORT_ADDED:
                    break;
                case PORT_UPDATED:
                    if (hostRemovalEnabled && !event.port().isEnabled()) {
                        processPortDown(new ConnectPoint(device.id(), event.port().number()));
                    }
                    break;
                case PORT_REMOVED:
                    // Nothing to do?
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * When a device goes down, update the location of affected hosts.
     *
     * @param deviceId the device that goes down
     */
    private void processDeviceDown(DeviceId deviceId) {
        hostService.getConnectedHosts(deviceId).forEach(affectedHost -> affectedHost.locations().stream()
                .filter(hostLocation -> hostLocation.deviceId().equals(deviceId))
                .forEach(affectedLocation ->
                        providerService.removeLocationFromHost(affectedHost.id(), affectedLocation))
        );
    }

    /**
     * When a port goes down, update the location of affected hosts.
     *
     * @param connectPoint the port that goes down
     */
    private void processPortDown(ConnectPoint connectPoint) {
        hostService.getConnectedHosts(connectPoint).forEach(affectedHost ->
                providerService.removeLocationFromHost(affectedHost.id(), new HostLocation(connectPoint, 0L))
        );
    }

}


text:
namespace MVP.Api.Models.MicrosoftAccount
{
    using Newtonsoft.Json;

    /// <summary>
    /// Defines a model for stored credentials of a Microsoft Account.
    /// </summary>
    public class MSACredentials
    {
        /// <summary>
        /// Gets or sets the user's ID for the MSA.
        /// </summary>
        [JsonProperty("user_id")]
        public string UserId { get; set; }

        /// <summary>
        /// Gets or sets the token for accessing services for the MSA.
        /// </summary>
        [JsonProperty("access_token")]
        public string AccessToken { get; set; }

        /// <summary>
        /// Gets or sets the token for refreshing the access token for the MSA.
        /// </summary>
        [JsonProperty("refresh_token")]
        public string RefreshToken { get; set; }

        /// <summary>
        /// Gets or sets the time until the access token expires.
        /// </summary>
        [JsonProperty("expires_in")]
        public long ExpiresIn { get; set; }
    }
}

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE HTML>

<title>Uses of Package org.opensextant.extractors.geo.social (Xponents Extraction Toolkit)</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="dc.created" content="2022-02-02">
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
<link rel="stylesheet" type="text/css" href="../../../../../jquery/jquery-ui.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

copyright             OpenSextant.org, 2013-2021

SEARCH:
<input type="text" id="search" value="search" disabled="disabled">
<input type="reset" id="reset" value="reset" disabled="disabled">

Uses of Package
org.opensextant.extractors.geo.social

Packages that use org.opensextant.extractors.geo.social

Package
Description

org.opensextant.extractors.geo.social

Social Geoinferencing

Classes in org.opensextant.extractors.geo.social used by org.opensextant.extractors.geo.social

Class
Description

GeoInference

This is a light wrapper around TextMatch + Geocoding interfaces.

GeoInferencer

A geoinferencer infers location on users and their messages.

SocialGeo

A base-class that has the various hooks for logging, dev/test/evaluation,
 common dictionaries/resources, and helpful connectivity items.

XponentGeocoder

Pipeline focused on improving the location metadata for Tweets or Weibo or
 other social media that has metadata about user or messaging location.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

copyright             OpenSextant.org, 2013-2021

Copyright © 2013–2022. All rights reserved.


text:
package io.gravitee.am.repository.oauth2.api;

import io.gravitee.am.repository.jdbc.oauth2.oidc.JdbcRequestObjectRepository;
import io.gravitee.am.repository.oauth2.AbstractOAuthTest;
import io.gravitee.am.repository.oidc.model.RequestObject;
import io.reactivex.observers.TestObserver;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

/**
 * @author Eric LELEU (eric.leleu at graviteesource.com)
 * @author GraviteeSource Team
 */
public class RequestObjectRepositoryPurgeTest extends AbstractOAuthTest {
    @Autowired
    private JdbcRequestObjectRepository requestObjectRepository;

    @Test
    public void shouldPurge() {
        Instant now = Instant.now();
        RequestObject object1 = new RequestObject();
        object1.setDomain("domain");
        object1.setClient("client");
        object1.setExpireAt(new Date(now.plus(1, ChronoUnit.MINUTES).toEpochMilli()));

        RequestObject object2 = new RequestObject();
        object2.setDomain("domain");
        object2.setClient("client");
        object2.setExpireAt(new Date(now.minus(1, ChronoUnit.MINUTES).toEpochMilli()));

        requestObjectRepository.create(object1).test().awaitTerminalEvent();
        requestObjectRepository.create(object2).test().awaitTerminalEvent();

        assertNotNull(requestObjectRepository.findById(object1.getId()).blockingGet());
        assertNull(requestObjectRepository.findById(object2.getId()).blockingGet());

        TestObserver<Void> testPurge = requestObjectRepository.purgeExpiredData().test();
        testPurge.awaitTerminalEvent();
        testPurge.assertNoErrors();

        assertNotNull(requestObjectRepository.findById(object1.getId()).blockingGet());
        assertNull(requestObjectRepository.findById(object2.getId()).blockingGet());

    }

}


text:
Write-Host $env:APPVEYOR_JOB_ID
Write-Host $env:APPVEYOR_API_URL

#######################################################################
###     Setup variables from Appveyor                               ###
#######################################################################
$repoPath = Resolve-Path .
$buildVersion = $env:appveyor_build_version
$branchName = $env:appveyor_repo_branch
$repoName = $env:appveyor_repo_name
$nugetUrl = $env:nuget_gallery_url
$nugetKey = $env:nuget_api_key
$mygetUrl = $env:myget_gallery_url
$mygetKey = $env:myget_api_key

# normal build specific
$treatBuildWarningsAsErrors = $env:treatBuildWarningsAsErrors
$runCodeAnalysis = $env:runCodeAnalysis
$appveyorNugetUpdateStrategyPrivate = $env:appveyor_nuget_update_strategy_private
$appveyorNugetUpdateStrategyPublic = $env:appveyor_nuget_update_strategy_public

#######################################################################
###     Download and dot source tools to use                        ###
#######################################################################
NuGet sources add -Name NaosMyGet -Source https://www.myget.org/F/naos-nuget/api/v3/index.json
NuGet sources add -Name ObcMyGet -Source https://www.myget.org/F/obeautifulcode-nuget/api/v3/index.json
$TempBuildPackagesDir = "../TempTools/packages"
if (-not (Test-Path $TempBuildPackagesDir)) { md $TempBuildPackagesDir | Out-Null }
$TempBuildPackagesDir = Resolve-Path $TempBuildPackagesDir
NuGet install 'Naos.Powershell.Build' -Prerelease -OutputDirectory $TempBuildPackagesDir
NuGet install 'Naos.Build.Packaging' -Prerelease -OutputDirectory $TempBuildPackagesDir
NuGet install 'Naos.Build.Conventions.RepoConfig' -Prerelease -OutputDirectory $TempBuildPackagesDir

$repoConfigFile = (ls $TempBuildPackagesDir -Filter 'RepoConfig.ps1' -Recurse).FullName
if ($repoConfigFile -eq $null) {
	ls $TempBuildPackagesDir -Recurse | %{ $_.FullName }
	throw "Could not find 'RepoConfig.ps1' in $TempBuildPackagesDir"
}
&$repoConfigFile -ThrowOnPendingUpdate -PreRelease -RepositoryPath $repoPath

$nuSpecTemplateFile = $(ls $TempBuildPackagesDir -Recurse | ?{$_.Name -eq 'NaosNuSpecTemplate.template-nuspec'}).FullName
Push-AppveyorArtifact $nuSpecTemplateFile

$nugetFunctionsScriptPath = $(ls $TempBuildPackagesDir -Recurse | ?{$_.Name -eq 'NuGet-Functions.ps1'}).FullName

. $nugetFunctionsScriptPath

#######################################################################
###     Setup NuGet/Artifact scriptblocks                           ###
#######################################################################
$nugetScriptblock = { param([string] $fileName)
   Write-Host "Pushing $fileName to Build Artifacts"
   Push-AppveyorArtifact $fileName

   Write-Host "Pushing $fileName to AppVeyor Gallery"
   Nuget-PublishPackage -packagePath $fileName -apiUrl $nugetUrl -apiKey $nugetKey

   Write-Host "Pushing $fileName to MyGet Gallery"
   Nuget-PublishPackage -packagePath $fileName -apiUrl $mygetUrl -apiKey $mygetKey
}

$artifactScriptBlock = { param([string] $fileName)
   Write-Host "Pushing $fileName to Build Artifacts"
   Push-AppveyorArtifact $fileName
}

#######################################################################
###     Setup Prerequistes and run build                            ###
#######################################################################
&$artifactScriptBlock($nuSpecTemplateFile)

$customMsBuildLogger = 'C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll'

$buildScript = Join-Path (Join-Path (ls $TempBuildPackagesDir/Naos.Powershell.Build.*).FullName 'scripts') 'Build.ps1'

&$buildScript -Version $buildVersion -SourceDirectory (Resolve-Path '.') -BuildPackagesDirectory $TempBuildPackagesDir -PackagesOutputDirectory (Resolve-Path '.') -BranchName $branchName -GalleryUrl $appveyorNugetUrl -PackageUpdateStrategyPrivateGallery $appveyorNugetUpdateStrategyPrivate -PackageUpdateStrategyPublicGallery $appveyorNugetUpdateStrategyPublic -TreatBuildWarningsAsErrors ($treatBuildWarningsAsErrors -eq 'true') -RunCodeAnalysis ($runCodeAnalysis -eq 'true') -NuSpecTemplateFilePath $nuSpecTemplateFile -Authors 'Naos Project' -PushNuGetPackageFile $nugetScriptblock -SaveFileAsBuildArtifact $artifactScriptBlock -CustomMsBuildLogger $customMsBuildLogger -Run


text:
class FakeUpload
  attr_accessor :file, :original_filename

  def initialize(file)
    @file = file
    @original_filename = File.basename file
  end

  def tempfile
    open(@file)
  end
end


text:
/**
 *
 * Process Editor
 *
 * (C) 2009, 2010 inubit AG
 * (C) 2014 the authors
 *
 */
package com.inubit.research.validation;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.frapu.code.visualization.ProcessModel;
import net.frapu.code.visualization.ProcessObject;
import org.xml.sax.SAXException;

/**
 *
 * @author tmi
 */
public class Validator {
    private ProcessModel model;
    private List<ValidationMessage> messages = null;
    private static Map<Class<? extends ProcessModel>, ModelValidator> supportedModels = new HashMap<Class<? extends ProcessModel>, ModelValidator>();

    @SuppressWarnings("CallToThreadDumpStack")
    public Validator(ProcessModel model, Map<Class<? extends ProcessModel>, ModelValidator> supportedModels) {
        this.model = model;
        this.supportedModels = supportedModels;
    }

    public List<ValidationMessage> getAllMessages() {
        if(messages == null) performCheck();
        return messages;
    }

    public List<ValidationMessage> getMessages(boolean errors, boolean warnings,
            boolean infos) {
        int typeBits = 0;
        if (errors) typeBits |= ValidationMessage.TYPE_ERROR;
        if (warnings) typeBits |= ValidationMessage.TYPE_WARNING;
        if (infos) typeBits |= ValidationMessage.TYPE_INFO;
        return getMessagesOfTypes(typeBits);
    }

    public List<ValidationMessage> getErrorMessages() {
        return getMessagesOfTypes(ValidationMessage.TYPE_ERROR);
    }

    public List<ValidationMessage> getWarningMessages() {
        return getMessagesOfTypes(ValidationMessage.TYPE_WARNING);
    }

    public List<ValidationMessage> getInformationMessages() {
        return getMessagesOfTypes(ValidationMessage.TYPE_INFO);
    }

    private List<ValidationMessage> getMessagesOfTypes(int typeBits) {
        if(messages == null) performCheck();
        List<ValidationMessage> selectedMessages =
                        new LinkedList<ValidationMessage>();
        for (ValidationMessage message : messages) {
            if ((message.getType() & typeBits) != 0) {
                selectedMessages.add(message);
            }
        }
        return selectedMessages;
    }

    public void performCheck() {
        messages = new LinkedList<ValidationMessage>();
        if (! isSupportedModel()) {

            MessageTexts messageTexts = null;
            try {
                messageTexts = getCommonMessages();
            } catch (IOException ex) {
                Logger.getLogger(Validator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ParserConfigurationException ex) {
                Logger.getLogger(Validator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SAXException ex) {
                Logger.getLogger(Validator.class.getName()).log(Level.SEVERE, null, ex);
            }
            messages.add(new ValidationMessage(ValidationMessage.TYPE_ERROR,
                    messageTexts.getLongText("unsupportedModel"),
                    messageTexts.getShortText("unsupportedModel"),
                    new LinkedList<ProcessObject>()));
            return;
        }
        ModelValidator mvi = supportedModels.get(model.getClass());
        messages = mvi.doValidation(model);
    }

    private boolean isSupportedModel() {
        return supportedModels.containsKey(model.getClass());
    }

    private MessageTexts getCommonMessages() throws IOException, ParserConfigurationException, SAXException {
        InputStream stream = this.getClass().getResourceAsStream("/validation-messages.xml");
        return new MessageTexts(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream));
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using FlatMate.Module.Common.Api;

namespace FlatMate.Module.Common
{
    public static class PartialListExtension
    {
        public static PartialList<TOut> MapTo<T, TOut>(this PartialList<T> partialList, Func<T, TOut> mapFunc)
        {
            return new PartialList<TOut>(partialList.Items.Select(mapFunc), partialList.Limit, partialList.Offset, partialList.Total);
        }
    }

    public class PartialList<T>
    {
        public PartialList(IEnumerable<T> items, int limit, int offset, int total)
        {
            Items = items;
            Limit = limit;
            Offset = offset;
            Total = total;
        }

        public PartialList(IEnumerable<T> items, PartialListParameter parameter, int total)
        {
            Items = items;
            Limit = parameter.Limit;
            Offset = parameter.Offset;
            Total = total;
        }

        public IEnumerable<T> Items { get; }

        public int Limit { get; }

        public int Offset { get; }

        public int Total { get; }
    }
}


text:
/**************************************************
 * Created by nanyuantingfeng on 2018/8/6 11:51.
 **************************************************/

const path = require('path');

module.exports = function getCWDPackageVersion() {
  const p = path.join(process.cwd(), 'package.json');
  const obj = require(p);

  if (obj && obj.version) {
    return obj.version;
  }

  return null;
};


text:
""" discover and run doctests in modules and test files."""

import pytest, py
from _pytest.python import FixtureRequest, FuncFixtureInfo
from py._code.code import TerminalRepr, ReprFileLocation

def pytest_addoption(parser):
    group = parser.getgroup("collect")
    group.addoption("--doctest-modules",
        action="store_true", default=False,
        help="run doctests in all .py modules",
        dest="doctestmodules")
    group.addoption("--doctest-glob",
        action="store", default="test*.txt", metavar="pat",
        help="doctests file matching pattern, default: test*.txt",
        dest="doctestglob")

def pytest_collect_file(path, parent):
    config = parent.config
    if path.ext == ".py":
        if config.option.doctestmodules:
            return DoctestModule(path, parent)
    elif (path.ext in ('.txt', '.rst') and parent.session.isinitpath(path)) or \
        path.check(fnmatch=config.getvalue("doctestglob")):
        return DoctestTextfile(path, parent)

class ReprFailDoctest(TerminalRepr):
    def __init__(self, reprlocation, lines):
        self.reprlocation = reprlocation
        self.lines = lines
    def toterminal(self, tw):
        for line in self.lines:
            tw.line(line)
        self.reprlocation.toterminal(tw)

class DoctestItem(pytest.Item):
    def repr_failure(self, excinfo):
        doctest = py.std.doctest
        if excinfo.errisinstance((doctest.DocTestFailure,
                                  doctest.UnexpectedException)):
            doctestfailure = excinfo.value
            example = doctestfailure.example
            test = doctestfailure.test
            filename = test.filename
            if test.lineno is None:
                lineno = None
            else:
                lineno = test.lineno + example.lineno + 1
            message = excinfo.type.__name__
            reprlocation = ReprFileLocation(filename, lineno, message)
            checker = py.std.doctest.OutputChecker()
            REPORT_UDIFF = py.std.doctest.REPORT_UDIFF
            filelines = py.path.local(filename).readlines(cr=0)
            lines = []
            if lineno is not None:
                i = max(test.lineno, max(0, lineno - 10)) # XXX?
                for line in filelines[i:lineno]:
                    lines.append("%03d %s" % (i+1, line))
                    i += 1
            else:
                lines.append('EXAMPLE LOCATION UNKNOWN, not showing all tests of that example')
                indent = '>>>'
                for line in example.source.splitlines():
                    lines.append('??? %s %s' % (indent, line))
                    indent = '...'
            if excinfo.errisinstance(doctest.DocTestFailure):
                lines += checker.output_difference(example,
                        doctestfailure.got, REPORT_UDIFF).split("\n")
            else:
                inner_excinfo = py.code.ExceptionInfo(excinfo.value.exc_info)
                lines += ["UNEXPECTED EXCEPTION: %s" %
                            repr(inner_excinfo.value)]
                lines += py.std.traceback.format_exception(*excinfo.value.exc_info)
            return ReprFailDoctest(reprlocation, lines)
        else:
            return super(DoctestItem, self).repr_failure(excinfo)

    def reportinfo(self):
        return self.fspath, None, "[doctest]"

class DoctestTextfile(DoctestItem, pytest.File):
    def runtest(self):
        doctest = py.std.doctest
        # satisfy `FixtureRequest` constructor...
        self.funcargs = {}
        self._fixtureinfo = FuncFixtureInfo((), [], {})
        fixture_request = FixtureRequest(self)
        failed, tot = doctest.testfile(
            str(self.fspath), module_relative=False,
            optionflags=doctest.ELLIPSIS,
            extraglobs=dict(getfixture=fixture_request.getfuncargvalue),
            raise_on_error=True, verbose=0)

class DoctestModule(DoctestItem, pytest.File):
    def runtest(self):
        doctest = py.std.doctest
        if self.fspath.basename == "conftest.py":
            module = self.config._conftest.importconftest(self.fspath)
        else:
            module = self.fspath.pyimport()
        # satisfy `FixtureRequest` constructor...
        self.funcargs = {}
        self._fixtureinfo = FuncFixtureInfo((), [], {})
        fixture_request = FixtureRequest(self)
        failed, tot = doctest.testmod(
            module, raise_on_error=True, verbose=0,
            extraglobs=dict(getfixture=fixture_request.getfuncargvalue),
            optionflags=doctest.ELLIPSIS)


text:
import DevicesView from 'device_manager/view/DevicesView';
import Devices from 'device_manager/model/Devices';
import { Model } from 'backbone';

describe('DevicesView', () => {
  var model;
  var view;
  var editorModel;
  var em;

  beforeEach(() => {
    model = new Devices([]);
    view = new DevicesView({
      collection: model,
      config: { em: new Model() },
    });
    document.body.innerHTML = '

';
    document.body.querySelector('#fixtures').appendChild(view.render().el);
  });

  afterEach(() => {
    view.collection.reset();
  });

  test('The content is not empty', () => {
    expect(view.el.innerHTML).toBeTruthy();
  });

  test('No options without devices', () => {
    expect(view.getOptions()).toEqual('');
  });

  test('Render new button', () => {
    view.collection.add({});
    expect(view.$el.html()).toBeTruthy();
  });

  describe('With configs', () => {
    beforeEach(() => {
      editorModel = new Model();
      model = new Devices([{ name: 'test1' }, { name: 'test2' }]);
      view = new DevicesView({
        collection: model,
        config: { em: editorModel },
      });
      document.body.innerHTML = '

';
      document.body.querySelector('#fixtures').appendChild(view.render().el);
    });

    test('Update device on select change', () => {
      view.$el.find('select').val('test2');
      view.updateDevice();
      expect(view.config.em.get('device')).toEqual('test2');
    });

    test('Render options', () => {
      expect(view.getOptions()).toEqual('<option value="test1">test1</option><option value="test2">test2</option>');
    });
  });
});


text:
class Solution(object):
    def twoSum_slow(self, numbers, target):
        left, right = 0, len(numbers) - 1

        while left < right:
            num = numbers[left] + numbers[right]

            if num == target:
                return [left + 1, right + 1]
            elif num < target:
                left += 1
            elif num > target:
                right -= 1

    def twoSum_slowest(self, numbers, target):
        for i in range(len(numbers)):
            left, right = i + 1, len(numbers) - 1
            tmp = target - numbers[i]
            while left <= right:
                mid = (left + right) // 2
                if numbers[mid] == tmp:
                    return [i + 1, mid + 1]
                elif tmp < numbers[mid]:
                    right = mid - 1
                elif tmp > numbers[mid]:
                    left = mid + 1

    # dictionary
    def twoSum(self, numbers, target):
        dic = {}
        for i, num in enumerate(numbers):
            if target-num in dic:
                return [dic[target-num]+1, i+1]
            dic[num] = i


text:
FactoryGirl.define do
  factory :menu do

  end

end


text:
(function() {

  window.SettingsViewModel = function() {
    this.list_filter_mode = ko.observable('');
    return this;
  };

}).call(this);


text:
@interface PodsDummy_JSSideSlipMenu : NSObject
@end
@implementation PodsDummy_JSSideSlipMenu
@end


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>com.rallydev.rest.client (Rally Rest API for Java 2.1)</title>
<meta name="date" content="2014-07-07">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Package

Next Package

Frames

No Frames

All Classes

Package com.rallydev.rest.client

Provides the underlying http client implementations.

See: Description

Class Summary

Class
Description

ApiKeyClient

A HttpClient which authenticates using an API Key.

BasicAuthClient

A HttpClient which authenticates using basic authentication (username/password).

HttpClient

A HttpClient implementation providing connectivity to Rally.

Package com.rallydev.rest.client Description

Provides the underlying http client implementations.

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Package

Next Package

Frames

No Frames

All Classes


text:
describe CriteriaController do
  let(:admin) { create :admin }
  let(:assignment) { create :assignment }
  let(:grouping) { create :grouping, assignment: assignment }
  let(:submission) { create :submission, grouping: grouping }

  shared_examples 'callbacks' do
    before :each do
      @assignment = create(:assignment_with_criteria_and_results)
      @crit = create(criterion, assignment: assignment, max_mark: 3.0)
      @assignment.groupings.each do |grouping|
        create(:mark, result: grouping.current_result, mark: @crit.max_mark, criterion: @crit)
      end
    end
    describe 'An authenticated and authorized admin doing a DELETE' do
      it 'should update the relevant assignment\'s stats' do
        old_average = @assignment.results_average
        old_median = @assignment.results_median
        delete_as admin,
                  :destroy,
                  params: { assignment_id: @assignment.id, id: @crit.id },
                  format: :js
        assignment.reload
        expect(@assignment.results_median).to be >= old_median
        expect(@assignment.results_average).to be >= old_average
      end
    end
    context 'when changing the bonus' do
      it 'should be able to update the bonus value' do
        get_as admin,
               :update,
               params: { assignment_id: @assignment.id, id: @crit.id,
                         criterion => { name: 'one', bonus: true } },
               format: :js
        expect(@crit.reload.bonus).to be true
      end

      it 'should update the relevant assignment\'s stats' do
        old_average = @assignment.results_average
        old_median = @assignment.results_median
        get_as admin,
               :update,
               params: { assignment_id: @assignment.id, id: @crit.id,
                         criterion => { name: 'one', bonus: true } },
               format: :js
        @assignment.reload
        expect(@assignment.results_median).to be >= old_median
        expect(@assignment.results_average).to be >= old_average
      end
    end
  end

  describe 'Using Checkbox Criterion' do
    let(:criterion) { :checkbox_criterion }
    include_examples 'callbacks'
  end

  describe 'Using Flexible Criteria' do
    let(:criterion) { :flexible_criterion }
    include_examples 'callbacks'

    let(:flexible_criterion) do
      create(:flexible_criterion,
             assignment: assignment,
             position: 1,
             name: 'Flexible Criterion')
    end
    let(:flexible_criterion2) do
      create(:flexible_criterion,
             assignment: assignment,
             position: 2,
             name: 'Flexible Criterion 2')
    end
    describe 'An unauthenticated and unauthorized user doing a GET' do
      context '#index' do
        it 'should respond with redirect' do
          get :index, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#new' do
        it 'should respond with redirect' do
          get :new, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#edit' do
        it 'should respond with redirect' do
          get :edit, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#update' do
        it 'should respond with redirect' do
          put :update, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#destroy' do
        it 'should respond with redirect' do
          delete :destroy, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#update_positions' do
        it 'should respond with redirect' do
          get :update_positions, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context 'with an assignment' do
        context 'and a submission' do
          context '#edit' do
            it 'should respond with redirect' do
              get :edit, params: { assignment_id: assignment.id, submission_id: submission.id, id: 1 }
              is_expected.to respond_with :redirect
            end
          end
        end
      end

      context '#download' do
        it 'should respond with redirect' do
          get :download, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end
    end

    describe 'An unauthenticated and unauthorized user doing a POST' do
      context '#index' do
        it 'should respond with redirect' do
          post :index, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#new' do
        it 'should respond with redirect' do
          post :new, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#update' do
        it 'should respond with redirect' do
          put :update, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#edit' do
        it 'should respond with redirect' do
          post :edit, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#destroy' do
        it 'should respond with redirect' do
          delete :destroy, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end
    end

    describe 'An authenticated and authorized admin doing a GET' do
      context '#index' do
        before(:each) do
          get_as admin, :index, params: { assignment_id: assignment.id }
        end
        it 'should respond assign assignment and criteria' do
          expect(assigns(:assignment)).to be_truthy
          expect(assigns(:criteria)).to be_truthy
        end

        it 'should render the edit template' do
          is_expected.to render_template(:index)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#new' do
        before(:each) do
          get_as admin,
                 :new,
                 params: { assignment_id: assignment.id },
                 format: :js
        end

        it 'should respond with appropriate content' do
          expect(assigns(:assignment)).to be_truthy
        end

        it 'should render the new template' do
          is_expected.to render_template(:new)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#edit' do
        before(:each) do
          get_as admin,
                 :edit,
                 params: { assignment_id: 1, id: flexible_criterion.id },
                 format: :js
        end

        it 'should respond with appropriate content' do
          expect(assigns(:criterion)).to be_truthy
        end

        it 'should render edit template' do
          is_expected.to render_template(:edit)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#update' do
        context 'with errors' do
          before(:each) do
            expect_any_instance_of(FlexibleCriterion).to receive(:save).and_return(false)
            expect_any_instance_of(FlexibleCriterion).to(
              receive(:errors).and_return(ActiveModel::Errors.new(flexible_criterion))
            )

            get_as admin,
                   :update,
                   params: { assignment_id: 1, id: flexible_criterion.id,
                             flexible_criterion: { name: 'one', max_mark: 10 } },
                   format: :js
          end

          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
          end

          it 'should respond with unprocessable entity' do
            is_expected.to respond_with(:unprocessable_entity)
          end
        end

        context 'without errors' do
          before(:each) do
            get_as admin,
                   :update,
                   params: { assignment_id: 1, id: flexible_criterion.id,
                             flexible_criterion: { name: 'one', max_mark: 10 } },
                   format: :js
          end

          it 'successfully assign criterion' do
            expect(assigns(:criterion)).to be_truthy
          end

          it 'should render the update template' do
            is_expected.to render_template(:update)
          end
        end
      end
    end

    describe 'An authenticated and authorized admin doing a POST' do
      context '#index' do
        before(:each) do
          post_as admin, :index, params: { assignment_id: assignment.id }
        end
        it 'should respond with appropriate content' do
          expect(assigns(:assignment)).to be_truthy
          expect(assigns(:criteria)).to be_truthy
        end

        it 'should render the index template' do
          is_expected.to render_template(:index)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#create' do
        context 'with save error' do
          before(:each) do
            expect_any_instance_of(FlexibleCriterion).to receive(:save).and_return(false)
            expect_any_instance_of(FlexibleCriterion).to receive(:errors).and_return(ActiveModel::Errors.new(self))
            post_as admin,
                    :create,
                    params: { assignment_id: assignment.id, flexible_criterion: { name: 'first', max_mark: 10 },
                              new_criterion_prompt: 'first', criterion_type: 'FlexibleCriterion' },
                    format: :js
          end
          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
            expect(assigns(:assignment)).to be_truthy
          end

          it 'should respond with unprocessable entity' do
            is_expected.to respond_with(:unprocessable_entity)
          end
        end

        context 'without error on an assignment as the first criterion' do
          before(:each) do
            post_as admin,
                    :create,
                    params: { assignment_id: assignment.id, flexible_criterion: { name: 'first' },
                              new_criterion_prompt: 'first', criterion_type: 'FlexibleCriterion', max_mark_prompt: 10 },
                    format: :js
          end
          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
            expect(assigns(:assignment)).to be_truthy
          end
          it 'should render the create template' do
            is_expected.to render_template(:'criteria/create')
          end

          it 'should respond with success' do
            is_expected.to respond_with(:success)
          end
        end

        context 'without error on an assignment that already has criteria' do
          before(:each) do
            post_as admin,
                    :create,
                    params: { assignment_id: assignment.id, flexible_criterion: { name: 'first' },
                              new_criterion_prompt: 'first', criterion_type: 'FlexibleCriterion', max_mark_prompt: 10 },
                    format: :js
          end
          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
            expect(assigns(:assignment)).to be_truthy
          end
          it 'should render the create template' do
            is_expected.to render_template(:'criteria/create')
          end

          it 'should respond with success' do
            is_expected.to respond_with(:success)
          end
        end
      end

      context '#edit' do
        before(:each) do
          post_as admin,
                  :edit,
                  params: { assignment_id: 1, id: flexible_criterion.id },
                  format: :js
        end

        it ' should respond with appropriate content' do
          expect(assigns(:criterion)).to be_truthy
        end

        it 'should render the edit template' do
          is_expected.to render_template(:edit)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      it 'should be able to update_positions' do
        post_as admin,
                :update_positions,
                params: { criterion: [flexible_criterion2.id, flexible_criterion.id],
                          assignment_id: assignment.id },
                format: :js
        is_expected.to render_template('criteria/update_positions')
        is_expected.to respond_with(:success)

        c1 = FlexibleCriterion.find(flexible_criterion.id)
        expect(c1.position).to eql(2)
        c2 = FlexibleCriterion.find(flexible_criterion2.id)
        expect(c2.position).to eql(1)
      end
    end

    describe 'An authenticated and authorized admin doing a DELETE' do
      it ' should be able to delete the criterion' do
        delete_as admin,
                  :destroy,
                  params: { assignment_id: 1, id: flexible_criterion.id },
                  format: :js
        expect(assigns(:criterion)).to be_truthy
        i18t_strings = [I18n.t('flash.criteria.destroy.success')].map { |f| extract_text f }
        expect(i18t_strings).to eql(flash[:success].map { |f| extract_text f })
        is_expected.to respond_with(:success)

        expect { FlexibleCriterion.find(flexible_criterion.id) }.to raise_error(ActiveRecord::RecordNotFound)
      end
    end
  end

  describe 'Using Rubric Criteria' do
    let(:criterion) { :rubric_criterion }
    include_examples 'callbacks'

    let(:rubric_criterion) do
      create(:rubric_criterion,
             assignment: assignment,
             position: 1,
             name: 'Rubric Criterion')
    end
    let(:rubric_criterion2) do
      create(:rubric_criterion,
             assignment: assignment,
             position: 2,
             name: 'Rubric Criterion 2')
    end
    describe 'An unauthenticated and unauthorized user doing a GET' do
      context '#index' do
        it 'should respond with redirect' do
          get :index, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#new' do
        it 'should respond with redirect' do
          get :new, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#edit' do
        it 'should respond with redirect' do
          get :edit, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end

        context 'with an assignment' do
          context 'and a submission' do
            context '#edit' do
              it 'should respond with redirect' do
                get :edit, params: { assignment_id: assignment.id, submission_id: submission.id, id: 1 }
                is_expected.to respond_with :redirect
              end
            end
          end
        end
      end

      context '#destroy' do
        it 'should respond with redirect' do
          delete :destroy, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#update' do
        it 'should respond with redirect' do
          put :update, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#update_positions' do
        it 'should respond with redirect' do
          get :update_positions, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#download' do
        it 'should respond with redirect' do
          get :download, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end
    end

    describe 'An unauthenticated and unauthorized user doing a POST' do
      context '#index' do
        it 'should respond with redirect' do
          post :index, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#new' do
        it 'should respond with redirect' do
          post :new, params: { assignment_id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#edit' do
        it 'should respond with redirect' do
          post :edit, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#update' do
        it 'should respond with redirect' do
          put :update, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end

      context '#destroy' do
        it 'should respond with redirect' do
          delete :destroy, params: { assignment_id: 1, id: 1 }
          is_expected.to respond_with :redirect
        end
      end
    end

    describe 'An authenticated and authorized admin doing a GET' do
      context '#index' do
        before(:each) do
          get_as admin, :index, params: { assignment_id: assignment.id }
        end
        it 'should respond assign assignment and criteria' do
          expect(assigns(:assignment)).to be_truthy
          expect(assigns(:criteria)).to be_truthy
        end

        it 'should render the edit template' do
          is_expected.to render_template(:index)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#new' do
        before(:each) do
          get_as admin,
                 :new,
                 params: { assignment_id: assignment.id },
                 format: :js
        end

        it 'should respond with appropriate content' do
          expect(assigns(:assignment)).to be_truthy
        end

        it 'should render the new template' do
          is_expected.to render_template(:new)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#edit' do
        before(:each) do
          get_as admin,
                 :edit,
                 params: { assignment_id: 1, id: rubric_criterion.id },
                 format: :js
        end

        it 'should respond with appropriate content' do
          expect(assigns(:criterion)).to be_truthy
        end

        it 'should render edit template' do
          is_expected.to render_template(:edit)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#update' do
        context 'with errors' do
          before(:each) do
            expect_any_instance_of(RubricCriterion).to receive(:save).and_return(false)
            expect_any_instance_of(RubricCriterion).to(
              receive(:errors).and_return(ActiveModel::Errors.new(rubric_criterion))
            )
            get_as admin,
                   :update,
                   params: { assignment_id: 1, id: rubric_criterion.id,
                             rubric_criterion: { name: 'one', max_mark: 10 } },
                   format: :js
          end

          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
          end

          it 'should respond with unprocessable entity' do
            is_expected.to respond_with(:unprocessable_entity)
          end
        end

        context 'without errors' do
          before(:each) do
            get_as admin,
                   :update,
                   params: { assignment_id: 1, id: rubric_criterion.id,
                             rubric_criterion: { name: 'one', max_mark: 10 } },
                   format: :js
          end

          it 'successfully assign criterion' do
            expect(assigns(:criterion)).to be_truthy
          end

          it 'should render the update template' do
            is_expected.to render_template(:update)
          end
        end
      end
    end

    describe 'An authenticated and authorized admin doing a POST' do
      context '#index' do
        before(:each) do
          post_as admin, :index, params: { assignment_id: assignment.id }
        end
        it 'should respond with appropriate content' do
          expect(assigns(:assignment)).to be_truthy
          expect(assigns(:criteria)).to be_truthy
        end

        it 'should render the index template' do
          is_expected.to render_template(:index)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      context '#create' do
        context 'with save error' do
          before(:each) do
            expect_any_instance_of(RubricCriterion).to receive(:save).and_return(false)
            expect_any_instance_of(RubricCriterion).to receive(:errors).and_return(ActiveModel::Errors.new(self))
            post_as admin,
                    :create,
                    params: { assignment_id: assignment.id, max_mark_prompt: 10,
                              new_criterion_prompt: 'first', criterion_type: 'RubricCriterion' },
                    format: :js
          end
          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
            expect(assigns(:assignment)).to be_truthy
          end

          it 'should respond with unprocessable entity' do
            is_expected.to respond_with(:unprocessable_entity)
          end
        end

        context 'without error on an assignment as the first criterion' do
          before(:each) do
            post_as admin,
                    :create,
                    params: { assignment_id: assignment.id,
                              new_criterion_prompt: 'first', criterion_type: 'RubricCriterion', max_mark_prompt: 10 },
                    format: :js
          end
          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
            expect(assigns(:assignment)).to be_truthy
          end
          it 'should render the create template' do
            is_expected.to render_template(:'criteria/create')
          end

          it 'should respond with success' do
            is_expected.to respond_with(:success)
          end
        end

        context 'without error on an assignment that already has criteria' do
          before(:each) do
            post_as admin,
                    :create,
                    params: { assignment_id: assignment.id, rubric_criterion: { name: 'first' },
                              new_criterion_prompt: 'first', criterion_type: 'RubricCriterion', max_mark_prompt: 10 },
                    format: :js
          end
          it 'should respond with appropriate content' do
            expect(assigns(:criterion)).to be_truthy
            expect(assigns(:assignment)).to be_truthy
          end
          it 'should render the create template' do
            is_expected.to render_template(:'criteria/create')
          end

          it 'should respond with success' do
            is_expected.to respond_with(:success)
          end
        end
      end

      context '#edit' do
        before(:each) do
          post_as admin,
                  :edit,
                  params: { assignment_id: 1, id: rubric_criterion.id },
                  format: :js
        end

        it ' should respond with appropriate content' do
          expect(assigns(:criterion)).to be_truthy
        end

        it 'should render the edit template' do
          is_expected.to render_template(:edit)
        end

        it 'should respond with success' do
          is_expected.to respond_with(:success)
        end
      end

      it 'should be able to update_positions' do
        post_as admin,
                :update_positions,
                params: { criterion: [rubric_criterion2.id, rubric_criterion.id],
                          assignment_id: assignment.id },
                format: :js
        is_expected.to render_template('criteria/update_positions')
        is_expected.to respond_with(:success)

        c1 = RubricCriterion.find(rubric_criterion.id)
        expect(c1.position).to eql(2)
        c2 = RubricCriterion.find(rubric_criterion2.id)
        expect(c2.position).to eql(1)
      end
    end

    describe 'An authenticated and authorized admin doing a DELETE' do
      it ' should be able to delete the criterion' do
        delete_as admin,
                  :destroy,
                  params: { assignment_id: 1, id: rubric_criterion.id },
                  format: :js
        expect(assigns(:criterion)).to be_truthy
        i18t_string = [I18n.t('flash.criteria.destroy.success')].map { |f| extract_text f }
        expect(i18t_string).to eql(flash[:success].map { |f| extract_text f })
        is_expected.to respond_with(:success)

        expect { RubricCriterion.find(rubric_criterion.id) }.to raise_error(ActiveRecord::RecordNotFound)
      end
    end
  end

  describe 'An authenticated and authorized admin performing yml actions' do
    let!(:rubric_criterion) do
      create(:rubric_criterion,
             assignment: assignment,
             position: 1,
             name: 'Rubric Criterion')
    end
    let!(:flexible_criterion) do
      create(:flexible_criterion,
             assignment: assignment,
             position: 2,
             name: 'Flexible Criterion')
    end
    let!(:checkbox_criterion) do
      create(:checkbox_criterion,
             assignment: assignment,
             position: 3,
             name: 'Checkbox Criterion')
    end
    let(:mixed_file) { fixture_file_upload('files/criteria/upload_yml_mixed.yaml', 'text/yaml') }
    let(:invalid_mixed_file) { fixture_file_upload('files/criteria/upload_yml_mixed_invalid.yaml', 'text/yaml') }
    let(:empty_file) { fixture_file_upload('files/empty_file', 'text/yaml') }
    let(:test_upload_download_file) { fixture_file_upload('files/criteria/criteria_upload_download.yaml', 'text/yaml') }
    let(:expected_download) { fixture_file_upload('files/criteria/download_yml_output.yaml', 'text/yaml') }
    let(:round_max_mark_file) { fixture_file_upload('files/criteria/round_max_mark.yaml', 'text/yaml') }
    let(:partially_valid_file) { fixture_file_upload('files/criteria/partially_valid_file.yaml', 'text/yaml') }
    let(:uploaded_file) { fixture_file_upload('files/criteria/upload_yml_mixed.yaml', 'text/yaml') }
    let(:no_type_file)  { fixture_file_upload('files/criteria/marking_criteria_no_type.yml', 'text/yaml') }

    context 'When a file containing a mixture of entries is uploaded' do

      it 'raises an error if the file does not include any criteria' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: empty_file }

        expect(flash[:error].map { |f| extract_text f })
          .to eq([I18n.t('upload_errors.blank')].map { |f| extract_text f })
      end

      it 'deletes all criteria previously created' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.where(type: 'RubricCriterion').find_by(name: rubric_criterion.name)).to be_nil
        expect(assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: flexible_criterion.name)).to be_nil
        expect(assignment.criteria.where(type: 'CheckboxCriterion').find_by(name: checkbox_criterion.name)).to be_nil
      end

      it 'maintains the order between entries and positions for criteria' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.map { |cr| [cr.name, cr.position] })
          .to match_array([['cr30', 1],
                           ['cr20', 2],
                           ['cr100', 3],
                           ['cr40', 4],
                           ['cr80', 5],
                           ['cr50', 6],
                           ['cr60', 7],
                           ['cr90', 8]])
      end

      it 'creates all criteria with properly formatted entries' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.pluck(:name)).to contain_exactly('cr30',
                                                                    'cr20',
                                                                    'cr100',
                                                                    'cr80',
                                                                    'cr60',
                                                                    'cr90',
                                                                    'cr40',
                                                                    'cr50')
        expect(flash[:success].map { |f| extract_text f })
          .to eq([I18n.t('upload_success', count: 8)].map { |f| extract_text f })
      end

      it 'creates rubric criteria with properly formatted entries' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }
        expect(assignment.criteria.where(type: 'RubricCriterion').pluck(:name)).to contain_exactly('cr30', 'cr90')
        cr1 = assignment.criteria.where(type: 'RubricCriterion').find_by(name: 'cr30')
        expect(cr1.levels.size).to eq(5)
        expect(cr1.max_mark).to eq(5.0)
        expect(cr1.bonus).to be true
        expect(cr1.ta_visible).to be false
        expect(cr1.peer_visible).to be true
        # Since there are only 5 levels in this rubric criterion, if each of the following queries return an entity,
        # then this rubric criterion is properly sat up.
        expect(cr1.levels.find_by(name: 'Beginner', description: 'Fail', mark: 0)).not_to be_nil
        expect(cr1.levels.find_by(name: 'Hmm', description: 'Almost fail', mark: 1)).not_to be_nil
        expect(cr1.levels.find_by(name: 'Average', description: 'Not bad', mark: 2)).not_to be_nil
        expect(cr1.levels.find_by(name: 'Good', description: 'Alright', mark: 3)).not_to be_nil
        expect(cr1.levels.find_by(name: 'Excellent', description: 'Impressive', mark: 5)).not_to be_nil

        cr2 = assignment.criteria.where(type: 'RubricCriterion').find_by(name: 'cr90')
        expect(cr2.max_mark).to eq(4.6)
        expect(cr2.levels.size).to eq(5)
        expect(cr2.ta_visible).to be true
        expect(cr2.peer_visible).to be false
        expect(cr2.bonus).to be false
      end

      it 'creates flexible criteria with properly formatted entries' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.where(type: 'FlexibleCriterion').pluck(:name))
          .to contain_exactly('cr20', 'cr50', 'cr80', 'cr60')

        cr80 = assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr80')
        expect(cr80.max_mark).to eq(10.0)
        expect(cr80.description).to eq('')
        expect(cr80.ta_visible).to be true
        expect(cr80.peer_visible).to be true
        expect(cr80.bonus).to be false

        cr20 = assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr20')
        expect(cr20.max_mark).to eq(2.0)
        expect(cr20.description).to eq('I am flexible')
        expect(cr20.ta_visible).to be true
        expect(cr20.peer_visible).to be true
        expect(cr20.bonus).to be false

        cr50 = assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr50')
        expect(cr50.bonus).to be true
        expect(cr50.max_mark).to eq(1.0)
        expect(cr50.description).to eq('Another flexible.')
        expect(cr50.ta_visible).to be true
        expect(cr50.peer_visible).to be false

        cr60 = assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr60')
        expect(cr60.max_mark).to eq(10.0)
        expect(cr60.description).to eq('')
        expect(cr60.ta_visible).to be true
        expect(cr60.peer_visible).to be false
        expect(cr60.bonus).to be false
      end

      it 'creates checkbox criteria with properly formatted entries' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.where(type: 'CheckboxCriterion').pluck(:name)).to contain_exactly('cr100', 'cr40')
        cr1 = assignment.criteria.where(type: 'CheckboxCriterion').find_by(name: 'cr100')
        expect(cr1.bonus).to be true
        expect(cr1.max_mark).to eq(5.0)
        expect(cr1.description).to eq('I am checkbox')
        expect(cr1.ta_visible).to be true
        expect(cr1.peer_visible).to be false
      end

      it 'creates criteria being case insensitive with the type given' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.where(type: 'FlexibleCriterion').pluck(:name))
          .to contain_exactly('cr20', 'cr80', 'cr60', 'cr50')
      end

      it 'creates criteria that lack a description' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }

        expect(assignment.criteria.where(type: 'FlexibleCriterion').pluck(:name)).to include('cr80')
        expect(assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr80').description).to eq('')
      end

      it 'creates criteria with the default visibility options if these are not given in the entries' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: mixed_file }
        expect(assignment.criteria.pluck(:name)).to include('cr100', 'cr60')
        expect(assignment.criteria.where(type: 'CheckboxCriterion').find_by(name: 'cr100').ta_visible).to be true
        expect(assignment.criteria.where(type: 'CheckboxCriterion').find_by(name: 'cr100').peer_visible).to be false
        expect(assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr60').ta_visible).to be true
        expect(assignment.criteria.where(type: 'FlexibleCriterion').find_by(name: 'cr60').peer_visible).to be false
      end

      it 'creates criteria with rounded (up to first digit after decimal point) maximum mark' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: round_max_mark_file }
        expect(assignment.criteria.where(type: 'RubricCriterion').first.name).to eq('cr90')

        expect(assignment.criteria.where(type: 'RubricCriterion').first.max_mark).to eq(4.6)
      end
      it 'does not create criteria with format errors in entries' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: invalid_mixed_file }

        expect(assignment.criteria.pluck(:name)).not_to include('cr40', 'cr50', 'cr70')
        expect(flash[:error].map { |f| extract_text f })
          .to eq([I18n.t('criteria.errors.invalid_format') + ' cr40, cr70, cr50'].map { |f| extract_text f })
      end

      it 'does not create criteria with an invalid mark' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: invalid_mixed_file }

        expect(assignment.criteria.pluck(:name)).not_to include('cr40', 'cr50')
      end

      it 'does not create criteria that have both visibility options set to false' do
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: invalid_mixed_file }

        expect(assignment.criteria.pluck(:name)).not_to include('cr70')
      end

      it 'does not create criteria that have unmatched keys / more keys than required' do
        expect(assignment.criteria.where(type: 'RubricCriterion').length).to eq(1)
        post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: partially_valid_file }
        expect(assignment.criteria.where(type: 'RubricCriterion').length).to eq(1)
        expect(flash[:error]).not_to be_nil
      end

      context 'when there is no type specified for one of the criteria' do
        it 'flashes an error message' do
          post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: no_type_file }
          expect(flash[:error]).not_to be_nil
        end
      end

      context 'When some criteria have been previously uploaded and and admin performs a download' do
        it 'responds with appropriate status' do
          post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: uploaded_file }

          get :download, params: { assignment_id: assignment.id }

          expect(response.status).to eq(200)
        end

        it 'sends the correct information' do
          post_as admin, :upload, params: { assignment_id: assignment.id, upload_file: test_upload_download_file }
          get :download, params: { assignment_id: assignment.id }

          expect(YAML.safe_load(response.body, [Symbol], symbolize_names: true))
            .to eq(YAML.safe_load(expected_download.read, symbolize_names: true))
        end
      end
    end
  end

  context '#upload' do
    include_examples 'a controller supporting upload', formats: [:yml] do
      let(:params) { { assignment_id: assignment.id } }
    end
  end
end