text:
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;

using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack.LindenUDP;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenSim.Services.Connectors.Hypergrid;

using OpenMetaverse;
using OpenMetaverse.Packets;
using log4net;
using Nini.Config;
using Mono.Addins;

using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;

namespace OpenSim.Region.CoreModules.Framework.UserManagement
{
    [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
    public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople
    {
        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        protected bool m_Enabled;
        protected List<Scene> m_Scenes = new List<Scene>();

        protected IServiceThrottleModule m_ServiceThrottle;
        // The cache
        protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();

        protected bool m_DisplayChangingHomeURI = false;

        #region ISharedRegionModule

        public virtual void Initialise(IConfigSource config)
        {
            string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name);
            if (umanmod == Name)
            {
                m_Enabled = true;
                Init();
                m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
            }

            if(!m_Enabled)
            {
                return;
            }

            IConfig userManagementConfig = config.Configs["UserManagement"];
            if (userManagementConfig == null)
                return;

            m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false);
        }

        public virtual bool IsSharedModule
        {
            get { return true; }
        }

        public virtual string Name
        {
            get { return "BasicUserManagementModule"; }
        }

        public virtual Type ReplaceableInterface
        {
            get { return null; }
        }

        public virtual void AddRegion(Scene scene)
        {
            if (m_Enabled)
            {
                lock (m_Scenes)
                {
                    m_Scenes.Add(scene);
                }

                scene.RegisterModuleInterface<IUserManagement>(this);
                scene.RegisterModuleInterface<IPeople>(this);
                scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
                scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
            }
        }

        public virtual void RemoveRegion(Scene scene)
        {
            if (m_Enabled)
            {
                scene.UnregisterModuleInterface<IUserManagement>(this);
                lock (m_Scenes)
                {
                    m_Scenes.Remove(scene);
                }
            }
        }

        public virtual void RegionLoaded(Scene s)
        {
            if (m_Enabled && m_ServiceThrottle == null)
                m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
        }

        public virtual void PostInitialise()
        {
        }

        public virtual void Close()
        {
            lock (m_Scenes)
            {
                m_Scenes.Clear();
            }

            lock (m_UserCache)
                m_UserCache.Clear();
        }

        #endregion ISharedRegionModule

        #region Event Handlers

        protected virtual void EventManager_OnPrimsLoaded(Scene s)
        {
            // let's sniff all the user names referenced by objects in the scene
            m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
            s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
        }

        protected virtual void EventManager_OnNewClient(IClientAPI client)
        {
            client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed);
            client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest);
            client.OnAvatarPickerRequest += new AvatarPickerRequest(HandleAvatarPickerRequest);
        }

        protected virtual void HandleConnectionClosed(IClientAPI client)
        {
            client.OnNameFromUUIDRequest -= new UUIDNameRequest(HandleUUIDNameRequest);
            client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
            client.OnConnectionClosed -= new Action<IClientAPI>(HandleConnectionClosed);
        }

        protected virtual void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
        {
//            m_log.DebugFormat(
//                "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
//                uuid, remote_client.Name);
            if(m_Scenes.Count <= 0)
                return;

            if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
            {
                client.SendNameReply(uuid, "Mr", "OpenSim");
            }
            else
            {
                UserData user;
                /* bypass that continuation here when entry is already available */
                lock (m_UserCache)
                {
                    if (m_UserCache.TryGetValue(uuid, out user))
                    {
                        if (!user.IsUnknownUser && user.HasGridUserTried)
                        {
                            client.SendNameReply(uuid, user.FirstName, user.LastName);
                            return;
                        }
                    }
                }

                // Not found in cache, queue continuation
                m_ServiceThrottle.Enqueue("uuidname", uuid.ToString(),  delegate
                {
                    //m_log.DebugFormat("[YYY]: Name request {0}", uuid);

                    // As least upto September 2013, clients permanently cache UUID -> Name bindings.  Some clients
                    // appear to clear this when the user asks it to clear the cache, but others may not.
                    //
                    // So to avoid clients
                    // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
                    // instead drop the request entirely.
                    if(!client.IsActive)
                        return;
                    if (GetUser(uuid, out user))
                    {
                        if(client.IsActive)
                            client.SendNameReply(uuid, user.FirstName, user.LastName);
                    }
//                    else
//                        m_log.DebugFormat(
//                            "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
//                            uuid, client.Name);
                });
            }
        }

        public virtual void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
        {
            //EventManager.TriggerAvatarPickerRequest();

            m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);

            List<UserData> users = GetUserData(query, 500, 1);

            AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
            // TODO: don't create new blocks if recycling an old packet

            AvatarPickerReplyPacket.DataBlock[] searchData =
                new AvatarPickerReplyPacket.DataBlock[users.Count];
            AvatarPickerReplyPacket.AgentDataBlock agentData = new AvatarPickerReplyPacket.AgentDataBlock();

            agentData.AgentID = avatarID;
            agentData.QueryID = RequestID;
            replyPacket.AgentData = agentData;
            //byte[] bytes = new byte[AvatarResponses.Count*32];

            int i = 0;
            foreach (UserData item in users)
            {
                UUID translatedIDtem = item.Id;
                searchData[i] = new AvatarPickerReplyPacket.DataBlock();
                searchData[i].AvatarID = translatedIDtem;
                searchData[i].FirstName = Utils.StringToBytes((string)item.FirstName);
                searchData[i].LastName = Utils.StringToBytes((string)item.LastName);
                i++;
            }
            if (users.Count == 0)
            {
                searchData = new AvatarPickerReplyPacket.DataBlock[0];
            }
            replyPacket.Data = searchData;

            AvatarPickerReplyAgentDataArgs agent_data = new AvatarPickerReplyAgentDataArgs();
            agent_data.AgentID = replyPacket.AgentData.AgentID;
            agent_data.QueryID = replyPacket.AgentData.QueryID;

            List<AvatarPickerReplyDataArgs> data_args = new List<AvatarPickerReplyDataArgs>();
            for (i = 0; i < replyPacket.Data.Length; i++)
            {
                AvatarPickerReplyDataArgs data_arg = new AvatarPickerReplyDataArgs();
                data_arg.AvatarID = replyPacket.Data[i].AvatarID;
                data_arg.FirstName = replyPacket.Data[i].FirstName;
                data_arg.LastName = replyPacket.Data[i].LastName;
                data_args.Add(data_arg);
            }
            client.SendAvatarPickerReply(agent_data, data_args);
        }

        protected virtual void AddAdditionalUsers(string query, List<UserData> users)
        {
        }

        #endregion Event Handlers

        #region IPeople

        public virtual List<UserData> GetUserData(string query, int page_size, int page_number)
        {
             if(m_Scenes.Count <= 0)
                return new List<UserData>();;

            // search the user accounts service
            List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);

            List<UserData> users = new List<UserData>();
            if (accs != null)
            {
                foreach (UserAccount acc in accs)
                {
                    UserData ud = new UserData();
                    ud.FirstName = acc.FirstName;
                    ud.LastName = acc.LastName;
                    ud.Id = acc.PrincipalID;
                    ud.HasGridUserTried = true;
                    ud.IsUnknownUser = false;
                    users.Add(ud);
                }
            }

            // search the local cache
            foreach (UserData data in m_UserCache.Values)
            {
                if (data.Id != UUID.Zero && !data.IsUnknownUser &&
                    users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
                    (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
                    users.Add(data);
            }

            AddAdditionalUsers(query, users);

            return users;

        }

        #endregion IPeople

        protected virtual void CacheCreators(SceneObjectGroup sog)
        {
            //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
            AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);

            foreach (SceneObjectPart sop in sog.Parts)
            {
                AddUser(sop.CreatorID, sop.CreatorData);
                foreach (TaskInventoryItem item in sop.TaskInventory.Values)
                    AddUser(item.CreatorID, item.CreatorData);
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="uuid"></param>
        /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
        /// <returns></returns>
        protected virtual bool TryGetUserNames(UUID uuid, string[] names)
        {
            if (names == null)
                names = new string[2];

            if (TryGetUserNamesFromCache(uuid, names))
                return true;

            if (TryGetUserNamesFromServices(uuid, names))
                return true;

            return false;
        }

        protected virtual bool TryGetUserNamesFromCache(UUID uuid, string[] names)
        {
            lock (m_UserCache)
            {
                if (m_UserCache.ContainsKey(uuid))
                {
                    names[0] = m_UserCache[uuid].FirstName;
                    names[1] = m_UserCache[uuid].LastName;

                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Try to get the names bound to the given uuid, from the services.
        /// </summary>
        /// <returns>True if the name was found, false if not.</returns>
        /// <param name='uuid'></param>
        /// <param name='names'>The array of names if found.  If not found, then names[0] = "Unknown" and names[1] = "User"</param>
        protected virtual bool TryGetUserNamesFromServices(UUID uuid, string[] names)
        {
            if(m_Scenes.Count <= 0)
                return false;

            UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);

            if (account != null)
            {
                names[0] = account.FirstName;
                names[1] = account.LastName;

                UserData user = new UserData();
                user.FirstName = account.FirstName;
                user.LastName = account.LastName;

                lock (m_UserCache)
                    m_UserCache[uuid] = user;

                return true;
            }
            else
            {
                // Let's try the GridUser service
                GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
                if (uInfo != null)
                {
                    string url, first, last, tmp;
                    UUID u;
                    if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
                    {
                        AddUser(uuid, first, last, url);

                        if (m_UserCache.ContainsKey(uuid))
                        {
                            names[0] = m_UserCache[uuid].FirstName;
                            names[1] = m_UserCache[uuid].LastName;

                            return true;
                        }
                    }
                    else
                        m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
                }
//                else
//                {
//                    m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
//                }

                names[0] = "Unknown";
                names[1] = "UserUMMTGUN9";

                return false;
            }
        }

        #region IUserManagement

        public virtual UUID GetUserIdByName(string name)
        {
            string[] parts = name.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 2)
                throw new Exception("Name must have 2 components");

            return GetUserIdByName(parts[0], parts[1]);
        }

        public virtual UUID GetUserIdByName(string firstName, string lastName)
        {
            if(m_Scenes.Count <= 0)
                return UUID.Zero;

            // TODO: Optimize for reverse lookup if this gets used by non-console commands.
            lock (m_UserCache)
            {
                foreach (UserData user in m_UserCache.Values)
                {
                    if (user.FirstName == firstName && user.LastName == lastName)
                        return user.Id;
                }
            }

            UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName);

            if (account != null)
                return account.PrincipalID;

            return UUID.Zero;
        }

        public virtual string GetUserName(UUID uuid)
        {
            UserData user;
            GetUser(uuid, out user);
            return user.FirstName + " " + user.LastName;
        }

        public virtual Dictionary<UUID,string> GetUsersNames(string[] ids)
        {
            Dictionary<UUID,string> ret = new Dictionary<UUID,string>();
            if(m_Scenes.Count <= 0)
                return ret;

            List<string> missing = new List<string>();
            Dictionary<UUID,string> untried = new Dictionary<UUID, string>();

            // look in cache
            UserData userdata = new UserData();

            UUID uuid = UUID.Zero;
            foreach(string id in ids)
            {
                if(UUID.TryParse(id, out uuid))
                {
                    lock (m_UserCache)
                    {
                        if (m_UserCache.TryGetValue(uuid, out userdata) &&
                                userdata.FirstName != "Unknown" && userdata.FirstName != string.Empty)
                        {
                            string name = userdata.FirstName + " " + userdata.LastName;

                            if(userdata.HasGridUserTried)
                                ret[uuid] = name;
                            else
                            {
                                untried[uuid] = name;
                                missing.Add(id);
                            }
                        }
                        else
                            missing.Add(id);
                    }
                }
            }

            if(missing.Count == 0)
                return ret;

            // try user account service
            List<UserAccount> accounts = m_Scenes[0].UserAccountService.GetUserAccounts(
                                    m_Scenes[0].RegionInfo.ScopeID, missing);

            if(accounts.Count != 0)
            {
                foreach(UserAccount uac in accounts)
                {
                    if(uac != null)
                    {
                        string name = uac.FirstName + " " + uac.LastName;
                        ret[uac.PrincipalID] = name;
                        missing.Remove(uac.PrincipalID.ToString()); // slowww
                        untried.Remove(uac.PrincipalID);

                        userdata = new UserData();
                        userdata.Id = uac.PrincipalID;
                        userdata.FirstName = uac.FirstName;
                        userdata.LastName = uac.LastName;
                        userdata.HomeURL = string.Empty;
                        userdata.IsUnknownUser = false;
                        userdata.HasGridUserTried = true;
                        lock (m_UserCache)
                            m_UserCache[uac.PrincipalID] = userdata;
                    }
                }
            }

            if (missing.Count == 0 || m_Scenes[0].GridUserService == null)
                return ret;

            // try grid user service

            GridUserInfo[] pinfos = m_Scenes[0].GridUserService.GetGridUserInfo(missing.ToArray());
            if(pinfos.Length > 0)
            {
                foreach(GridUserInfo uInfo in pinfos)
                {
                    if (uInfo != null)
                    {
                        string url, first, last, tmp;

                        if(uInfo.UserID.Length <= 36)
                            continue;

                        if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out uuid, out url, out first, out last, out tmp))
                        {
                            if (url != string.Empty)
                            {
                                try
                                {
                                    userdata = new UserData();
                                    userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
                                    userdata.LastName = "@" + new Uri(url).Authority;
                                    userdata.Id = uuid;
                                    userdata.HomeURL = url;
                                    userdata.IsUnknownUser = false;
                                    userdata.HasGridUserTried = true;
                                    lock (m_UserCache)
                                        m_UserCache[uuid] = userdata;

                                    string name =  userdata.FirstName + " " + userdata.LastName;
                                    ret[uuid] = name;
                                    missing.Remove(uuid.ToString());
                                    untried.Remove(uuid);
                                }
                                catch
                                {
                                }
                            }
                        }
                    }
                }
            }

            // add the untried in cache that still failed
            if(untried.Count > 0)
            {
                foreach(KeyValuePair<UUID, string> kvp in untried)
                {
                    ret[kvp.Key] = kvp.Value;
                    missing.Remove((kvp.Key).ToString());
                }
            }

            // add the UMMthings ( not sure we should)
            if(missing.Count > 0)
            {
                foreach(string id in missing)
                {
                    if(UUID.TryParse(id, out uuid) && uuid != UUID.Zero)
                    {
                        if (m_Scenes[0].LibraryService != null &&
                             (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
                             ret[uuid] = "Mr OpenSim";
                        else
                            ret[uuid] = "Unknown UserUMMAU43";
                    }
                }
             }

            return ret;
        }

        public virtual string GetUserHomeURL(UUID userID)
        {
            UserData user;
            if(GetUser(userID, out user))
            {
                return user.HomeURL;
            }
            return string.Empty;
        }

        public virtual string GetUserServerURL(UUID userID, string serverType)
        {
            UserData userdata;
            if(!GetUser(userID, out userdata))
            {
                return string.Empty;
            }

            if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
            {
                return userdata.ServerURLs[serverType].ToString();
            }

            if (!string.IsNullOrEmpty(userdata.HomeURL))
            {
//                m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);

                UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
                try
                {
                    userdata.ServerURLs = uConn.GetServerURLs(userID);
                }
                catch(System.Net.WebException e)
                {
                    m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message);
                    userdata.ServerURLs = new Dictionary<string, object>();
                }
                catch (Exception e)
                {
                    m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e);
                    userdata.ServerURLs = new Dictionary<string, object>();
                }

                if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
                    return userdata.ServerURLs[serverType].ToString();
            }

            return string.Empty;
        }

        public virtual string GetUserUUI(UUID userID)
        {
            string uui;
            GetUserUUI(userID, out uui);
            return uui;
        }

        public virtual bool GetUserUUI(UUID userID, out string uui)
        {
            UserData ud;
            bool result = GetUser(userID, out ud);

            if (ud != null)
            {
                string homeURL = ud.HomeURL;
                string first = ud.FirstName, last = ud.LastName;
                if (ud.LastName.StartsWith("@"))
                {
                    string[] parts = ud.FirstName.Split('.');
                    if (parts.Length >= 2)
                    {
                        first = parts[0];
                        last = parts[1];
                    }
                    uui = userID + ";" + homeURL + ";" + first + " " + last;
                    return result;
                }
            }

            uui = userID.ToString();
            return result;
        }

        #region Cache Management
        public virtual bool GetUser(UUID uuid, out UserData userdata)
        {
            if(m_Scenes.Count <= 0)
            {
                userdata = new UserData();
                return false;
            }

            lock (m_UserCache)
            {
                if (m_UserCache.TryGetValue(uuid, out userdata))
                {
                    if (userdata.HasGridUserTried)
                    {
                        return true;
                    }
                }
                else
                {
                    userdata = new UserData();
                    userdata.Id = uuid;
                    userdata.FirstName = "Unknown";
                    userdata.LastName = "UserUMMAU42";
                    userdata.HomeURL = string.Empty;
                    userdata.IsUnknownUser = true;
                    userdata.HasGridUserTried = false;
                }
            }

            /* BEGIN: do not wrap this code in any lock here
             * There are HTTP calls in here.
             */
            if (!userdata.HasGridUserTried)
            {
                /* rewrite here */
                UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
                if (account != null)
                {
                    userdata.FirstName = account.FirstName;
                    userdata.LastName = account.LastName;
                    userdata.HomeURL = string.Empty;
                    userdata.IsUnknownUser = false;
                    userdata.HasGridUserTried = true;
                }
            }

            if (!userdata.HasGridUserTried)
            {
                GridUserInfo uInfo = null;
                if (null != m_Scenes[0].GridUserService)
                {
                    uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
                }
                if (uInfo != null)
                {
                    string url, first, last, tmp;
                    UUID u;
                    if(uInfo.UserID.Length <= 36)
                    {
                        /* not a UUI */
                    }
                    else if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
                    {
                        if (url != string.Empty)
                        {
                            userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
                            userdata.HomeURL = url;
                            try
                            {
                                userdata.LastName = "@" + new Uri(url).Authority;
                                userdata.IsUnknownUser = false;
                            }
                            catch
                            {
                                userdata.LastName = "@unknown";
                            }
                            userdata.HasGridUserTried = true;
                        }
                    }
                    else
                        m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
                }
            }
            /* END: do not wrap this code in any lock here */

            lock (m_UserCache)
            {
                m_UserCache[uuid] = userdata;
            }
            return !userdata.IsUnknownUser;
        }

        public virtual void AddUser(UUID uuid, string first, string last, bool isNPC = false)
        {
            lock(m_UserCache)
            {
                if(!m_UserCache.ContainsKey(uuid))
                {
                    UserData user = new UserData();
                    user.Id = uuid;
                    user.FirstName = first;
                    user.LastName = last;
                    user.IsUnknownUser = false;
                    user.HasGridUserTried = isNPC;
                    m_UserCache.Add(uuid, user);
                }
            }
        }

        public virtual void AddUser(UUID uuid, string first, string last, string homeURL)
        {
            //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);

            UserData oldUser;
            lock (m_UserCache)
            {
                if (m_UserCache.TryGetValue(uuid, out oldUser))
                {
                    if (!oldUser.IsUnknownUser)
                    {
                        if (homeURL != oldUser.HomeURL && m_DisplayChangingHomeURI)
                        {
                            m_log.DebugFormat("[USER MANAGEMENT MODULE]: Different HomeURI for {0} {1} ({2}): {3} and {4}",
                                first, last, uuid.ToString(), homeURL, oldUser.HomeURL);
                        }
                        /* no update needed */
                        return;
                    }
                }
                else if(!m_UserCache.ContainsKey(uuid))
                {
                    oldUser = new UserData();
                    oldUser.HasGridUserTried = false;
                    oldUser.IsUnknownUser = false;
                    if (homeURL != string.Empty)
                    {
                        oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
                        try
                        {
                            oldUser.LastName = "@" + new Uri(homeURL).Authority;
                            oldUser.IsUnknownUser = false;
                        }
                        catch
                        {
                            oldUser.LastName = "@unknown";
                        }
                    }
                    else
                    {
                        oldUser.FirstName = first;
                        oldUser.LastName = last;
                    }
                    oldUser.HomeURL = homeURL;
                    oldUser.Id = uuid;
                    m_UserCache.Add(uuid, oldUser);
                }
            }
        }

        public virtual void AddUser(UUID id, string creatorData)
        {
            // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);

            if(string.IsNullOrEmpty(creatorData))
            {
                AddUser(id, string.Empty, string.Empty, string.Empty);
            }
            else
            {
                string homeURL;
                string firstname = string.Empty;
                string lastname = string.Empty;

                //creatorData = <endpoint>;<name>

                string[] parts = creatorData.Split(';');
                if(parts.Length > 1)
                {
                    string[] nameparts = parts[1].Split(' ');
                    firstname = nameparts[0];
                    for(int xi = 1; xi < nameparts.Length; ++xi)
                    {
                        if(xi != 1)
                        {
                            lastname += " ";
                        }
                        lastname += nameparts[xi];
                    }
                }
                else
                {
                    firstname = "Unknown";
                    lastname = "UserUMMAU5";
                }
                if (parts.Length >= 1)
                {
                    homeURL = parts[0];
                    if(Uri.IsWellFormedUriString(homeURL, UriKind.Absolute))
                    {
                        AddUser(id, firstname, lastname, homeURL);
                    }
                    else
                    {
                        m_log.DebugFormat("[SCENE]: Unable to parse Uri {0} for CreatorID {1}", parts[0], creatorData);

                        lock (m_UserCache)
                        {
                            if(!m_UserCache.ContainsKey(id))
                            {
                                UserData newUser = new UserData();
                                newUser.Id = id;
                                newUser.FirstName = firstname + "." + lastname.Replace(' ', '.');
                                newUser.LastName = "@unknown";
                                newUser.HomeURL = string.Empty;
                                newUser.HasGridUserTried = false;
                                newUser.IsUnknownUser = true; /* we mark those users as Unknown user so a re-retrieve may be activated */
                                m_UserCache.Add(id, newUser);
                            }
                        }
                    }
                }
                else
                {
                    lock(m_UserCache)
                    {
                        if(!m_UserCache.ContainsKey(id))
                        {
                            UserData newUser = new UserData();
                            newUser.Id = id;
                            newUser.FirstName = "Unknown";
                            newUser.LastName = "UserUMMAU4";
                            newUser.HomeURL = string.Empty;
                            newUser.IsUnknownUser = true;
                            newUser.HasGridUserTried = false;
                            m_UserCache.Add(id, newUser);
                        }
                    }
                }
            }
        }
        #endregion

        public virtual bool IsLocalGridUser(UUID uuid)
        {
            lock (m_Scenes)
            {
                if (m_Scenes.Count == 0)
                    return true;
                UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
                if (account == null || (account != null && !account.LocalToGrid))
                    return false;
            }

            return true;
        }

        #endregion IUserManagement

        protected virtual void Init()
        {
            AddUser(UUID.Zero, "Unknown", "User");
            RegisterConsoleCmds();
        }

        protected virtual void RegisterConsoleCmds()
        {
            MainConsole.Instance.Commands.AddCommand("Users", true,
                "show name",
                "show name <uuid>",
                "Show the bindings between a single user UUID and a user name",
                String.Empty,
                HandleShowUser);

            MainConsole.Instance.Commands.AddCommand("Users", true,
                "show names",
                "show names",
                "Show the bindings between user UUIDs and user names",
                String.Empty,
                HandleShowUsers);

            MainConsole.Instance.Commands.AddCommand("Users", true,
                "reset user cache",
                "reset user cache",
                "reset user cache to allow changed settings to be applied",
                String.Empty,
                HandleResetUserCache);
        }

        protected virtual void HandleResetUserCache(string module, string[] cmd)
        {
            lock(m_UserCache)
            {
                m_UserCache.Clear();
            }
        }

        protected virtual void HandleShowUser(string module, string[] cmd)
        {
            if (cmd.Length < 3)
            {
                MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
                return;
            }

            UUID userId;
            if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
                return;

            UserData ud;

            if(!GetUser(userId, out ud))
            {
                MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
                return;
            }

            ConsoleDisplayTable cdt = new ConsoleDisplayTable();
            cdt.AddColumn("UUID", 36);
            cdt.AddColumn("Name", 30);
            cdt.AddColumn("HomeURL", 40);
            cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);

            MainConsole.Instance.Output(cdt.ToString());
        }

        protected virtual void HandleShowUsers(string module, string[] cmd)
        {
            ConsoleDisplayTable cdt = new ConsoleDisplayTable();
            cdt.AddColumn("UUID", 36);
            cdt.AddColumn("Name", 30);
            cdt.AddColumn("HomeURL", 40);
            cdt.AddColumn("Checked", 10);

            Dictionary<UUID, UserData> copyDict;
            lock(m_UserCache)
            {
                copyDict = new Dictionary<UUID, UserData>(m_UserCache);
            }

            foreach(KeyValuePair<UUID, UserData> kvp in copyDict)
            {
                cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL, kvp.Value.HasGridUserTried ? "yes" : "no");
            }

            MainConsole.Instance.Output(cdt.ToString());
        }

    }

}


text:
See also:
[$.fn.editable](editable.md)

Hovering text input plugin. Call on an element to contain the editor, then pass in an element for the editor to hover
over as a method argument. Use for editing text-only contents of non-editable elements such as \<div\>s and \<td\>s.
Copies css from the target element to the editor.

## $.fn.dbEditorArea()
Initialise the plugin.

## $.fn.dbEditorArea('getCurrentElement')
Get the element currently being edited, as a jQuery selection.

## $.fn.dbEditorArea('setValue', newValue)
Set the value of the editor

## $.fn.dbEditorArea('getValue')
Get the value of the editor

## $.fn.dbEditorArea('show', element, value)
Show the editor over the given element, with the given value.

## $.fn.dbEditorArea('hide')
Hide the editor

## $.fn.dbEditorArea('repaint')
Re-apply the css form the currenly edited element to the editor.

## $.fn.dbEditorArea('selectText', range)
Set the text selection / cursor position. Accepts "start", "end", or "all" as the range options.

redpajama_set_name: RedPajamaGithub


text:
/*
 * Main.cpp
 *
 *  Created on: Jan 7, 2015
 *      Author: mda
 */

#include <QApplication>
#include <string>
#include "util/Logger.h"
#include "scripts.h"
#include "Properties.h"
#include "PropertyReader.h"
#include "VideoTesting.h"
#include "SubFactory.h"
#include "Stage.h"
#include "StateTester.h"

int main(int argc, char** argv) {

    Timer* logTimer = new Timer();
    QApplication app(argc, argv);
    Logger logger("Main");
    Logger::initialize(Logger::Level::TRACE,true, true, logTimer);
    logger.trace("Logger initialized.");

    PropertyReader* propReader;
    Properties* settings;
    if (argc > 1) {
        propReader = new PropertyReader(argv[1]);
    } else {
        propReader = new PropertyReader("../src/settings/settings.txt");
    }
    // Set logging level
    settings = propReader->load();
    std::string loggingLevel = settings->getProperty("LOGGING_LEVEL");
    if (loggingLevel == "OFF") {
        Logger::setLoggingLevel(Logger::Level::OFF);
    } else if (loggingLevel == "TRACE") {
        Logger::setLoggingLevel(Logger::Level::TRACE);
    } else if (loggingLevel == "INFO") {
        Logger::setLoggingLevel(Logger::Level::INFO);
    } else if (loggingLevel == "DEBUG") {
        Logger::setLoggingLevel(Logger::Level::DEBUG);
    } else if (loggingLevel == "WARN") {
        Logger::setLoggingLevel(Logger::Level::WARN);
    } else if (loggingLevel == "ERROR") {
        Logger::setLoggingLevel(Logger::Level::ERROR);
    }

    // Set default HSV Filter values
    if (!settings->getProperty("LOW_HUE").empty()) {
        HSVFilter::defaultLowH = std::stoi(settings->getProperty("LOW_HUE"));
    }
    if (!settings->getProperty("HIGH_HUE").empty()) {
        HSVFilter::defaultHighH = std::stoi(settings->getProperty("HIGH_HUE"));
    }
    if (!settings->getProperty("LOW_SATURATION").empty()) {
        HSVFilter::defaultLowS = std::stoi(settings->getProperty("LOW_SATURATION"));
    }
    if (!settings->getProperty("HIGH_SATURATION").empty()) {
        HSVFilter::defaultHighS = std::stoi(settings->getProperty("HIGH_SATURATION"));
    }
    if (!settings->getProperty("LOW_VALUE").empty()) {
        HSVFilter::defaultLowV = std::stoi(settings->getProperty("LOW_VALUE"));
    }
    if (!settings->getProperty("HIGH_VALUE").empty()) {
        HSVFilter::defaultHighV = std::stoi(settings->getProperty("HIGH_VALUE"));
    }

    std::string mode = settings->getProperty("MODE");

    if (mode == "HSVTEST") {
        VideoTesting vt(0); //camera id or file name
        vt.run(1); //0 = video; 1 = webcam; 2 = image
    } else {
        init_signal_handler();

        SubFactory* subFactory = new SubFactory(settings);
        Stage* mainStage = new Stage(NULL, subFactory);

        mainStage->setViewContent(mode);
        mainStage->initialize();

        delete propReader;
    }
    return app.exec();

}


text:
Block quotes may or may not contain a citation. If they do, that citation should be in a footer element. The citation should also contain a `cite` element wrapping the title of the work with a link if appropriate.

See MDN Articles:

- [Blockquote](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote#attr-cite)
- [Cite](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)


text:
package tv.amwa.maj.extensions.example;

import tv.amwa.maj.industry.MediaEnumerationValue;
import tv.amwa.maj.integer.Int64;

/**
 *
Different genres of resource.

 *
 * @see TypeDefinitions#DCMIType
 *
 *
 */
public enum DCMIType
    implements MediaEnumerationValue {

    /**
Moving image element.
 */
    MovingImage (1l),
    /**
Still image element.
 */
    StillImage (2l),
    /**
Sound element.
 */
    Sound (3l),
    /**
Data set element.
 */
    DataSet (4l),
    ;

    private final long value;

    DCMIType(long value) { this.value = value; }

    @Int64 public long value() { return value; }

    public String symbol() {

        return "DCMIType_" + name();
    }

}


text:
/**
 * RequestQueue
 * Request images from the camera server, and keep a recent history.
 * Allows us to throttle camera requests, drop old frames, etc.
 */
function RequestQueue()
{
	this.queue = []; // A queue of {url, date, image}
	this.maxLength = 4;

	// References to other objects.
	this.camera = null;

	/**
	 * Make a request to the image server.
	 * Has internal callbacks that handle state information.
	 */
	this.request = function(url)
	{
		var that = this;
		var d = new Date();
		var now = d.getTime();
		var entry = {};

		// Success Cb
		var onLoad = function(url, requestDate)
		{
			var time = (new Date()).getTime();

			that.camera.counts.load++;

			// Don't update image if it's older than the current one.
			if(that.camera.times.lastLoaded_requestDate >= requestDate) {
				return;
			}

			// Update image.
			that.camera.curFrame.src = url;

			// TODO/FIXME [android-webkit-bug]
			// XXX: Stupid Android Webkit (only) bug?
			// onLoad() fires, but image is not complete!
			if(!that.camera.curFrame.complete) {
				console.log('Image load incomplete: ' + url);
				that.camera.counts.load--;
				return;
			}

			that.camera.times.lastLoaded = time;
			that.camera.times.lastLoaded_requestDate = requestDate;
			if(!that.camera.times.firstLoaded) {
				that.camera.times.firstLoaded = time;
			}

			// FIXME: Ugly call
			that.camera.controller.view.updateCameraView(that.camera);
		}

		// Fail Cb
		var onFail = function() {
			that.camera.times.lastFailed = (new Date()).getTime();
			that.camera.counts.fail++;
			// FIXME: Ugly call.
			that.camera.controller.view.updateCameraView(that.camera);
		}

		// Abort Cb
		var onAbort = function() {
			that.camera.times.lastAborted = (new Date()).getTime();
			that.camera.counts.abort++;
			// FIXME: Ugly call.
			that.camera.controller.view.updateCameraView(that.camera);
		}

		// If queue is full, make room.
		while(this.queue.length >= this.maxLength) {
			var data = this.queue.shift();
			data.image.src = null;
		}

		// Perform request
		entry['url'] = url;
		entry['date'] = now;

		entry['image'] = new Image();
		entry['image'].onload = function() { onLoad(url, now); };
		entry['image'].onerror = function() { onFail(); };
		entry['image'].onabort = function() { onAbort(); };
		entry['image'].src = url;

		this.queue.push(entry);

		this.camera.counts.request++;
		this.camera.times.lastRequested = now;
		if(!this.camera.times.firstRequested) {
			this.camera.times.firstRequested = now;
		}

		// FIXME: Ugly call
		this.camera.controller.view.updateCameraView(that.camera);
	}

	/**
	 * Queue capacity exhausted?
	 */
	this.isFull = function()
	{
		return this.queue.length >= this.maxLength;
	}

	/**
	 * Percentage of queue used.
	 */
	this.percentFull = function()
	{
		return this.queue.length / this.maxLength;
	}

	/**
	 * Age of the last queue item.
	 */
	this.newest = function()
	{
		if(this.queue.length == 0) {
			return null;
		}
		return this.queue[this.queue.length-1].date;
	}

	/**
	 * Age of the first queue item.
	 */
	this.oldest = function()
	{
		if(this.queue.length == 0) {
			return null;
		}
		return this.queue[0].date;
	}

	/**
	 * Purge all queue items from before (and including) last met
	 * request date.
	 */
	this.purgeOld = function()
	{
		var found = 0;
		var obj = null;

		for(var i = 0; i < this.queue.length; i++) {
			if(this.queue[i].date > this.camera.times.lastLoaded_requestDate) {
				break;
			}
			found++;
		}

		if(!found) {
			return;
		}

		this.camera.counts.cachePurge += found-1;

		while(found > 0) {
			obj = this.queue.shift();
			delete obj.image;
			found--;
		}
	}
}


text:
from __future__ import print_function, absolute_import

from .anyQt import QtGui, QtCore
from .anyQt.QtGui import QTreeWidgetItem

class PTree(object):

    def __init__(self, parent=None, on_select=None):
        self._widget = QtGui.QTreeWidget(parent)
        self._widget.setColumnCount(1)
        self._keys = []
        self._allkeys = set()
        self._allitems = {}
        self._leafitems_rev = {}
        self._widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        self._widget.itemPressed.connect(self._itemPressed)
        self._widget.setDragEnabled(True)
        self._on_select = on_select

    def widget(self):
        return self._widget

    @QtCore.pyqtSlot(QTreeWidgetItem, int)
    def _itemPressed(self, item, column):
        if id(item) in self._leafitems_rev:
            t = self._leafitems_rev[id(item)]
            if self._on_select is not None:
                self._on_select(t)
            self._widget.setDragEnabled(True)
        else:
            self._widget.setDragEnabled(False)

    def append(self, key):
        assert key not in self._keys
        head, tail = key[0], key[1:]
        if head not in self._allkeys:
            self._allkeys.add(head)
            e = QTreeWidgetItem()
            e.setText(0, head)
            self._widget.addTopLevelItem(e)
            self._allitems[head] = e
            w = e
        else:
            w = self._allitems[head]
        t = key[1:]
        prev = (head,)
        while len(t) > 0:
            head, tail = t[0], t[1:]
            phead = prev + (head,)
            if phead not in self._allkeys:
                self._allkeys.add(phead)
                e = QTreeWidgetItem()
                e.setText(0, head)
                w.addChild(e)
                self._allitems[phead] = e
                w = e
            else:
                w = self._allitems[phead]
            t = tail
            prev = phead
        key = tuple(key)
        self._keys.append(key)
        self._leafitems_rev[id(w)] = key

    def _remove_empty_group(self, group):
        g = len(group)
        nr_items = len([k for k in self._allitems.keys() if k[:g] == group])
        min = 1 if g > 1 else 0
        if nr_items == min:
            if len(group) == 1:
                group = group[0]
                self._allkeys.remove(group)
                w = self._allitems.pop(group)
                ind = self._widget.indexOfTopLevelItem(w)
                self._widget.takeTopLevelItem(ind)
            else:
                self._allkeys.remove(group)
                w = self._allitems.pop(group)
                parent = group[:-1]
                if len(parent) == 1: parent = parent[0]
                ww = self._allitems[parent]
                ww.removeChild(w)

    def remove(self, key):
        key = tuple(key)
        assert key in self._keys

        self._keys.remove(key)
        self._allkeys.remove(key)
        w = self._allitems.pop(key)
        self._leafitems_rev.pop(id(w))
        if len(key) == 1:
            ind = self._widget.indexOfTopLevelItem(w)
            self._widget.takeTopLevelItem(ind)
        else:
            parent = key[:-1]
            if len(parent) == 1: parent = parent[0]
            ww = self._allitems[parent]
            ww.removeChild(w)
        for n in range(len(key), 0, -1):
            group = key[:n]
            self._remove_empty_group(group)

    def sync(self):
        pass


text:
    #pragma warning (push)
    #pragma warning (disable: 4100 4702)
#endif

#include <grpcpp/grpcpp.h>
#include <grpcpp/impl/codegen/rpc_method.h>
#include <grpcpp/impl/codegen/service_type.h>
#include <grpcpp/impl/codegen/status.h>

#ifdef _MSC_VER
    #pragma warning (pop)
#endif

#include <boost/assert.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>

#include <functional>
#include <memory>
#include <thread>

namespace bond { namespace ext { namespace gRPC { namespace detail {

/// @brief Implementation class that hold the state associated with
/// receiving incomming calls for one method.
///
/// There only needs to be one of these per method in a service, and it can
/// be re-used for receiving subsequent calls. A new detail::unary_call_impl
/// is created for each individual call to hold the call-specific data. Once
/// the invocation of the user callback along with the call-specific data
/// has been enqueued in the thread pool, detail::service_unary_call_data
/// re-enqueues itself to get the next call.
template <typename TRequest, typename TResponse, typename TThreadPool>
struct service_unary_call_data : io_manager_tag
{
    /// The type of the user-defined callback that will be invoked upon receipt
    /// of this call.
    typedef std::function<void(unary_call<TRequest, TResponse> call)> CallbackType;

    using uc_impl = unary_call_impl<TRequest, TResponse>;

    /// The service implementing the method.
    service<TThreadPool>* _service;
    /// The index of the method. Method indices correspond to the order in
    /// which they were registered with detail::service::AddMethod
    int _methodIndex;
    /// The completion port to post IO operations to.
    grpc::ServerCompletionQueue* _cq;
    /// The thread pool implementation to use to invoke the user callback.
    std::shared_ptr<TThreadPool> _threadPool;
    /// The user code to invoke when a call to this method is received.
    CallbackType _cb;
    /// Individual state for one specific call to this method.
    std::unique_ptr<uc_impl> _receivedCall;

    service_unary_call_data(
        service<TThreadPool>* service,
        int methodIndex,
        grpc::ServerCompletionQueue* cq,
        std::shared_ptr<TThreadPool> threadPool,
        CallbackType cb)
        : _service(service),
          _methodIndex(methodIndex),
          _cq(cq),
          _threadPool(threadPool),
          _cb(cb),
          _receivedCall(new uc_impl)
    {
        BOOST_ASSERT(service);
        BOOST_ASSERT(cq);
        BOOST_ASSERT(threadPool);
        BOOST_ASSERT(cb);
    }

    void invoke(bool ok) override
    {
        if (ok)
        {
            // Capture the data associated with this one incomming request
            // so that we can pass it to the user callback. When we create
            // the unary_call to pass to the user callback, the unary_call
            // and unary_call_impl start collaborating to manage the
            // lifetime of the unary_call_impl.
            {
                // We have to manually release the pointer from
                // _receivedCall to capture it in the lambda. When we can
                // use C++14, we can simplify this by using lambda's
                // capture-by-move.
                auto receivedCall = boost::intrusive_ptr<uc_impl>{ _receivedCall.release() };

                _threadPool->schedule([this, receivedCall]() mutable
                {
                    _cb(unary_call<TRequest, TResponse> { std::move(receivedCall) });
                });
            }

            // create new state for the next request that will be received
            _receivedCall.reset(new uc_impl);
            _service->queue_receive(
                _methodIndex,
                &_receivedCall->context(),
                &_receivedCall->request(),
                &_receivedCall->responder(),
                _cq,
                this);
        }
        else
        {
            // we're shutting down, so don't requeue
        }
    }
};

} } } } //namespace bond::ext::gRPC::detail


text:
package org.apache.ambari.server.controller.internal;

import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.H2DatabaseCleaner;
import org.apache.ambari.server.actionmanager.ActionType;
import org.apache.ambari.server.actionmanager.TargetHostType;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.controller.ActionRequest;
import org.apache.ambari.server.controller.ActionResponse;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.spi.Predicate;
import org.apache.ambari.server.controller.spi.Request;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.controller.utilities.PredicateBuilder;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
import org.apache.ambari.server.customactions.ActionDefinition;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

public class ActionResourceProviderTest {

  private Injector injector;

  public static ActionResourceProvider getActionDefinitionResourceProvider(
      AmbariManagementController managementController) {
    Resource.Type type = Resource.Type.Action;

    return (ActionResourceProvider) AbstractControllerResourceProvider.getResourceProvider(
        type,
        PropertyHelper.getPropertyIds(type),
        PropertyHelper.getKeyPropertyIds(type),
        managementController);
  }

  public static Set<ActionResponse> getActions(AmbariManagementController controller,
                                               Set<ActionRequest> requests)
      throws AmbariException {
    ActionResourceProvider provider = getActionDefinitionResourceProvider(controller);
    return provider.getActionDefinitions(requests);
  }

  @Before
  public void setup() throws Exception {
    InMemoryDefaultTestModule module = new InMemoryDefaultTestModule();
    injector = Guice.createInjector(module);
    injector.getInstance(GuiceJpaInitializer.class);
  }

  @After
  public void teardown() throws AmbariException, SQLException {
    H2DatabaseCleaner.clearDatabaseAndStopPersistenceService(injector);
  }

  @Test
  public void testGetResources() throws Exception {
    Resource.Type type = Resource.Type.Action;
    AmbariMetaInfo am = createNiceMock(AmbariMetaInfo.class);
    AmbariManagementController managementController = createNiceMock(AmbariManagementController.class);
    expect(managementController.getAmbariMetaInfo()).andReturn(am).anyTimes();

    List<ActionDefinition> allDefinition = new ArrayList<ActionDefinition>();
    allDefinition.add(new ActionDefinition(
        "a1", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY,
        Short.valueOf("100"), null));
    allDefinition.add(new ActionDefinition(
        "a2", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY,
        Short.valueOf("100"), null));
    allDefinition.add(new ActionDefinition(
        "a3", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY,
        Short.valueOf("100"), null));

    Set<ActionResponse> allResponse = new HashSet<ActionResponse>();
    for (ActionDefinition definition : allDefinition) {
      allResponse.add(definition.convertToResponse());
    }

    ActionDefinition namedDefinition = new ActionDefinition(
        "a1", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY,
        Short.valueOf("100"), null);

    Set<ActionResponse> nameResponse = new HashSet<ActionResponse>();
    nameResponse.add(namedDefinition.convertToResponse());

    expect(am.getAllActionDefinition()).andReturn(allDefinition).once();
    expect(am.getActionDefinition("a1")).andReturn(namedDefinition).once();

    replay(managementController, am);

    ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
        type,
        PropertyHelper.getPropertyIds(type),
        PropertyHelper.getKeyPropertyIds(type),
        managementController);

    Set<String> propertyIds = new HashSet<String>();

    propertyIds.add(ActionResourceProvider.ACTION_NAME_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.ACTION_TYPE_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.DEFAULT_TIMEOUT_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.DESCRIPTION_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.INPUTS_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.TARGET_COMPONENT_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.TARGET_HOST_PROPERTY_ID);
    propertyIds.add(ActionResourceProvider.TARGET_SERVICE_PROPERTY_ID);

    // create the request
    Request request = PropertyHelper.getReadRequest(propertyIds);

    // get all ... no predicate
    Set<Resource> resources = provider.getResources(request, null);

    Assert.assertEquals(allResponse.size(), resources.size());
    for (Resource resource : resources) {
      String actionName = (String) resource.getPropertyValue(ActionResourceProvider.ACTION_NAME_PROPERTY_ID);
      String actionType = (String) resource.getPropertyValue(ActionResourceProvider.ACTION_TYPE_PROPERTY_ID);
      String defaultTimeout = (String) resource.getPropertyValue(ActionResourceProvider.DEFAULT_TIMEOUT_PROPERTY_ID);
      String description = (String) resource.getPropertyValue(ActionResourceProvider.DESCRIPTION_PROPERTY_ID);
      String inputs = (String) resource.getPropertyValue(ActionResourceProvider.INPUTS_PROPERTY_ID);
      String comp = (String) resource.getPropertyValue(ActionResourceProvider.TARGET_COMPONENT_PROPERTY_ID);
      String svc = (String) resource.getPropertyValue(ActionResourceProvider.TARGET_SERVICE_PROPERTY_ID);
      String host = (String) resource.getPropertyValue(ActionResourceProvider.TARGET_HOST_PROPERTY_ID);
      Assert.assertTrue(allResponse.contains(new ActionResponse(actionName, actionType,
          inputs, svc, comp, description, host, defaultTimeout)));
    }

    // get actions named a1
    Predicate predicate =
        new PredicateBuilder().property(ActionResourceProvider.ACTION_NAME_PROPERTY_ID).
            equals("a1").toPredicate();
    resources = provider.getResources(request, predicate);

    Assert.assertEquals(1, resources.size());
    Assert.assertEquals("a1", resources.iterator().next().
        getPropertyValue(ActionResourceProvider.ACTION_NAME_PROPERTY_ID));

    // verify
    verify(managementController);
  }
}


text:
@extends('layouts.admin-main')

@section('content')

Update password

        <form class="form-horizontal" action="{{ route('admin.users.update-password', ['user' => $user->id]) }}" method="post">
          @csrf
          @method('PATCH')

has('current_password') ? ' has-error' : '' }}">
            Current password*

              {{ Form::password('current_password', array(
                'class' => 'form-control', 'autocomplete' => 'off',
                'placeholder' => 'Enter current password'))
              }}
              @if( $errors->has('current_password'))

                     {{ $errors->first('current_password') }}

              @endif

has('new_password') ? ' has-error' : '' }}">
            New password*

              {{ Form::password('new_password', array(
                'class' => 'form-control', 'autocomplete' => 'off',
                'placeholder' => 'Enter new password'))
              }}
              @if( $errors->has('new_password'))

                     {{ $errors->first('new_password') }}

              @endif

has('new_password_confirmation') ? ' has-error' : '' }}">
            Confirm new password*

              {{ Form::password('new_password_confirmation', array(
                'class' => 'form-control', 'autocomplete' => 'off',
                'placeholder' => 'Enter new password'))
              }}
              @if( $errors->has('new_password_confirmation'))

                     {{ $errors->first('new_password_confirmation') }}

              @endif

                <button type="submit" class="btn btn-primary">  Update</button>

        </form>

@endsection


text:
$(document).ready(function(e) {

	// Week view scripts
	$("#week-view-sel-peak").click(function () {
		$('.week-table-avg').fadeOut(100, "swing" , function() {
			$('.week-table-peak').fadeIn(100);
		});
		$('#week-view-sel-avg').next().removeClass('ui-state-active');
	});
	$("#week-view-sel-avg").click(function () {
		$('.week-table-peak').fadeOut(100, "swing" , function() {
			$('.week-table-avg').fadeIn(100);
		});
		$('#week-view-sel-peak').next().removeClass('ui-state-active');
	});
	$("#week-view-sel-peak").click();

    var autorefresh = setInterval(function () {
		$("#streamstats").load("./?page=api&task=html_live_stats").fadeIn("slow");
	}, 2500);

	$("#search-date").datepicker({dateFormat:'yy-mm-dd', firstDay: 1});
	$("#search-dateto").datepicker({dateFormat:'yy-mm-dd', firstDay: 1});

	// Week picker
	// thanks to http://stackoverflow.com/questions/1289633/how-to-use-jquery-ui-calendar-date-picker-for-week-rather-than-day
	var startDate;
    var endDate;

    var selectCurrentWeek = function() {
        window.setTimeout(function () {
            $('.week-picker').find('.ui-datepicker-current-day a').addClass('ui-state-active')
        }, 1);
    }

    $('.week-picker').datepicker( {
        showOtherMonths: true,
        selectOtherMonths: true,
		dateFormat: 'yy-mm-dd',
		firstDay: 1,
        onSelect: function(dateText, inst) {
            var date = $(this).datepicker('getDate');
            startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 1);
            endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() - date.getDay() + 7);
            var dateFormat = inst.settings.dateFormat || $.datepicker._defaults.dateFormat;
            $('#startDate').val($.datepicker.formatDate( dateFormat, startDate, inst.settings ));
            $('#endDate').val($.datepicker.formatDate( dateFormat, endDate, inst.settings ));

            selectCurrentWeek();
        },
        beforeShowDay: function(date) {
            var cssClass = '';
            if(date >= startDate && date <= endDate)
                cssClass = 'ui-datepicker-current-day';
            return [true, cssClass];
        },
        onChangeMonthYear: function(year, month, inst) {
            selectCurrentWeek();
        }
    });

    $('.week-picker .ui-datepicker-calendar tr').live('mousemove', function() { $(this).find('td a').addClass('ui-state-hover'); });
    $('.week-picker .ui-datepicker-calendar tr').live('mouseleave', function() { $(this).find('td a').removeClass('ui-state-hover'); });

	// Week view top results
	var top = $("#top-1").text();
	$('.table-week tr td').each(function() {
		if($(this).text() == top) {
			$(this).css("font-weight", "bold");
		}
	});

	// User account slider
	$("#user-access-slider").slider({
    	value: 10,
		min: 0,
		max: 40,
		step: 10,
		slide: function( event, ui ) {
			switch(ui.value) {
				case 0:
					$("#user-access-slider-desc").text("0 (Account disabled)");
					break;
				case 10:
					$("#user-access-slider-desc").text("10 (Normal, access to live & search)");
					break;
				case 20:
					$("#user-access-slider-desc").text("20 (Extended, access to live, search & week view)");
					break;
				case 30:
					$("#user-access-slider-desc").text("30 (Stream admin, cccess to all data and stream admin)");
					break;
				case 40:
					$("#user-access-slider-desc").text("40 (RadioPanel admin, access to all parts of site)");
					break;
				case 50:
					$("#user-access-slider-desc").text("50 (How?!)");
					break;
				default:
					$("#user-access-slider-desc").text(ui.value+" (How?!)");
			}
			$("#user-access-slider-input").val(ui.value);
		}
	});
	$("#user-access-slider-desc").text("10 (Normal, access to live & search)");
});

function weekViewZoom(date, hour) {
	$("#week-view-dialog").load("./?page=api&task=html_display_date&date="+date+"&time="+hour);
	$("#week-view-dialog").dialog({modal: true, title: 'Hour zoom', minWidth: 850, minHeight: 300, height: 'auto', position: { my: 'top', at: 'top+30' }});
}


text:
require 'ohm'
require 'faye'
require 'json'
require 'sinatra/base'
require 'teahouse/room'
require 'teahouse/message'
module Teahouse
  class App < Sinatra::Base
    use Faye::RackAdapter, mount: '/faye', timeout: 25

    set :default_encoding, 'utf-8'
    set :public_folder, Proc.new { File.join(root, '..', 'themes', 'bootstrap') }

    helpers do
      def build_locals(uuid, username)
        @room  = Room.find_or_create_by_uuid(uuid)
        room_h = @room.build_hash
        room_h['username'] = username
        room_h
      end

      def html(view)
        File.read(File.join(settings.public_folder, "#{view.to_s}.html"))
      end
    end

    get '/rooms/:uuid/admins/:username.?:format?', provides: [:html, :json] do
      if params[:format] == 'json'
        @locals = build_locals(params[:uuid], params[:username])
        @room.add_admin(params[:username])
        content_type :js, charset: 'utf-8'
        "#{params[:callback]}(#{@locals.to_json})"
      else
        html :index
      end
    end

    get '/rooms/:uuid/users/:username.?:format?', provides: [:html, :json] do
      if params[:format] == 'json'
        @locals = build_locals(params[:uuid], params[:username])
        @room.add_participant(params[:username])
        content_type :js, charset: 'utf-8'
        "#{params[:callback]}(#{@locals.to_json})"
      else
        html :index
      end
    end

    post '/rooms/:uuid/messages/:username' do
      content_type :json, charset: 'utf-8'
      @room    = Room.find_or_create_by_uuid(params[:uuid])
      @message = Message.create(username: params[:username], content: params[:content], created_at: Time.now.to_i)
      @room.messages.push(@message)
      @message.to_hash.to_json
    end

  end
end


text:
var spawn = require('child_process').spawn,
    request = require('request'),
    expect = require('chai').expect;

var testUtils = {
  spawn: function (cmd, args, options) {
    before(function spawnChildProcess (done) {
      // Start up a child server
      this.child = spawn(cmd, args, options);

      // After it loads, callback
      setTimeout(done, 1000);
    });
    after(function killChildProcess (done) {
      // Kill the child process
      var child = this.child;
      delete this.child;
      child.kill();

      // When it leaves, callback
      child.on('exit', function (code) {
        done();
      });
    });
  },
  request: function (url) {
    before(function requestFn (done) {
      var that = this;
      request(url, function handleResponse (err, res, body) {
        // Save the error, response, and body
        that.err = err;
        that.res = res;
        that.body = body;

        // Callback with the error
        done(err);
      });
    });
    after(function cleanup () {
      delete this.err;
      delete this.res;
      delete this.body;
    });
  }
};

describe('jojo', function () {
  describe('run via CLI', function () {
    testUtils.spawn('node', ['../../../bin/jojo'], {
      cwd: __dirname + '/test_files/cli'
    });

    testUtils.request('http://localhost:11550/1900-05-17-the-wonderful-wizard-of-oz');
    it('serves articles', function () {
      expect(this.body).to.contain('
The Wonderful Wizard of Oz
');
    });
  });

  describe('integrated into a server', function () {
    testUtils.spawn('node', ['app.js'], {
      cwd: __dirname + '/test_files/integrated'
    });

    describe('with response to an index page', function () {
      testUtils.request('http://localhost:11550/');
      it('serves an index page', function () {
        expect(this.body).to.contain('
');
        expect(this.body).to.contain('the-wonderful-wizard-of-oz');
      });
    });

    describe('with respect to articles', function () {
      testUtils.request('http://localhost:11550/1900-05-17-the-wonderful-wizard-of-oz');
      it('serves articles', function () {
        expect(this.body).to.contain('
The Wonderful Wizard of Oz
');
      });
    });

    describe('with respect to a URL unfriendly article', function () {
      testUtils.request('http://localhost:11550/1900-05-17-plus-colon-hello');
      it('slugifies article titles', function () {
        expect(this.res.statusCode).to.equal(200);
      });
    });

    describe('with response to RSS', function () {
      testUtils.request('http://localhost:11550/index.xml');
      it('serves an RSS feed', function () {
        expect(this.body).to.contain('<id>/1900-05-17-the-wonderful-wizard-of-oz</id>');
      });
    });
  });
});

describe('jojo running with no articles', function () {
  testUtils.spawn('node', ['app.js'], {
    cwd: __dirname + '/test_files/empty_app'
  });

  testUtils.request('http://localhost:11550/');
  it('serves content', function () {
    expect(this.body).to.contain('
');
  });
});


text:
package pl.iterators.kebs.instances

import pl.iterators.kebs.instances.util.{CurrencyString, LocaleString, UUIDString}

trait UtilInstances extends CurrencyString with LocaleString with UUIDString

object UtilInstances extends UtilInstances


text:
<?php

namespace App\Http\Controllers\Www;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class IndexController extends Controller
{
	/**
	 * Display a listing of the resource.
	 *
	 * @return \Illuminate\Http\Response
	 */
	public function index()
	{

		$cdn = CDNVENDOR('boot335/css/bootstrap.min.css');
		return view('www.index.index');
	}
}


text:
'''
Wrapper Script for the MQTT Modular Input

Because Splunk can't directly invoke Java , we use this python wrapper script that
simply proxys through to the Java program
'''
import os, sys, signal
from subprocess import Popen

JAVA_MAIN_CLASS = 'com.splunk.modinput.mqtt.MQTTModularInput'
MODINPUT_NAME = 'mqtt'
SECURE_TRANSPORT = "tls"
#SECURE_TRANSPORT = "ssl"

def checkForRunningProcess():

    canonPath = getPIDFilePath()
    if os.path.isfile(canonPath):
      pidfile = open(canonPath, "r")
      pidfile.seek(0)
      old_pid = pidfile.readline()
      try:
        os.kill(int(old_pid),signal.SIGKILL)
      except :
        pass
      pidfile.close()
      os.remove(canonPath)

def writePidFile():
    canonPath = getPIDFilePath()
    pid = str(process.pid)
    f = open(canonPath, 'w')
    f.write(pid)
    f.close()

def getPIDFilePath():
    return MODINPUT_HOME+MODINPUT_NAME+"_ta.pid"

def usage():
    print "usage: %s [--scheme|--validate-arguments]"
    sys.exit(2)

def do_run():
    xml_str = sys.stdin.read()
    sys.argv.append(xml_str)
    run_java()

def do_scheme():
    run_java()

def do_validate():
    xml_str = sys.stdin.read()
    sys.argv.append(xml_str)
    run_java()

def build_windows_classpath():

    rootdir = MODINPUT_HOME + "bin\\lib\\"
    classpath = ""
    for filename in os.listdir(rootdir):
      classpath = classpath + rootdir+filename+";"
    return classpath

def run_java():
    global process,SPLUNK_HOME,MODINPUT_HOME
    if sys.platform.startswith('linux') or sys.platform.startswith('sunos') or sys.platform.startswith('aix') or sys.platform.startswith('hp-ux') or sys.platform.startswith('freebsd')  or sys.platform == 'darwin':

      if (not os.environ.has_key('JAVA_HOME')):
         JAVA_EXECUTABLE = 'java'
      else:
         JAVA_EXECUTABLE = os.path.expandvars('$JAVA_HOME') + "/bin/java"

      SPLUNK_HOME = os.path.expandvars('$SPLUNK_HOME')
      MODINPUT_HOME = SPLUNK_HOME + "/etc/apps/"+MODINPUT_NAME+"_ta/"
      CLASSPATH = MODINPUT_HOME + "bin/lib/*"
    elif sys.platform == 'win32':

      if (not os.environ.has_key('JAVA_HOME')):
         JAVA_EXECUTABLE = 'java'
      else:
         JAVA_EXECUTABLE = os.path.expandvars('%JAVA_HOME%') + "\\bin\\java"

      SPLUNK_HOME = os.path.expandvars('%SPLUNK_HOME%')
      MODINPUT_HOME = SPLUNK_HOME  + "\\etc\\apps\\"+MODINPUT_NAME+"_ta\\"
      CLASSPATH = build_windows_classpath()
    else:
      sys.stderr.writelines("ERROR Unsupported platform\n")
      sys.exit(2)

    if RUNMODE == 3:
      checkForRunningProcess()

    java_args = [ JAVA_EXECUTABLE, "-classpath",CLASSPATH,"-Xms64m","-Xmx64m","-Dsplunk.securetransport.protocol="+SECURE_TRANSPORT,JAVA_MAIN_CLASS]
    java_args.extend(sys.argv[1:])

    # Now we can run our command
    process = Popen(java_args)
    if RUNMODE == 3:
      writePidFile()
    # Wait for it to complete
    process.wait()
    sys.exit(process.returncode)

def signal_handler(signal, frame):
        #kill the java process
        process.kill()
        #exit this script
        sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

if __name__ == '__main__':
    global RUNMODE

    if len(sys.argv) > 1:
        if sys.argv[1] == "--scheme":
            RUNMODE = 1
            do_scheme()
        elif sys.argv[1] == "--validate-arguments":
            RUNMODE = 2
            do_validate()
        else:
            usage()
    else:
        RUNMODE = 3
        do_run()


text:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.github.julman99.jesync</groupId>
    <artifactId>jesync</artifactId>
    <version>0.8.1</version>
    <packaging>jar</packaging>

    <name>JESync</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty</artifactId>
            <version>3.6.1.Final</version>
        </dependency>
        <dependency>
            <groupId>net.sf.jopt-simple</groupId>
            <artifactId>jopt-simple</artifactId>
            <version>4.4</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>14.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.github.julman99.jesync.JESync</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <descriptors>
                        <!--<descriptorRef>jar-with-dependencies</descriptorRef>-->

                        <descriptor>src/main/assembly/dist.xml</descriptor>
                    </descriptors>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/assembly</directory>
                <excludes>
                    <exclude>*</exclude>
                </excludes>
            </resource>

            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>*</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>


text:
using System;

namespace MyHealth.Model
{
    public class ClinicSummary
    {
        public int ClinicSummaryId { get; set; }

        public DateTime Date { get; set; }

        public int TenantId { get; set; }

        public Tenant Tenant { get; set; }

        public int NewPatients { get; set; }

        public int NewPatientsVariation { get; set; }

        public double MonthProfit { get; set; }

        public double MonthProfitVariation { get; set; }

        public double AnualProfit { get; set; }

        public double AnualProfitVariation { get; set; }
    }
}


text:
..  Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

..    http://www.apache.org/licenses/LICENSE-2.0

..  Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

Python Target Parametrization
=============================

Summary
-------

For any supported runtime, TVM should produce numerically
correct results.  Therefore, when writing unit tests that validate
the numeric output, these unit tests should be run on all supported
runtimes.  Since this is a very common use case, TVM has helper
functions to parametrize unit tests such that they will run on all
targets that are enabled and have a compatible device.

A single python function in the test suite can expand to several
parameterized unit tests, each of which tests a single target device.
In order for a test to be run, all of the following must be true.

- The test exists in a file or directory that has been passed to
  `pytest`.

- The pytest marks applied to the function, either explicitly or
  through target parametrization, must be compatible with the
  expression passed to pytest's `-m` argument.

- For parametrized tests using the `target` fixture, the target must
  appear in the environment variable `TVM_TEST_TARGETS`.

- For parametrized tests using the `target` fixture, the build
  configuration in `config.cmake` must enable the corresponding
  runtime.

Unit-Test File Contents
-----------------------

.. _pytest-marks: https://docs.pytest.org/en/6.2.x/mark.html

The recommended method to run a test on multiple targets is by
parametrizing the test.  This can be done explicitly for a fixed list
of targets by decorating with
``@tvm.testing.parametrize_targets('target_1', 'target_2', ...)``, and
accepting ``target`` or ``dev`` as function arguments.  The function
will be run once for each target listed, and the success/failure of
each target is reported separately.  If a target cannot be run because
it is disabled in the `config.cmake`, or because no appropriate
hardware is present, then that target will be reported as skipped.

.. code-block:: python

    # Explicit listing of targets to use.
    @tvm.testing.parametrize_target('llvm', 'cuda')
    def test_function(target, dev):
        # Test code goes here

For tests that should run correctly on all targets, the decorator can
be omitted.  Any test that accepts a ``target`` or ``dev`` argument
will automatically be parametrized over all targets specified in
``TVM_TEST_TARGETS``.  The parametrization provides the same
pass/fail/skipped report for each target, while allowing the test
suite to be easily extended to cover additional targets.

.. code-block:: python

    # Implicitly parametrized to run on all targets
    # in environment variable TVM_TEST_TARGETS
    def test_function(target, dev):
        # Test code goes here

The ``@tvm.testing.parametrize_targets`` can also be used as a bare
decorator to explicitly draw attention to the parametrization, but has
no additional effect.

.. code-block:: python

    # Explicitly parametrized to run on all targets
    # in environment variable TVM_TEST_TARGETS
    @tvm.testing.parametrize_targets
    def test_function(target, dev):
        # Test code goes here

Specific targets can be excluded or marked as expected to fail using
the ``@tvm.testing.exclude_targets`` or
``@tvm.testing.known_failing_targets`` decorators.  For more
information on their intended use cases, please see their docstrings.

In some cases it may be necessary to parametrize across multiple
parameters.  For instance, there may be target-specific
implementations that should be tested, where some targets have more
than one implementation.  These can be done by explicitly
parametrizing over tuples of arguments, such as shown below.  In these
cases, only the explicitly listed targets will run, but they will
still have the appropriate ``@tvm.testing.requires_RUNTIME`` mark
applied to them.

.. code-block:: python

   @pytest.mark.parametrize('target,impl', [
        ('llvm', cpu_implementation),
        ('cuda', gpu_implementation_small_batch),
        ('cuda', gpu_implementation_large_batch),
    ])
    def test_function(target, dev, impl):
        # Test code goes here

The parametrization functionality is implemented
on top of pytest marks.  Each test function can
be decorated with `pytest marks <pytest-marks>`_
to include metadata.  The most frequently applied
marks are as follows.

- ``@pytest.mark.gpu`` - Tags a function as using GPU
  capabilities. This has no effect on its own, but can be paired with
  command-line arguments ``-m gpu`` or ``-m 'not gpu'`` to restrict
  which tests pytest will execute.  This should not be called on its
  own, but is part of other marks used in unit-tests.

- ``@tvm.testing.uses_gpu`` - Applies ``@pytest.mark.gpu``.  This
  should be used to mark unit tests that may use the GPU, if one is
  present.  This decorator is only needed for tests that explicitly
  loop over ``tvm.testing.enabled_targets()``, but that is no longer
  the preferred style of writing unit tests (see below).  When using
  ``tvm.testing.parametrize_targets()``, this decorator is implicit
  for GPU targets, and does not need to be explicitly applied.

- ``@tvm.testing.requires_gpu`` - Applies ``@tvm.testing.uses_gpu``,
  and additionally marks that the test should be skipped
  (``@pytest.mark.skipif``) entirely if no GPU is present.

- ``@tvfm.testing.requires_RUNTIME`` - Several decorators
  (e.g. ``@tvm.testing.requires_cuda``), each of which skips a test if
  the specified runtime cannot be used. A runtime cannot be used if it
  is disabled in the ``config.cmake``, or if a compatible device is
  not present. For runtimes that use the GPU, this includes
  ``@tvm.testing.requires_gpu``.

When using parametrized targets, each test run is decorated with the
``@tvm.testing.requires_RUNTIME`` that corresponds to the target
being used.  As a result, if a target is disabled in ``config.cmake``
or does not have appropriate hardware to run, it will be explicitly
listed as skipped.

There also exists a ``tvm.testing.enabled_targets()`` that returns
all targets that are enabled and runnable on the current machine,
based on the environment variable ``TVM_TEST_TARGETS``, the build
configuration, and the physical hardware present.  Most current tests
explicitly loop over the targets returned from ``enabled_targets()``,
but it should not be used for new tests.  The pytest output for this
style silently skips runtimes that are disabled in ``config.cmake``,
or do not have a device on which they can run.  In addition, the test
halts on the first target to fail, which is ambiguous as to whether
the error occurs on a particular target, or on every target.

.. code-block:: python

    # Old style, do not use.
    def test_function():
        for target,dev in tvm.testing.enabled_targets():
            # Test code goes here

Running locally
---------------

To run the python unit-tests locally, use the command ``pytest`` in
the ``${TVM_HOME}`` directory.

- Environment variables
    - ``TVM_TEST_TARGETS`` should be a semicolon-separated list of
      targets to run. If unset, will default to the targets defined in
      ``tvm.testing.DEFAULT_TEST_TARGETS``.

      Note: If ``TVM_TEST_TARGETS`` does not contain any targets that
      are both enabled, and have an accessible device of that type,
      then the tests will fall back to running on the ``llvm`` target
      only.

    - ``TVM_LIBRARY_PATH`` should be a path to the ``libtvm.so``
      library. This can be used, for example, to run tests using a
      debug build. If unset, will search for ``libtvm.so`` relative to
      the TVM source directory.

- Command-line arguments

    - Passing a path to a folder or file will run only the unit tests
      in that folder or file. This can be useful, for example, to
      avoid running tests located in ``tests/python/frontend`` on a
      system without a specific frontend installed.

    - The ``-m`` argument only runs unit tests that are tagged with a
      specific pytest marker. The most frequent usage is to use ``m
      gpu`` to run only tests that are marked with
      ``@pytest.mark.gpu`` and use a GPU to run. It can also be used
      to run only tests that do not use a GPU, by passing ``m 'not
      gpu'``.

      Note: This filtering takes place after the selection of targets
      based on the ``TVM_TEST_TARGETS`` environment variable.  Even if
      ``-m gpu`` is specified, if ``TVM_TEST_TARGETS`` does not
      contain GPU targets, no GPU tests will be run.

Running in local docker container
---------------------------------

.. _tlcpack: https://hub.docker.com/u/tlcpack

The ``docker/bash.sh`` script can be used to run unit tests inside the
same docker image as is used by the CI.  The first argument should
specify which docker image to run (e.g. ``docker/bash.sh ci_gpu``).
Allowed image names are defined at the top of the Jenkinsfile located
in the TVM source directory, and map to images at `tlcpack`_.

If no additional arguments are given, the docker image will be loaded
with an interactive bash session.  If a script is passed as an
optional argument (e.g. ``docker/bash.sh ci_gpu tests/scripts/task_python_unittest.sh``), then that script will be
executed inside the docker image.

Note: The docker images contain all system dependencies, but do not
include the ``build/config.cmake`` configuration file for those
systems.  The TVM source directory is used as the home directory of
the docker image, and so this will default to using the same
config/build directories as the local config.  One solution is to
maintain separate ``build_local`` and ``build_docker`` directories,
and make a symlink from ``build`` to the appropriate folder when
entering/exiting docker.

Running in CI
-------------

Everything in the CI starts from the task definitions present in the
Jenkinsfile.  This includes defining which docker image gets used,
what the compile-time configuration is, and which tests are included
in which stages.

- Docker images

  Each task of the Jenkinsfile (e.g. 'BUILD: CPU') makes calls to
  ``docker/bash.sh``.  The argument following the call to
  docker/bash.sh defines the docker image in CI, just as it does
  locally.

- Compile-time configuration

  The docker image does not have the ``config.cmake`` file built into
  it, so this is the first step in each of the ``BUILD`` tasks.  This
  is done using the ``tests/scripts/task_config_build_*.sh`` scripts.
  Which script is used depends on the build being tested, and is
  specified in the Jenkinsfile.

  Each ``BUILD`` task concludes by packing a library for use in later
  tests.

- Which tests run

  The ``Unit Test`` and ``Integration Test`` stages of the Jenkinsfile
  determine how ``pytest`` is called.  Each task starts by unpacking a
  compiled library that was previous compiled in the ``BUILD`` stage,
  then runs a test script
  (e.g. ``tests/script/task_python_unittest.sh``).  These scripts set
  the files/folders and command-line options that are passed to
  ``pytest``.

  Several of these scripts include the ``-m gpu`` option, which
  restricts the tests to only run tests that include the
  ``@pytest.mark.gpu`` mark.