I try to use eclipse P2 to enable a tool of mine for auto-updating itself on eclipse start up. While doing so, I want to use an UpdateOperation which is only suited to "my" feature with id "my.feature.id". Whenever this query gets issued in an eclipse installation it has an empty result and thus nothing to update.
So: How do I use the QueryUtil right to get a collection containing only my feature for update as input for an UpdateOperation?
The following method is called when wanting to start the update on eclipse start up:
public class P2Util {
public static IStatus checkForUpdates(IProvisioningAgent agent, IProgressMonitor monitor) {
ProvisioningSession session = new ProvisioningSession(agent);
IQuery<IInstallableUnit> query = QueryUtil.createLatestQuery(QueryUtil.createIUQuery("my.feature.id"));
UpdateCheckActivator.info("Update Query Expression: " + query.getExpression());
IProfileRegistry registry= (IProfileRegistry)agent.getService(IProfileRegistry.SERVICE_NAME);
IProfile profile= registry.getProfile(IProfileRegistry.SELF);
IQueryResult<IInstallableUnit> result = profile.query(query, monitor);
Set<IInstallableUnit> unitsForUpdate = result.toUnmodifiableSet();
UpdateOperation operation = new UpdateOperation(session, unitsForUpdate);
}
}
The solution is very simple but confusing at first. The query trying to find features with "my.feature.id" was querying for the wrong id.
In the feature.xml of my feature it is "my.feature.id" but the installable unit gets for unobvious reasons the suffix "feature.group". If one adds this to the id in the query, you get the correct result and the update operation succeeds as expected.
Related
While integrating with VSTS, I accidentally wiped out the stack rank in VSTS for my 100+ features. My first choice would be to undo the import. Does anyone know how I could revert the action on either the Aha or VSTS side? My second choice would be to edit one by one. I can go into the details of each story and see the original stack rank, but I can't seem to be able to find where I could then reenter it one by one.
If there isn't any other action performed on these work items after that, the quick way is getting the Stack Rank value in the previous revision of the work items and updating the work items with the returned stack rand via coding. Following is the code sample to update the value of Stack Rank to previous version for a single work item:
using Microsoft.TeamFoundation.Client;
using System;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace ConsoleX
{
class Program
{
static void Main(string[] args)
{
Uri url = new Uri("https://vstsaccount.visualstudio.com");
TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(url);
WorkItemStore wis = ttpc.GetService<WorkItemStore>();
int workitemid = 12;
WorkItem wi = wis.GetWorkItem(workitemid);
int previousrevision = wi.Revision - 2;
string previousstackrank = wi.Revisions[previousrevision].Fields["Stack Rank"].Value.ToString();
wi.Fields["Stack Rank"].Value = previousstackrank;
wi.Save();
}
}
}
For you scenario, just add some code to query that 100+ features and update them one by one.
Currently I'm using Eclipse with Nokia/Red plugin which allows me to write robot framework test suites. Support is Python 3.6 and Selenium for it.
My project is called "Automation" and Test suites are in .robot files.
Test suites have test cases which are called "Keywords".
Test Cases
Create New Vehicle
Create new vehicle with next ${registrationno} and ${description}
Navigate to data section
Those "Keywords" are imported from python library and look like:
#keyword("Create new vehicle with next ${registrationno} and ${description}")
def create_new_vehicle_Simple(self,registrationno, description):
headerPage = HeaderPage(TestCaseKeywords.driver)
sideBarPage = headerPage.selectDaten()
basicVehicleCreation = sideBarPage.createNewVehicle()
basicVehicleCreation.setKennzeichen(registrationno)
basicVehicleCreation.setBeschreibung(description)
TestCaseKeywords.carnumber = basicVehicleCreation.save()
The problem is that when I run test cases, in log I only get result of this whole python function, pass or failed. I can't see at which step it failed- is it at first or second step of this function.
Is there any plugin or other solution for this case to be able to see which exact python function pass or fail? (of course, workaround is to use in TC for every function a keyword but that is not what I prefer)
If you need to "step into" a python defined keyword you need to use python debugger together with RED.
This can be done with any python debugger,if you like to have everything in one application, PyDev can be used with RED.
Follow below help document, if you will face any problems leave a comment here.
RED Debug with PyDev
If you are wanting to know which statement in the python-based keyword failed, you simply need to have it throw an appropriate error. Robot won't do this for you, however. From a reporting standpoint, a python based keyword is a black box. You will have to explicitly add logging messages, and return useful errors.
For example, the call to sideBarPage.createNewVehicle() should throw an exception such as "unable to create new vehicle". Likewise, the call to basicVehicleCreation.setKennzeichen(registrationno) should raise an error like "failed to register the vehicle".
If you don't have control over those methods, you can do the error handling from within your keyword:
#keyword("Create new vehicle with next ${registrationno} and ${description}")
def create_new_vehicle_Simple(self,registrationno, description):
headerPage = HeaderPage(TestCaseKeywords.driver)
sideBarPage = headerPage.selectDaten()
try:
basicVehicleCreation = sideBarPage.createNewVehicle()
except:
raise Exception("unable to create new vehicle")
try:
basicVehicleCreation.setKennzeichen(registrationno)
except:
raise exception("unable to register new vehicle")
...
I am developing a unit test project where I create an item in a test, then create sub items for it in the following test.
These tests are parameterized tests, and these parameters are collected in the runtime, so when the project starts it starts. It fails to retrieve the parent item from the database because they are not created yet "as I haven't run the first test yet".
Is there a workaround for this?
The first function:
[Test, Sequential]
public void AddInitiative([ValueSourceAttribute("Get_AddInitiatives_Data_FromExcel")]AddInitiative Initiative_Object)
{
string URL = "http://" + Server_name + Port_number + "/IntegrationHub/IntegrationHub.svc/RestUnsecure/AddInitiative";
string Token = Get_Security_token("gpmdev\\administrator", "Xyz7890", TenantID_Input);
var Response = POST_Request(Initiative_Object, URL, Token);
Guid Returned_GUID = GenericSerializer<Guid>.DeserializeFromJSON(Response);
DataBase_Queries DB = new DataBase_Queries();
List<StrategyItem> StrategyItemsFromDB=DB.GetStrategyItemByID(Returned_GUID.ToString());
Assert.AreEqual(Initiative_Object.Initiative.Name_En, StrategyItemsFromDB[0].Name_En);
}
The second function that fails:
[Test, Sequential]
public void AddInitiativeMilestones([ValueSourceAttribute("Get_AddInitiativeMilestones_Data_FromExcel")]AddMilestone Milestone_Object)
{
string URL = "http://" + Server_name + Port_number + "/IntegrationHub/IntegrationHub.svc/RestUnsecure/AddInitiativeMilestones";
string Token = Get_Security_token("gpmdev\\administrator", "Xyz7890", TenantID_Input);
var Response = POST_Request(Milestone_Object, URL, Token);
List<Milestone> Returned_Milestone = GenericSerializer<List<Milestone>>.DeserializeFromJSON(Response);
DataBase_Queries DB = new DataBase_Queries();
List<StrategyItem> StrategyItemsFromDB = DB.GetStrategyItemByID(Returned_Milestone[0].ID.ToString());
Assert.AreEqual(Milestone_Object.Milestones[0].Name_En, Returned_Milestone[0].Name_En);
Assert.AreEqual(Milestone_Object.Milestones[0].Name_En,StrategyItemsFromDB[0].Name_En);
}
Update: When I clicked from the GUI on Clear fixture the test data was reloaded, but it there a way to do that without the GUI?
It's generally bad practice in unit tests to have one test depend on (i.e. use output from) another test. In this case, with NUnit, it's actually impossible.
It's impossible because NUnit creates tests long before they are executed. NUnit will call your TestCaseSource methods at what we call "load time" when NUnit decides what tests exists and populates a GUI if you use one.
The code in your tests executes at "run time" for the tests. In a gui, this may happen multiple times for each load - every time you click Run, for example.
Note that I'm explaining this in terms of a GUI because it's an easy way to conceptualize it. NUnit works the same way whether you are running in batch or interactively.
If you want something to happen only once, before any tests are run, you can use OneTimeSetUp (TestFixtureSetUp in NUnit V2) to set it up. You can use a member of the class to save whatever you need from that execution and access it from your tests. However, this will still happen at "run time", decades (in computer terms) after your tests have been loaded.
I'm writing an auto number plugin for MS Dynamics CRM 2015. It works on the creation of an opportunity, when a new number needs to be generated. The current number is stored in another entity, which is retrieved at the time of creating the opportunity and then adds 1. The auto number entity is then updated with the new number (except it isn't as this isn't working at the moment).
At the moment the number is retrieved and 1 is added to it and is used in the opportunity correctly. However, as the update to the auto number entity does not occur when another opportunity is created it gets the same number as the previous one.
Here's my plugin code so far:
protected void ExecuteGenerateOpportunityAutoNumber(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName == OPPORTUNITY_ENTITY_NAME)
{
if (!entity.Attributes.Contains(OPPORTUNITY_REF_ID))
{
try
{
string newId = RetrieveAndUpdateLastId(service);
entity.Attributes.Add(OPPORTUNITY_REF_ID, newId);
}
catch (FaultException ex)
{
throw new InvalidPluginExecutionException("GenerateOpportunityAutoNumber plugin error: ", ex);
//tracingService.Trace("GenerateOpportunityAutoNumber plugin error: {0}", ex.Message);
}
}
}
}
}
The RetrieveAndUpdateLastId method code is below:
private string RetrieveAndUpdateLastId(IOrganizationService service)
{
lock (lastIdentifierLock)
{
string result = null;
ColumnSet cols = new ColumnSet();
cols.AddColumns(LAST_REF_LAST_VALUE, LAST_REF_PRIMARY_KEY);
QueryExpression query = new QueryExpression();
query.ColumnSet = cols;
query.EntityName = LAST_REF_ENTITY_NAME;
EntityCollection ec = service.RetrieveMultiple(query);
if (ec.Entities.Count >= 1)
{
foreach (Entity identifier in ec.Entities)
{
if (identifier.Attributes.Contains(LAST_REF_LAST_VALUE))
{
int? lastValue = identifier[LAST_REF_LAST_VALUE] as int?;
if (lastValue != null)
{
string newValue = (lastValue.Value + 1).ToString().PadLeft(7, '0');
result = String.Format("SN{0}", newValue); //This is clearly happening as I'm getting the next number back.
identifier[LAST_REF_LAST_VALUE] = lastValue.Value + 1;
//Tried this also:
//identifier.Attributes.Remove(LAST_REF_LAST_VALUE);
//identifier.Attributes.Add(LAST_REF_LAST_VALUE, lastValue.Value + 1);
service.Update(identifier); //This doesn't seem to be happening.
break;
}
}
}
}
return result;
}
}
No error is thrown but the update of the auto number just isn't happening. I've checked the user I'm running this as has the required update privileges on the auto number entity as well. Any ideas?
UPDATE
After debugging I found that it was throwing an error that the Principal user is missing the prvWrite privilege. This would explain why the update isn't happening, but now raises another issue. I've setup the plugin to run as a specific user (one with the correct privileges), but the Guid of the 'Principal user' in the error was of the calling user. Why would it run as the calling user when I've set it up to use a specific user?
UPDATE 2
I think I may have found the issue but wonder if anyone else can confirm / shed some more light on this. It seems that according to this, the issue may lie with the user not being in a specific AD group, specifically
User account (A) needs the privilege prvActOnBehalfOfAnotherUser,
which is included in the Delegate role.
Alternately, for Active Directory directory service deployments only,
user account (A) under which the impersonation code is to run can be
added to the PrivUserGroup group in Active Directory. This group is
created by Microsoft Dynamics CRM during installation and setup. User
account (A) does not have to be associated with a licensed Microsoft
Dynamics CRM user. However, the user who is being impersonated (B)
must be a licensed Microsoft Dynamics CRM user.
For my purposes I think the user I'm trying to run as needs to be in PrivUserGroup in AD (which it's not), otherwise it defaults to the calling user.
UPDATE 3
I've been able to identify 2 fundamental problems. The first is as explained above, in that the context always runs as the calling user. The 2nd is that when either giving the calling user system admin privileges OR creating the IOrganizationService with a null parameter it still doesn't update. HOWEVER, and this seems very odd, these 2 scenarios DO work when profiling the plugin. Why would this be?
UPDATE 4
It seems I may have resolved the issue, though I'm not certain (hence why I've not written an answer as yet). As per the documentation we've added the user to be impersonated into the PrivUserGroup. The plugin now works. However, I don't understand why this is needed. Also, is this best practice in this scenario or have I done something that should never be done?
On a related note I also unregistered the plugin before deploying it this time, so I'm now wondering if this solved this issue. To confirm I've now removed the user from the PrivUserGroup in AD, but this takes some time (not sure exactly how long) to filter through apparently. If it still works then it looks like this actually resolved it. Do you normally need to unregister a plugin before re-deploying it to make sure it works?
UPDATE 5
Ok, so this if my final update. I'm not marking this as the answer as I'm not 100% certain, but it appears that removing the assembly using the plugin registration tool may have done the trick. From everything I've read you shouldn't need to unregister a plugin to redeploy, so my perhaps my assembly was corrupt somehow and by removing it and creating it again using the new assembly solve the issue. Unfortunately I don't have the original assembly to test with.
I would suggest to debug your plugin. Following article contains a video that describes how to debug plugins using Plugin Debugger and Plugin Regitration Tool - http://blogs.msdn.com/b/devkeydet/archive/2015/02/17/debug-crm-online-plugins.aspx
Updated How to have 2 instances of IOrganizationService for user context and system:
Open Plugin.cs file.
Locate following code:
internal IOrganizationService OrganizationService
{
get;
private set;
}
Add following code after:
internal IOrganizationService SystemOrganizationService
{
get;
private set;
}
Find following code:
// Use the factory to generate the Organization Service.
this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);
Add following code after:
this.SystemOrganizationService = factory.CreateOrganizationService(null);
Use this instance of IOrganizationService in the place where you need higher level of privileges.
I am getting files from Oracle UCM via RIDC. I am using DataBinder as follows :
IdcClient client =getUCMConnection();
DataBinder dataBinder = client.createBinder ();
dataBinder.putLocal ("IdcService", "GET_FILE");
dataBinder.putLocal ("dID", dID);
IdcContext userContext = new IdcContext(username);
ServiceResponse response = client.sendRequest (userContext, dataBinder);
InputStream fstream = response.getResponseStream ();
....... etc.
I want to ask, how can I get "ALL VERSIONS" of a document instead of latest released one?
First you have to call the service DOC_INFO, you can get the result set of the revision by using the REVISION_HISTORY set.
You will get specific dID for each version, you iterate them and use GET_FILE with dID as a parameter for each one of them
I can't test it right now but I think the service you are looking for is GET_INFO, try it and check all the resultsets you get I'm pretty sure one of them has the info for all the document's revisions.
You can use the service REV_HISTORY to get the result set REVISIONS which contains info of all the revisions.